/* ═══════════════════════════════════════════════════════════════════════════
   Diverse Talent · components.css
   Tones, the shell (header, menu, language panel, footer …) and every foundation
   component. Each block starts with the markup it expects; the same snippets, with
   notes, are in tools/README.md and live at /styleguide/.

   The signature pieces (the living bloom, the petal window scene, the dial, the legend,
   the journey stem, the doors) are NOT here: they live in bloom.css.

   Contents
     1  Tones, petal colours    7  Suggestion bar           13  FAQ, tabs, segmented
     2  Icons, medallions       8  Preloader, progress      14  Forms, chips, toast
     3  Buttons and links       9  Footer, seam             15  Monograms, people
     4  Brand, header          10  Panels, petal rows, cards 16  Marquee, carousel, rotator
     5  Overlays, menu         11  Photo frames, plates     17  Page hero
     6  Language panel         12  Ghost numerals, stats, steps  18  Motion helpers
   ═══════════════════════════════════════════════════════════════════════════ */

@layer components {

/* ───────────────────────────────────────────── 1 Tones and petal colours ──
   A tone paints a .section or a .panel and re-points the semantic colours, so
   every component inside adapts: text, links, focus ring, buttons, petals, rows.
   Use them on sections (.section--forest), panels (.panel--mist-clay) or anything (.tone-gold).

   Text on forest, blue and plum is white. Text on gold and sage is ink, never white.
   Text on clay is ink-deep (white is for large type only there). */

.tone-bone, .section--bone, .panel--bone {
  --bg: var(--bone); --fg: var(--ink); --fg-muted: var(--slate); --heading: var(--ink);
  --link: var(--forest); --accent: var(--forest); --rule: var(--line); --focus: var(--forest-deep);
  --row: var(--white); --field: var(--white); --ghost: var(--bone-deep); --stat: initial;
  --btn-bg: var(--forest); --btn-fg: var(--white); --btn-bg-hover: var(--forest-deep); --btn-line: var(--forest); --donate-line: transparent;
  --p1: var(--forest); --p2: var(--gold); --p3: var(--clay); --p4: var(--blue); --p5: var(--plum); --p6: var(--sage);
}
.tone-white, .section--white, .panel--white {
  --bg: var(--white); --fg: var(--ink); --fg-muted: var(--slate); --heading: var(--ink);
  --link: var(--forest); --accent: var(--forest); --rule: var(--line); --focus: var(--forest-deep);
  --row: var(--bone); --field: var(--white); --ghost: var(--bone-deep); --stat: initial;
  --btn-bg: var(--forest); --btn-fg: var(--white); --btn-bg-hover: var(--forest-deep); --btn-line: var(--forest); --donate-line: transparent;
  --p1: var(--forest); --p2: var(--gold); --p3: var(--clay); --p4: var(--blue); --p5: var(--plum); --p6: var(--sage);
}
.tone-mist-forest, .section--mist-forest, .panel--mist-forest,
.tone-mist-gold, .section--mist-gold, .panel--mist-gold,
.tone-mist-clay, .section--mist-clay, .panel--mist-clay,
.tone-mist-blue, .section--mist-blue, .panel--mist-blue,
.tone-mist-plum, .section--mist-plum, .panel--mist-plum,
.tone-mist-sage, .section--mist-sage, .panel--mist-sage {
  --fg: var(--ink); --fg-muted: var(--slate); --heading: var(--ink);
  --rule: var(--ink-a16); --focus: var(--forest-deep);
  --row: var(--white); --field: var(--white); --ghost: var(--white-a40); --stat: initial;
  --btn-bg: var(--forest); --btn-fg: var(--white); --btn-bg-hover: var(--forest-deep); --btn-line: var(--forest); --donate-line: transparent;
  --p1: var(--forest); --p2: var(--gold); --p3: var(--clay); --p4: var(--blue); --p5: var(--plum); --p6: var(--sage);
}
.tone-mist-forest, .section--mist-forest, .panel--mist-forest { --bg: var(--forest-mist); --link: var(--forest); --accent: var(--forest); }
.tone-mist-gold, .section--mist-gold, .panel--mist-gold { --bg: var(--gold-mist); --link: var(--gold-deep); --accent: var(--gold-deep); }
.tone-mist-clay, .section--mist-clay, .panel--mist-clay { --bg: var(--clay-mist); --link: var(--clay-deep); --accent: var(--clay-deep); }
.tone-mist-blue, .section--mist-blue, .panel--mist-blue { --bg: var(--blue-mist); --link: var(--blue-deep); --accent: var(--blue-deep); }
.tone-mist-plum, .section--mist-plum, .panel--mist-plum { --bg: var(--plum-mist); --link: var(--plum-deep); --accent: var(--plum-deep); }
.tone-mist-sage, .section--mist-sage, .panel--mist-sage { --bg: var(--sage-mist); --link: var(--sage-deep); --accent: var(--sage-deep); }

.tone-forest, .section--forest, .panel--forest,
.tone-forest-deep, .section--forest-deep, .panel--forest-deep {
  --bg: var(--forest); --fg: var(--white); --fg-muted: var(--on-forest-muted); --heading: var(--white);
  --link: var(--white); --accent: var(--gold); --rule: var(--white-a24); --focus: var(--gold);
  --row: var(--ink-a24); --field: var(--white); --ghost: var(--white-a10); --stat: var(--gold);
  --btn-bg: var(--gold); --btn-fg: var(--ink); --btn-bg-hover: var(--gold-hover); --btn-line: var(--white); --donate-line: transparent;
  --p1: var(--gold); --p2: var(--gold); --p3: var(--gold); --p4: var(--gold); --p5: var(--gold); --p6: var(--gold);
}
.tone-forest-deep, .section--forest-deep, .panel--forest-deep { --bg: var(--forest-deep); }
.tone-gold, .section--gold, .panel--gold {
  --bg: var(--gold); --fg: var(--ink); --fg-muted: var(--forest-deep); --heading: var(--ink);
  --link: var(--ink); --accent: var(--forest-deep); --rule: var(--ink-a24); --focus: var(--ink);
  --row: var(--white-a40); --field: var(--white); --ghost: var(--white-a24); --stat: initial;
  --btn-bg: var(--forest); --btn-fg: var(--white); --btn-bg-hover: var(--forest-deep); --btn-line: var(--ink); --donate-line: var(--ink);
  --p1: var(--forest-deep); --p2: var(--forest-deep); --p3: var(--forest-deep); --p4: var(--forest-deep); --p5: var(--forest-deep); --p6: var(--forest-deep);
}
.tone-clay, .section--clay, .panel--clay {
  --bg: var(--clay); --fg: var(--ink-deep); --fg-muted: var(--ink-deep); --heading: var(--ink-deep);
  --link: var(--ink-deep); --accent: var(--ink-deep); --rule: var(--ink-a24); --focus: var(--ink-deep);
  --row: var(--white-a24); --field: var(--white); --ghost: var(--white-a16); --stat: initial;
  --btn-bg: var(--white); --btn-fg: var(--ink); --btn-bg-hover: var(--bone); --btn-line: var(--ink-deep); --donate-line: transparent;
  --p1: var(--white); --p2: var(--white); --p3: var(--white); --p4: var(--white); --p5: var(--white); --p6: var(--white);
}
.tone-blue, .section--blue, .panel--blue,
.tone-plum, .section--plum, .panel--plum {
  --fg: var(--white); --fg-muted: var(--white); --heading: var(--white);
  --link: var(--white); --accent: var(--white); --rule: var(--white-a40); --focus: var(--white);
  --row: var(--ink-a16); --field: var(--white); --ghost: var(--white-a16); --stat: initial;
  --btn-bg: var(--white); --btn-fg: var(--ink); --btn-bg-hover: var(--bone); --btn-line: var(--white); --donate-line: transparent;
  --p1: var(--white); --p2: var(--white); --p3: var(--white); --p4: var(--white); --p5: var(--white); --p6: var(--white);
}
.tone-blue, .section--blue, .panel--blue { --bg: var(--blue); }
.tone-plum, .section--plum, .panel--plum { --bg: var(--plum); }
.tone-sage, .section--sage, .panel--sage {
  --bg: var(--sage); --fg: var(--ink); --fg-muted: var(--ink); --heading: var(--ink);
  --link: var(--ink); --accent: var(--forest-deep); --rule: var(--ink-a24); --focus: var(--ink);
  --row: var(--white-a40); --field: var(--white); --ghost: var(--white-a24); --stat: initial;
  --btn-bg: var(--forest-deep); --btn-fg: var(--white); --btn-bg-hover: var(--ink); --btn-line: var(--ink); --donate-line: transparent;
  --p1: var(--forest-deep); --p2: var(--forest-deep); --p3: var(--forest-deep); --p4: var(--forest-deep); --p5: var(--forest-deep); --p6: var(--forest-deep);
}
/* What a form says when a field is wrong: clay-deep on light grounds, the text colour on solid ones. */
:is(.tone-bone, .section--bone, .panel--bone, .tone-white, .section--white, .panel--white, [class*="tone-mist-"], [class*="section--mist-"], [class*="panel--mist-"]) { --error: var(--clay-deep); }
:is(.tone-forest, .section--forest, .panel--forest, .tone-forest-deep, .section--forest-deep, .panel--forest-deep, .tone-gold, .section--gold, .panel--gold, .tone-clay, .section--clay, .panel--clay, .tone-blue, .section--blue, .panel--blue, .tone-plum, .section--plum, .panel--plum, .tone-sage, .section--sage, .panel--sage) { --error: var(--fg); }
:is([class*="tone-"], [class*="section--"], [class*="panel--"]) { color: var(--fg); }
[class*="tone-"] { background: var(--bg); }

/* One petal colour for one thing. Each colour belongs to a community and keeps that meaning:
   forest seniors · gold youth · clay ethnic minorities · blue refugees · plum partners · sage volunteers.
   <span class="medallion c-clay">…</span>   <li class="c-sage">…</li>   <div class="stat c-blue">…</div>
   --c-on is for large type and icons on --c (clay with white is 3.8: never body text). */
.c-forest { --c: var(--forest); --c-deep: var(--forest-deep); --c-mist: var(--forest-mist); --c-on: var(--white); }
.c-gold { --c: var(--gold); --c-deep: var(--gold-deep); --c-mist: var(--gold-mist); --c-on: var(--ink); }
.c-clay { --c: var(--clay); --c-deep: var(--clay-deep); --c-mist: var(--clay-mist); --c-on: var(--white); }
.c-blue { --c: var(--blue); --c-deep: var(--blue-deep); --c-mist: var(--blue-mist); --c-on: var(--white); }
.c-plum { --c: var(--plum); --c-deep: var(--plum-deep); --c-mist: var(--plum-mist); --c-on: var(--white); }
.c-sage { --c: var(--sage); --c-deep: var(--sage-deep); --c-mist: var(--sage-mist); --c-on: var(--ink); }

/* ───────────────────────────────────────────── 2 Icons and medallions ──
   {{ icon('mail') }}  →  <svg class="icon" viewBox="0 0 48 48" aria-hidden="true"><use href="#i-mail"/></svg>
   One family: 48 box, 1.75px stroke that does not scale, round caps and joins, currentColor. */

.sprite { position: absolute; inline-size: 0; block-size: 0; overflow: hidden; }
.sprite :is(path, circle, ellipse, line, polyline, polygon, rect) { vector-effect: non-scaling-stroke; }
.icon {
  flex: none;
  inline-size: 1.5rem;
  block-size: 1.5rem;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
  overflow: visible;
}
.icon--up { rotate: -90deg; }
.icon--down { rotate: 90deg; }
.icon--back { transform: scaleX(-1); }   /* a chevron that points to the start side */

/* Medallion: a line icon in a filled circle (the core of the bloom). Mist with a deep icon by default.
   <span class="medallion c-clay">{{ icon('focus-inclusion') }}</span>
   medallion--solid  the petal colour itself        medallion--white  a white disc (on colour)
   medallion--ghost  the row tint of the ground      sizes --sm 2.75rem · 3.5rem · --lg 4.5rem · --xl 6rem */
.medallion {
  --size: 3.5rem;
  flex: none;
  display: inline-grid;
  place-items: center;
  inline-size: var(--size);
  block-size: var(--size);
  border-radius: 50%;
  background: var(--c-mist);
  color: var(--c-deep);
}
.medallion > .icon { inline-size: calc(var(--size) * .5); block-size: calc(var(--size) * .5); }
.medallion--sm { --size: 2.75rem; }
.medallion--lg { --size: 4.5rem; }
.medallion--xl { --size: 6rem; }
.medallion--solid { background: var(--c); color: var(--c-on); }
.medallion--white { background: var(--white); color: var(--c-deep); }
.medallion--ghost { background: var(--row); color: currentColor; }

/* A petal as a small mark: in a legend, beside a label, wherever a dot would have been.
   <span class="petal c-plum" aria-hidden="true"></span>      Size follows the text (1.1em tall); --size overrides. */
.petal {
  flex: none;
  display: inline-block;
  block-size: var(--size, 1.1em);
  aspect-ratio: 20.648 / 45.125;
  background: var(--c);
  -webkit-mask: var(--petal-mask) center / 100% 100% no-repeat;
  mask: var(--petal-mask) center / 100% 100% no-repeat;
  vertical-align: -0.16em;
}

/* ─────────────────────────────────────────────────── 3 Buttons and links ──
   <a class="btn btn--primary" href="…">Volunteer with us</a>
   <a class="btn btn--secondary" href="…">See our journey</a>
   <a class="btn btn--donate" href="{{ url('donate') }}">Donate</a>
   Pill, at least 48px high. The label says exactly what happens; no arrows glued on.
   Primary is forest; on a forest section it turns gold by itself (tones). Donate is always gold. */

.btn {
  --_bg: var(--btn-bg);
  --_fg: var(--btn-fg);
  --_hover: var(--btn-bg-hover);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6em;
  min-block-size: var(--btn-h);
  padding: .55rem 1.6rem;
  border: 2px solid transparent;
  border-radius: var(--r-full);
  background: var(--_bg);
  color: var(--_fg);
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: var(--fw-display);
  line-height: var(--lh-ui);
  letter-spacing: var(--tracking-ui);
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur-2) ease, border-color var(--dur-2) ease, color var(--dur-2) ease, scale var(--dur-1) var(--ease-out);
}
.btn:active { scale: .97; }
.btn > .icon { inline-size: 1.4em; block-size: 1.4em; margin-inline-start: -.2em; }
.btn--primary { --_bg: var(--btn-bg); --_fg: var(--btn-fg); }
.btn--secondary { --_bg: transparent; --_fg: var(--btn-line); --_hover: var(--row); border-color: var(--btn-line); }
.btn--donate { --_bg: var(--gold); --_fg: var(--ink); --_hover: var(--gold-hover); border-color: var(--donate-line); }
.btn--lg { min-block-size: 3.5rem; padding-inline: 2rem; font-size: 1.1875rem; }
.btn--block { display: flex; inline-size: 100%; }
/* With an icon, a label that needs two lines starts beside the icon instead of centring each line. */
.btn:has(> .icon) { text-align: start; }
@media (hover: hover) and (pointer: fine) {
  .btn:hover { background: var(--_hover); }
}

/* A round button for controls (close, carousel arrows, pause). 48px. */
.round-btn {
  flex: none;
  display: inline-grid;
  place-items: center;
  inline-size: 3rem;
  block-size: 3rem;
  border: 2px solid var(--btn-line);
  border-radius: 50%;
  color: var(--btn-line);
  transition: background-color var(--dur-2) ease, color var(--dur-2) ease, scale var(--dur-1) var(--ease-out), opacity var(--dur-2) ease;
}
.round-btn:active { scale: .94; }
.round-btn:disabled, .round-btn[aria-disabled="true"] { opacity: .35; cursor: default; }
@media (hover: hover) and (pointer: fine) {
  .round-btn:not(:disabled):hover { background: var(--btn-line); color: var(--bg); }
}

/* Text link with a petal lying under it: the logo's petal as an underline.
   <a class="link-petal" href="…">Read the whole journey</a>    One line of text only. */
.link-petal {
  position: relative;
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  justify-self: start;
  inline-size: fit-content;
  max-inline-size: 100%;
  min-block-size: var(--target);
  padding-block-end: .5em;
  color: var(--heading);
  font-weight: var(--fw-strong);
  line-height: var(--lh-ui);
  text-decoration: none;
}
.link-petal::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: .1em;
  block-size: .38em;
  background: var(--accent);
  -webkit-mask: var(--petal-mask-flat) center / 100% 100% no-repeat;
  mask: var(--petal-mask-flat) center / 100% 100% no-repeat;
  transform-origin: left center;   /* lint-ok: mirrored for RTL in lang.css */
  pointer-events: none;
}
.link-petal:is(:hover, :focus-visible)::after { animation: dt-petal-grow var(--dur-4) var(--ease-out); }

/* ──────────────────────────────────────────────────── 4 Brand and header ── */

.brand {
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: .6rem;
  min-block-size: var(--target);
  color: var(--ink);
  text-decoration: none;
}
.brand__mark { flex: none; display: block; inline-size: 2.75rem; block-size: 2.75rem; }
.brand__mark > img { inline-size: 100%; block-size: 100%; object-fit: contain; }
.brand__name {
  font-family: var(--font-latin);
  font-size: 1.375rem;
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.015em;   /* lint-ok: the wordmark is always Latin, always Gabarito */
  white-space: nowrap;
}

.site-header {
  position: sticky;
  inset-block-start: 0;
  z-index: var(--z-header);
  background: var(--bone);
  transition: transform var(--dur-3) var(--ease-out), box-shadow var(--dur-3) ease;
  /* No view-transition-name here or on the mark: see the note in base.css. */
}
.site-header.is-stuck { box-shadow: var(--shadow); }
.site-header.is-hidden { transform: translateY(-115%); box-shadow: none; }
.site-header__bar {
  display: flex;
  align-items: center;
  column-gap: clamp(.75rem, .2rem + 1.6vw, 1.75rem);
  row-gap: .25rem;
  inline-size: min(100% - 2 * var(--gutter), var(--container-wide));
  min-block-size: 4.75rem;
  margin-inline: auto;
  padding-block: .75rem;
}
.site-nav { flex: 1 1 auto; min-inline-size: 0; display: flex; justify-content: center; }
.site-nav__list { display: flex; flex-wrap: nowrap; gap: .25rem; white-space: nowrap; }
.site-nav__link {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--target);
  padding-inline: .85rem;
  border-radius: var(--r-full);
  color: var(--ink);
  font-size: 1.0625rem;
  font-weight: var(--fw-medium);
  line-height: var(--lh-ui);
  text-decoration: none;
}
/* The petal that marks a page: it lies under the label, in that page's own petal colour, and
   grows from the start side on hover and focus. On the current page it stays. */
.site-nav__link > span, .site-menu__link > span { position: relative; }
.site-nav__link > span::after, .site-menu__link > span::after {
  content: "";
  position: absolute;
  inset-inline: -.05em;
  inset-block-start: calc(100% + .16em);
  block-size: .36em;
  background: var(--c);
  -webkit-mask: var(--petal-mask-flat) center / 100% 100% no-repeat;
  mask: var(--petal-mask-flat) center / 100% 100% no-repeat;
  opacity: 0;
  transform: scaleX(.2);
  transform-origin: left center;   /* lint-ok: mirrored for RTL in lang.css */
  transition: transform var(--dur-3) var(--ease-out), opacity var(--dur-2) ease;
  pointer-events: none;
}
.site-nav__link:is(:hover, :focus-visible, [aria-current="page"]) > span::after,
.site-menu__link:is(:hover, :focus-visible, [aria-current="page"]) > span::after { opacity: 1; transform: none; }
.site-nav__link[aria-current="page"] { font-weight: var(--fw-strong); }

.site-tools { flex: none; display: flex; align-items: center; gap: .5rem; margin-inline-start: auto; }

/* Quiet pill buttons of the shell: language, menu. */
.tool-btn {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-inline-size: var(--target);
  min-block-size: var(--target);
  padding-inline: .7rem;
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-full);
  background: transparent;
  color: var(--ink);
  font-size: 1rem;
  font-weight: var(--fw-medium);
  line-height: var(--lh-ui);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--dur-2) ease, border-color var(--dur-2) ease, scale var(--dur-1) var(--ease-out);
}
.tool-btn:active { scale: .96; }
@media (hover: hover) and (pointer: fine) {
  .tool-btn:hover { background: var(--white); }
}
.menu-btn { display: none; border-color: var(--forest); background: var(--forest); color: var(--white); padding-inline: .9rem 1.1rem; }
@media (hover: hover) and (pointer: fine) {
  .menu-btn:hover { background: var(--forest-deep); }
}
.site-header__cta { white-space: nowrap; }

/* What the measured level shows and hides (see header.html). */
.site-header:is([data-level="1"], [data-level="3"], [data-level="4"], [data-level="5"], [data-level="6"]) .lang-btn__name { display: none; }
.site-header:is([data-level="2"], [data-level="3"], [data-level="4"], [data-level="5"], [data-level="6"]) .site-nav { display: none; }
.site-header:is([data-level="2"], [data-level="3"], [data-level="4"], [data-level="5"], [data-level="6"]) .menu-btn { display: inline-flex; }
.site-header:is([data-level="4"], [data-level="5"], [data-level="6"]) .menu-btn__label { display: none; }
.site-header:is([data-level="4"], [data-level="5"], [data-level="6"]) .menu-btn { padding-inline: 0; }
.site-header:is([data-level="5"], [data-level="6"]) .site-header__cta { display: none; }
/* The tightest state (320px wide, long wordmark neighbours): fixed sizes, so the bar cannot outgrow the screen. */
.site-header[data-level="6"] .site-header__bar { column-gap: 10px; min-block-size: 4.25rem; }
.site-header[data-level="6"] .site-tools { gap: 6px; }
.site-header[data-level="6"] .tool-btn { inline-size: 44px; block-size: 44px; padding-inline: 0; }
.site-header[data-level="6"] .tool-btn > .icon { inline-size: 24px; block-size: 24px; }
.site-header[data-level="6"] .brand { gap: 8px; }
.site-header[data-level="6"] .brand__mark { inline-size: 38px; block-size: 38px; }
.site-header[data-level="6"] .brand__name { font-size: 19px; }      /* lint-ok: the last resort at 320px; still above the 16px floor */

/* Without JavaScript: no measuring and no menu. The nav wraps under the logo instead. */
html:not(.js) .site-header { position: static; }
html:not(.js) .site-header__bar { flex-wrap: wrap; }
html:not(.js) .site-nav { order: 3; flex-basis: 100%; justify-content: flex-start; }
html:not(.js) .site-nav__list { flex-wrap: wrap; white-space: normal; }

/* ───────────────────────────────────────────────────── 5 Overlays, menu ──
   The menu and the language panel are native <dialog> elements that fill the screen.
   They open from the button that was pressed (core.js sets --ox --oy --or): the ground grows
   as a circle, and inside it the six petals of the mark burst outward once and fade. */

.overlay {
  position: fixed;
  inset: 0;
  inline-size: 100%;
  block-size: 100%;
  margin: 0;
  background: var(--bone);
  color: var(--ink);
  overflow: hidden;
  clip-path: circle(0px at var(--ox, 100%) var(--oy, 0%));
  transition: clip-path var(--dur-3) var(--ease-in-out);
}
.overlay[open] { display: flex; flex-direction: column; }
.overlay:focus, .overlay:focus-visible { outline: none; }   /* after a tap the dialog itself holds the focus (core.js) */
.overlay::backdrop { background: transparent; }
.overlay.is-open { clip-path: circle(var(--or, 150vmax) at var(--ox, 100%) var(--oy, 0%)); transition: clip-path 620ms var(--ease-bloom); }
.overlay__bloom {
  position: absolute;
  inset-block-start: var(--oy, 0px);
  left: var(--ox, 100%);   /* lint-ok: a physical point measured by JavaScript */
  z-index: 0;
  inline-size: 80vmax;
  block-size: 80vmax;
  margin: -40vmax;
  opacity: 0;
  pointer-events: none;
}
.overlay__bloom > .mark { inline-size: 100%; block-size: 100%; }
.overlay__bloom .mark__core { display: none; }
.overlay.is-open .overlay__bloom { animation: dt-overlay-bloom 950ms var(--ease-bloom) both; }
.overlay__bar {
  position: relative;
  z-index: 1;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  inline-size: min(100% - 2 * var(--gutter), var(--container-wide));
  min-block-size: 4.75rem;
  margin-inline: auto;
  padding-block: .75rem;
}
.overlay__body {
  position: relative;
  z-index: 1;
  flex: 1 1 auto;
  min-block-size: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: thin;
  scrollbar-color: var(--line) transparent;
}
.overlay__close { --btn-line: var(--forest); --bg: var(--bone); }

/* Rows that cascade in once the overlay is open. core.js numbers them with --i. */
.overlay [data-cascade] > * {
  opacity: 0;
  transform: translateY(.9rem);
  transition: opacity var(--dur-3) ease, transform var(--dur-4) var(--ease-out);
}
.overlay.is-open [data-cascade] > * {
  opacity: 1;
  transform: none;
  transition-delay: calc(160ms + var(--i, 0) * 36ms);
}
@media (prefers-reduced-motion: reduce) {
  .overlay, .overlay.is-open { clip-path: none; transition: opacity var(--dur-2) ease; }
  .overlay { opacity: 0; }
  .overlay.is-open { opacity: 1; }
  .overlay [data-cascade] > * { opacity: 1; transform: none; transition: none; }
  .overlay__bloom { display: none; }
}

.site-menu__body {
  display: grid;
  align-content: start;
  gap: clamp(2rem, 6vw, 4rem);
  padding-block: clamp(1rem, 4vw, 3rem) clamp(2rem, 6vw, 4rem);
  padding-inline: max(var(--gutter), (100% - var(--container)) / 2);   /* padding, not width: focus rings need the room */
}
.site-menu__list { display: grid; gap: .25rem; }
.site-menu__link {
  display: flex;
  align-items: center;
  gap: 1rem;
  min-block-size: 4rem;
  padding-block: .4rem;
  border-radius: var(--r-row);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: clamp(1.875rem, 1.3rem + 2.6vw, 3rem);
  font-weight: var(--fw-hero);
  line-height: var(--lh-display);
  letter-spacing: var(--tracking-display);
  text-decoration: none;
}
/* Six links, six petals: each carries its own. */
.site-menu__link::before {
  content: "";
  flex: none;
  block-size: .9em;
  aspect-ratio: 20.648 / 45.125;
  background: var(--c);
  -webkit-mask: var(--petal-mask) center / 100% 100% no-repeat;
  mask: var(--petal-mask) center / 100% 100% no-repeat;
  transform-origin: 50% 100%;
  transition: scale var(--dur-3) var(--ease-pop), rotate var(--dur-3) var(--ease-out);
}
.site-menu__link:is(:hover, :focus-visible)::before { scale: 1.25; rotate: calc(30deg * var(--dir)); }
.site-menu__link > span::after { block-size: .2em; inset-block-start: calc(100% + .1em); }
.site-menu__tools { display: grid; gap: 1.25rem; justify-items: start; }
.site-menu__tools > .btn { min-inline-size: min(100%, 18rem); }
.site-menu__note { max-inline-size: 22em; color: var(--slate); font-size: var(--fs-small); }
@media (min-width: 56rem) {
  .site-menu__body { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); align-items: start; }
  .site-menu__tools { padding-block-start: .75rem; }
}

/* ─────────────────────────────────────────────────── 6 Language panel ── */

.lang-panel__title { font-size: var(--fs-sub); }
.lang-panel__body {
  display: grid;
  gap: clamp(1.5rem, 4vw, 4rem);
  align-content: start;
  padding-block: clamp(.5rem, 2vw, 1.5rem) clamp(2rem, 5vw, 3.5rem);
  padding-inline: max(var(--gutter), (100% - var(--container-wide)) / 2);
}
/* The greeting: the mark says hello in the language under the pointer, and turns one petal each time. */
.lang-panel__hello { display: none; }
@media (min-width: 64rem) {
  .lang-panel__body { grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); align-items: center; align-content: center; }
  .lang-panel__hello { display: grid; justify-items: center; gap: 1.5rem; }
  .lang-panel__ring { display: block; inline-size: min(100%, 19rem); aspect-ratio: 1; margin-block: -2rem; transition: rotate 700ms var(--ease-out); }
  .lang-panel__ring > .mark { inline-size: 100%; block-size: 100%; }
  .lang-panel__greeting {
    display: block;
    min-block-size: 2.4em;
    color: var(--ink);
    font-family: var(--font-display);
    font-size: clamp(1.75rem, 1rem + 2vw, 2.75rem);
    font-weight: var(--fw-display);
    line-height: var(--lh-display);
    text-align: center;
    transition: opacity var(--dur-1) ease;
  }
  .lang-panel__greeting.is-swapping { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .lang-panel__ring { transition: none; } }
.lang-list { display: grid; gap: .6rem; grid-template-columns: repeat(auto-fill, minmax(min(15.5rem, 100%), 1fr)); }
.lang-list > li:nth-child(6n + 1) { --c: var(--forest); }
.lang-list > li:nth-child(6n + 2) { --c: var(--gold); }
.lang-list > li:nth-child(6n + 3) { --c: var(--clay); }
.lang-list > li:nth-child(6n + 4) { --c: var(--blue); }
.lang-list > li:nth-child(6n + 5) { --c: var(--plum); }
.lang-list > li:nth-child(6n) { --c: var(--sage); }
.lang-row {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-areas: "petal native mark" "petal english mark";
  align-items: center;
  column-gap: .9rem;
  min-block-size: 4.5rem;
  padding: .6rem 1rem .6rem 1.1rem;
  border-radius: var(--r-row);
  background: var(--white);
  color: var(--ink);
  text-decoration: none;
  line-height: 1.3;
  transition: background-color var(--dur-2) ease, scale var(--dur-1) var(--ease-out);
}
.lang-row:active { scale: .98; }
.lang-row::before {
  content: "";
  grid-area: petal;
  block-size: 1.5rem;
  aspect-ratio: 20.648 / 45.125;
  background: var(--c);
  -webkit-mask: var(--petal-mask) center / 100% 100% no-repeat;
  mask: var(--petal-mask) center / 100% 100% no-repeat;
  transform-origin: 50% 100%;
  transition: scale var(--dur-3) var(--ease-pop);
}
.lang-row__native { grid-area: native; align-self: end; font-size: 1.3125rem; font-weight: var(--fw-strong); }
.lang-row__english { grid-area: english; align-self: start; color: var(--slate); font-family: var(--font-latin-text); font-size: 1rem; line-height: 1.3; }
.lang-row__current {
  grid-area: mark;
  display: grid;
  place-items: center;
  inline-size: 2.25rem;
  block-size: 2.25rem;
  border-radius: 50%;
  background: var(--gold);
  color: var(--ink);
}
.lang-row__current > .icon { inline-size: 1.25rem; block-size: 1.25rem; stroke-width: 2.25; }
.lang-row[aria-current="true"] { background: var(--forest); color: var(--white); }
.lang-row[aria-current="true"]::before { background: var(--gold); }
.lang-row[aria-current="true"] .lang-row__english { color: var(--on-forest-muted); }
@media (hover: hover) and (pointer: fine) {
  .lang-row:not([aria-current="true"]):hover { background: var(--bone-deep); }
  .lang-row:hover::before { scale: 1.3; }
}
.lang-row:focus-visible::before { scale: 1.3; }

/* ─────────────────────────────────────────────────── 7 Suggestion bar ──
   Docked to the bottom edge of the viewport, laid out in the direction of the language it offers.
   Narrow screens: one low, full-width strip: the globe, the offer as a button, a cross to close.
   The question is still read out there, but not shown: the button says the same thing, and a low
   strip leaves the first screen to the page.
   From 48rem: a floating capsule in the middle of the bottom edge, with the question and the words
   of the close button.
   core.js publishes the room the bar takes as --dock-h on <html> (0px when there is no bar). */

.suggest {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: var(--z-suggest);
  display: flex;
  align-items: center;
  gap: .5rem;
  padding: .5rem .75rem max(.5rem, env(safe-area-inset-bottom));
  border-block-start: 1.5px solid var(--line);
  border-start-start-radius: 1.25rem;
  border-start-end-radius: 1.25rem;
  background: var(--white);
  box-shadow: 0 -10px 30px -18px rgb(30 67 56 / .35);
  transform: translateY(calc(100% + 2rem));
  transition: transform var(--dur-4) var(--ease-out);
}
.suggest.is-in { transform: none; }
.suggest__text { max-inline-size: none; color: var(--ink); font-size: 1.0625rem; font-weight: var(--fw-medium); line-height: var(--lh-ui); }
.suggest__text:empty { display: none; }
.suggest__actions { flex: 1 1 auto; display: flex; align-items: center; gap: .4rem; min-inline-size: 0; }
.suggest__yes { flex: 1 1 auto; padding-inline: 1.1rem; }
.suggest__no { border-color: transparent; }
@media (max-width: 47.99rem) {
  .suggest__text { position: absolute; inline-size: 1px; block-size: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }   /* read out, not shown */
  .suggest__no { inline-size: var(--target); padding-inline: 0; }
  .suggest__no-label { display: none; }                     /* the button keeps its name: aria-label carries the same words */
}
@media (min-width: 48rem) {
  .suggest {
    inset-block-end: max(.75rem, env(safe-area-inset-bottom));
    gap: .9rem;
    inline-size: fit-content;
    max-inline-size: min(100% - 2rem, 54rem);
    margin-inline: auto;
    padding-block: .5rem;
    padding-inline: .7rem .6rem;
    border: 1.5px solid var(--line);
    border-radius: 2.25rem;
    box-shadow: var(--shadow);
  }
  .suggest__text { flex: 1 1 auto; min-inline-size: 9rem; text-wrap: balance; }
  .suggest__actions { flex: none; gap: .5rem; }
  .suggest__yes { flex: none; padding-inline: 1.3rem; }
}
@media (prefers-reduced-motion: reduce) { .suggest { transition: none; } }

/* ──────────────────────────────────────────── 8 Preloader and progress ──
   Preloader: on bone, the six petals arrive along their own six axes and settle into the exact
   mark, then the gold core pops. CSS runs it all (it starts with the first paint and ends even if
   no script arrives); core.js adds the flight into the header mark. */

.preloader { display: none; }
html.js.dt-intro .preloader {
  position: fixed;
  inset: 0;
  z-index: var(--z-preloader);
  display: grid;
  place-items: center;
  background: var(--bone);
  animation: dt-pre-out 320ms 1260ms both var(--ease-in-out);
}
html.js.dt-intro .preloader.is-handoff { animation: none; }
html.dt-failsafe .preloader { display: none !important; }
.preloader__mark { inline-size: min(60vmin, 22rem); aspect-ratio: 1; will-change: transform; }
.preloader__svg { inline-size: 100%; block-size: 100%; overflow: visible; }
/* Each petal sits in a group already turned to its own angle, so "up" here is outward along its axis. */
.preloader__svg .mark__petal {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: dt-pre-petal 560ms cubic-bezier(.3, 1.35, .6, 1) both;
}
.preloader__svg g:nth-of-type(2) .mark__petal { animation-delay: 60ms; }
.preloader__svg g:nth-of-type(3) .mark__petal { animation-delay: 120ms; }
.preloader__svg g:nth-of-type(4) .mark__petal { animation-delay: 180ms; }
.preloader__svg g:nth-of-type(5) .mark__petal { animation-delay: 240ms; }
.preloader__svg g:nth-of-type(6) .mark__petal { animation-delay: 300ms; }
.preloader__svg .mark__core {
  transform-box: fill-box;
  transform-origin: 50% 50%;
  animation: dt-pre-core 420ms 520ms var(--ease-pop) both;
}
/* While the intro runs, the marks it will land on stay out of sight. */
html.js.dt-intro .brand__mark--shared > img,
html.js.dt-intro [data-intro-target] { visibility: hidden; }

/* Scroll progress: six small segments in the six petal colours, filling in order as the page is read. */
.progress { display: none; }
html.js .progress {
  position: fixed;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: var(--z-progress);
  display: flex;
  gap: 3px;
  block-size: 4px;
  pointer-events: none;
}
.progress__seg { flex: 1 1 0; min-inline-size: 0; overflow: hidden; }
.progress__fill {
  display: block;
  block-size: 100%;
  background: var(--c);
  transform: scaleX(0);
  transform-origin: left center;   /* lint-ok: mirrored for RTL in lang.css */
  will-change: transform;
}

/* ───────────────────────────────────────────────── 9 Footer and seam ──
   Seam (DIRECTION 5): where a coloured section meets the one above, its top edge is
   one long petal curve, never a straight line or a wave.
   <section class="section section--forest"><div class="seam" aria-hidden="true"></div> … </section>
   The seam takes the section's own --bg and rises into the section above, which
   is given room for it automatically. seam--flip mirrors the curve; data-still stops it swelling. */

.seam {
  position: absolute;
  inset-inline: 0;
  inset-block-end: calc(100% - 1px);
  block-size: var(--seam-h);
  transform-origin: 50% 100%;
  pointer-events: none;
}
.seam::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--bg);
  -webkit-mask: url("../img/art/seam-petal.svg") center / 100% 100% no-repeat;
  mask: url("../img/art/seam-petal.svg") center / 100% 100% no-repeat;
}
.seam--flip::before { transform: scaleX(-1); }
:is(.section, .page-hero):has(+ :is(.section, .site-footer) > .seam),
main:has(+ .site-footer > .seam) > :last-child { padding-block-end: calc(var(--section-pad) + var(--seam-h)); }

.site-footer {
  position: relative;
  background: var(--bg);
  color: var(--fg);
  padding-block: clamp(2.5rem, 2rem + 3vw, 4.5rem) calc(clamp(1.5rem, 1rem + 2vw, 2.5rem) + var(--dock-h, 0px));   /* --dock-h: room for the language suggestion bar while it is there */
}
.site-footer a { color: var(--white); text-decoration: none; }
.site-footer__inner { display: grid; gap: clamp(2.5rem, 2rem + 3vw, 4.5rem); }
.site-footer__lead { display: grid; gap: 1.5rem 3rem; align-items: center; }
.site-footer__brand { display: flex; align-items: center; gap: 1.1rem; }
/* The mark on a white disc: its top petal is forest, so it never stands on green directly. */
.site-footer__mark {
  flex: none;
  display: grid;
  place-items: center;
  inline-size: 5.5rem;
  block-size: 5.5rem;
  border-radius: 50%;
  background: var(--white);
}
.site-footer__mark > .mark { inline-size: 120%; block-size: 120%; max-inline-size: none; }
.site-footer__name {
  max-inline-size: none;
  color: var(--white);
  font-family: var(--font-latin);
  font-size: 1.75rem;
  font-weight: 800;
  line-height: 1.1;
  letter-spacing: -0.015em;   /* lint-ok: the wordmark is always Latin, always Gabarito */
  white-space: nowrap;
}
.site-footer__about { display: grid; gap: .6rem; }
.site-footer__desc { max-inline-size: 26em; color: var(--white); font-size: var(--fs-lead); font-weight: var(--fw-medium); line-height: var(--lh-sub); text-wrap: balance; }
.site-footer__rel { max-inline-size: 30em; color: var(--on-forest-muted); }
.backtotop {
  display: inline-flex;
  align-items: center;
  gap: .9rem;
  min-block-size: var(--target);
  justify-self: start;
  font-weight: var(--fw-strong);
  line-height: var(--lh-ui);
}
.backtotop .medallion { transition: translate var(--dur-3) var(--ease-out); }
@media (hover: hover) and (pointer: fine) {
  .backtotop:hover .medallion { translate: 0 -4px; }
}
@media (min-width: 62rem) {
  .site-footer__lead { grid-template-columns: auto minmax(0, 1fr) auto; }
  .backtotop { justify-self: end; }
}

.site-footer__grid { display: grid; gap: 2.5rem 3rem; grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr)); }
.site-footer__label {
  margin-block-end: .75rem;
  color: var(--gold);
  font-family: var(--font-text);
  font-size: var(--fs-small);
  font-weight: var(--fw-strong);
  line-height: var(--lh-ui);
  letter-spacing: var(--tracking-ui);
  text-wrap: balance;
}
.site-footer__links { display: grid; }
.site-footer__links a, .site-footer__reach a, .site-footer__social a, .site-footer__base a, .site-footer__facts a {
  display: inline-flex;
  align-items: center;
  gap: .7rem;
  min-inline-size: var(--target);
  min-block-size: var(--target);
  line-height: var(--lh-ui);
}
.site-footer__links a[aria-current="page"] { font-weight: var(--fw-strong); }
.site-footer__address { max-inline-size: 18em; line-height: var(--lh-text); }
.site-footer__address > a { display: inline; color: var(--white); text-decoration: underline; text-decoration-thickness: .06em; text-underline-offset: var(--underline-offset); text-decoration-color: var(--white-a40); }
.site-footer__reach { display: grid; gap: .25rem; margin-block-start: 1rem; }
.site-footer__reach .icon { color: var(--gold); }
.site-footer__social { display: grid; gap: .35rem; }
.site-footer__social .medallion { color: var(--gold); }
.site-footer__facts { display: grid; gap: .6rem; color: var(--on-forest-muted); }
.site-footer__facts li { max-inline-size: 24em; line-height: var(--lh-text); }
@media (hover: hover) and (pointer: fine) {
  .site-footer__links a:hover, .site-footer__reach a:hover span, .site-footer__social a:hover > span:nth-child(2), .site-footer__base a:hover, .site-footer__facts a:hover > span {
    text-decoration: underline;
    text-decoration-thickness: .1em;
    text-underline-offset: var(--underline-offset);
    text-decoration-color: var(--gold);
  }
  .site-footer__address > a:hover { text-decoration-color: var(--gold); }
}

.site-footer__langlist { display: flex; flex-wrap: wrap; gap: .5rem; }
.site-footer__langlist a {
  display: inline-flex;
  align-items: center;
  min-block-size: var(--target);
  padding-inline: 1rem;
  border: 1.5px solid var(--white-a24);
  border-radius: var(--r-full);
  font-size: 1rem;
  line-height: 1.4;
  transition: background-color var(--dur-2) ease, border-color var(--dur-2) ease;
}
.site-footer__langlist a[aria-current="true"] { border-color: var(--gold); background: var(--gold); color: var(--ink); font-weight: var(--fw-strong); }
@media (hover: hover) and (pointer: fine) {
  .site-footer__langlist a:not([aria-current="true"]):hover { background: var(--white-a16); border-color: var(--white-a40); }
}
.site-footer__langs:focus { outline: none; }

.site-footer__base {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: .5rem 2rem;
  padding-block-start: 1.25rem;
  border-block-start: 1px solid var(--white-a24);
  color: var(--on-forest-muted);
  font-size: var(--fs-small);
}
.site-footer__base p { max-inline-size: none; }

/* ─────────────────────────────── 10 Panels, petal rows and cards ──
   Panel: a large flat colour field, 28px corners (20px on phones).
   <div class="panel panel--clay"> … </div>
   Solid: forest · gold · clay · blue · plum · sage.   Mist: mist-forest … mist-sage.   Also white, bone.
   panel--leaf / panel--leaf-flip round two opposite corners far more, like the leaf frame.
   Vary panels by role. Do not chop a section into rows of identical cards. */

.panel {
  position: relative;
  padding: clamp(1.5rem, 1rem + 2.6vw, 3.25rem);
  border-radius: var(--r-panel);
  background: var(--bg);
  color: var(--fg);
}
.panel--snug { padding: clamp(1.25rem, 1rem + 1.2vw, 2rem); }
.panel--leaf { border-start-start-radius: clamp(3.5rem, 2rem + 8vw, 8rem); border-end-end-radius: clamp(3.5rem, 2rem + 8vw, 8rem); }
.panel--leaf-flip { border-start-end-radius: clamp(3.5rem, 2rem + 8vw, 8rem); border-end-start-radius: clamp(3.5rem, 2rem + 8vw, 8rem); }
.panel > * + * { margin-block-start: var(--flow, 1rem); }
.panel > .petal-rows, .panel > .cluster, .panel > .btn { margin-block-start: 1.5rem; }

/* Petal rows: every list is a stack of tinted rows, each starting with a small petal.
   On a light ground the petals run through the six colours of the mark in order; on a solid colour
   they are the one colour that shows. A c- class on the list or on a row fixes the colour.
   <ul class="petal-rows" role="list"><li>Learn to operate the fundus camera</li> … </ul>
   Rich rows: <li><strong>Title</strong><span>One line about it.</span></li> with class petal-rows--rich */
.petal-rows { display: grid; gap: .6rem; }
.petal-rows > li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: .9rem;
  padding: .9rem 1.15rem;
  border-radius: var(--r-row);
  background: var(--row);
  max-inline-size: none;
}
.petal-rows > li::before {
  content: "";
  block-size: 1.3rem;
  aspect-ratio: 20.648 / 45.125;
  margin-block-start: calc((1lh - 1.3rem) / 2);
  background: var(--p1);
  -webkit-mask: var(--petal-mask) center / 100% 100% no-repeat;
  mask: var(--petal-mask) center / 100% 100% no-repeat;
}
.petal-rows > li:nth-child(6n + 2)::before { background: var(--p2); }
.petal-rows > li:nth-child(6n + 3)::before { background: var(--p3); }
.petal-rows > li:nth-child(6n + 4)::before { background: var(--p4); }
.petal-rows > li:nth-child(6n + 5)::before { background: var(--p5); }
.petal-rows > li:nth-child(6n)::before { background: var(--p6); }
.petal-rows:is(.c-forest, .c-gold, .c-clay, .c-blue, .c-plum, .c-sage) > li::before,
.petal-rows > li:is(.c-forest, .c-gold, .c-clay, .c-blue, .c-plum, .c-sage)::before { background: var(--c); }
.petal-rows--rich > li > * { grid-column: 2; }
.petal-rows--rich > li > :first-child { color: var(--heading); font-weight: var(--fw-strong); }
.petal-rows--rich > li > :not(:first-child) { color: var(--fg-muted); }
.petal-rows--plain > li { padding-inline: 0; background: none; }

/* Card: one event, one story. The whole card is the link; the title carries it.
   <article class="card c-clay">
     <div class="frame frame--leaf" data-reveal="leaf">{{ picture(slug, { sizes: '…' }) }}</div>
     <p class="card__meta">11 October 2025</p>
     <h3 class="card__title"><a href="…">Nurture Our Future at the Legislative Council</a></h3>
     <p>One or two sentences.</p>
   </article>
   card--panel puts it on a white panel. */
.card { position: relative; display: grid; align-content: start; gap: .7rem; }
.card > .frame, .card > .figure { margin-block-end: .5rem; }
.card__meta {
  display: flex;
  align-items: center;
  gap: .6rem;
  max-inline-size: none;
  color: var(--fg-muted);
  font-size: var(--fs-small);
  font-weight: var(--fw-medium);
  line-height: var(--lh-ui);
}
.card__meta::before {
  content: "";
  flex: none;
  block-size: 1.1rem;
  aspect-ratio: 20.648 / 45.125;
  background: var(--c);
  -webkit-mask: var(--petal-mask) center / 100% 100% no-repeat;
  mask: var(--petal-mask) center / 100% 100% no-repeat;
}
.card__title { font-size: var(--fs-sub); }
.card__title > a { color: inherit; text-decoration: none; }
.card__title > a::after { content: ""; position: absolute; inset: 0; border-radius: var(--r-row); }
.card__title > a:focus-visible { outline: none; }
.card__title > a:focus-visible::after { outline: 3px solid var(--focus); outline-offset: 6px; }
.card > p:not(.card__meta) { color: var(--fg-muted); }
.card--panel { padding: clamp(1.1rem, .9rem + 1vw, 1.75rem); border-radius: var(--r-panel); background: var(--white); }
@media (hover: hover) and (pointer: fine) {
  .card:has(.card__title > a:hover) .card__title { text-decoration: underline; text-decoration-thickness: .08em; text-underline-offset: var(--underline-offset); }
}

/* ──────────────────────────────── 11 Photo frames, figures and plates ──
   Photographs live in the logo's own shapes, never in small-radius rectangles.
   <figure class="figure c-forest">
     <div class="frame frame--leaf" data-reveal="leaf">{{ picture('2026-09-22-caritas-camera-01', { sizes: '(min-width: 56rem) 40vw, 92vw' }) }}</div>
     <figcaption>{{ caption('2026-09-22-caritas-camera-01') }}</figcaption>
   </figure>
   frame--petal       the petal of the mark, tip up (portraits, details, feature moments). True ratio, about 3:7.
   frame--petal-60 … -300   the same petal turned in 60 degree steps, as it lies in the mark.
   frame--leaf        a rectangle with two opposite corners fully rounded (groups, wide photographs). 3:2.
   frame--leaf-flip   its mirror, for pairs. (In right-to-left pages the two swap by themselves.)
   frame--rim         a thin rim of the petal colour round the shape (set c-… on the frame or the figure).
   The shapes are masks drawn by the art producer (src/img/art/mask-*.svg), stretched to the frame.
   Ratio: frame--square · --portrait (4/5) · --landscape (4/3) · --wide (3/2) · --tall (3/5), or --ar on the frame.
   Every photograph carries its dated caption. */

.frame {
  position: relative;
  aspect-ratio: var(--ar, 4 / 5);
  overflow: hidden;
  isolation: isolate;
}
.frame > picture, .frame > img { display: block; inline-size: 100%; block-size: 100%; }
.frame img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  object-position: var(--focal-x, 50%) var(--focal-y, 50%);
  background: var(--ph, transparent);
}
.frame--petal, [class*="frame--petal-"] {
  --ar: 20.648 / 45.125;   /* the petal's true proportion */
  -webkit-mask: var(--mask) center / 100% 100% no-repeat;
  mask: var(--mask) center / 100% 100% no-repeat;
}
.frame--petal { --mask: url("../img/art/mask-petal.svg"); }
/* The same petal as it lies in the mark, turned in 60 degree steps (clockwise from the top one). */
.frame--petal-60 { --mask: url("../img/art/mask-petal-60.svg"); --ar: 40.171 / 27.123; }
.frame--petal-120 { --mask: url("../img/art/mask-petal-120.svg"); --ar: 40.171 / 27.123; }
.frame--petal-180 { --mask: url("../img/art/mask-petal-180.svg"); }
.frame--petal-240 { --mask: url("../img/art/mask-petal-240.svg"); --ar: 40.171 / 27.123; }
.frame--petal-300 { --mask: url("../img/art/mask-petal-300.svg"); --ar: 40.171 / 27.123; }
.frame--leaf, .frame--leaf-flip {
  --ar: 3 / 2;             /* the ratio the leaf is drawn at: its two corners are true quarter circles */
  -webkit-mask: var(--mask) center / 100% 100% no-repeat;
  mask: var(--mask) center / 100% 100% no-repeat;
}
.frame--leaf { --mask: url("../img/art/mask-leaf.svg"); }
.frame--leaf-flip { --mask: url("../img/art/mask-leaf-flip.svg"); }
/* A rim of the petal colour round the photograph, following the shape: it keeps the outline where a
   picture is pale at its edge (white walls on a bone page) and while the picture loads. Needs a c- class. */
.frame--rim { background: var(--c); }
.frame--rim > picture {
  position: absolute;
  inset: var(--rim, 5px);
  inline-size: auto;
  block-size: auto;
  -webkit-mask: var(--mask) center / 100% 100% no-repeat;
  mask: var(--mask) center / 100% 100% no-repeat;
}
.frame.frame--square { --ar: 1; }
.frame.frame--portrait { --ar: 4 / 5; }
.frame.frame--landscape { --ar: 4 / 3; }
.frame.frame--wide { --ar: 3 / 2; }
.frame.frame--tall { --ar: 3 / 5; }      /* a fuller petal: more of the photograph, still clearly the petal */

.figure { display: grid; gap: .9rem; }
.figure > figcaption {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: .7rem;
  max-inline-size: 30em;
  color: var(--fg-muted);
  font-size: var(--fs-small);
  line-height: max(1.5, calc(var(--lh-text) - .15));   /* 1.5 in Latin and Cyrillic; taller where the script needs it */
}
.figure > figcaption::before {
  content: "";
  block-size: 1.1rem;
  aspect-ratio: 20.648 / 45.125;
  margin-block-start: calc((1lh - 1.1rem) / 2);
  background: var(--c);
  -webkit-mask: var(--petal-mask) center / 100% 100% no-repeat;
  mask: var(--petal-mask) center / 100% 100% no-repeat;
}
.figure--center > figcaption { justify-self: center; }

/* Two photographs that lean together: a leaf and its mirror.
   <div class="frame-pair" data-reveal="gather">
     <figure class="figure"><div class="frame frame--leaf">…</div><figcaption>…</figcaption></figure>
     <figure class="figure"><div class="frame frame--leaf-flip">…</div><figcaption>…</figcaption></figure>
   </div> */
.frame-pair { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); align-items: start; isolation: isolate; }
.frame-pair > :first-child { grid-column: 1 / span 8; grid-row: 1; }
.frame-pair > :last-child {
  grid-column: 6 / -1;
  grid-row: 1;
  margin-block-start: 42%;
  z-index: 1;
  /* a rim of the ground colour round the leaf's own outline (a box-shadow would be cut by the mask) */
  filter: drop-shadow(8px 0 0 var(--bg)) drop-shadow(-8px 0 0 var(--bg)) drop-shadow(0 8px 0 var(--bg)) drop-shadow(0 -8px 0 var(--bg));
}
.frame-pair > :first-child > figcaption { max-inline-size: 56%; }

/* Plate: an event that has no photograph. A flat colour leaf in the event's colour carrying the
   date as large type and an icon medallion. Dignified, never a grey placeholder.
   <div class="frame frame--leaf plate c-clay" data-reveal="leaf">
     <span class="medallion medallion--white">{{ icon('ev-climbing') }}</span>
     <p class="plate__date">26 August 2025</p>
   </div>
   The medallion and the date sit in the leaf's two square corners (they change sides with leaf-flip). */
.plate {
  display: grid;
  align-content: space-between;
  justify-items: start;
  gap: 1rem;
  padding: clamp(1.25rem, 7%, 2.5rem);
  background: var(--c);
  color: var(--c-on);
}
.plate > .medallion { justify-self: end; }
.plate.frame--leaf-flip { justify-items: end; text-align: end; }
.plate.frame--leaf-flip > .medallion { justify-self: start; }
.plate__date {
  max-inline-size: 9em;
  color: inherit;
  font-family: var(--font-display);
  font-size: var(--fs-section);
  font-weight: var(--fw-hero);
  line-height: var(--lh-display);
  letter-spacing: var(--tracking-display);
  text-wrap: balance;
}

/* ──────────────────────────── 12 Ghost numerals, stats and steps ──
   Ghost numeral: very large, low contrast, behind the content. ONLY on real sequences and years of the journey.
   <div class="has-ghost"><span class="ghost-num" aria-hidden="true">2025</span> … </div> */

.has-ghost { position: relative; isolation: isolate; }
.ghost-num {
  position: absolute;
  inset-block-start: var(--ghost-y, 0em);
  inset-inline-start: var(--ghost-x, -.03em);
  z-index: -1;
  color: var(--ghost);
  font-family: var(--font-latin);
  font-size: var(--fs-ghost);
  font-weight: 800;
  line-height: .8;
  letter-spacing: -0.04em;   /* lint-ok: Western digits only */
  font-variant-numeric: lining-nums;
  white-space: nowrap;
  pointer-events: none;
  user-select: none;
}
.ghost-num--end { inset-inline: auto var(--ghost-x, -.03em); }
.panel.has-ghost { overflow: clip; }
.panel.has-ghost > .ghost-num { --ghost-y: .14em; --ghost-x: .12em; }

/* Stat: a counted number with its label. True numbers only. The final value is in the HTML;
   core.js counts up to it.
   <div class="stat c-clay"><p class="stat__num"><span data-count>15</span></p><p class="stat__label">languages on this site</p></div>
   "more than 20" is written <span data-count>20</span>+ */
.stat { display: grid; gap: .35rem; align-content: start; }
.stat__num {
  max-inline-size: none;
  color: var(--stat, var(--heading));
  font-family: var(--font-latin);
  font-size: var(--fs-stat);
  font-weight: 800;
  line-height: .95;
  letter-spacing: -0.035em;   /* lint-ok: Western digits only */
  font-variant-numeric: tabular-nums lining-nums;
  white-space: nowrap;
  direction: ltr;               /* "20+" stays "20+" in Urdu: Western digits, the plus after them */
  unicode-bidi: isolate;
  text-align: -webkit-match-parent;   /* Chromium knows only the prefixed keyword; Safari and Firefox take the next line */
  text-align: match-parent;
}
.stat__label { max-inline-size: 16em; color: var(--fg-muted); font-size: var(--fs-body); line-height: 1.45; text-wrap: balance; }
.stat:is(.c-forest, .c-gold, .c-clay, .c-blue, .c-plum, .c-sage) { --stat: var(--c-deep); }   /* light grounds only */
.stat--row { grid-template-columns: auto minmax(0, 1fr); align-items: baseline; column-gap: 1rem; }
.stat--sm .stat__num { font-size: clamp(2.5rem, 2rem + 2.2vw, 3.75rem); }

/* Steps: for a REAL sequence only (the four steps of a screening day).
   <ol class="steps" role="list">
     <li class="step"><p class="step__label">Step 1</p><h3 class="step__title">Registration</h3><p>…</p></li> …
   </ol>
   The numeral is drawn by a CSS counter (always Western digits); a line with a petal joins the steps. */
.steps {
  counter-reset: step;
  display: grid;
  gap: clamp(2rem, 4vw, 3rem) clamp(1.5rem, 3vw, 2.5rem);
  grid-template-columns: repeat(auto-fit, minmax(min(14.5rem, 100%), 1fr));
}
.step {
  counter-increment: step;
  position: relative;
  display: grid;
  align-content: start;
  gap: .6rem;
  padding-block-start: 3.4rem;
  border-block-start: 3px solid var(--rule);
  isolation: isolate;
}
.step::before {
  content: counter(step, decimal);
  position: absolute;
  inset-block-start: .35rem;
  inset-inline-end: 0;
  z-index: -1;
  color: var(--ghost);
  font-family: var(--font-latin);
  font-size: clamp(5.5rem, 4.5rem + 4vw, 8.5rem);
  font-weight: 800;
  line-height: .85;
  letter-spacing: -0.04em;   /* lint-ok: Western digits only */
  pointer-events: none;
}
.step::after {
  content: "";
  position: absolute;
  inset-block-start: -1.55rem;
  inset-inline-start: 0;
  block-size: 1.5rem;
  aspect-ratio: 20.648 / 45.125;
  background: var(--p1);
  -webkit-mask: var(--petal-mask) center / 100% 100% no-repeat;
  mask: var(--petal-mask) center / 100% 100% no-repeat;
}
.step:nth-child(6n + 2)::after { background: var(--p2); }
.step:nth-child(6n + 3)::after { background: var(--p3); }
.step:nth-child(6n + 4)::after { background: var(--p4); }
.step:nth-child(6n + 5)::after { background: var(--p5); }
.step:nth-child(6n)::after { background: var(--p6); }
.step__label { color: var(--fg-muted); font-size: var(--fs-small); font-weight: var(--fw-strong); line-height: var(--lh-ui); }
.step__title { font-size: var(--fs-sub); }
.step > p:not(.step__label) { color: var(--fg-muted); }

/* ───────────────────────────── 13 FAQ, tabs and segmented control ──
   FAQ: native <details>, so it works without JavaScript; core.js animates the height.
   <div class="faq">
     <details class="faq__item">
       <summary class="faq__q"><span>Who are you?</span><span class="faq__mark" aria-hidden="true">{{ icon('plus') }}</span></summary>
       <div class="faq__a"><p>…</p></div>
     </details> …
   </div> */

.faq { display: grid; gap: .6rem; }
.faq__item { border-radius: var(--r-row); background: var(--row); }
.faq__q {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 1rem;
  min-block-size: 4.25rem;
  padding: .9rem 1rem .9rem 1.4rem;
  border-radius: var(--r-row);
  color: var(--heading);
  font-family: var(--font-display);
  font-size: var(--fs-lead);
  font-weight: var(--fw-sub);
  line-height: var(--lh-sub);
}
.faq__mark {
  display: grid;
  place-items: center;
  inline-size: 2.75rem;
  block-size: 2.75rem;
  border-radius: 50%;
  background: var(--bg);
  color: var(--heading);
  transition: rotate var(--dur-3) var(--ease-out), background-color var(--dur-2) ease, color var(--dur-2) ease;
}
.faq__item[open] > .faq__q > .faq__mark, .faq__item.is-opening > .faq__q > .faq__mark { rotate: 45deg; background: var(--heading); color: var(--bg); }
.faq__item.is-closing > .faq__q > .faq__mark { rotate: 0deg; background: var(--bg); color: var(--heading); }
.faq__a { padding-inline: 1.4rem; overflow: hidden; }
.faq__a::after { content: ""; display: block; block-size: 1.35rem; }
.faq__a > * + * { margin-block-start: .8em; }

/* Segmented control and tabs.
   <div class="tabs" data-tabs>
     <div class="segmented" role="tablist" aria-label="…">
       <button class="segmented__btn" type="button" role="tab" id="t-a" aria-controls="p-a" aria-selected="true">Schools</button>
       <button class="segmented__btn" type="button" role="tab" id="t-b" aria-controls="p-b" aria-selected="false">Companies</button>
     </div>
     <div class="tabs__panel" role="tabpanel" id="p-a" aria-labelledby="t-a" tabindex="0">…</div>
     <div class="tabs__panel" role="tabpanel" id="p-b" aria-labelledby="t-b" tabindex="0">…</div>
   </div>
   Without JavaScript the tab list is hidden and every panel shows, one under the other. */
.segmented {
  position: relative;
  display: inline-flex;
  flex-wrap: wrap;
  gap: 2px;
  max-inline-size: 100%;
  padding: 4px;
  border-radius: 1.9rem;
  background: var(--row);
  isolation: isolate;
}
.segmented__btn {
  position: relative;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: var(--target);
  padding-inline: 1.25rem;
  border-radius: var(--r-full);
  color: var(--heading);
  font-weight: var(--fw-medium);
  line-height: var(--lh-ui);
  transition: color var(--dur-2) ease, scale var(--dur-1) var(--ease-out);
}
.segmented__btn:active { scale: .97; }
.segmented__btn:is([aria-selected="true"], [aria-pressed="true"]) { color: var(--btn-fg); font-weight: var(--fw-strong); }
.segmented:not(.has-thumb) .segmented__btn:is([aria-selected="true"], [aria-pressed="true"]) { background: var(--btn-bg); }
.segmented__thumb {
  position: absolute;
  inset-block-start: 0;
  left: 0;   /* lint-ok: positioned by JavaScript from measured physical offsets */
  z-index: 0;
  border-radius: var(--r-full);
  background: var(--btn-bg);
  transition: transform var(--dur-3) var(--ease-out), inline-size var(--dur-3) var(--ease-out);
  pointer-events: none;
}
html:not(.js) [role="tablist"] { display: none; }
.tabs__panel { margin-block-start: 1.5rem; }
.tabs__panel:focus-visible { outline-offset: 6px; }

/* ───────────────────────────────────── 14 Forms, chips and the toast ──
   There is no backend: a form opens the visitor's own email app with what they typed
   (core.js, data-mailto) and says so in a toast. Without JavaScript the form's action does the same.
   <form class="form" action="mailto:{{ site.org.email }}" method="post" enctype="text/plain"
         data-mailto="{{ site.org.email }}" data-mailto-subject="…" data-toast="…">
     <div class="field">
       <label class="field__label" for="c-name">Your name</label>
       <input class="field__input" id="c-name" name="name" type="text" autocomplete="name" required>
     </div>
     <div class="field">
       <label class="field__label" for="c-msg">Your message</label>
       <textarea class="field__input" id="c-msg" name="message" rows="5" required></textarea>
       <p class="field__hint">…</p>
     </div>
     <fieldset class="field">
       <legend class="field__label">Amount</legend>
       <div class="chips">
         <label class="chip"><input type="radio" name="amount" value="HK$100" checked><span>HK$100</span></label> …
       </div>
     </fieldset>
     <button class="btn btn--primary" type="submit">Open my email app</button>
   </form> */

.form { display: grid; gap: 1.35rem; }
.field { display: grid; gap: .45rem; }
.field__label {
  color: var(--heading);
  font-size: 1.0625rem;
  font-weight: var(--fw-strong);
  line-height: var(--lh-ui);
}
.field__input {
  inline-size: 100%;
  min-block-size: 3.25rem;
  padding: .75rem 1rem;
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-field);
  background: var(--field);
  color: var(--ink);
  font-size: 1.0625rem;
  line-height: var(--lh-ui);
  transition: border-color var(--dur-2) ease;
}
textarea.field__input { min-block-size: 8.5rem; line-height: var(--lh-text); resize: vertical; }
.field__input::placeholder { color: var(--slate); opacity: 1; }
.field__input:focus-visible { border-color: var(--forest); }
.field__hint { color: var(--fg-muted); font-size: var(--fs-small); }
/* core.js adds this under a field that is empty or malformed, in the page's own words (data-error). */
.field.is-invalid .field__input { border-color: var(--clay-deep); border-width: 2px; }
.field__error {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: .55rem;
  max-inline-size: none;
  color: var(--error, var(--clay-deep));
  font-size: var(--fs-small);
  font-weight: var(--fw-strong);
}
.field__error::before {
  content: "";
  block-size: 1rem;
  aspect-ratio: 20.648 / 45.125;
  margin-block-start: calc((1lh - 1rem) / 2);
  background: currentColor;
  -webkit-mask: var(--petal-mask) center / 100% 100% no-repeat;
  mask: var(--petal-mask) center / 100% 100% no-repeat;
}
html:not(.js) [data-copy] { display: none; }
.form__actions { display: flex; flex-wrap: wrap; align-items: center; gap: .75rem 1.25rem; }
.form__note { color: var(--fg-muted); font-size: var(--fs-small); }

/* Chips: a small set of choices (giving amounts, topics). Real radio buttons or checkboxes inside labels. */
.chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.chip { position: relative; display: inline-flex; }
.chip > input { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; margin: 0; opacity: 0; cursor: pointer; }
.chip > span {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-block-size: var(--btn-h);
  min-inline-size: 5.25rem;
  padding-inline: 1.25rem;
  border: 1.5px solid var(--line-strong);
  border-radius: var(--r-full);
  background: var(--field);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 1.0625rem;
  font-weight: var(--fw-display);
  line-height: var(--lh-ui);
  transition: background-color var(--dur-2) ease, border-color var(--dur-2) ease, color var(--dur-2) ease, scale var(--dur-1) var(--ease-out);
}
.chip > input:active + span { scale: .97; }
.chip > input:checked + span { border-color: var(--forest); background: var(--forest); color: var(--white); }
.chip > input:focus-visible + span { outline: 3px solid var(--focus); outline-offset: 3px; }
.chip--gold > input:checked + span { border-color: var(--gold); background: var(--gold); color: var(--ink); }

/* Toast: one polite line at the foot of the screen (core.js: DT.toast). */
.toast-region {
  position: fixed;
  inset-inline: 0;
  inset-block-end: calc(1rem + var(--dock-h, 0px) + env(safe-area-inset-bottom));
  z-index: var(--z-toast);
  display: grid;
  justify-items: center;
  gap: .5rem;
  padding-inline: 1rem;
  pointer-events: none;
}
.toast {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: .8rem;
  max-inline-size: min(100%, 34rem);
  padding: .95rem 1.3rem;
  border-radius: 1.25rem;
  background: var(--forest-deep);
  color: var(--white);
  font-weight: var(--fw-medium);
  line-height: max(1.45, calc(var(--lh-text) - .15));
  box-shadow: var(--shadow);
  pointer-events: auto;
  opacity: 0;
  transform: translateY(1.25rem);
  transition: opacity var(--dur-2) ease, transform var(--dur-3) var(--ease-out);
}
.toast::before {
  content: "";
  block-size: 1.2rem;
  aspect-ratio: 20.648 / 45.125;
  margin-block-start: calc((1lh - 1.2rem) / 2);
  background: var(--gold);
  -webkit-mask: var(--petal-mask) center / 100% 100% no-repeat;
  mask: var(--petal-mask) center / 100% 100% no-repeat;
}
.toast__text { max-inline-size: none; }
.toast__title { display: block; font-weight: var(--fw-strong); }
.toast.is-in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) { .toast { transform: none; transition: opacity var(--dur-2) ease; } }

/* ──────────────────────────────────────── 15 Monograms and people ──
   Monogram: a person is initials in a circle (a core). No portraits, no stock faces.
   <span class="monogram c-forest" aria-hidden="true" data-reveal="pop">MK</span>
   Person: name and role in type only.
   <div class="person c-forest">
     <span class="monogram" aria-hidden="true" data-reveal="pop">{{ site.people[0].monogram }}</span>
     <h3 class="person__name">Michael Kalyan</h3>
     <p class="person__role">Project Lead</p>
   </div> */

.monogram {
  --size: 5.5rem;
  flex: none;
  display: inline-grid;
  place-items: center;
  inline-size: var(--size);
  block-size: var(--size);
  border-radius: 50%;
  background: var(--c);
  color: var(--c-on);
  font-family: var(--font-latin);
  font-size: calc(var(--size) * .36);
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0em;
  white-space: nowrap;
}
.monogram--long { font-size: calc(var(--size) * .25); }
.monogram--lg { --size: 7.5rem; }
.monogram--sm { --size: 4rem; }
.monogram--white { background: var(--white); color: var(--c-deep); }

.person { display: grid; justify-items: start; gap: .35rem; }
.person > .monogram { margin-block-end: .75rem; }
.person__name { font-size: var(--fs-sub); }
.person__role { color: var(--c-deep); font-size: var(--fs-lead); font-weight: var(--fw-strong); line-height: var(--lh-sub); }

/* ───────────────────────────────── 16 Marquee, carousel and rotator ──
   Names, not logos: the organisations we have worked alongside, as a line of large type whose
   speed follows the scroll (core.js). Without JavaScript, or under reduced motion, it is simply a wrapping list.
   <div class="marquee" data-marquee>
     <ul class="marquee__list" role="list"><li>Fun-Tastic</li> <li>HKCECES</li> … </ul>
     <div class="container">
       <button class="round-btn marquee__toggle" type="button" data-motion-toggle
               data-label-pause="{{ t('a11y.motion.pause') }}" data-label-play="{{ t('a11y.motion.play') }}"
               aria-label="{{ t('a11y.motion.pause') }}">{{ icon('pause', { class: 'icon--pause' }) }}{{ icon('play', { class: 'icon--play' }) }}</button>
     </div>
   </div>
   Place it outside .container: the moving line runs edge to edge, the still list lines up with the container. */

.marquee { position: relative; }
.marquee__viewport { overflow: clip; padding-block: .25em; }
.marquee__list { display: flex; flex-wrap: wrap; gap: .75rem 2rem; inline-size: min(100% - 2 * var(--gutter), var(--container)); margin-inline: auto; }
.marquee__list > li {
  display: inline-flex;
  align-items: center;
  gap: 2rem;
  max-inline-size: none;
  color: var(--heading);
  font-family: var(--font-display);
  font-size: var(--fs-sub);
  font-weight: var(--fw-sub);
  line-height: var(--lh-sub);
}
.marquee__list > li::before {
  content: "";
  flex: none;
  block-size: .9em;
  aspect-ratio: 20.648 / 45.125;
  background: var(--p1);
  -webkit-mask: var(--petal-mask) center / 100% 100% no-repeat;
  mask: var(--petal-mask) center / 100% 100% no-repeat;
}
.marquee__list > li:nth-child(6n + 2)::before { background: var(--p2); }
.marquee__list > li:nth-child(6n + 3)::before { background: var(--p3); }
.marquee__list > li:nth-child(6n + 4)::before { background: var(--p4); }
.marquee__list > li:nth-child(6n + 5)::before { background: var(--p5); }
.marquee__list > li:nth-child(6n)::before { background: var(--p6); }
.marquee.is-running .marquee__track { display: flex; inline-size: max-content; will-change: transform; }
.marquee.is-running .marquee__list { flex: none; flex-wrap: nowrap; inline-size: auto; margin-inline: 0; white-space: nowrap; padding-inline-end: 2rem; }
.marquee.is-running .marquee__list > li { font-size: var(--fs-section); font-weight: var(--fw-display); line-height: var(--lh-display); }
.marquee__toggle { display: none; margin-block-start: 1.25rem; }
.marquee.is-running .marquee__toggle { display: inline-grid; }
.marquee__toggle[aria-pressed="true"] { background: var(--btn-line); color: var(--bg); }

/* Carousel: a snapping rail with previous / next, usable by swipe, wheel, keyboard and buttons.
   Add data-pin and, on desktop with a fine pointer, the rail is pinned and moved by the vertical scroll instead.
   <div class="carousel" data-carousel role="group" aria-roledescription="{{ t('a11y.carousel.role') }}" aria-label="…">
     <div class="carousel__viewport" tabindex="0">
       <ul class="carousel__rail" role="list">
         <li class="carousel__item" aria-roledescription="{{ t('a11y.carousel.slide') }}">…</li> …
       </ul>
     </div>
     <div class="carousel__nav container">
       <button class="round-btn" type="button" data-carousel-prev aria-label="{{ t('a11y.carousel.prev') }}">{{ icon('chevron', { class: 'icon--back' }) }}</button>
       <button class="round-btn" type="button" data-carousel-next aria-label="{{ t('a11y.carousel.next') }}">{{ icon('chevron') }}</button>
     </div>
   </div>
   Place it outside .container: the rail lines its first item up with the container edge by itself. */
.carousel { --item: min(82vw, 24rem); --gap: clamp(1rem, 2vw, 1.75rem); --edge: max(var(--gutter), (100% - var(--container)) / 2); }
.carousel__viewport {
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--edge);
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.carousel__viewport::-webkit-scrollbar { display: none; }
.carousel__viewport:focus-visible { outline-offset: -3px; }
.carousel__rail { display: flex; gap: var(--gap); inline-size: max-content; padding-inline: var(--edge); }
.carousel__item { flex: none; inline-size: var(--item); max-inline-size: none; scroll-snap-align: start; }
.carousel__nav { display: flex; gap: .6rem; margin-block-start: 1.75rem; }
html:not(.js) .carousel__nav { display: none; }
.carousel.is-pinned .carousel__viewport { overflow-x: clip; overflow-y: visible; scroll-snap-type: none; }   /* the rail runs out past the viewport's ends; it must not widen the page */
.carousel.is-pinned .carousel__rail { will-change: transform; }

/* Rotator: one line that changes (hello in fifteen languages). The first child is the real text; the
   others are decoration and say so (aria-hidden).
   <span class="rotator" data-rotator="2.6">
     <span lang="en">Hello</span><span lang="zh-Hant-HK" aria-hidden="true">你好</span><span lang="ur" dir="rtl" aria-hidden="true">السلام علیکم</span> …
   </span>
   Every line shares one cell, so the widest one sets the width and nothing jumps. Without JavaScript
   or with reduced motion only the first line shows. */
.rotator { display: inline-grid; vertical-align: bottom; overflow: clip; overflow-clip-margin: .4em; }
.rotator > * { grid-area: 1 / 1; white-space: nowrap; }
.rotator > [aria-hidden="true"] { visibility: hidden; }
.rotator.is-ready > :is(.is-current, .is-leaving) { visibility: visible; }

/* ───────────────────────────────────────────────────── 17 Page hero ──
   Page hero for the inner pages: a tinted field, the page title, one lead, optional actions, and on
   the end side an art slot (a framed photograph, or a bloom from the signature kit).
   <section class="page-hero section--mist-sage">
     <div class="container page-hero__inner">
       <div class="page-hero__text">
         <h1 class="h-page" data-reveal="lines">{{ th('about.hero.title') }}</h1>
         <p class="lead" data-reveal="fade">{{ t('about.hero.lead') }}</p>
         <div class="cluster"> buttons </div>
       </div>
       <div class="page-hero__art"> … </div>
     </div>
   </section>
   Its lower edge is the petal seam into the bone page (set --hero-next if the next section is not bone). */

.page-hero {
  position: relative;
  padding-block: clamp(2.5rem, 1.6rem + 4.4vw, 6rem) calc(clamp(2.5rem, 1.6rem + 4.4vw, 6rem) + var(--seam-h));
  background: var(--bg);
  color: var(--fg);
  overflow: clip;
}
.page-hero::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: -1px;
  block-size: var(--seam-h);
  background: var(--hero-next, var(--bone));
  -webkit-mask: url("../img/art/seam-petal.svg") center / 100% 100% no-repeat;
  mask: url("../img/art/seam-petal.svg") center / 100% 100% no-repeat;
  transform: scaleX(var(--dir));
}
main > .page-hero:last-child::after { content: none; }
.page-hero__inner { position: relative; z-index: 1; display: grid; gap: 2rem clamp(2rem, 5vw, 5rem); align-items: center; }
.page-hero__text { display: grid; gap: 1.25rem; justify-items: start; }
.page-hero__text > .cluster { margin-block-start: .5rem; }
.page-hero__art { inline-size: 100%; max-inline-size: 26rem; }
.page-hero__art > .mark { inline-size: min(100%, 20rem); block-size: auto; margin-inline: auto; }
@media (min-width: 56rem) {
  .page-hero__inner { grid-template-columns: minmax(0, 7fr) minmax(0, 5fr); }
  .page-hero__inner:not(:has(.page-hero__art)) { grid-template-columns: minmax(0, 1fr); }
  .page-hero__art { justify-self: end; }
}
@media (max-width: 55.99rem) {
  .page-hero__art > .mark { inline-size: min(60%, 12rem); margin-inline: 0; }
}

/* The mark drawn inline ({{> mark}}): the real geometry, so its petals can move. */
.mark { display: block; overflow: visible; }

/* ───────────────────────────────────────────── 18 Motion helpers ──
   Markup written by core.js while a heading is revealed, and the pause button's icon swap. */

.dt-line, .dt-word { clip-path: inset(calc(var(--mask-pad) * -1) -100vw calc(var(--mask-pad) * -1.1) -100vw); }
.dt-line { display: block; }
.dt-word { display: inline-block; vertical-align: top; }
.dt-line__in, .dt-word__in { display: block; will-change: transform; }
.dt-word__in { display: inline-block; }
[data-count] { font-variant-numeric: tabular-nums lining-nums; }
[data-parallax], [data-magnetic], [data-turn] { will-change: transform; }
[data-motion-toggle] .icon--play, [data-motion-toggle][aria-pressed="true"] .icon--pause { display: none; }
[data-motion-toggle][aria-pressed="true"] .icon--play { display: block; }

}   /* end @layer components */

/* Keyframes live outside the layer (they are global either way). */
@keyframes dt-petal-grow {
  from { transform: scaleX(.2); opacity: .4; }
  to { transform: none; opacity: 1; }
}
@keyframes dt-overlay-bloom {
  0% { transform: scale(.1) rotate(0deg); opacity: 0; }
  12% { opacity: .9; }
  100% { transform: scale(6) rotate(60deg); opacity: 0; }
}
@keyframes dt-pre-petal {
  0% { transform: translateY(-40px) scale(.6); opacity: 0; }
  45% { opacity: 1; }
  100% { transform: none; opacity: 1; }
}
@keyframes dt-pre-core {
  from { transform: scale(.3); opacity: 0; }
  to { transform: none; opacity: 1; }
}
@keyframes dt-pre-out {
  to { opacity: 0; visibility: hidden; }
}
