/* ==========================================================================
   Afthonios Course Shell — shared styles used by every course
   All block styles live here or in /_core/blocks/*.css. Courses never inline
   their own CSS; they only provide course.json + assets.
   ========================================================================== */

/* ── Fonts (extracted from Rise SCORM) ── */
@font-face {
  font-family: "Be Vietnam";
  src: url("fonts/BeVietnam-Regular.woff") format("woff");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Be Vietnam";
  src: url("fonts/BeVietnam-Bold.woff") format("woff");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Be Vietnam";
  src: url("fonts/BeVietnam-Italic.woff") format("woff");
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: "Lato";
  src: url("fonts/Lato2-Regular.woff") format("woff");
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Lato";
  src: url("fonts/Lato2-Bold.woff") format("woff");
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Lato";
  src: url("fonts/Lato2-Italic.woff") format("woff");
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: "Lato";
  src: url("fonts/Lato2-Light.woff") format("woff");
  font-weight: 300; font-style: normal; font-display: swap;
}

:root {
  /* ── Brand ── */
  --brand: #c2410c;
  --brand-rgb: 194, 65, 12;     /* RGB triplet for rgba(var(--brand-rgb), α) */
  --brand-hover: #a63a0a;
  --brand-soft: #fff7ed;
  --brand-dark: #7c2d12;

  /* ── Semantic: Success ── */
  --success: #15803d;
  --success-soft: #f0fdf4;
  --success-text: #14532d;

  /* ── Semantic: Danger ── */
  --danger: #b91c1c;
  --danger-soft: #fef2f2;
  --danger-text: #7f1d1d;

  /* ── Semantic: Warning ── */
  --warning: #d97706;
  --warning-soft: #fffbeb;
  --warning-text: #92400e;

  /* ── Semantic: Info ── */
  --info: #1d4ed8;
  --info-soft: #eff6ff;
  --info-text: #1e3a8a;

  /* ── Neutrals ── */
  --text: #1a1a2e;
  --text-soft: #556;
  --bg: #ffffff;
  --bg-soft: #f7f5f2;      /* warm gray for gated sections + cards */
  --bg-mid: #edebe8;
  --border: #e0ddd8;
  --shadow-sm: 0 2px 12px rgba(0,0,0,.05);
  --shadow-md: 0 4px 20px rgba(0,0,0,.10);

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;

  --font-body: "Lato", -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-head: "Be Vietnam", -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  /* ── Spacing tokens ── */
  --space-section: 3rem;             /* vertical padding per block section */
  --space-section-lg: 6rem;          /* larger section spacing (e.g. header) */
  --space-block: 2rem;               /* standard gap between elements */
  --space-inline: 3rem;              /* horizontal content padding (desktop) */

  /* ── Accent bar (decorative rule) ── */
  --accent-height: 0.5rem;           /* thickness — consistent everywhere */
  --accent-width-short: 7.6rem;      /* used on DÉCOUVRIR hero blocks */
  --accent-width-long: 16rem;        /* used on course title header */
  --accent-color: var(--brand);      /* always brand color */
  --accent-radius: 2px;

  /* ── Width tokens (two-layer system, matching Rise layout) ── */
  /* Layer 1: __wrap  = outer container (padding box)             */
  /* Layer 2: __col   = inner content column (where text sits)    */
  --wrap-max: 920px;                 /* outer container, always L (92rem) */
  --content-max: 760px;              /* inner content column (76rem) — Rise default */
  --pad-x: clamp(1.25rem, 4vw, 3rem);

  /* --- S/M/L sizing system — values from Rise's compiled CSS --- */
  /* Rise uses html{font-size:62.5%} so 1rem = 10px; we do the same. */
  --size-width-s: 520px;             /* Rise .custom-width-sm  (52rem) */
  --size-width-m: 760px;             /* Rise .custom-width-med (76rem) */
  --size-width-l: 920px;             /* Rise .custom-width-lg  (92rem) */
  --size-pad-s: 30px;                /* Rise block padding S (slider preset) */
  --size-pad-m: 60px;                /* Rise block padding M (default) */
  --size-pad-l: 100px;               /* Rise block padding L */
  --size-cell-s: 10px;               /* Rise .cell-padding-sm  (1rem) */
  --size-cell-m: 15px;               /* Rise .cell-padding-med (1.5rem) */
  --size-cell-l: 30px;               /* Rise .cell-padding-lg  (3rem) */
}

/* Generic S/M/L modifiers — any block can opt in.
   Width: controls the INNER CONTENT column (not the outer wrap).
   Targets: __inner, __container, __col (template pattern), __wrap (fallback).
   !important is used because per-block CSS (like .block-table__inner
   { max-width: var(--content-max) }) would otherwise win via specificity.
   The S/M/L system is meant to be authoritative when explicitly set. */
.block.block--w-s > .block__inner,
.block.block--w-s > [class*="__inner"]:first-child,
.block.block--w-s [class*="__container"],
.block.block--w-s [class*="__col"] { max-width: var(--size-width-s) !important; }
.block.block--w-m > .block__inner,
.block.block--w-m > [class*="__inner"]:first-child,
.block.block--w-m [class*="__container"],
.block.block--w-m [class*="__col"] { max-width: var(--size-width-m) !important; }
.block.block--w-l > .block__inner,
.block.block--w-l > [class*="__inner"]:first-child,
.block.block--w-l [class*="__container"],
.block.block--w-l [class*="__col"] { max-width: var(--size-width-l) !important; }

/* Block padding: vertical whitespace around the block. */
.block.block--pad-s { padding-top: var(--size-pad-s); padding-bottom: var(--size-pad-s); }
.block.block--pad-m { padding-top: var(--size-pad-m); padding-bottom: var(--size-pad-m); }
.block.block--pad-l { padding-top: var(--size-pad-l); padding-bottom: var(--size-pad-l); }

/* Dark background blocks (ACCENT / BLACK / DARK) → white text + decoratives.
   Use high specificity to override template-level color: var(--text). */
.block.block--bg-dark,
.block.block--bg-dark h1, .block.block--bg-dark h2,
.block.block--bg-dark h3, .block.block--bg-dark h4,
.block.block--bg-dark p, .block.block--bg-dark li,
.block.block--bg-dark span, .block.block--bg-dark a,
.block.block--bg-dark div,
.block.block--bg-dark [class*="__heading"],
.block.block--bg-dark [class*="__text"],
.block.block--bg-dark [class*="__quote"] { color: #fff !important; }
.block.block--bg-dark a { text-decoration: underline; }

* { box-sizing: border-box; }
html { font-size: 62.5%; }             /* 1rem = 10px */
body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--text);
  background: var(--bg);
  font-size: 1.7rem;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;                  /* prevent horizontal scroll on narrow screens */
}
img { max-width: 100%; height: auto; display: block; }

/* Global responsive safety — prevent text overflow on narrow viewports */
p, h1, h2, h3, h4, li, div { overflow-wrap: break-word; word-wrap: break-word; }

/* Course layout ----------------------------------------------------------- */
/* Note: .course-header + .block-text-on-image styles live in their template
   files (_core/templates/*.html). Do not redefine them here. */
.course {
  max-width: 100%;
  margin: 0 auto;
}
.course__title {
  font-size: clamp(2.4rem, 3.6vw, 3.2rem);
  line-height: 1.25;
  margin: 0 0 1rem;
  font-weight: 700;
  letter-spacing: -.01em;
}
.course__accent {
  width: 4rem; height: .4rem;
  background: var(--brand);
  border-radius: 2px;
  margin: 0 auto;
}

.course__body { padding: 0; }

/* Generic block wrapper — every block sits inside this.
   Blocks can opt into full-width or centered via modifiers. */
.block {
  padding: 1.5rem var(--pad-x);
  max-width: 100%;
  margin: 0; /* No margins between blocks — backgrounds must butt up seamlessly */
}
/* Sub-pixel gaps between adjacent colored blocks are fixed via box-shadow
   in applySizing() (blocks.js) — each colored block bleeds 1px downward. */
.block__inner { max-width: var(--content-max); margin: 0 auto; }
.block--tint  { background: var(--bg-soft); }
.block--full  { padding-left: 0; padding-right: 0; }
/* Full-bleed blocks — no side padding, edge-to-edge like Rise original.
   For quote-background and image-hero we ALSO break out of any parent
   container's max-width via the 100vw + negative-margin trick, so the
   image spans the entire viewport width like Rise. Requires that
   ancestor containers have overflow: visible (review-item__frame does). */
.block.block-image--overlay,
.block.block-image-hero,
.block.block-quote--background,
.block.block-quote.block-quote--background { padding-left: 0; padding-right: 0; }
.block.block-quote--background {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
  max-width: 100vw;
}

/* Gate / Continue — button styling lives in _core/templates/continue.html
   Disappear is two-phased (driven by shell.js openGate):
     1. .is-fading  → button opacity → 0 in place (no collapse, so it doesn't
                      get clipped from below by a shrinking wrapper)
     2. .is-clicked → wrapper height + padding collapse, scroll starts in
                      parallel (slower easing for a calmer settle) */
.block-continue.is-fading .continue-btn,
.block-continue.is-clicked .continue-btn {
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s ease;
}
.block-continue.is-clicked {
  max-height: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin: 0;
  overflow: hidden;
  transition: max-height .55s cubic-bezier(.4, 0, .2, 1),
              padding    .55s cubic-bezier(.4, 0, .2, 1),
              margin     .55s cubic-bezier(.4, 0, .2, 1);
}
.gated {
  overflow: hidden;
  max-height: 0;
  opacity: 0;
  transition: opacity .4s ease;
}
.gated.is-revealed {
  max-height: none;
  opacity: 1;
  padding: 1rem 0 2rem;
  overflow: visible;   /* Override hidden so the gate is no longer a scroll
                          container — prevents browser auto-scroll when popups
                          or interactive blocks inside the gate extend beyond
                          the gate's content box. */
}

/* Reveal animation on scroll --------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(18px);
  transition: opacity .7s ease, transform .7s ease;
}
.reveal.is-visible { opacity: 1; transform: none; }
/* Wer weniger Bewegung bestellt hat, bekommt den Inhalt sofort und ohne
   Einfahrt. Fehlte bisher: jeder Block ist auch dann geglitten. */
@media (prefers-reduced-motion: reduce) {
  .reveal,
  .reveal.is-visible {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* Text blocks (paragraph / heading-paragraph / subheading-paragraph),
   statement (d/b/c), text-on-image, divider, objectives, video:
   all styles live in _core/templates/<name>.html */

/* Block: image ----------------------------------------------------------- */
/* Default = Rise M (720px). Opt in to wider via `"width": "l"` in course.json. */
.block-image__inner { max-width: var(--content-max); margin: 0 auto; }
.block-image__img { border-radius: var(--radius-md); box-shadow: var(--shadow-sm); }
.block-image--hero .block-image__inner { max-width: 100%; }
.block-image--hero .block-image__img { border-radius: 0; width: 100%; }
.block-image__caption { text-align: center; margin: .8rem 0 0; font-size: 1.4rem; color: var(--text-soft); font-style: italic; }

/* Block: text-aside (image + text two-column) — Rise `block-image--text-aside`.
   Three column ratios driven by imageSize + reverse layout via image.align.
   Rise lets the image render at its natural aspect ratio (or its crop ratio
   from `dimensions`), capped by max-height: 70rem / min-height: 20rem. We do
   *not* force a fixed height — that was the source of the "all images same
   size" regression.

   Container: Rise's .block-image__container has 92rem content + 6rem
   padding × 2 with box-sizing: initial = 104rem outer. We use max-width
   104rem so column percentages compute against 1040px. */
.block-text-aside__inner {
  max-width: 104rem;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;            /* medium default 50/50 */
  gap: 3rem;
  align-items: center;
}
.block-text-aside--small .block-text-aside__inner {
  grid-template-columns: 41.6667% 58.3333%;  /* small: image 5/12 */
}
.block-text-aside--large .block-text-aside__inner {
  grid-template-columns: 75% 25%;            /* large: image 9/12 */
}
.block-text-aside--reverse.block-text-aside--small .block-text-aside__inner {
  grid-template-columns: 58.3333% 41.6667%;
}
.block-text-aside--reverse.block-text-aside--large .block-text-aside__inner {
  grid-template-columns: 25% 75%;
}

/* At ≥90em (1440px) Rise widens the image column by one 12-column unit
   AND pulls it outside the container with margin-inline-start: -8.33%.
   We swap to flexbox here because in CSS Grid, percentage margins on
   grid items are computed against the COLUMN width — so -8.33% only
   nudged 26-42px instead of Rise's full -87px. With flexbox, the
   margin references the FLEX CONTAINER (the inner), giving the proper
   overhang. */
@media (min-width: 90em) {
  .block-text-aside__inner {
    display: flex;
    grid-template-columns: none;             /* drop the grid override */
  }
  .block-text-aside--reverse .block-text-aside__inner {
    flex-direction: row-reverse;
  }
  .block-text-aside__figure { flex: 0 0 58.3333%; }                       /* medium 50→58.33% */
  .block-text-aside--small .block-text-aside__figure { flex: 0 0 50%; }   /* small  41.67→50% */
  .block-text-aside--large .block-text-aside__figure { flex: 0 0 83.3333%; } /* large  75→83.33% */
  .block-text-aside__text { flex: 1 1 auto; min-width: 0; }
  /* Bleed: with flexbox, the percentage margin references the flex
     container (1040px), so -8.33% ≈ -87px. */
  .block-text-aside__figure {
    margin-inline-start: -8.3333%;
  }
  .block-text-aside--reverse .block-text-aside__figure {
    margin-inline-start: 0;
    margin-inline-end: -8.3333%;
  }
  /* Two-column text variant: no figure, no bleed — equal split. */
  .block-text-aside--text-text .block-text-aside__text {
    flex: 1 1 50%;
  }
}
/* Two-column text variant (family=text, variant="two column"): no image,
   both columns are text. Equal width, larger gap. align-items: start so the
   columns top-align rather than centring around an absent image. */
.block-text-aside--text-text .block-text-aside__inner {
  grid-template-columns: 1fr 1fr;
  gap: 4rem;
  align-items: start;
}
.block-text-aside__text--aside { /* identical to base text — class exists for hooks */ }
/* Rise's `.block-image__figure` has min-height: 40rem; flex-direction: column;
   justify-content: center — so short images sit centred in a 400px floor.
   That was the missing piece: with our previous 20rem floor, every short
   landscape rendered at its natural height alone, while Rise reserved 400px
   for vertical alignment with the text column. */
.block-text-aside__figure {
  /* Only kill the vertical default <figure> margins — leave inline alone
     so the @media (min-width: 90em) bleed rule above can apply
     margin-inline-start: -8.33% without being overridden by source order. */
  margin-block: 0;
  min-height: 40rem;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.block-text-aside__figure--empty { min-height: 0; }
.block-text-aside__img {
  width: 100%;
  height: auto;                       /* natural aspect; aspect-ratio attrs prevent CLS */
  max-height: 70rem;                  /* Rise's image-wrapper cap */
  object-fit: cover;                  /* preserves ratio when max-height clamps */
  border-radius: var(--radius-md);
  display: block;
}
.block-text-aside--zoomable .block-text-aside__img {
  cursor: zoom-in;
  transition: transform 0.15s ease-out;
}
.block-text-aside--zoomable .block-text-aside__img:hover {
  transform: scale(1.01);
}

/* Image lightbox — opened by clicking a zoomOnClick image. */
.image-lightbox {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0, 0, 0, 0.85);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 4rem;
  cursor: zoom-out;
  opacity: 0;
  transition: opacity 0.2s ease-out;
}
.image-lightbox.is-open {
  display: flex;
  opacity: 1;
}
.image-lightbox__img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: var(--radius-md);
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.5);
}
.image-lightbox__close {
  position: absolute;
  top: 2rem;
  right: 2rem;
  width: 4rem;
  height: 4rem;
  font-size: 2.4rem;
  color: white;
  background: rgba(255, 255, 255, 0.15);
  border: none;
  border-radius: 50%;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
  transition: background 0.15s;
}
.image-lightbox__close:hover {
  background: rgba(255, 255, 255, 0.3);
}

/* Download-Knopf ueber einem Bild (Galerie, Raster, Karussell, Lightbox).
   Er erscheint beim Ueberfahren, damit er das Bild nicht dauerhaft
   verdeckt. Auf Geraeten ohne Zeiger (Touch) gibt es kein Hover — dort
   steht er immer, sonst waere er unerreichbar. Bei Tastaturfokus ebenso. */
/* Wird auf einen BESTEHENDEN Container gesetzt (Karussell-Slide,
   Rasterzelle, Einzelbild-Rahmen) — kein eigener Wrapper, damit die
   Rise-Groessenregeln der Bilder unveraendert greifen. Deshalb hier auch
   nur position, sonst nichts. */
.has-download {
  position: relative;
}
.image-download-btn {
  position: absolute;
  top: 1rem;
  right: 1rem;
  width: 3.6rem;
  height: 3.6rem;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.92);
  color: #2a2530;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.28);
  cursor: pointer;
  opacity: 0;
  /* Unsichtbar heisst auch unklickbar — ein Knopf mit opacity:0 wuerde
     sonst den Zoom-Klick in der Bildecke abfangen. */
  pointer-events: none;
  transform: translateY(-4px);
  transition:
    opacity 0.18s ease,
    transform 0.18s ease,
    background-color 0.18s ease;
}
.has-download:hover .image-download-btn,
.image-download-btn:focus-visible {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
.image-download-btn:hover {
  background: #ffffff;
}
@media (hover: none) {
  .image-download-btn {
    opacity: 1;
    pointer-events: auto;
    transform: none;
  }
}
@media (prefers-reduced-motion: reduce) {
  .image-download-btn {
    transition: none;
  }
}
/* In der Lightbox links oben, gegenueber dem Schliessen-Kreuz — und immer
   sichtbar: dort ist das Bild ohnehin gross und der Knopf verdeckt nichts. */
.image-lightbox__download {
  top: 2rem;
  left: 2rem;
  right: auto;
  width: 4rem;
  height: 4rem;
  opacity: 1;
  pointer-events: auto;
  transform: none;
}
.block-text-aside__text p { margin: 0 0 1rem; }
.block-text-aside__text p:last-child { margin-bottom: 0; }
/* Override generic .reveal on text-aside — children animate individually */
.block-text-aside.reveal {
  opacity: 1; transform: none;
}
.block-text-aside .block-text-aside__figure {
  opacity: 0; transform: translateX(-40px);
  transition: opacity .6s ease-out, transform .6s ease-out;
}
.block-text-aside--reverse .block-text-aside__figure {
  transform: translateX(40px);
}
.block-text-aside .block-text-aside__text {
  opacity: 0; transform: translateX(40px);
  transition: opacity .6s ease-out .15s, transform .6s ease-out .15s;
}
.block-text-aside--reverse .block-text-aside__text {
  transform: translateX(-40px);
}
.block-text-aside.is-visible .block-text-aside__figure,
.block-text-aside.is-visible .block-text-aside__text {
  opacity: 1; transform: none;
}
@media (prefers-reduced-motion: reduce) {
  .block-text-aside .block-text-aside__figure,
  .block-text-aside .block-text-aside__text { opacity: 1; transform: none; transition: none; }
}
/* Tablet/mobile — Rise stacks at < 48em. */
@media (max-width: 47.9375em) {
  .block-text-aside__inner,
  .block-text-aside--small .block-text-aside__inner,
  .block-text-aside--large .block-text-aside__inner,
  .block-text-aside--reverse.block-text-aside--small .block-text-aside__inner,
  .block-text-aside--reverse.block-text-aside--large .block-text-aside__inner {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  /* When stacked, reverse still keeps text-after-image (image leads). */
  .block-text-aside--reverse .block-text-aside__inner > :first-child { order: 2; }
  .block-text-aside--reverse .block-text-aside__inner > :last-child  { order: 1; }
  /* Rise drops the figure floor on stacked layout — the text below would
     otherwise look orphaned next to a 400px reservation. */
  .block-text-aside__figure { min-height: 0; }
}

/* Block: quote ----------------------------------------------------------- */
.block-quote {
  background: var(--bg-soft);
  padding: 3rem var(--pad-x);
  text-align: center;
}
.block-quote__text {
  max-width: 680px; margin: 0 auto 1rem;
  font-size: 1.9rem; font-style: italic; font-weight: 500;
  line-height: 1.5;
}
/* No injected guillemets — quote marks live in the content or in the
   variant-specific templates (curly “…”). Adding « » here in brand
   colour produced ugly orange marks Rise never shows. */
.block-quote__author {
  font-size: 1.3rem;
  color: var(--text-soft);
  text-transform: uppercase;
  letter-spacing: .1em;
  font-weight: 700;
}

/* Block: knowledge-check ------------------------------------------------- */
.block-knowledge-check { padding: 2rem var(--pad-x); }
.block-knowledge-check__inner {
  max-width: var(--content-max); margin: 0 auto;
  background: var(--bg-soft);
  padding: 2rem 2.2rem;
  border-radius: var(--radius-md);
}
.block-knowledge-check__question { margin: 0 0 1.25rem; font-size: 1.8rem; font-weight: 700; }
.block-knowledge-check__hint { color: var(--text-soft); font-size: 1.4rem; margin-bottom: 1rem; }
.block-knowledge-check__options { display: flex; flex-direction: column; gap: .6rem; margin-bottom: 1.25rem; }
.block-knowledge-check__option {
  display: flex; align-items: center; gap: 1rem;
  background: #fff;
  border: 2px solid var(--border);
  border-radius: var(--radius-sm);
  padding: .95rem 1.1rem;
  cursor: pointer;
  transition: all .15s ease;
  font-size: 1.55rem;
  line-height: 1.45;
}
.block-knowledge-check__option:hover { border-color: var(--brand); background: var(--brand-soft); }
.block-knowledge-check__option.is-selected { border-color: var(--brand); background: var(--brand-soft); }
.block-knowledge-check__option.is-correct { border-color: var(--success); background: var(--success-soft); }
.block-knowledge-check__option.is-wrong   { border-color: var(--danger); background: var(--danger-soft); }
.block-knowledge-check__option.is-missed  { border-color: var(--success); border-style: dashed; background: var(--success-soft); }
.block-knowledge-check__checkbox {
  flex: 0 0 2.2rem; width: 2.2rem; height: 2.2rem;
  border: 2px solid var(--border);
  border-radius: 4px;
  display: flex; align-items: center; justify-content: center;
  background: #fff;
  margin-top: .1em;
}
.block-knowledge-check__option.is-selected .block-knowledge-check__checkbox { background: var(--brand); border-color: var(--brand); }
.block-knowledge-check__option.is-correct  .block-knowledge-check__checkbox { background: var(--success); border-color: var(--success); }
.block-knowledge-check__option.is-wrong    .block-knowledge-check__checkbox { background: var(--danger); border-color: var(--danger); }
.block-knowledge-check__checkbox svg { opacity: 0; transition: opacity .15s; color: #fff; width: 16px; height: 16px; }
.block-knowledge-check__option.is-selected .block-knowledge-check__checkbox svg,
.block-knowledge-check__option.is-correct .block-knowledge-check__checkbox svg,
.block-knowledge-check__option.is-wrong .block-knowledge-check__checkbox svg { opacity: 1; }
.block-knowledge-check__submit {
  display: block; margin: 0 auto;
  background: var(--brand); color: #fff; border: 0;
  padding: .9rem 3rem; border-radius: 999px;
  font: inherit; font-size: 1.4rem; font-weight: 700; letter-spacing: 0.04em;
  text-transform: uppercase; cursor: pointer;
  letter-spacing: .05em;
}
.block-knowledge-check__submit:disabled { background: var(--bg-mid); cursor: not-allowed; }
.block-knowledge-check__feedback {
  margin-top: 2rem;
  display: none;
  text-align: center;
}
.block-knowledge-check__feedback.is-visible { display: block; }
.kc-result__icon { margin: 0 auto 1rem; }
.kc-result__icon .kc-icon {
  width: 8rem; height: 8rem;
  border: 2.5px solid currentColor;
  border-radius: 50%;
  padding: 1.8rem;
}
.block-knowledge-check__feedback.is-correct .kc-icon { color: var(--success, #16a34a); }
.block-knowledge-check__feedback.is-incorrect .kc-icon { color: var(--danger, #c2410c); }
.kc-result__label { font-size: 1.8rem; font-weight: 700; margin-bottom: 0.5rem; }
.kc-result__msg { font-size: 1.4rem; color: var(--text-soft); }
.block-knowledge-check__retry {
  margin-top: 1.5rem;
  background: transparent;
  border: 2px solid var(--text);
  color: var(--text);
  padding: .8rem 2.4rem;
  border-radius: 999px;
  font: inherit; font-size: 1.3rem; font-weight: 700;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: background .2s;
}
.block-knowledge-check__retry:hover { background: var(--bg-soft, #f5f5f5); }
.kc-retry-icon { width: 2rem; height: 2rem; vertical-align: middle; margin-right: .4rem; position: relative; top: -1px; }

/* Block: labeled-graphic ------------------------------------------------- */
/* All styles live in _core/templates/labeled-graphic.html (scoped to
   .block-labeled-graphic .hotspot). Do NOT add hotspot rules here — they
   would leak into any block that uses a .hotspot class. */

/* Block: accordion ------------------------------------------------------- */
.block-accordion__inner {
  max-width: var(--content-max); margin: 0 auto;
  background: #fff; border-radius: var(--radius-md);
  box-shadow: 0 1px 4px rgba(0,0,0,.06);
}
.block-accordion__item { border-bottom: 1px solid var(--border); }
.block-accordion__item:last-child { border-bottom: 0; }
.block-accordion__item:first-child { border-top: none; }
.block-accordion__trigger {
  width: 100%;
  background: transparent; border: 0;
  padding: 1.6rem 2rem;
  text-align: left;
  font: inherit; font-weight: 700; font-size: 1.7rem;
  color: var(--text);
  cursor: pointer;
  display: flex; justify-content: space-between; align-items: center;
  gap: 1rem;
}
.block-accordion__trigger::after {
  content: "+";
  font-size: 2rem; color: var(--brand);
  font-weight: 400;
  transition: transform .2s;
}
.block-accordion__item.is-open .block-accordion__trigger::after { transform: rotate(45deg); }
.block-accordion__body {
  /* Closing: opacity fades immediately while height collapses (parallel) */
  max-height: 0; overflow: hidden;
  opacity: 0;
  transition: max-height .3s ease, opacity .2s ease;
  padding: 0 2rem;
  font-size: 1.55rem; line-height: 1.55;
}
/* Opening: height grows first (.3s), then content fades in (.25s after a
   .15s delay). Without the delay the opacity transition runs in parallel
   with max-height — perceptually invisible because the small clipped area
   masks it. Closing keeps the parallel transition (no override) so the
   fade-out is clearly visible as the panel collapses. */
.block-accordion__item.is-open .block-accordion__body {
  max-height: 2000px; opacity: 1; padding: 0 2rem 1.6rem;
  transition: max-height .3s ease, opacity .25s ease .15s;
}
.block-accordion__img {
  width: 100%; max-width: 100%; border-radius: 4px;
  margin-bottom: 1rem; display: block;
}

/* Block: attachment ------------------------------------------------------ */
.block-attachment__inner { max-width: var(--content-max); margin: 0 auto; }
.block-attachment__card {
  display: flex; align-items: center; gap: 1.2rem;
  background: var(--bg-soft);
  padding: 1rem 1.2rem;
  border-radius: var(--radius-md);
  text-decoration: none;
  color: inherit;
  transition: box-shadow .2s;
}
.block-attachment__card:hover { box-shadow: var(--shadow-sm); }
.block-attachment__icon {
  flex: 0 0 4rem; height: 4rem;
  background: var(--danger-soft); color: var(--danger);
  border-radius: var(--radius-sm);
  display: flex; align-items: center; justify-content: center;
  font-weight: 800;
  font-size: 1.2rem;
}
.block-attachment__name { font-weight: 700; font-size: 1.55rem; }
.block-attachment__download { margin-left: auto; font-size: 1.8rem; color: var(--brand); }

/* Block: porter-questionnaire iframe wrapper ----------------------------- */
/* Width widened to full content column; height is set dynamically in JS   */
/* from postMessage('porter:height') — no internal scrolling.              */
.block-porter__inner {
  max-width: var(--content-max);
  margin: 0 auto;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
  background: #fff;
}
.block-porter__iframe {
  width: 100%;
  height: 900px; /* fallback before postMessage arrives */
  border: 0;
  display: block;
}

/* Block: table ----------------------------------------------------------- */
/* Rise-style: brand-orange header, zebra body, rich HTML inside cells.     */
.block-table__inner {
  max-width: var(--content-max); margin: 0 auto; overflow-x: auto;
}
.block-table__tbl {
  width: 100%;
  border-collapse: collapse;
  background: #fff;
  font-size: 1.05rem;
  line-height: 1.6;
}
.block-table__cell {
  padding: var(--size-cell-m);       /* default = Rise M (15px) */
  vertical-align: middle;            /* matches Lena's Rise default */
  border: 1px solid #eae4d4;
}
/* Per-table cell padding override (matches Rise cell-padding S/M/L). */
.block-table--cellpad-s .block-table__cell { padding: var(--size-cell-s); }
.block-table--cellpad-m .block-table__cell { padding: var(--size-cell-m); }
.block-table--cellpad-l .block-table__cell { padding: var(--size-cell-l); }
.block-table__cell--top { vertical-align: top; }
.block-table__cell--middle { vertical-align: middle; }
.block-table__cell--bottom { vertical-align: bottom; }
.block-table__row--head .block-table__cell {
  background: var(--brand);
  color: #fff;
  font-weight: 700;
  font-size: 1.15rem;
  text-align: center;
  border-right-color: rgba(255,255,255,.25);
  border-bottom: 0;
  vertical-align: middle;
  /* padding inherits from --size-cell-* via the generic cell rule — keeps
     S/M/L consistent between header and body. */
}
.block-table__row--alt .block-table__cell { background: #f5f1e6; }
.block-table__cell p { margin: 0 0 .9rem; }
.block-table__cell p:last-child { margin-bottom: 0; }
.block-table__cell strong { font-weight: 700; }
@media (max-width: 600px) {
  .block-table__tbl { font-size: .95rem; }
  .block-table__cell { padding: .8rem .9rem; }
  .block-table__row--head .block-table__cell { font-size: 1rem; padding: .85rem .9rem; }
}

/* Rise "text/table" variant — raw HTML table injected directly.
   Rise provides inline styles for widths, bg colours, alignment etc.
   We just add border-collapse, base font, responsive overflow, and
   cell spacing so it integrates with our shell. */
.block-table--html .rise-table-wrap {
  overflow-x: auto;
}
.block-table--html table {
  width: 100%;
  border-collapse: collapse;
  background: #fff;
  font-size: 1.05rem;
  line-height: 1.6;
}
.block-table--html th,
.block-table--html td {
  padding: var(--size-cell-m, 15px);
  border: 1px solid #eae4d4;
}
.block-table--html th {
  font-weight: 700;
  font-size: 1.15rem;
}
.block-table--html .fr-alternate-rows tr:nth-child(even) td { background: #f5f1e6; }
.block-table--html p { margin: 0 0 .5rem; }
.block-table--html p:last-child { margin-bottom: 0; }
@media (max-width: 600px) {
  .block-table--html table { font-size: .95rem; }
  .block-table--html th, .block-table--html td { padding: .8rem .9rem; }
}

/* Block: gallery-grid — two / three / four column image grid -------------- */
/* Block: gallery-grid — two / three / four column image grid -------------- */
/* Remove parent .block side-padding so the grid's own padding controls spacing */
.block-gallery--grid { padding-left: 0 !important; padding-right: 0 !important; }
/* Rise: .block-gallery__container { max-width:92rem; padding-inline:2rem }
   Columns use flex width:50%/33%/25% with padding-inline:.75rem (7.5px gap).
   html{font-size:62.5%} → 92rem = 920px, 2rem = 20px, .75rem = 7.5px.
   We replicate this with CSS grid: container 920px, gap 15px, padding 20px. */
.block-gallery-grid {
  display: grid; gap: 15px;
  /* Rise container: 92rem content + 2rem padding each side = 96rem total.
     With border-box (our global default): max-width must include padding.
     920px + 40px = 960px total. */
  max-width: 960px; margin: 0 auto;
  padding: 0 20px;
}
.block-gallery-grid--2col { grid-template-columns: repeat(2, 1fr); }
.block-gallery-grid--3col { grid-template-columns: repeat(3, 1fr); }
.block-gallery-grid--4col { grid-template-columns: repeat(4, 1fr); }
.block-gallery-grid__cell img {
  width: 100%; display: block;
}
.block-gallery-grid__caption {
  font-family: var(--font-body); font-size: 1.4rem; line-height: 1.6;
  color: var(--text-soft); margin-top: .6rem; text-align: left;
}
.block-gallery-grid__caption p { margin: 0; }
.block-gallery-grid__caption sup { font-size: 0.85em; }
@media (max-width: 768px) {
  .block-gallery-grid--3col,
  .block-gallery-grid--4col { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 480px) {
  .block-gallery-grid { grid-template-columns: 1fr !important; }
}

/* Block: gallery single */
.block-gallery__single { max-width: var(--wrap-max); margin: 0 auto; }
.block-gallery__single-img { width: 100%; display: block; border-radius: var(--radius-sm); }
.block-gallery__caption,
.block-carousel__caption {
  font-family: var(--font-body); font-size: 1.1rem; line-height: 1.5;
  color: var(--text-soft); padding: .8rem 1rem; text-align: center;
}
.block-gallery__caption p,
.block-carousel__caption p { margin: 0; }

/* Block: carousel — slider with arrows + dots ----------------------------- */
/* Gallery carousel — Rise shows slides one at a time with prev/next arrows.
   Matches Rise original: large plain chevrons positioned well outside,
   wide container (--wrap-max), subtle border, no box-shadow on arrows. */
.block-carousel {
  padding: 3rem 0 2rem !important; position: relative;
  max-width: var(--wrap-max); margin: 0 auto;
}
.block-carousel__track-wrapper {
  overflow: hidden; border-radius: .75rem;
  border: 1px solid #e0ddd8;
  background: #fff;
}
.block-carousel__track {
  display: flex; transition: transform .5s cubic-bezier(.4,0,.2,1);
}
.block-carousel__slide { flex: 0 0 100%; min-width: 100%; }
.block-carousel__slide img { width: 100%; display: block; }
/* Arrows — very large plain chevrons like Rise original */
.block-carousel__arrow {
  position: absolute; top: 50%; transform: translateY(-50%);
  background: none; border: none;
  cursor: pointer; display: flex; align-items: center; justify-content: center;
  font-size: 8rem; font-weight: 200; color: #c0bdb8; z-index: 3;
  padding: 0; line-height: 1;
  transition: color .2s ease;
  -webkit-user-select: none; user-select: none;
}
.block-carousel__arrow:hover { color: #888; }
.block-carousel__arrow--prev { left: -7rem; }
.block-carousel__arrow--next { right: -7rem; }
.block-carousel__arrow:disabled { opacity: .2; cursor: default; pointer-events: none; }
/* Dots */
.block-carousel__dots {
  display: flex; justify-content: center; gap: 1rem; margin-top: 2rem;
}
.block-carousel__dot {
  width: 14px; height: 14px; border-radius: 50%;
  background: #ddd; border: 2px solid #ccc; cursor: pointer; padding: 0;
  transition: background .25s ease, border-color .25s ease;
}
.block-carousel__dot.is-active {
  background: var(--accent-color); border-color: var(--accent-color);
}
@media (max-width: 1100px) {
  .block-carousel__arrow { font-size: 5rem; }
  .block-carousel__arrow--prev { left: -4rem; }
  .block-carousel__arrow--next { right: -4rem; }
}
@media (max-width: 768px) {
  .block-carousel__arrow { font-size: 3rem; }
  .block-carousel__arrow--prev { left: 0.5rem; }
  .block-carousel__arrow--next { right: 0.5rem; }
  .block-carousel__arrow { background: rgba(255,255,255,.7); border-radius: 50%; width: 40px; height: 40px; }
}

/* Block: timeline ────────────────────────────────────────────────────────
   Rise-style stacked card timeline. Each card is a rectangle with a
   theme-coloured left accent stripe; a 1px vertical connector line
   stitches consecutive cards together via the wrapper's `::after`.

   Structure:
     .block-timeline
       .block-timeline__inner          ← outer width container
         .timeline__container          ← flex column, holds card-wrappers
           .timeline__card-wrapper     ← positions card + connector ::after
             .timeline-card
               .timeline-card__body    ← card surface w/ accent stripe
                 .timeline-card__date  ← italic theme-coloured header
                 .timeline-card__title ← bold heading
                 .timeline-card__description ← body text
                 .timeline-card__image ← optional media
   Verified against Rise's compiled lib/rise/dcf50f7e.css. */
.block-timeline { background: #fff; }
.block-timeline__inner {
  max-width: var(--content-max); margin: 0 auto;
  padding-block: 2rem; padding-inline: 2rem;
}
.timeline__container {
  display: flex; flex-direction: column; align-items: center;
  position: relative; z-index: 2;
}
.timeline__card-wrapper {
  position: relative; width: 100%; max-width: 80rem;
}
/* 1px connector line above every card except the first (continuous via the
   gap between cards). Length 7rem matches Rise. */
.timeline__card-wrapper::after {
  content: ""; position: absolute;
  inset-block-start: -7rem; inset-inline-start: 50%;
  height: 6.7rem; width: 0;
  border-inline-start: 1px solid rgba(0, 0, 0, .15);
}
.timeline__card-wrapper:first-child::after { display: none; }
.timeline__card-wrapper:not(:last-child) { margin-block-end: 7rem; }

.timeline-card {
  position: relative; width: 100%;
  border-radius: .4rem;
  background: #fff;
}
/* Drop shadow (Rise applies via a ::before pseudo for layer compositing). */
.timeline-card::before {
  content: ""; position: absolute; inset: 0;
  border-radius: .4rem;
  box-shadow: 0 0 1rem 0 rgba(0, 0, 0, .1);
  pointer-events: none;
}
.timeline-card__body {
  position: relative; overflow: hidden;
  border-radius: .4rem;
  padding-block: 3rem 4rem; padding-inline: 3rem;
  min-height: 8rem;
}
/* Left accent stripe — 4px solid theme colour. */
.timeline-card__body::before {
  content: ""; position: absolute;
  inset-block: 0; inset-inline-start: 0;
  width: .4rem;
  background: var(--accent, var(--brand, #c2410c));
  border-radius: .4rem 0 0 .4rem;
}
.timeline-card__date {
  font-family: var(--font-head, var(--font-body));
  font-size: 1.3rem; font-weight: 700; font-style: italic;
  color: var(--accent, var(--brand, #c2410c));
  margin-block-end: 1rem;
  text-transform: uppercase; letter-spacing: .05em;
}
.timeline-card__title {
  margin: 0 0 1rem;
  font-size: 2rem; font-weight: 700;
  line-height: 1.3;
  color: var(--text, #1a1a2e);
}
.timeline-card__description {
  font-size: 1.5rem; line-height: 1.55;
  color: var(--text, #1a1a2e);
}
.timeline-card__description p { margin: 0 0 1rem; }
.timeline-card__description p:last-child { margin-bottom: 0; }
.timeline-card__description strong { font-weight: 700; }
.timeline-card__description em { font-style: italic; }
.timeline-card__image {
  display: block; width: 100%; height: auto;
  margin-block-start: 2rem;
  border-radius: .3rem;
}

/* Block: sorting — interactive drag-and-drop activity -------------------- */
.sorting-activity {
  display: flex; flex-direction: column; align-items: center;
  width: 100%; max-width: var(--wrap-max); margin: 0 auto;
  padding: 2.5rem var(--pad-x);
  gap: 1.5rem;
  position: relative;
}
.sorting-instruction {
  /* Reads as guidance, not as a CTA — muted ink + slightly larger than the
     original 1rem accent-color text which looked like a button. */
  color: var(--text-soft);
  font-size: 1.08rem;
  font-weight: 500;
  text-align: center;
  letter-spacing: .01em;
  line-height: 1.45;
  max-width: 40em;
  margin: 0 0 .3rem;
}
/* Card — width + height set by JS syncCardSize() */
.sorting-card {
  background: #fff; border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0,0,0,.1);
  border-top: 4px solid var(--accent-color);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  text-align: center; padding: 1.5rem 2rem;
  cursor: grab; user-select: none;
}
.sorting-card:active { cursor: grabbing; }
.sorting-card.dragging { visibility: hidden; }
.sorting-card p {
  font-size: clamp(1.15rem, 2.4vw, 1.5rem); font-weight: 600;
  line-height: 1.6; color: var(--text); margin: 0;
}
.sorting-drag-handle { color: #bbb; font-size: 2.2rem; margin-top: .75rem; letter-spacing: 4px; }
/* Drag clone — follows cursor */
.sorting-clone {
  position: fixed; background: #fff; border-radius: 8px;
  box-shadow: 0 6px 24px rgba(0,0,0,.18);
  border-top: 4px solid var(--accent-color);
  display: flex; align-items: center; justify-content: center;
  text-align: center; padding: 1.5rem 2rem;
  font-size: clamp(1.15rem, 2.4vw, 1.5rem); font-weight: 600;
  line-height: 1.6; color: var(--text);
  z-index: 9999; pointer-events: none;
}
/* Shake animation — incorrect answer */
@keyframes sortingShake {
  0%, 100% { transform: translate(0,0); }
  12%  { transform: translate(-14px,0); }
  24%  { transform: translate(11px,0); }
  36%  { transform: translate(-8px,0); }
  48%  { transform: translate(5px,0); }
  60%  { transform: translate(-3px,0); }
  72%  { transform: translate(0,0); }
}
/* Drop zones — side-by-side, aspect-ratio 3:2 */
.sorting-dropzones {
  display: flex; gap: .5rem; width: 100%; max-width: 860px; margin-top: .5rem;
}
.sorting-dropzone {
  flex: 1; background: var(--bg-soft, #f0f0f0);
  border: 2px dashed var(--border, #ccc); border-radius: 10px;
  aspect-ratio: 3/2;
  display: flex; align-items: center; justify-content: center;
  padding: 1rem;
  transition: border-color .2s ease, background .2s ease, box-shadow .2s ease;
  overflow: hidden; min-width: 0;
}
.sorting-dropzone.drag-over {
  border-color: var(--accent-color); background: rgba(194,65,12,.05);
}
.sorting-dropzone.correct-flash {
  border-color: var(--accent-color); background: rgba(194,65,12,.10);
  box-shadow: inset 0 0 20px rgba(194,65,12,.15);
}
.sorting-dropzone-label {
  font-family: var(--font-head); font-size: 1.5rem; font-weight: 700;
  color: #ccc; text-transform: uppercase; pointer-events: none;
}
/* Completion message */
.sorting-complete {
  font-size: 1.1rem; font-weight: 600; color: var(--accent-color);
  text-align: center; padding: 1.5rem;
}

/* Storyline embed (fallback) --------------------------------------------- */
.block-storyline__inner {
  max-width: var(--content-max); margin: 0 auto;
  border-radius: var(--radius-md);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  background: var(--bg-soft);
  padding: 2rem;
  text-align: center;
  color: var(--text-soft);
}

/* Image Hero — Rise `.block-image--hero` 1:1 ------------------------------ */
.block-image-hero__inner {
  max-width: var(--content-max);
  margin: 0 auto;
}
.block-image-hero__img {
  display: block;
  max-width: 100%;
  height: auto;
  margin: 0 auto;
}
/* Caption — narrower than the image (Rise: margin-inline: 8.33%) with a
   thin bottom border for that "figcaption with rule" look. */
.block-image-hero__caption {
  font-family: var(--font-body);
  font-size: 1.2rem;
  line-height: 1.5;
  color: var(--text-soft, #666);
  margin-block: .75rem 0;
  margin-inline: 8.3333%;
  padding-block: 1.3rem 1.3rem;
  border-block-end: .1rem solid var(--line, rgba(0,0,0,.12));
}
.block-image-hero__caption p {
  font-size: inherit;
  margin-block: 0; margin-inline: 0;
}
.block-image-hero__caption a {
  color: var(--accent, var(--brand, #c2410c));
  text-decoration: underline;
}

/* Full-bleed variant — image fills the wrap width, optionally taller than
   content-max. Background-image used so cover/center works for any ratio. */
.block-image-hero--full .block-image-hero__inner {
  max-width: var(--wrap-max);
}
.block-image-hero__img--full {
  width: 100%;
  aspect-ratio: 16 / 9;
  max-height: 70rem;
  background-position: 50%;
  background-size: cover;
  background-repeat: no-repeat;
}

/* Gallery ------------------------------------------------------------------ */
/* Gallery single-image fallback ------------------------------------------- */
.block-gallery { max-width: var(--content-max); margin: 0 auto; }
/* Grid galleries use the full wrap width (92rem / 920px), not content-max */
.block-gallery.block-gallery--grid { max-width: none; }
.block-gallery__single img {
  display: block; width: 100%; max-width: 720px; height: auto;
  margin: 0 auto; border-radius: 8px;
  box-shadow: 0 2px 12px rgba(0,0,0,.06);
}

/* Tabs — card layout with scrollable bar + arrow nav ----------------------- */
.block-tabs__card {
  max-width: 820px; margin: 0 auto 2rem;
  background: #fff; border-radius: 10px;
  box-shadow: 0 2px 16px rgba(0,0,0,.07);
  border: 1px solid #e8e5e0; overflow: hidden;
}
.block-tabs__bar-wrapper {
  position: relative; display: flex; align-items: stretch;
}
.block-tabs__arrow {
  flex-shrink: 0; width: 44px;
  background: var(--accent-color); color: #fff;
  border: none; cursor: pointer;
  font-size: 1.76rem; font-weight: 700;
  display: none; align-items: center; justify-content: center;
  z-index: 2; transition: opacity .2s ease;
  font-family: var(--font-head);
}
.block-tabs__arrow:hover { opacity: .85; }
.block-tabs__arrow.is-visible { display: flex; }
.block-tabs__bar {
  display: flex; flex: 1; overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none; scroll-behavior: smooth;
  background: var(--bg-soft, #f5f3ef);
}
.block-tabs__bar::-webkit-scrollbar { display: none; }
.block-tabs__tab {
  flex: 1; flex-shrink: 0;
  padding: 1.84rem 2rem;
  font-family: var(--font-head); font-size: 1.12rem;
  font-weight: 700; text-transform: uppercase;
  letter-spacing: .08em; color: var(--text);
  background: transparent; border: none;
  border-right: 1px solid #e0ddd8;
  border-bottom: 1px solid #e0ddd8;
  cursor: pointer; transition: color .25s ease, background .25s ease;
  white-space: nowrap; text-align: center;
}
.block-tabs__tab:last-child { border-right: none; }
.block-tabs__tab:hover { color: var(--accent-color); }
.block-tabs__tab.is-active {
  color: var(--accent-color); background: #fff;
  border-bottom-color: transparent;
}
.block-tabs__panel { display: none; padding: 2rem 2.5rem; }
.block-tabs__panel.is-active {
  display: flex; flex-direction: column; gap: 1.5rem;
}
.block-tabs__panel-text {
  font-size: 1.52rem; line-height: 1.65; color: var(--text);
  font-family: var(--font-body);
}
.block-tabs__panel-text p { margin-bottom: 1.36rem; }
.block-tabs__panel-text p:last-child { margin-bottom: 0; }
.block-tabs__panel-text strong { font-weight: 700; }
.block-tabs__panel-image { display: flex; justify-content: center; align-items: center; }
.block-tabs__panel-image img { width: 100%; display: block; }
@media (max-width: 768px) {
  .block-tabs__card { margin: 0 1.6rem 2rem; max-width: none; }
  .block-tabs__tab { padding: 1.2rem; font-size: .96rem; }
  .block-tabs__panel { padding: 2.4rem 2rem; }
  .block-tabs__arrow { width: 36px; font-size: 1.52rem; }
}

/* Section ------------------------------------------------------------------ */
.block-section { max-width: var(--content-max); margin: 0 auto; }
.block-section__title {
  font-size: 1.6rem; font-weight: 700;
  color: var(--text-main);
  border-bottom: 3px solid var(--brand);
  padding-bottom: 0.5rem;
}

/* Process ------------------------------------------------------------------ */
.block-process { max-width: var(--content-max); margin: 0 auto; }
.block-process__steps { display: flex; flex-direction: column; gap: 1.5rem; }
.block-process__step {
  display: flex; gap: 1.2rem; align-items: flex-start;
}
.block-process__num {
  flex-shrink: 0; width: 2.5rem; height: 2.5rem;
  display: flex; align-items: center; justify-content: center;
  background: var(--brand); color: white;
  font-weight: 700; font-size: 1.1rem;
  border-radius: 50%;
}
.block-process__body { flex: 1; }
.block-process__title {
  font-size: 1.05rem; font-weight: 700;
  color: var(--text-main); margin-bottom: 0.3rem;
}
.block-process__text { color: var(--text-main); }

/* Quote with image (side-by-side layout) ----------------------------------- */
.block-quote--image .block-quote__wrap {
  max-width: var(--wrap-max); margin: 0 auto;
  padding: 0 var(--pad-x);
  position: relative;
}
.block-quote--image .block-quote__row {
  display: flex; align-items: center; gap: 3rem;
  max-width: var(--content-max); margin: 0 auto;
  padding: 2rem 0;
  position: relative;
}
/* Large decorative quote mark in background — Rise puts this top-LEFT
   between the image and text and renders it BIG (≈26rem). Curly opening
   double quote, low opacity so it sits behind the text. */
.block-quote--image .block-quote__row::before {
  content: "\201C";
  font-family: var(--font-head), Georgia, serif;
  font-size: 26rem; line-height: 1;
  position: absolute; top: -3rem; left: 33%;
  color: var(--text); opacity: .08;
  pointer-events: none; z-index: 0;
}
.block-quote--image .block-quote__img-col {
  flex: 0 0 35%; max-width: 35%;
  position: relative; z-index: 1;
}
.block-quote--image .block-quote__big-img {
  width: 100%; height: auto; display: block;
}
.block-quote--image .block-quote__text-col {
  flex: 1; text-align: center;
  position: relative; z-index: 1;
}
.block-quote--image .block-quote__mark {
  display: none; /* using the ::before pseudo-element instead */
}
.block-quote--image .block-quote__text {
  font-family: var(--font-head);
  font-size: 1.8rem; font-weight: 300; font-style: italic;
  line-height: 1.6; margin: 0; padding: 0 0 .8rem;
}
/* Inline formatting — container weight is 300, so the browser's default
   "bolder" for <strong> only bumps to 400 (regular). Restore 700 explicitly. */
.block-quote--image .block-quote__text strong { font-weight: 700; }
.block-quote--image .block-quote__text em { font-style: italic; }
/* Rise's legacy-quote-mark behaviour (default for v=1, opt-in for v=2):
   target the *inner* <p>:first-child / :last-child so the marks render
   inline with the text content rather than as separate lines above/below.
   Earlier impl targeted the blockquote itself, which made the ::before/
   ::after sit on their own line because the inner <p> is a block element. */
.block-quote--image:not(.block-quote--no-legacy-quotes) .block-quote__text > :first-child::before {
  content: "\201C"; display: inline;
}
.block-quote--image:not(.block-quote--no-legacy-quotes) .block-quote__text > :last-child::after {
  content: "\201D"; display: inline;
}
.block-quote--image .block-quote__caption--plain {
  font-size: 1.3rem; color: var(--text-soft, #666);
  margin-top: .6rem;
}
/* Prevent template CSS from adding extra "— " prefix */
.block-quote--image .block-quote__caption--plain::before { content: none !important; }
@media (max-width: 768px) {
  .block-quote--image .block-quote__row { flex-direction: column; }
  .block-quote--image .block-quote__img-col { flex: none; max-width: 60%; margin: 0 auto; }
  .block-quote--image .block-quote__row::before { font-size: 10rem; }
}

/* Flashcard (stack) ---------------------------------------------------------------- */
/* ── Flashcard — matching Rise's .flashcard component ──
   Rise: square card (28rem–46rem), both faces absolute, scale(.9)→scale(1),
   back uses theme bg (white), flip btn bottom-right, nav buttons below. */
.block-flashcard-stack {
  max-width: var(--wrap-max); margin: 0 auto;
  text-align: center;
  position: relative;
}
.block-flashcard-stack__clip {
  display: inline-block; overflow: hidden;
  width: 100%; max-width: var(--wrap-max);
  padding-block: 5rem;  /* Rise `.carousel-slides` padding: breathing room
                           top+bottom; controls overlap back into it. */
}
/* Flip mechanic — Rise-1:1 (extracted from its compiled flashcard.css).
   Both faces rotate individually around Y; the container carries the
   perspective. The elegance comes from staggered opacity transitions:
   transform runs 0.6s, opacity runs only 0.1s, with offset delays so the
   outgoing face fades just after the incoming face starts to show. Faces
   pass each other edge-on without visible overlap. */
.block-flashcard-stack__card {
  display: inline-block;
  position: relative;
  width: 100%;
  max-width: 46rem;
  min-height: 28rem;
  max-height: 46rem;
  aspect-ratio: 1 / 1;
  cursor: pointer;
  /* Rise puts perspective directly on the card (not on a parent) so the
     3D rendering context is local to this card. preserve-3d ensures the
     face rotateY transforms aren't flattened back to 2D. */
  perspective: 1000px;
  transform-style: preserve-3d;
  /* Card breathes from .9 → 1.0 on flip (feels like it grows toward
     the viewer). Transition in isolation from the face rotateY. */
  transform: scale(.9) translateZ(0);
  transition: transform .5s cubic-bezier(.6, 0, .4, 1);
}
.block-flashcard-stack__card.is-flipped {
  transform: scale(1) translateZ(0);
}
/* Rise `.flashcard-side-flip__btn--round` 1:1 — circular pill with a white
   60%-opacity background (#fff9) so the icon stays readable on dark images.
   Solid white on hover. */
.block-flashcard-stack__flip-icon {
  position: absolute; top: .8rem; right: .8rem;
  width: 3.2rem; height: 3.2rem;
  background-color: rgba(255, 255, 255, .6);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  z-index: 3; pointer-events: none;
  opacity: 1;
  transition: background-color .15s ease;
}
.block-flashcard-stack__card:hover .block-flashcard-stack__flip-icon {
  background-color: #fff;
}
.block-flashcard-stack__flip-icon svg {
  width: 2.2rem; height: 1.6rem; color: #000; stroke-width: 2;
}
.block-flashcard-stack__face {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  will-change: transform;
  border: 1px solid rgba(0,0,0,.08);
  box-shadow: 0 .4rem 1.2rem .2rem rgba(0,0,0,.05);
}
.block-flashcard-stack__front {
  transform: rotateY(0deg);
  background: #fff;
  padding: 0;
  z-index: 2;
  opacity: 1;
  /* opacity fades out fast just after flip starts — Rise values */
  transition: transform .6s, opacity .1s linear 0s;
}
.block-flashcard-stack__back {
  transform: rotateY(180deg);
  background: var(--bg, #fff);
  color: var(--text);
  /* Rise: padding lives on the description, not the face itself */
  padding: 0;
  overflow: auto;
  opacity: 0;
  transition: transform .6s, opacity .1s linear .5s;
}
.block-flashcard-stack__card.is-flipped .block-flashcard-stack__front {
  opacity: 0; transform: rotateY(-180deg); z-index: 0;
  transition: transform .6s, opacity .1s linear .1s;
}
.block-flashcard-stack__card.is-flipped .block-flashcard-stack__back {
  opacity: 1; transform: rotateY(0deg); z-index: 1;
  transition: transform .6s, opacity .1s linear 0s;
}
/* Instant-reset state: kills the flip transition briefly so that an in-flight
   back-to-front reset (when navigating away from a flipped card) happens
   while the card is off-screen mid-push, not after it slides back in. */
.block-flashcard-stack__card.no-flip-transition .block-flashcard-stack__face {
  transition: none !important;
}
/* Front image: fullbleed, covers the entire card */
.block-flashcard-stack__img {
  width: 100%; height: 100%;
  object-fit: cover;
  position: absolute; inset: 0;
}
/* Front text hidden behind image — only visible if no image */
.block-flashcard-stack__front .block-flashcard-stack__text {
  position: relative; z-index: 1;
  font-size: 1.6rem; line-height: 1.5;
  padding: 2rem;
  font-weight: 400;
}
/* Back text — Rise has two variants based on content length:
     --short       2.9rem / 1.25 / centered, big margins     (.flashcard-side__description--short)
     --long-overflow  2rem / 1.5625 / left-aligned           (.flashcard-side__description--long-overflow)
   Renderer decides by stripped text length in JS. */
.block-flashcard-stack__back .block-flashcard-stack__text {
  font-family: var(--font-head, var(--font-body));
  font-weight: 300;
  overflow-wrap: break-word;
}
.block-flashcard-stack__back .block-flashcard-stack__text--short {
  font-size: 2.9rem; line-height: 1.25;
  /* Rise default is text-align: start (left). Per-paragraph inline styles
     (`<p style="text-align: center;">…`) override this — those come through
     from the Rise source verbatim via setHTML. */
  text-align: start;
  margin-block: 5.5rem 5.7rem;
  margin-inline: 2.5rem;
}
.block-flashcard-stack__back .block-flashcard-stack__text--long {
  font-size: 2rem; line-height: 1.5625;
  text-align: start;
  margin-block: 1.3rem;
  padding-inline: 2.5rem;
  width: 100%;
}
.block-flashcard-stack__back .block-flashcard-stack__text p {
  margin: 0 0 .8rem;
}
.block-flashcard-stack__back .block-flashcard-stack__text--short p {
  margin: 0;
}
.block-flashcard-stack__back .block-flashcard-stack__text p:last-child { margin-bottom: 0; }
.block-flashcard-stack__back .block-flashcard-stack__text strong { font-weight: 700; }
.block-flashcard-stack__back .block-flashcard-stack__text em { font-style: italic; }
/* Flip-icon "visually-hidden" modifier — same semantics as the grid
   variant: Rise's `settings.showHint: false` hides the icon, not text. */
.block-flashcard-stack__flip-icon--hidden {
  opacity: 0.00001;
  pointer-events: none;
}
/* Nav — Rise `.carousel-controls` 1:1.
   Rise layout: flex row with prev(order 0) / counter(1) / next(2).
   margin-block: -3.5rem 0 pulls controls up slightly so they overlap into
   the slide area. Both buttons share the same theme-decorative style;
   prev/next get opacity .3 when aria-disabled. */
.block-flashcard-stack__nav {
  display: flex; align-items: center;
  justify-content: center;
  margin-block: -3.5rem 0;
  margin-inline: auto;
}
/* Button — Rise `.block-flashcard-carousel .carousel-controls-prev/next` 1:1.
   background-color + border use theme-decorative (accent); color uses
   theme-decorative-fg for the icon stroke. */
.block-flashcard-stack__prev,
.block-flashcard-stack__next {
  width: 4.2rem; height: 4.2rem; border-radius: 50%;
  border: 1px solid var(--accent, #c2410c);
  background-color: var(--accent, #c2410c);
  color: var(--accent-fg, #fff);
  cursor: pointer; flex-shrink: 0; padding: 0;
  display: inline-flex; align-items: center; justify-content: center;
  outline-offset: .3rem;
  transition: opacity .2s;
}
/* Icon wrapper — Rise sets height: 2rem on the icon container; SVG inside
   stretches to 100% height. We style the SVG directly since that's all we
   render, with the same 2rem height cap. */
.block-flashcard-stack__prev > svg,
.block-flashcard-stack__next > svg {
  display: block; height: 2rem; width: auto;
}
.block-flashcard-stack__prev { order: 0; }
.block-flashcard-stack__next { order: 2; }
.block-flashcard-stack__prev[aria-disabled="true"],
.block-flashcard-stack__next[aria-disabled="true"] {
  opacity: .3; cursor: default;
}
/* Progress area between the buttons (Rise order: 1).
   Rise uses three breakpoints for width + margin-inline:
     default (desktop): width 16rem, margin-inline 6.8rem  ← this is the one
     ≤ 47.9375em (tablet): width 13rem, margin-inline 2rem
     ≤ 22.4375em (phone): width 10rem, margin-inline 2rem
   Together with two 4.2rem buttons this gives ~380px total — matches the
   380×42 `.carousel-controls` size Rise shows in its inspector. */
.block-flashcard-stack__progress-inner {
  order: 1;
  display: flex; flex-direction: column; align-items: stretch;
  width: 16rem; margin-inline: 6.8rem;
  position: relative; text-align: center;
}
@media (max-width: 47.9375em) {
  .block-flashcard-stack__progress-inner { width: 13rem; margin-inline: 2rem; }
}
@media (max-width: 22.4375em) {
  .block-flashcard-stack__progress-inner { width: 10rem; }
}
.block-flashcard-stack__counter {
  font-family: var(--font-body); font-size: 1.4rem;
  font-style: italic; letter-spacing: .005em; line-height: 1.285714;
  color: var(--text);
  margin-block-end: 1rem;
  white-space: nowrap;
}
/* Counter-line — Rise's *normal-mode* rendering (the framed-box version with
   a thick runner is scoped to `@media (forced-colors: active)` for Windows
   High Contrast Mode; that's not what ships for regular users).
   Normal mode is just two thin 1px bottom borders that overlap:
     - Track: 1px solid progress-track color, bottom only
     - Runner: 1px solid accent, absolute, pinned to start, no vertical inset
       (static position = top of parent, but since parent is 1px tall the
       runner's border-bottom coincides with the track's border-bottom for
       the filled portion). */
.block-flashcard-stack__bar {
  width: 100%; position: relative;
  border-block-end: 1px solid #c0c0c0;
}
.block-flashcard-stack__bar-fill {
  border-block-end: 1px solid var(--accent, #c2410c);
  position: absolute;
  inset-inline-start: 0;
  transition: width .3s;
}
/* Slide animations — single continuous push through the clip wrapper
   Each half has its own easing: ease-in on exit (accelerates), ease-out on entry (decelerates) */
/* Push keyframes preserve scale(.9) — navigation always happens in the
   unflipped state, so we bake the base scale in to avoid a jump when the
   animation takes over the transform. */
@keyframes fc-push-next {
  0%      { transform: translateX(0)     scale(.9); animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  49.99%  { transform: translateX(-160%) scale(.9); }
  50%     { transform: translateX(160%)  scale(.9); animation-timing-function: cubic-bezier(0, .55, .45, 1); }
  100%    { transform: translateX(0)     scale(.9); }
}
@keyframes fc-push-prev {
  0%      { transform: translateX(0)     scale(.9); animation-timing-function: cubic-bezier(.55, 0, 1, .45); }
  49.99%  { transform: translateX(160%)  scale(.9); }
  50%     { transform: translateX(-160%) scale(.9); animation-timing-function: cubic-bezier(0, .55, .45, 1); }
  100%    { transform: translateX(0)     scale(.9); }
}
.block-flashcard-stack__card.fc-push-next { animation: fc-push-next .5s linear forwards; }
.block-flashcard-stack__card.fc-push-prev { animation: fc-push-prev .5s linear forwards; }

.block-flashcard-stack__empty {
  padding: 2rem; color: var(--text-muted);
  font-style: italic;
}
@media (max-width: 600px) {
  .block-flashcard-stack__card { max-width: 28rem; }
  .block-flashcard-stack__prev,
  .block-flashcard-stack__next { width: 3.6rem; height: 3.6rem; }
}

/* Flashcard (grid, default) ----------------------------------------------------------- */
.block-flashcard {
  /* Rise `.block-flashcards` has NO max-width — width comes from the inner
     `__wrapper`. Width capped by lesson container, not the block itself. */
  margin: 0 auto;
  /* Keep the scale-pulse visible even when a tight parent container clips. */
  overflow: visible;
}
/* Rise `flashcardSize` modifier → card max dimensions. Small caps at
   28rem (Rise's `.flashcard--small`), Large stays at the base 46rem cap.
   Auto (no modifier) also inherits the 46rem cap but can shrink with the
   grid — i.e. Small is the only truly distinct visual mode right now. */
.block-flashcard--size-small .block-flashcard__card {
  max-width: 28rem;
}
/* Rise background-type modifiers — surface color + text contrast.
   Rise's compiled rules apply across many blocks; we narrow scope to
   .block-flashcard for now (extend to a shared .bg--type-* layer when
   we implement other blocks). */
.block-flashcard.bg--type-tint  { background: rgba(193, 64, 12, .06); }
.block-flashcard.bg--type-light { background: #fafafa; }
.block-flashcard.bg--type-gray  { background: #eaeaeb; }
.block-flashcard.bg--type-dark  { background: #1a1a2e; color: #fff; }
.block-flashcard.bg--type-black { background: #000;    color: #fff; }
.block-flashcard.bg--type-accent { background: var(--accent, #c2410c); color: #fff; }
.block-flashcard.bg--type-color  { background: var(--bg-color, #1a1a2e); color: #fff; }
/* Card mode WHITE — forces white card surface even on dark/colored
   backgrounds (Rise `block-card--white`). Applies to both faces; back
   keeps its --bg-back override unless cardMode forces white. */
.block-flashcard--card-white .block-flashcard__face {
  background: #fff !important;
  color: var(--text, #1a1a2e);
}
/* Flip-icon "visually-hidden" modifier — Rise's `settings.showHint: false`
   doesn't hide a text hint (Rise has no auto text-hint at all); it hides
   the flip-button ICON in the corner. This sr-only pattern matches Rise's
   own `.flashcard-side-flip__btn--visually-hidden` rule. */
.block-flashcard__flip-icon--hidden {
  opacity: 0.00001;
  pointer-events: none;
}
.block-flashcard__grid {
  /* Rise `.block-flashcards__wrapper` 1:1 — verified against Inspector
     measurements (face=412.2px visual = 458px physical with .9 scale,
     image=340.2 = 378 ≈ 38rem, frame 40px = 4rem padding-inline).
     Critical: `box-sizing: initial` (= content-box). max-width applies
     to the CONTENT area, padding-inline is OUTSIDE it. With border-box
     the inner content shrinks by the padding (~120px) and cards become
     ~70% of Rise's size — that's why our frames looked too thin. */
  box-sizing: initial;
  max-width: 102rem;
  margin-inline: auto;
  display: flex; flex-wrap: wrap;
  justify-content: center;
  text-align: center;
  gap: .2rem;
  padding-inline: 2rem;
}
@media (min-width: 33.75em) { .block-flashcard__grid { padding-inline: 3rem; } }
@media (min-width: 60em)    { .block-flashcard__grid { padding-inline: 6rem; } }
/* Flip mechanic — Rise-1:1 (see flashcard-stack rules above for details).
   Perspective lives on the card itself (not the grid) so each card has its
   own 3D context and the rotating face foreshortens correctly. preserve-3d
   is required because the card carries a scale transform; without it, face
   rotateY would flatten into 2D. */
.block-flashcard__card {
  position: relative;
  /* Rise `.flashcard { width: 48%; max-width: 46rem; min-width: 28rem }` 1:1.
     The aspect-ratio: 1/1 here replaces Rise's `:after { padding-block-end: 100% }`
     square-via-padding-hack. */
  width: 48%;
  max-width: 46rem;
  min-width: 28rem;
  aspect-ratio: 1 / 1;
  cursor: pointer;
  perspective: 1000px;
  transform-style: preserve-3d;
  /* Scale pulse — Rise base rule `.flashcard { transform: scale(.9) }` +
     `.flashcard--flipped { transform: scale(1) }` applies to BOTH grid and
     stack variants. (The `scale(1)` override in Rise CSS lives under
     `@media print`, not a grid override — earlier analysis misread the
     scope.) Card breathes from 90% → 100% on flip. */
  transform: scale(.9) translateZ(0);
  transition: transform .5s cubic-bezier(.6, 0, .4, 1);
}
.block-flashcard__card.is-flipped {
  transform: scale(1) translateZ(0);
}
@media (max-width: 37.4375em) {
  /* 1 column (phone) */
  .block-flashcard__card { width: 100%; }
}
.block-flashcard__card .block-flashcard__face {
  position: absolute; inset: 0; width: 100%; height: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  will-change: transform;
  border: 1px solid rgba(0,0,0,.08);
  box-shadow: 0 .4rem 1.2rem .2rem rgba(0,0,0,.05);
}
.block-flashcard__card .block-flashcard__front {
  transform: rotateY(0deg);
  background: #fff; padding: 0;
  z-index: 2;
  opacity: 1;
  /* Match back face: text content longer than the card needs to scroll
     within the face, not leak above/below the card boundary. Fix for
     small cards with multi-line content (test-2 block #1) where text
     was rendering outside the visible card. */
  overflow: auto;
  transition: transform .6s, opacity .1s linear 0s;
}
/* Rise `--border-block-start: 0.3rem solid var(--color-theme)` — accent
   stripe applies to ALL front faces EXCEPT fullimage. Verified against
   Rise's compiled CSS:
     .flashcard-side__content--front:not(--fullimage){border-block-start:var(--border-block-start)}
   Back never gets the stripe regardless of mode (Rise renders backs
   softer/greyer; their compiled rule is `.flashcard-side--back{border:1px solid #0000}`). */
.block-flashcard__card .block-flashcard__front:not(.block-flashcard__front--fullimage) {
  border-block-start: .3rem solid var(--accent, #c2410c);
}
.block-flashcard__card .block-flashcard__back {
  transform: rotateY(180deg);
  /* Rise renders the back slightly off-white ("eingekraut") to separate
     it visually from the front and the surrounding lesson page. #fafafa is
     Rise's own Gray-theme background value — subtle enough to read as
     "different side" without feeling like a theme mismatch. */
  background: var(--bg-back, #fafafa); color: var(--text);
  padding: 0; overflow: auto;
  opacity: 0;
  transition: transform .6s, opacity .1s linear .5s;
}
.block-flashcard__card.is-flipped .block-flashcard__front {
  opacity: 0; transform: rotateY(-180deg); z-index: 0;
  transition: transform .6s, opacity .1s linear .1s;
}
.block-flashcard__card.is-flipped .block-flashcard__back {
  opacity: 1; transform: rotateY(0deg); z-index: 1;
  transition: transform .6s, opacity .1s linear 0s;
}
/* ── Image rendering per mode ─────────────────────────────────────────
   fullimage : Rise `.flashcard-side__img--full` — fills the face, object-fit cover.
   image     : Rise `.flashcard-side__img--centered --large` — max-height
                38rem, parent face adds padding-inline 4rem. (We treat all
                Rise --image sides as --large until the extractor also
                surfaces flashcardSize; small variant caps at 18rem.)
*/
.block-flashcard__card .block-flashcard__img {
  width: 100%; height: 100%; object-fit: cover;
  position: relative; border-radius: 0;
}
/* Crop wrapper — sits where a plain <img> would and behaves the same
   way (max-height/max-width, centered via parent face's flex center),
   while clipping the over-sized img inside to the crop region. The
   aspect-ratio comes from the renderer (`--crop-aspect: cropPxW/cropPxH`)
   so the wrapper takes the shape of the cropped pixels regardless of
   source image dimensions. */
.block-flashcard__card .block-flashcard__img-crop {
  position: relative;
  overflow: hidden;
  aspect-ratio: var(--crop-aspect, 1);
  /* Width is the limiting dimension: clamp to container, but never
     wider than (38rem × aspect) so portrait crops can't get extra-wide.
     Height follows from aspect-ratio. */
  width: min(100%, calc(38rem * var(--crop-aspect, 1)));
  max-height: 38rem;
  /* Centering handled by face's `justify-content: center`/`align-items: center`. */
}
/* For fullimage mode (face has no padding-inline; image fills face),
   the wrapper should also fill the face — override the size cap. */
.block-flashcard__card .block-flashcard__front--fullimage .block-flashcard__img-crop,
.block-flashcard__card .block-flashcard__back--fullimage .block-flashcard__img-crop {
  width: 100%; height: 100%;
  max-width: none; max-height: none;
  margin: 0;
  aspect-ratio: auto;
}
.block-flashcard__card .block-flashcard__img--cropped {
  position: absolute;
  width: auto; height: auto;
  max-width: none; max-height: none;
  object-fit: cover;
}
.block-flashcard__card .block-flashcard__front--image,
.block-flashcard__card .block-flashcard__back--image {
  /* Rise `.flashcard-side__content--image.--large` 1:1 — padding-inline
     4rem. Vertical positioning is handled by the image's own
     `margin-block: auto` + `max-height: 38rem`, NOT by face padding.
     Selector mirrors `.block-flashcard__card .block-flashcard__front`
     (the rule that sets `padding: 0`) so specificity matches and our
     image padding actually wins the cascade. */
  padding-block: 0;
  padding-inline: 4rem;
}
.block-flashcard__front--image .block-flashcard__img,
.block-flashcard__back--image .block-flashcard__img {
  width: auto; height: auto;
  max-width: 100%; max-height: 38rem;
  margin-block: auto; margin-inline: auto;
  object-fit: contain;
}
/* Classic (Rise-1:1): image-mode sides don't render visible text. Any
   description on an image-side is treated as <img alt> only. A Signature
   variant with sichtbarem overlay-text can sit behind a separate modifier
   (`--overlay`) later without touching these rules. */
/* Rise `.flashcard-side-flip__btn--round` 1:1 — circular pill with a white
   60%-opacity background (#fff9) so the icon stays readable on dark images.
   Solid white on hover. */
.block-flashcard__card .block-flashcard__flip-icon {
  position: absolute; top: .8rem; right: .8rem;
  width: 3.2rem; height: 3.2rem;
  background-color: rgba(255, 255, 255, .6);
  border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  z-index: 2; pointer-events: none;
  opacity: 1;
  transition: background-color .15s ease;
}
.block-flashcard__card:hover .block-flashcard__flip-icon {
  background-color: #fff;
}
.block-flashcard__card .block-flashcard__flip-icon svg {
  width: 2.2rem; height: 1.6rem; color: #000; stroke-width: 2;
}
/* Shared typography; the short/long split only applies on the back side. */
.block-flashcard__card .block-flashcard__text {
  font-family: var(--font-head, var(--font-body)); font-weight: 300;
  overflow-wrap: break-word;
}
/* Front text — Rise base `.flashcard-side__description { font-size: 1.8rem }`,
   weight 300 (from the shared rule above). --short = single hero line,
   centered. --long = multi-paragraph, top-anchored scroll. */
.block-flashcard__front .block-flashcard__text {
  font-size: 1.8rem; line-height: 1.5;
  margin-inline: 2.5rem;
  text-align: center;
}
.block-flashcard__front .block-flashcard__text--long {
  font-size: 1.6rem; line-height: 1.5;
  margin-block: 0;
  padding-inline: 2.5rem;
  width: 100%;
  text-align: start;
}
/* Long front text → top-anchor instead of vertical-center, otherwise
   overflow scroll starts mid-content (same fix as we did for back). */
.block-flashcard__front:has(.block-flashcard__text--long) {
  justify-content: flex-start;
  padding-block: 1.5rem 0;
}
/* Back text — Rise `.flashcard-side__description--short` (1:1):
   2.9rem, line-height 1.25, centered. Big vertical margins (5.5rem top,
   5.7rem bottom) give the single-line "hero" feel Rise designed for on
   its 46rem-tall cards. */
.block-flashcard__back .block-flashcard__text--short {
  font-size: 2.9rem; line-height: 1.25;
  text-align: center;
  margin-block: 5.5rem 5.7rem;
  margin-inline: 2.5rem;
}
/* Back text — Rise `.flashcard-side__description--long-overflow` (1:1):
   2rem, tighter leading, left-aligned. Smaller margins because the text
   has multiple paragraphs and needs more room. */
.block-flashcard__back .block-flashcard__text--long {
  font-size: 2rem; line-height: 1.5625;
  text-align: start;
  margin-block: 0;
  padding-inline: 3rem;
  width: 100%;
}
/* When the back carries long text, the face's default `justify-content: center`
   clips the top of overflowing content and parks the scroll position in the
   middle — user sees "mitten drin", can't scroll up. Anchor to top and give
   Rise-like symmetric breathing room (title isn't flush against the edge). */
.block-flashcard__back:has(.block-flashcard__text--long) {
  justify-content: flex-start;
  padding-block: 3rem 2rem;
}
.block-flashcard__back .block-flashcard__text p { margin: 0 0 .8rem; }
.block-flashcard__back .block-flashcard__text--short p { margin: 0; }
.block-flashcard__back .block-flashcard__text p:last-child { margin-bottom: 0; }
/* Inline formatting inside flashcard text — face sets font-weight:300, so the
   browser's default "bolder" for <strong> only bumps to 400 (regular). Restore
   Rise's 700 weight explicitly; <em> is likewise restored to match stack. */
.block-flashcard__card .block-flashcard__text strong { font-weight: 700; }
.block-flashcard__card .block-flashcard__text em { font-style: italic; }
@media (max-width: 600px) {
  .block-flashcard__card { width: 100%; }   /* single column on mobile */
}

/* Block: matching ---------------------------------------------------------- */
/* Sits on the M line (content-max = 760px) — same footprint Rise uses for
   matching-interaction. Values (min-height/padding-block/font-size/line-height/
   margin-block-end/gap) mirror Rise's own compiled CSS 1:1 so the Rise-original
   density is preserved. */
.block-matching {
  padding: 1.6rem var(--pad-x);
}
.matching-question {
  max-width: var(--content-max); margin: 0 auto 2rem;
  padding-bottom: 1.6rem;
  border-bottom: 1px solid rgba(0, 0, 0, .12);
  font-size: 1.8rem; font-weight: 700;
}
/* Puzzle-style matching. Two columns; left is drag-sortable, right is static.
   Shape is driven by data-col on the piece (not ancestor classes) so the
   drag-ghost keeps its puzzle shape when cloned to body. Geometry:
   - col=1: rectangle with a KNOB protruding outside the right edge.
   - col=2: rectangle with a matching NOTCH on the left edge.
   Knob and notch are both 4rem diameter, centered vertically. */
.matching-interaction {
  max-width: var(--content-max); margin: 0 auto;
  display: flex; gap: 4rem;
  padding: 0;
  justify-content: space-between;
}
/* gap: 4rem matches Rise's compiled CSS 1:1. The knob (2rem protrusion right
   of col-1) and notch (2rem inset into col-2) leave ~2rem of visible air
   between knob-tip and notch-opening — the Rise original look. Rise bridges
   the gap with a jigsaw overlay only on matched pieces; unmatched pieces
   show the plain separation we reproduce here. */
.matching-interaction ul { flex: 1; list-style: none; padding: 0; margin: 0; }
.matching-interaction li {
  position: relative;
}
.matching-interaction li:not(:last-child) { margin-block-end: 2rem; }
.matching-interaction li.draggable { touch-action: none; }
.matching-interaction li.draggable:not(.draggable--dragging) { z-index: 0; }
.matching-interaction li.draggable--dragging { z-index: 1; }

.matching-interaction-piece {
  --piece-fill: #fff;
  --piece-border: rgba(0,0,0,.3);
  align-items: center;
  background-color: var(--piece-fill);
  border: 1px solid var(--piece-border); border-radius: .4rem;
  display: flex; font-size: 1.4rem; line-height: 2rem;
  min-height: 8rem;
  outline: none;
  padding-block: 1.2rem;
  position: relative;
  text-align: start;
  width: 100%;
  box-sizing: border-box;
}

/* col=1 (left) — rectangle, plus a KNOB pseudo protruding out to the right.
   The ::before draws the circular knob; the ::after masks the hairline seam
   where knob meets body. Both track --piece-fill so hover/match/error states
   stay visually coherent across body + knob. */
.matching-interaction-piece[data-col="1"] {
  padding-inline: 3.2rem 3.2rem;
  cursor: grab;
}
.matching-interaction-piece[data-col="1"]::before {
  content: "";
  position: absolute;
  right: -2rem; top: 50%;
  width: 4rem; height: 4rem;
  background-color: var(--piece-fill);
  border: 1px solid var(--piece-border);
  border-radius: 50%;
  clip-path: polygon(50% 0, 100% 0, 100% 100%, 50% 100%);
  box-sizing: border-box;
  transform: translateY(-50%);
  pointer-events: none;
  z-index: 1;
}
.matching-interaction-piece[data-col="1"]::after {
  content: "";
  position: absolute;
  right: -1px; top: 50%;
  width: 2px; height: calc(4rem - 2px);
  background-color: var(--piece-fill);
  transform: translateY(-50%);
  pointer-events: none;
  z-index: 2;
}

/* col=2 (right) — rectangle with a circular NOTCH carved on the left. Mask
   removes bg + border inside the notch radius. The curved outline along the
   notch is provided by .matching-interaction-piece-notch (a sibling of the
   piece, mounted on the LI so it isn't clipped by the piece's mask). */
.matching-interaction-piece[data-col="2"] {
  -webkit-mask-image: radial-gradient(4rem 4rem at 0 50%, #0000 calc(2rem - 1px), #000 calc(2rem - 1px));
  mask-image:         radial-gradient(4rem 4rem at 0 50%, #0000 calc(2rem - 1px), #000 calc(2rem - 1px));
  padding-inline: 5rem 3.2rem;
}
.matching-interaction-piece-notch {
  position: absolute;
  left: 0; top: 50%;
  width: 4rem; height: 4rem;
  background: transparent;
  border: 1px solid var(--piece-border, rgba(0,0,0,.3));
  border-radius: 50%;
  box-sizing: border-box;
  clip-path: polygon(50% 0, 100% 0, 100% 100%, 50% 100%);
  transform: translate(-2rem, -50%);
  pointer-events: none;
  z-index: 1;
}
.matching-interaction li.droppable--hover .matching-interaction-piece-notch { border-color: var(--brand); }
.matching-interaction li.is-correct .matching-interaction-piece-notch { border-color: var(--success, #16a34a); }
.matching-interaction li.is-wrong   .matching-interaction-piece-notch { border-color: var(--danger,  #dc2626); }
.matching-interaction li.draggable--dragging .matching-interaction-piece-notch { opacity: .3; }


/* Decoration (drag-handle stripe on the outside edge — left edge for col=1,
   right edge for col=2). */
.matching-interaction-piece-decoration {
  align-items: center;
  background-color: rgba(var(--brand-rgb, 194 65 12), .5);
  color: var(--brand-contrast, #fff);
  display: flex; justify-content: center;
  position: absolute;
  width: 2.4rem;
  inset-block: -1px;
}
.matching-interaction-piece-decoration > svg { height: 1.8rem; width: 1.8rem; }
.matching-interaction-piece[data-col="1"] > .matching-interaction-piece-decoration {
  border-radius: .4rem 0 0 .4rem;
  inset-inline-start: -1px;
}
.matching-interaction-piece[data-col="2"] > .matching-interaction-piece-decoration {
  border-radius: 0 .4rem .4rem 0;
  inset-inline-end: -1px;
}
.matching-interaction-piece-content {
  align-items: center;
  display: inline-flex; flex: 1;
  min-width: 0; overflow-wrap: anywhere;
}

.matching-interaction li:not(.draggable--dragging)
  .matching-interaction-piece:hover { --piece-fill: #f7f7f5; }

/* Drag ghost — cloned <li> lives in <body>, so CSS must not depend on column
   ancestors. Since pieces are styled via [data-col], the ghost keeps shape. */
.matching-ghost {
  position: fixed !important;
  list-style: none !important;
  margin: 0 !important;
  padding: 0 !important;
  z-index: 1000 !important;
  pointer-events: none;
  filter: drop-shadow(0 14px 28px rgba(0,0,0,.22));
  opacity: .96;
}

/* Right-column drop target highlight */
.matching-interaction li.droppable--hover .matching-interaction-piece {
  --piece-fill: var(--brand-soft, #fff7ed);
  --piece-border: var(--brand);
}
/* When dragging, fade the piece + its pseudos together via opacity on the LI
   so the puzzle silhouette stays coherent. */
.matching-interaction li.draggable--dragging > .matching-interaction-piece {
  opacity: .3;
}

/* Paired (live-snap). Grip stripe darkens to full brand, and the two cards
   slide symmetrically toward the center — each by half the 4rem flex-gap
   (2rem) so knob and notch meet exactly at the container midline. Applies
   to any docked pair during solve; only after "Valider" do wrong pairs lose
   .is-paired and snap back to the default open layout. */
.matching-interaction li.is-paired .matching-interaction-piece-decoration {
  background-color: var(--brand);
}
.matching-interaction-col-1 li.is-paired { transform: translateX(2rem); }
.matching-interaction-col-2 li.is-paired { transform: translateX(-2rem); }
.matching-interaction li.is-paired {
  transition: transform .35s cubic-bezier(.34, 1.56, .64, 1);
  cursor: default;
}
.matching-interaction li.is-paired .matching-interaction-piece[data-col="1"] {
  cursor: default;
}

/* Bounce-back when dropped on a wrong target. */
@keyframes matching-bounce {
  0%   { transform: translateX(0); }
  20%  { transform: translateX(-1.2rem); }
  40%  { transform: translateX( .9rem); }
  60%  { transform: translateX(-.6rem); }
  80%  { transform: translateX( .3rem); }
  100% { transform: translateX(0); }
}
.matching-interaction li.is-bouncing { animation: matching-bounce .45s ease-out; }

/* Final validation (all paired → click Valider). Rules target the LI too so
   they beat `:hover` specificity (0,3,2) and stay correct on pointer-over. */
.matching-interaction li.is-correct .matching-interaction-piece,
.matching-interaction li.is-correct .matching-interaction-piece:hover {
  --piece-fill: var(--success-soft, #f0fdf4);
  --piece-border: var(--success, #16a34a);
}
.matching-interaction li.is-correct .matching-interaction-piece-decoration {
  background-color: var(--success, #16a34a);
}
.matching-interaction li.is-wrong .matching-interaction-piece,
.matching-interaction li.is-wrong .matching-interaction-piece:hover {
  --piece-fill: var(--danger-soft, #fef2f2);
  --piece-border: var(--danger, #dc2626);
}
.matching-interaction li.is-wrong .matching-interaction-piece-decoration {
  background-color: var(--danger, #dc2626);
}

/* Locked = solved pairs that the user should not disturb while correcting
   the red ones. Cursor signals "not draggable", no hover-shade. */
.matching-interaction li.is-locked,
.matching-interaction li.is-locked .matching-interaction-piece {
  cursor: default;
}
.matching-interaction li.is-locked .matching-interaction-piece-decoration {
  /* Keep the decoration stripe the solved-state color (already set by
     is-correct). Just make sure it's not reverted by any hover variant. */
  background-color: var(--success, #16a34a);
}

/* Phone only (≤500px = Rise's own 31.25em breakpoint). Rise stays two-column
   at ALL widths, only shrinks the paired-slide offset — we do the same. We
   only collapse to one column below that, when the knob+notch geometry can't
   physically fit two columns side-by-side. */
@media (max-width: 31.25em) {
  .matching-interaction-col-1 li.is-paired { transform: translateX(2rem); }
  .matching-interaction-col-2 li.is-paired { transform: translateX(-2rem); }
  .matching-submit {
    padding: 1.2rem 3.2rem; min-width: 0; width: 100%; max-width: 32rem;
  }
}

/* Very narrow (sub-400px): stack. Knob/notch dropped — visual pairing cue
   falls back to the grip stripe + decoration. */
@media (max-width: 25em) {
  .matching-interaction { flex-direction: column; gap: 0; }
  .matching-interaction li:not(:last-child) { margin-block-end: 1rem; }
  .matching-interaction-piece[data-col="1"] { padding-inline: 3.2rem; }
  .matching-interaction-piece[data-col="1"]::before,
  .matching-interaction-piece[data-col="1"]::after { display: none; }
  .matching-interaction-piece[data-col="2"] {
    -webkit-mask-image: none; mask-image: none;
    padding-inline: 3.2rem;
  }
  .matching-interaction-piece-notch { display: none; }
  .matching-interaction-col-1 li.is-paired,
  .matching-interaction-col-2 li.is-paired { transform: none; }
}

/* Submit — Rise-style pill: wide, uppercase, full-brand, rounded end-caps. */
.matching-submit {
  display: block; margin: 3rem auto 0;
  padding: 1.4rem 4.5rem; font-size: 1.4rem; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase;
  border: none; border-radius: 999px; cursor: pointer;
  background: var(--brand); color: #fff;
  min-width: 20rem;
  transition: background .2s, opacity .2s, transform .1s;
}
.matching-submit:disabled { opacity: .35; cursor: not-allowed; }
.matching-submit:not(:disabled):hover { background: var(--brand-hover, #a63a0a); }
.matching-submit:not(:disabled):active { transform: translateY(1px); }
.matching-submit.is-ready { box-shadow: 0 0 0 0 var(--brand); animation: matching-ready-pulse 1.6s ease-out 1; }
@keyframes matching-ready-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(194, 65, 12, .5); }
  100% { box-shadow: 0 0 0 16px rgba(194, 65, 12, 0); }
}

/* Feedback */
.matching-feedback {
  max-width: var(--content-max); margin: 2rem auto 0;
  padding: 1.2rem 1.6rem; border-radius: .8rem;
  font-size: 1.5rem; display: flex; align-items: center; gap: .75rem;
}
.matching-feedback .kc-icon { width: 2.4rem; height: 2.4rem; flex-shrink: 0; }
.matching-feedback.is-correct   { background: var(--success-soft, #f0fdf4); color: var(--success, #16a34a); }
.matching-feedback.is-incorrect { background: var(--danger-soft,  #fef2f2); color: var(--danger,  #dc2626); }

@media (max-width: 600px) {
  .matching-arena { grid-template-columns: 1fr; gap: 1rem; }
}

/* Block: pie-chart --------------------------------------------------------- */
.block-pie-chart { max-width: var(--content-max); margin: 0 auto; }
.block-pie-chart__title {
  font-family: var(--font-family-head);
  font-size: 1.8rem; line-height: 1.4; color: var(--text);
  margin-bottom: 2.5rem; text-align: center;
}
.block-pie-chart__title p { margin: 0 0 .5rem; }
.block-pie-chart__row {
  display: flex; align-items: center; gap: 3rem;
  flex-wrap: wrap; justify-content: center;
}
.block-pie-chart__chart { flex: 0 0 24rem; max-width: 24rem; }
.block-pie-chart__svg { width: 100%; height: auto; display: block; }
.block-pie-chart__legend {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 1rem;
  min-width: 20rem;
}
.block-pie-chart__legend-item {
  display: flex; align-items: center; gap: 1rem;
  font-size: 1.6rem; line-height: 1.4;
}
.block-pie-chart__swatch {
  display: inline-block; width: 1.4rem; height: 1.4rem; flex-shrink: 0;
  border-radius: 3px; border: 1px solid rgba(0,0,0,.1);
}
.block-pie-chart__label { flex: 1 1 auto; font-weight: 600; }
.block-pie-chart__value { font-variant-numeric: tabular-nums; color: var(--text); font-weight: 500; }
@media (max-width: 600px) {
  .block-pie-chart__row { flex-direction: column; gap: 2rem; }
  .block-pie-chart__chart { flex: 0 0 auto; max-width: 20rem; }
  .block-pie-chart__legend { min-width: 0; width: 100%; }
}

/* Unknown block (fallback) ------------------------------------------------- */
.block--unknown {
  max-width: var(--content-max); margin: 0 auto;
  padding: 1.5rem; background: #fff3cd; color: #856404;
  border: 1px solid #ffc107; border-radius: var(--radius-md);
  font-size: 0.9rem;
}
