/* ============================================================
   LFFO Home — signature design language v2
   Heritage institution · watchmaker finish · living tree
   ============================================================ */

#lffo-home{position:relative;overflow-x:clip}

/* ---------- Clean white sections ---------- */
/* The old seasonal colour-washes (gold / blue / orange / red radials) were
   built for the dark field; on the white page they read as faint uneven tints
   — a smudged paper rather than a clean one. Removed. Content sections are now
   crisp white, with the cream standing-band and the navy passages carrying the
   rhythm instead. */
.season-summer,
.season-autumn{background:transparent}


/* =========================================================
   HERO
   ========================================================= */
/* The hero is sized to resolve inside one screen. Every vertical element in it
   now carries a vh term alongside its vw term, so on a short-but-wide window
   (a laptop at 900px tall) the type compresses instead of pushing the CTAs and
   the markets band below the fold. svh is used so mobile browser chrome does
   not add a phantom extra screen. */
.hero{
  position:relative;min-height:calc(100svh - 75px);display:flex;align-items:flex-start;
  /* Lifted a step for a brighter, more premium ground. The navy stops all
     move up together and the cool wash from above is strengthened, so the
     hero reads as a lit room rather than a dark one — the leaves and the
     gold both have more to sit against. The ramp between the stops is kept
     the same width, so it brightens without going flat. */
  background:
    radial-gradient(92% 72% at 50% -14%,rgba(150,198,232,.28),transparent 64%),
    linear-gradient(165deg,#1d4068 0%,#24487a 55%,#2b5793 100%);
  color:var(--white);overflow:hidden;
  padding-block:clamp(46px,6.4vh,110px) clamp(34px,4.4vh,88px);
}


/* The old halo — one big static, breathing circle behind the hero — is gone.
   Light in the hero now comes from the drift field itself: each piece in
   js/leaf-fall.js carries its own soft glow, in its own colour, that blooms
   as the piece comes into focus and fades with it. Many small, coloured,
   responsive lights read as premium; one fixed pale-blue disc read as a
   template hero glow. See css/style.css (.lffo-leaf) for the glow itself. */

/* ── The hero canopy is GONE ─────────────────────────────────────────────────
   `.hero-canopy` — the positioned overlay that held the home hero's drifting
   leaves — and its phone-only warm corner glow (`::after`, whose whole
   justification was "light coming through leaves") were removed along with
   the field itself. Section 1 carries no drifting leaves on any page; the
   markup went from index.html and the two spawn calls from
   js/home-effects.js.

   `@keyframes leafGust` STAYS, and is not dead code: it is the shared lean
   that makes a whole field drift together, and `.pres-leaves` below still
   uses it. It is defined here rather than beside that rule only because
   this is where it has always lived. */
@keyframes leafGust{
  0%,100%{transform:translate3d(calc(var(--gust) * -1),0,0)}
  38%    {transform:translate3d(var(--gust),0,0)}
  62%    {transform:translate3d(calc(var(--gust) * .35),0,0)}
}
/* The falling leaf's own box lives in style.css (.lffo-leaf), because the
   interior page heroes carry the same fall and never load this file. The blob
   rules that used to sit here — background, border-radius, mix-blend-mode —
   are gone with the blobs: a leaf is an SVG path now, in front of the ground,
   never multiplied against it.

   The president band takes the same shared gust as the canopy, a beat slower,
   so the two never lean in step. */
.pres-leaves{animation:leafGust 41s ease-in-out infinite;--gust:9px}
@media (prefers-reduced-motion:reduce){.pres-leaves{animation:none}}

/* margin-block:auto centres the copy in a tall viewport but, unlike
   align-items:center, lets the hero GROW when the content is taller than one
   screen instead of overflowing its own box — which mattered because .hero is
   overflow:hidden, so the markets band was being clipped on short windows. */
.hero-inner{position:relative;z-index:2;max-width:940px;margin-block:auto}
.hero-eyebrow{opacity:0;animation:fadeUp .8s var(--ease) .1s forwards}
/* The eyebrow is a single label, so it stays a single row. On a narrow phone
   'THE EUROPEAN FAMILY OFFICE ASSOCIATION' at full tracking overran the width
   and dropped to two lines; the gold rule then drew L→R into a two-row block,
   which read as a wrap, not a sweep. Below 720px the type and tracking ease
   just enough to hold one row down to ~340px, and nowrap guarantees it — the
   rule sweeps across a single line as intended. */
.hero-eyebrow{white-space:nowrap}
@media (max-width:720px){
  .hero-eyebrow{font-size:.63rem;letter-spacing:.1em}
}
@media (max-width:360px){
  .hero-eyebrow{font-size:.58rem;letter-spacing:.07em}
}
/* Eyebrow — the association's positioning line, a gold all-caps label. */
.hero-eyebrow{
  position:relative;z-index:2;
  font-family:var(--sans);font-size:.74rem;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;color:rgba(201,163,78,.88);
}
/* ── Statement cascade ──────────────────────────────────────────────────────
   The association's own three-movement line — Connecting / Shaping / Building —
   set as an engraved cascade rather than a paragraph. Each movement is its own
   row; the leading verb is struck in gold italic serif so the eye reads the
   three verbs as a vertical spine, and the closing "Europe's future" is gilded.
   The stat figures are NOT repeated here — they carry the STANDING section
   directly below. */
.hero-cascade{
  position:relative;z-index:2;margin:20px 0 0;
  /* Same face, style, weight and tracking as the interior page H1s and the
     old hero headline — LFFO Wordmark Italic at 400 with tracking released.
     Colour, not weight, is what separates the gold. */
  font-family:"LFFO Wordmark",var(--serif);font-style:italic;font-weight:400;
  color:rgba(255,255,255,.94);
  font-size:clamp(1.5rem,4.4vw,2.35rem);line-height:1.16;letter-spacing:.004em;
}
.hero-cascade .hc-line{
  display:block;
  opacity:0;transform:translateY(14px);
  animation:fadeUp .8s var(--ease) forwards;
}
.hero-cascade .hc-line:nth-child(1){animation-delay:.14s}
.hero-cascade .hc-line:nth-child(2){animation-delay:.30s}
.hero-cascade .hc-line:nth-child(3){animation-delay:.46s}
.hero-cascade .hc-verb{font-weight:400;color:var(--gold-bright)}
.hero-cascade .hc-key{color:rgba(201,163,78,.9)}
@media (prefers-reduced-motion:reduce){
  .hero-cascade .hc-line{opacity:1;transform:none;animation:none}
}

/* ── Active-in market band ───────────────────────────────────────────────────
   The fourteen markets close the hero. Left-aligned on phones/tablet; centred
   on desktop to sit under the centred masthead composition. Fades in last. */
.hero-countries{
  display:flex;align-items:center;justify-content:flex-start;gap:6px 9px;flex-wrap:wrap;
  margin-top:clamp(24px,4vh,54px);padding-top:clamp(16px,2.4vh,26px);border-top:1px solid var(--line-navy);
  font-size:.8rem;color:rgba(255,255,255,.6);
  opacity:0;animation:fadeUp .9s var(--ease) 1.4s forwards;
}
.hero-countries > span{white-space:nowrap}
.hc-label{color:rgba(223,233,247,.72);font-weight:600;letter-spacing:.14em;text-transform:uppercase;font-size:.68rem;margin-right:6px;white-space:nowrap}
/* Custom separator — a small gold leaf-tip lozenge (one sharp corner, three
   round: the site's single-point leaf motif) between markets. It is drawn on
   the ::before of every market that FOLLOWS another market, so the first and
   last markets never carry one — true at any wrap point. */
.hero-countries .hc-c + .hc-c::before{
  content:"";display:inline-block;vertical-align:middle;
  width:6px;height:6px;margin-right:9px;position:relative;top:-1px;
  background:linear-gradient(135deg,var(--gold-bright),var(--gold));
  border-radius:0 50% 50% 50%;transform:rotate(45deg);
  opacity:.85;
}
@media (prefers-reduced-motion:reduce){
  .hero-countries{animation:none;opacity:1}
}
@media (max-width:720px){
  .hero-cascade{font-size:clamp(1.35rem,7vw,1.8rem)}
}

.hero-title{
  color:var(--white);margin-top:22px;
  font-size:clamp(2.5rem,5.8vw,4.6rem);line-height:1.07;font-weight:600;letter-spacing:-.015em;
}
.hero-title .line{display:block}
.hero-title .sub-line{color:rgba(255,255,255,.92)}
.hero-title .w{display:inline-block;transform:translateY(115%);opacity:0;padding:.4em .3em;margin:-.4em -.3em}
.hero-title .w.show{animation:wordRise .85s cubic-bezier(.22,1,.36,1) forwards}
@keyframes wordRise{to{transform:translateY(0);opacity:1}}
.gilded{color:var(--gold);font-style:italic}

/* ── Hero watermark (the H1 name, ghosted — the monument mark) ──────────
   v3: the FULL association name is now set, as a two-line engraved-monument
   stack anchored to the top of the hero:

       LUXEMBOURG
       FOR  FAMILY  OFFICE

   Line 2 is set smaller with open letter-spacing so the two lines resolve to
   roughly equal optical width — the classic carved-lintel proportion. Nothing
   is visually hidden any more: the whole H1 is real, visible text, which is
   both better SEO and what the mark was always meant to say.

   SIZING IS FIT-DRIVEN, NOT TASTE-DRIVEN. Both lines are sized in vw so the
   longer line ("FOR FAMILY OFFICE", 17 characters) always fits the viewport
   with margin to spare — this is what was clipping letters off the right edge
   on phones before. The rem ceiling caps growth on wide desktops; there is no
   rem floor on the vw term, so it keeps shrinking to fit on narrow screens
   instead of overflowing. */
/* In normal flow at the top of .hero-inner — it reserves its own height, so the
   eyebrow and headline are pushed clear of it by construction rather than by a
   padding value that has to be re-tuned per breakpoint. (The hero is a centred
   flex container, so padding on .hero could never control this gap reliably —
   the content simply re-centred and the collision came back on short, wide
   viewports.) The negative left margin lets it bleed out to the container edge
   so it still reads as a monument behind the copy, not a label above it. */
/* POSITION + SCALE CHANGED (per request), everything else kept: the gold
   gradient, the slow sheen sweep and the lit gold outline on "Family Office"
   all remain. It now sits as a LARGER monument set into the right of the hero,
   vertically placed rather than banner-across-the-top — a backdrop behind the
   copy, which reads on the left. Absolute so it can be a true backdrop; the
   copy (.hero-inner, z-index:2) always sits above it. */
/* ── Hero monument — "key & keyhole" ─────────────────────────────────────
   The full name is a large HOLLOW wordmark (gold hairline outline, empty
   inside): the keyhole. The Section-1 label ("The European Family Office
   Association") is the KEY — a small solid-gold caps line with a lead rule that
   locks it to the top of the keyhole, right-aligned to the same edge so the two
   read as one stacked mark. They never overlap the headline, and — per request
   — nothing here glows or moves. */
.hero-monument{
  position:absolute;z-index:0;top:clamp(58px,12vh,116px);right:clamp(22px,4vw,68px);
  margin:0;display:flex;flex-direction:column;align-items:flex-end;gap:.55em;
  text-align:right;pointer-events:none;white-space:nowrap;
  font-family:var(--serif);text-transform:uppercase;line-height:.9;
}
/* Hollow outline letters with a slow horizontal SHINE SWEEP: the fill is a
   mostly-transparent gradient carrying one soft gold band that travels left to
   right across the whole wordmark, clipped to the glyphs, so a light rakes
   through the outlined name without changing its form. */
.hm-word{
  position:relative;font-weight:700;color:transparent;
  -webkit-text-stroke:1.1px rgba(201,163,78,.6);
  paint-order:stroke fill;
  background-image:linear-gradient(100deg,
    rgba(220,183,99,0) 38%, rgba(233,205,143,.75) 50%, rgba(220,183,99,0) 62%);
  background-size:260% 100%;background-position:130% 0;background-repeat:no-repeat;
  -webkit-background-clip:text;background-clip:text;
  animation:hmSweep 8s linear infinite;
}
.hm-word-2{animation-delay:.9s}
@keyframes hmSweep{
  0%{background-position:135% 0}
  100%{background-position:-35% 0}
}
.hm-word-1{font-size:min(9.4vw,5rem,7vh);letter-spacing:.006em}
.hm-word-2{font-size:min(6.25vw,3.3rem,4.55vh);letter-spacing:.05em;margin-top:.05em}
.hm-for{ -webkit-text-stroke-width:.85px }

/* Family Office — a subtle gold shimmer (a gentle pulse in the stroke) plus a
   scatter of small twinkling sparkles laid over the line. Typography untouched. */
.hm-word-2{animation:hmSweep 8s linear infinite, hmShimmer 4.5s ease-in-out infinite}
@keyframes hmShimmer{
  0%,100%{-webkit-text-stroke-color:rgba(201,163,78,.55)}
  50%{-webkit-text-stroke-color:rgba(240,214,150,.9)}
}
.hm-sparkles{position:absolute;inset:-10% -4%;pointer-events:none}
.hm-sparkles > i{
  position:absolute;left:var(--x);top:var(--y);width:7px;height:7px;transform:translate(-50%,-50%) scale(0);
  background:
    radial-gradient(circle,rgba(255,248,225,.95) 0%,rgba(233,205,143,.5) 40%,transparent 70%);
  opacity:0;animation:hmTwinkle 3.4s ease-in-out infinite;animation-delay:var(--d,0s);
}
.hm-sparkles > i::before,.hm-sparkles > i::after{
  content:"";position:absolute;inset:0;background:linear-gradient(#f6e6bd,#f6e6bd);
}
.hm-sparkles > i::before{clip-path:polygon(50% 0,58% 42%,100% 50%,58% 58%,50% 100%,42% 58%,0 50%,42% 42%)}
.hm-sparkles > i::after{transform:rotate(45deg) scale(.7)}
@keyframes hmTwinkle{
  0%,72%,100%{opacity:0;transform:translate(-50%,-50%) scale(0) rotate(0deg)}
  82%{opacity:.9;transform:translate(-50%,-50%) scale(1) rotate(18deg)}
  92%{opacity:0;transform:translate(-50%,-50%) scale(.4) rotate(30deg)}
}
@media (prefers-reduced-motion:reduce){
  .hm-word,.hm-word-2{animation:none}
  .hm-sparkles{display:none}
}

/* ── The monument's glow, on the phone too ───────────────────────────────────
   The sweep, the shimmer and the sparkles were already running at 390px, but
   at that size the gradient band and the 1.1px stroke were too faint to read
   as anything — the mark looked flat. On phones the sweep gets a brighter
   band and a shorter cycle, the lit stroke thickens a touch, and a soft gold
   bloom sits behind the whole lockup so the glow is visible even before the
   sweep passes. */
@media (max-width:720px){
  .hero-monument{position:relative}
  .hero-monument::before{
    content:"";position:absolute;left:-7%;right:-7%;top:-16%;bottom:-16%;
    z-index:-1;pointer-events:none;border-radius:50%;
    background:radial-gradient(ellipse at 50% 50%,
      rgba(220,183,99,.22) 0%,rgba(201,163,78,.11) 42%,rgba(201,163,78,0) 72%);
    filter:blur(9px);
    animation:hmBloomPhone 7.5s ease-in-out infinite;
  }
  @keyframes hmBloomPhone{
    0%,100%{opacity:.72;transform:scale(1)}
    50%    {opacity:1;transform:scale(1.05)}
  }
  .hm-word{
    -webkit-text-stroke-width:1.35px;
    background-image:linear-gradient(100deg,
      rgba(220,183,99,0) 34%, rgba(240,214,158,.95) 50%, rgba(220,183,99,0) 66%);
    animation-duration:6s;
  }
  .hm-word-2{animation-duration:6s,4s}
  .hm-sparkles > i{animation-duration:2.8s}
}
@media (max-width:720px) and (prefers-reduced-motion:reduce){
  .hero-monument::before{animation:none;opacity:.82}
}

/* ── Mobile hero (≤720px): the v42 composition — left-aligned, editorial ──────
   The monument returns to normal flow at the top of the copy, so it can never
   collide with the statement. Everything reads from the left; the market band
   closes the block. Sized in vw/clamp so it adapts from 320px up to 720px. */
@media (max-width:720px){
  .hero{min-height:auto}
  /* .hero is a centring flex container; without this the copy column would
     shrink-wrap to the widest nowrap child (the eyebrow) and overrun narrow
     phones. Pinning it to full width and clearing the flex min-width floor
     keeps every child inside the viewport from 320px up. */
  .hero-inner{width:100%;max-width:100%;min-width:0}
  .hero-monument{
    position:static;align-items:flex-start;text-align:left;
    margin:0 0 clamp(14px,2vh,22px);gap:.5em;max-width:100%;
  }
  .hm-eyebrow{font-size:.62rem;letter-spacing:.12em;gap:.55em;justify-content:flex-start;text-align:left;max-width:min(88vw,26em)}
  .hm-rule{width:22px}
  .hm-word-1{font-size:clamp(2.3rem,11.4vw,4.6rem)}
  .hm-word-2{font-size:clamp(1.55rem,7.9vw,3.15rem)}
  /* eyebrow may wrap on very small phones rather than force an overflow */
  .hero-eyebrow{text-align:left;white-space:normal}
  .hero-cascade{text-align:left}
  .hero-actions{gap:12px}
  .hero-countries{margin-top:36px;padding-top:22px;gap:7px 10px}
}


/* ── Desktop: the monument moves to the right ────────────────────────────
   The spine is gone; this is the original two-line monument, unchanged in
   design. What changed is where it sits. It is now set flush RIGHT at the top
   of the hero, mirroring the left placement it had before, which keeps the
   carved-lintel stack intact while giving the composition a different balance:
   the mark anchors the top-right, the copy runs from the left beneath it.

   It stays in normal flow, so it reserves its own height and can never collide
   with the eyebrow or headline at any viewport size. */
@media (min-width:721px){
  /* Watermark position/scale is handled on .hero-watermark directly (absolute,
     right, larger). Only the copy column width is set here. */
  .hero-inner{max-width:min(1240px,100%)}
}

/* ── Tablet band (721–1080px): the same nav is already collapsed here, and the
   canvas is too narrow to hold the copy on the left AND the monument on the
   right without a collision. So the monument stacks at the top of the copy, in
   normal flow — the identical key-on-keyhole mark, just above the headline
   instead of beside it. This is what keeps EVERY language clear at these
   widths, since the long FR/DE labels no longer share a row with the copy. */
@media (min-width:721px) and (max-width:1080px){
  .hero-monument{
    position:static;align-items:flex-start;text-align:left;
    margin:0 0 clamp(18px,2.4vh,28px);
  }
  .hm-eyebrow{justify-content:flex-start;text-align:left;max-width:min(80vw,32em)}
}

/* ── True desktop (≥1081px): the monument sits absolute at the top-right and
   the copy holds the left column. Capping the headline keeps EVERY language's
   copy inside that column so it never runs under the monument — the English
   composition the FR/DE/ES pages now match exactly. */
@media (min-width:1081px){
  .hero-headline{max-width:min(50vw,600px)}
  .hero-sub{max-width:min(46vw,540px)}
}

/* ── NEW HERO CONCEPT (desktop ≥1081px): "The wordmark leads" ────────────────
   A different composition, not the left-copy / right-watermark template. The
   watermark is INTEGRATED as the piece it always wanted to be — the hero's own
   masthead title: pulled into normal flow, centred, and set large so it reads
   as the name of the thing rather than a ghost in the corner. The statement,
   the actions and the fourteen markets are then built as a centred, symmetric
   column beneath it, framed top and bottom by gold rules. The BACKGROUND,
   colours and type are untouched. Desktop only; mobile/tablet unchanged. */
.hero-seal{display:none}
@media (min-width:1081px){
  .hero-inner{
    max-width:1120px;margin-inline:auto;text-align:center;
    display:flex;flex-direction:column;align-items:center;
  }
  /* the watermark, pulled into flow as the CENTRED masthead title */
  .hero-monument{
    position:static;order:-1;z-index:1;
    align-items:center;text-align:center;white-space:normal;
    width:100%;margin:clamp(4px,1vh,16px) auto clamp(6px,1.4vh,20px);
  }
  .hm-word-1{font-size:min(10.6vw,7rem);letter-spacing:.02em}
  .hm-word-2{font-size:min(6.7vw,4.05rem);letter-spacing:.06em;margin-top:.04em}
  /* At this size the 1.1px outline read too thin against the navy — the
     watermark lost the clarity it had when the mark was smaller. A heavier,
     brighter gold stroke restores it without filling the letters. */
  .hm-word{-webkit-text-stroke-width:1.7px;-webkit-text-stroke-color:rgba(210,173,90,.82)}

  /* a gold rule seats the masthead onto the statement below it */
  .hero-monument::after{
    content:"";display:block;width:120px;height:2px;border-radius:2px;
    margin:clamp(14px,2vh,26px) auto 0;
    background:linear-gradient(90deg,transparent,var(--gold-bright),transparent);
  }

  /* the concise positioning line, centred under the masthead */
  .hero-eyebrow{
    text-align:center;margin:clamp(12px,1.8vh,22px) auto 0;
    font-size:.86rem;letter-spacing:.26em;
  }
  /* the statement cascade — centred, larger, sitting between the two rules.
     Each movement holds its own single line at this width. */
  .hero-cascade{
    text-align:center;max-width:none;
    margin:clamp(18px,2.6vh,32px) auto clamp(26px,3.6vh,44px);
    font-size:clamp(1.85rem,2.5vw,2.5rem);line-height:1.32;
  }
  .hero-cascade .hc-line{white-space:nowrap}
  .hero-actions{justify-content:center}
  /* the market band, centred under the composition */
  .hero-countries{
    justify-content:center;text-align:center;
    max-width:min(760px,92%);margin-inline:auto;
    margin-top:clamp(28px,4vh,46px);
  }
}

/* Visible headline (styled, not the H1) */
/* The hero headline is set in the association's own hand, exactly as the
   eight interior page H1s are (css/style.css, .page-hero h1): LFFO Wordmark
   Italic at weight 400 with the negative tracking released. It was the one
   headline on the site still in Cormorant while every other page's H1 had
   moved to the wordmark.

   Same treatment, same face, same weight, same tracking — only the size
   differs, because this one has to hold four lines inside the hero rather
   than one line inside a page head. The gilded line keeps its gold; with the
   whole headline now italic, colour is what separates it, which is how the
   interior heads do it too. */
.hero-headline{
  position:relative;z-index:2;
  color:var(--white);margin-top:clamp(14px,2vh,22px);
  font-family:"LFFO Wordmark",var(--serif);font-style:italic;
  font-size:clamp(1.9rem,min(5.5vw,5.6vh),4.35rem);line-height:1.14;font-weight:400;letter-spacing:.004em;
}
/* ── The clip box has to be bigger than the type, on every side ──────────────
   Each line is overflow:hidden because that is the mask the word-rise needs:
   the words start at translateY(115%) and must be invisible until they travel
   up into the box. But a clip box sized to the LINE BOX is not sized to the
   INK, and an italic serif overruns its line box in every direction.

   Measured on the live page, Spanish at 1440: the last line reported
   clientHeight 66 against scrollHeight 71 — five pixels of ink thrown away
   along the bottom edge, which is the descender of the italic f in "futuro"
   and the y of "family". English lost the descender of the f in "future";
   French the same on "l'avenir de l'Europe". The old rule compensated only
   the BOTTOM edge and only by .12em, and compensated the top edge not at all,
   so tall italic ascenders were exposed as well. The left edge had the same
   fault until it was compensated earlier; this is the same bug on the other
   three sides, and it is why it kept reappearing in a different language on a
   different word every time the copy or the viewport changed.

   Sizing it: the wordmark's worst left side bearing is f at -123/1000 em, and
   p is -63 — their ink starts that far LEFT of the text origin, so any word
   beginning with one of them hangs outside its own box before a single line
   has wrapped. The value below is .5em, four times the worst case, so no
   glyph in the face can reach the mask edge at any size or viewport.

   The fix is one value on all four sides: .5em of room inside the mask,
   cancelled by an equal negative margin so nothing moves, resizes or re-wraps.
   At the hero's 55px type that is 19px of clearance — far more than any glyph
   in Cormorant italic overhangs — while remaining trivial next to the 115% of
   its own height that a word is translated by, so the mask still hides every
   word completely before it rises. Being in em, it scales with the type at
   every breakpoint instead of needing a value per viewport. */
.hero-headline .hl-line{
  display:block;
  /* NO CLIP AT ALL.

     This has now been reported four times, and every previous fix was the
     same shape of answer: keep the mask and move its edge further out. First
     padding on one side, then all four, then a clip-path opening three edges,
     then the fourth. Each one measured clean and each one still left a letter
     cut somewhere. When a fix has to be re-tuned that many times, the thing
     being tuned is wrong.

     The mask was only ever cosmetic — it made the words look like they rose
     from behind a line. The words still rise; they now fade in as they do it
     instead of being revealed by a clipped edge. Nothing clips the headline
     on any axis, at any size, in any language, so no glyph in any font can be
     cut by it — not the f at -123/1000 em, not the p, not a descender, not an
     accent. The failure mode is gone rather than avoided. */
}
.hero-headline .sub-line{color:rgba(255,255,255,.92)}
/* ── The word-rise, and why the transform must not survive it ────────────────
   Each word is an inline-block that rises into place. The rise itself is fine.
   What was not fine is that animation-fill-mode:forwards leaves the element
   holding transform:matrix(1,0,0,1,0,0) FOREVER after the animation ends — an
   identity transform, doing nothing, but still a transform.

   A transformed inline-block is painted through its own layer, and that layer
   is sized to the element's BORDER BOX. An italic serif does not fit inside its
   border box: the f begins 147/1000 em to the left of its own origin and the p
   and f descenders run well below the line box. Measured at 1440 against an
   identical unclipped render of the same words in the same face at the same
   size: 1,708 device pixels of ink present in one and absent from the other.
   Force transform:none and the same measurement returns ZERO.

   That is the whole thing. It was never the typeface — the letters really were
   being cut, by the leftover identity transform, which is why it survived a
   removed mask, four rounds of glyph surgery and 106 repaired terminals, and
   why it showed up worse on desktop, where the type is 50px and the overhang
   it loses is proportionally larger than at the 30px the phone sets.

   So the transform is cleared the moment it has finished doing its job:
   js/home-effects.js adds .settled on animationend, and this rule takes the
   element back to no transform, no animation, plain static text that paints
   like every other piece of type on the page. */
/* ── The word's box has to contain the word's ink ────────────────────────────
   Clearing the transform on settle (below) stopped the headline being cut, but
   it left a POP: while the word is animating it IS transformed, so it is
   painted through a layer sized to its border box, and an italic serif overruns
   that box on every side. Measured at 1440, 6,731 device pixels appeared at the
   instant .settled landed — the descenders and the f's left overhang arriving
   all at once on a word that had already stopped moving.

   The fix is to make the border box big enough that there is nothing left to
   clip at any point in the animation: .4em of padding top and bottom, .3em
   left and right, cancelled by an exactly equal negative margin so the advance,
   the line box and the wrap points are untouched. Verified at 1440, 1024, 768
   and 390: the settled hero is pixel-identical with and without it, and the
   pop measures ZERO. */
.hero-headline .w{
  display:inline-block;transform:translateY(38%);opacity:0;
  padding:.4em .3em;margin:-.4em -.3em;
}
.hero-headline .w.show{animation:wordRise .85s cubic-bezier(.22,1,.36,1) forwards}
/* The settled word keeps an IDENTITY transform rather than dropping to none.
   Dropping it takes the element off its paint layer, and text rasterises very
   slightly differently on a layer than off it — measured as a one-device-pixel
   outline around every glyph appearing the instant .settled landed. Nothing was
   clipped any more (the padding above sees to that), but the letters visibly
   re-sharpened on a word that had already stopped moving, which is the last
   thing between this and a perfectly smooth reveal.

   So the transform stays, at translateY(0): the animation ends and NOTHING
   changes. The clearing of animation-fill-mode still happens, which is what
   matters — a finished animation no longer holds the element's style. */
.hero-headline .w.settled,.hero-title .w.settled{animation:none;transform:translateY(0);opacity:1}

.hero-sub{
  color:rgba(255,255,255,.78);font-size:clamp(1.05rem,1.6vw,1.24rem);
  max-width:600px;margin-top:clamp(16px,2.4vh,28px);line-height:1.6;
  opacity:0;animation:fadeUp .9s var(--ease) 1.1s forwards;
}
.hero-actions{
  display:flex;gap:14px;flex-wrap:wrap;margin-top:clamp(20px,3.2vh,38px);
  opacity:0;animation:fadeUp .9s var(--ease) 1.25s forwards;
}
.hero-countries{
  display:flex;align-items:center;justify-content:flex-start;gap:6px 9px;flex-wrap:wrap;
  margin-top:clamp(24px,4vh,54px);padding-top:clamp(16px,2.4vh,26px);border-top:1px solid var(--line-navy);
  font-size:.8rem;color:rgba(255,255,255,.6);
  opacity:0;animation:fadeUp .9s var(--ease) 1.4s forwards;
}
.hero-countries > span{white-space:nowrap}
.hero-countries i{font-size:.42rem;color:rgba(210,222,240,.4)}
.hc-label{color:rgba(223,233,247,.72);font-weight:600;letter-spacing:.14em;text-transform:uppercase;font-size:.68rem;margin-right:6px;white-space:nowrap}
/* Wide desktops: tighten spacing so the markets read as one clean band */
@media (min-width:1180px){
  .hero-countries{gap:7px 10px;font-size:.8rem}
  .hero-countries i{font-size:.42rem}
}

@keyframes fadeUp{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}

/* =========================================================
   STANDING
   ---------------------------------------------------------
   Replaces the old counter band. Those numbers were a liability:
   "8 European markets" contradicted the fourteen stated everywhere else, and
   the members and events totals were placeholders no visitor could verify.
   What sits here now is only what the association can actually stand behind,
   said plainly. Numbers are spelled out in the serif so they read as
   institutional statements rather than growth metrics.
   ========================================================= */
.standing-section{
  padding-block:clamp(48px,6.5vw,80px);
  /* A whisper of light and a hairline — never a fill. See the note on the
     seasonal washes above. */
  background:var(--bg-alt);
  border-block:1px solid var(--line-soft);
  position:relative;z-index:1;
}
.visually-hidden{
  position:absolute;width:1px;height:1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;
}
.standing-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(22px,3vw,40px)}
.standing{display:flex;flex-direction:column;gap:10px}
.standing-rule{
  display:block;width:0;height:2px;border-radius:2px;
  background:linear-gradient(90deg,var(--gold),rgba(201,163,78,0));
  transition:width .9s var(--ease) .25s;
}
.standing.in .standing-rule{width:46px}
.standing-lead{
  font-family:var(--serif);font-weight:600;color:var(--navy);
  font-size:clamp(1.32rem,2.1vw,1.72rem);line-height:1.15;letter-spacing:-.01em;
}
.standing-note{font-size:.92rem;line-height:1.6;color:var(--ink-soft)}

@media (max-width:900px){
  .standing-grid{grid-template-columns:repeat(2,1fr);gap:28px 26px}
}
@media (max-width:560px){
  .standing-grid{grid-template-columns:1fr;gap:22px}
  .standing{
    display:grid;grid-template-columns:auto 1fr;column-gap:16px;row-gap:4px;
    padding-bottom:18px;border-bottom:1px solid var(--line);
  }
  .standing:last-child{border-bottom:none;padding-bottom:0}
  .standing-rule{grid-row:1 / span 2;width:2px;height:100%;
    background:linear-gradient(180deg,var(--gold),rgba(201,163,78,0));transition:none}
  .standing.in .standing-rule{width:2px}
  .standing-lead{font-size:1.22rem}
}

/* =========================================================
   MISSIONS
   ========================================================= */
.missions-section{position:relative;z-index:1}
.missions-branch{display:grid;grid-template-columns:repeat(3,1fr);gap:22px}
.mission{
  position:relative;background:var(--surface);border:1px solid var(--line);
  border-radius:var(--radius-lg);padding:34px 28px 30px;overflow:hidden;
  transition:transform .35s var(--ease),box-shadow .35s var(--ease),border-color .35s var(--ease);
}
.mission::before{
  content:"";position:absolute;left:0;top:0;height:100%;width:3px;
  background:var(--c);transform:scaleY(0);transform-origin:top;transition:transform .5s var(--ease);
}
.mission.in::before{transform:scaleY(1)}
.mission:hover{transform:translateY(-6px);box-shadow:var(--shadow-lg);border-color:color-mix(in srgb,var(--c) 40%,var(--line))}
.mission-index{
  position:absolute;top:22px;right:26px;font-family:var(--serif);
  font-size:2.4rem;font-weight:700;color:var(--gold-soft);line-height:1;transition:color .35s var(--ease);
}
.mission:hover .mission-index{color:color-mix(in srgb,var(--c) 30%,var(--gold-soft))}
.mission-node{
  position:absolute;top:-5px;left:-5px;width:10px;height:10px;border-radius:50%;
  background:var(--c);opacity:0;transform:scale(0);transition:all .4s var(--ease) .2s;
}
.mission.in .mission-node{opacity:1;transform:scale(1)}
.mission-icon{
  width:54px;height:54px;border-radius:14px;display:flex;align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--c) 12%,white);color:var(--c);margin-bottom:20px;
  transition:transform .4s var(--ease);
}
.mission:hover .mission-icon{transform:scale(1.08) rotate(-4deg)}
.mission-icon i{font-size:1.6rem}
.mission h3{margin-bottom:10px}
.mission p{font-size:.95rem}
.mission-cta{background:var(--navy);color:#fff;display:flex;flex-direction:column;justify-content:center;gap:16px;border-color:var(--navy)}
.mission-cta::before{display:none}
.mission-cta p{color:rgba(255,255,255,.82);font-size:1.05rem;font-family:var(--serif)}
.mission-link{display:inline-flex;align-items:center;gap:.5em;color:var(--gold);font-weight:600;font-size:.95rem}
.mission-link i{transition:transform .25s var(--ease)}
.mission-cta:hover .mission-link i{transform:translateX(5px)}

/* =========================================================
   PRESIDENT
   ========================================================= */
.president-section{
  position:relative;z-index:1;
  background:linear-gradient(160deg,#153157,#173a66 60%,#1c4174);
  color:#fff;padding-block:clamp(70px,10vw,130px);overflow:hidden;
}
.pres-leaves{position:absolute;inset:0;pointer-events:none;z-index:0}
.president-grid{
  position:relative;z-index:2;
  display:grid;grid-template-columns:.9fr 1.1fr;
  gap:clamp(36px,6vw,80px);align-items:center;
}
.pp-frame{position:relative;aspect-ratio:4/5;border-radius:var(--radius-lg);overflow:visible}
.pp-ring{
  position:absolute;inset:-12px;border-radius:calc(var(--radius-lg) + 8px);
  border:1.5px solid rgba(201,163,78,.35);
  animation:ringPulse 6s ease-in-out infinite;
}
@keyframes ringPulse{0%,100%{transform:scale(1);opacity:.5}50%{transform:scale(1.008);opacity:.9}}
.pp-placeholder{
  width:100%;height:100%;border-radius:var(--radius-lg);overflow:hidden;
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:14px;
  background:linear-gradient(150deg,var(--navy-soft),#0c1a2e);color:rgba(255,255,255,.4);
  border:1px solid var(--line-navy);box-shadow:var(--shadow-lg);
}
.pp-placeholder i{font-size:4rem}
.pp-placeholder span{font-size:.85rem;letter-spacing:.05em}
.pp-badge{
  position:absolute;bottom:16px;right:6px;width:60px;height:60px;border-radius:50%;
  background:var(--gold);color:var(--navy);display:flex;align-items:center;justify-content:center;
  box-shadow:0 10px 30px rgba(201,163,78,.4);z-index:3;
}
.pp-badge i{font-size:1.7rem}
.president-body .eyebrow{color:var(--gold)}
.president-quote{
  font-family:var(--serif);font-size:clamp(1.5rem,2.9vw,2.2rem);line-height:1.4;
  color:#fff;font-weight:500;margin:20px 0 26px;position:relative;
}
.president-quote::before{
  content:"\201C";position:absolute;left:-.45em;top:-.25em;
  color:var(--gold);opacity:.5;font-size:1.3em;font-family:var(--serif);
}
/* The quote is hand-broken into five phrases so that on a wide measure it
   breaks where the sentence breathes rather than where the box ends. Each
   phrase is its own block, and they rise in sequence.

   That only works while a phrase fits on one line. On a phone it does not:
   "in trust, independence, and the quality" wrapped, so the reader saw a
   deliberate-looking break in the middle of a clause with "quality" stranded
   above "of the people around the table" — the hand-set rhythm turned into
   what looks like a mistake. Below 720px the phrases therefore run inline and
   the paragraph wraps normally; the staggered reveal is kept, on opacity
   alone, because a translate on an inline box does nothing useful. */
/* No transform on the quote lines — they fade, and only fade.
   They used to rise 14px, and a transformed box paints through a layer sized to
   that box, which an italic serif at 1.6rem overruns: the lower lines were
   being cut while they moved and then arrived all at once when the transform
   reached none. Measured 12,132 device pixels appearing at the end of the
   reveal, on text that had already stopped.

   The hero headline solves the same problem with padding and an equal negative
   margin, because there the rise is the whole point. Here it is not — five
   phrases already arrive in sequence on their own delays, and the rise added
   nothing a reader could name. Removing it removes the layer, and with it any
   possibility of a clip: opacity alone can never cut a glyph. */
.pq-line{
  display:block;opacity:0;
  transition:opacity .6s var(--ease);
}
@media (max-width:720px){
  .pq-line{display:inline}
}
.president-section.lit .pq-line{opacity:1}
.president-section.lit .pq-line:nth-child(1){transition-delay:.05s}
.president-section.lit .pq-line:nth-child(2){transition-delay:.18s}
.president-section.lit .pq-line:nth-child(3){transition-delay:.31s}
.president-section.lit .pq-line:nth-child(4){transition-delay:.44s}
.president-section.lit .pq-line:nth-child(5){transition-delay:.57s}
.president-sign{margin-bottom:24px}
.ps-name{display:block;font-family:var(--serif);font-size:1.45rem;font-weight:600;color:var(--gold)}
.ps-role{display:block;font-size:.88rem;letter-spacing:.04em;color:rgba(255,255,255,.6);margin-top:2px}
.president-note{color:rgba(255,255,255,.72);font-size:1rem;max-width:520px;margin-bottom:28px}

/* =========================================================
   EVENTS
   ========================================================= */
.events-section{position:relative;z-index:1}
.head-row{display:flex;align-items:flex-end;justify-content:space-between;gap:20px;margin-bottom:42px;flex-wrap:wrap}
.events-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
.event-card{display:flex;flex-direction:column}
.ev-media{
  position:relative;background:var(--c);color:#fff;padding:22px;
  min-height:158px;display:flex;flex-direction:column;justify-content:space-between;overflow:hidden;
}
.ev-media[style*="--gold"]{color:var(--navy)}
.ev-leaf{
  position:absolute;top:-20px;right:-20px;width:90px;height:90px;
  border-radius:50% 0 50% 50%;background:rgba(255,255,255,.06);
  transform:rotate(20deg);transition:transform .5s var(--ease);
}
.event-card:hover .ev-leaf{transform:rotate(40deg) scale(1.1)}
.ev-type{position:relative;font-size:.74rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;opacity:.92}
.ev-date{position:relative;display:flex;flex-direction:column;line-height:1}
.ev-day{font-family:var(--serif);font-size:2.4rem;font-weight:700}
.ev-mon{font-size:.78rem;letter-spacing:.14em;text-transform:uppercase;opacity:.85;margin-top:4px}
.ev-body{padding:24px;display:flex;flex-direction:column;flex:1}
.ev-body h3{font-size:1.3rem;margin-bottom:8px}
.ev-meta{font-size:.82rem;color:var(--ink-soft);display:flex;align-items:center;gap:.4em;margin-bottom:12px}
.ev-meta i{color:var(--gold)}
.ev-body p{font-size:.92rem;flex:1}
.ev-link{margin-top:16px;display:inline-flex;align-items:center;gap:.45em;color:var(--brown);font-weight:600;font-size:.9rem}
.ev-link i{transition:transform .25s var(--ease)}
.event-card:hover .ev-link i{transform:translateX(4px)}

/* =========================================================
   KNOWLEDGE
   ========================================================= */
.knowledge-section{position:relative;z-index:1}
.knowledge-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:24px}
.k-card{display:flex;flex-direction:column}
.k-tag{
  align-self:flex-start;margin:20px 20px 0;padding:.35em .9em;border-radius:20px;
  background:var(--gold-soft);color:var(--brown);font-size:.72rem;font-weight:700;
  letter-spacing:.08em;text-transform:uppercase;
}
.k-body{padding:16px 24px 26px}
.k-cat{font-size:.78rem;font-weight:600;color:var(--gold);letter-spacing:.06em;text-transform:uppercase}
.k-body h3{font-size:1.25rem;margin:8px 0 10px;line-height:1.25}
.k-body p{font-size:.92rem}
.k-foot{display:inline-flex;align-items:center;gap:.45em;margin-top:16px;font-size:.82rem;color:var(--ink-soft)}
.k-foot i{color:var(--brown)}

/* =========================================================
   EUROPE AS ROOTS
   ========================================================= */
/* Background comes from .lit-navy in style.css. A flat var(--navy) here would
   win the cascade (home.css loads after style.css) and undo the lighting. */
.roots-section{position:relative;z-index:1;color:#fff;overflow:hidden}
/* ── Act 0: the sentence ─────────────────────────────────────────────────
   "Rooted in Luxembourg, growing across Europe" reveals left to right, and the
   figure begins growing as the last word lands.

   It is done with a mask rather than by wrapping every word in a span, for one
   specific reason: this heading carries data-i18n, and the translation engine
   replaces its innerHTML wholesale. Any inner structure would be destroyed the
   moment a reader switched to French, and the animation would silently stop
   working in three of the site's four languages. A mask lives entirely on the
   parent, so it survives every swap. Browsers without mask support show the
   heading immediately, which is a perfectly good outcome. */
.roots-section .section-head h2{
  color:#fff;
  -webkit-mask-image:linear-gradient(100deg,#000 40%,rgba(0,0,0,.25) 62%,transparent 76%);
  mask-image:linear-gradient(100deg,#000 40%,rgba(0,0,0,.25) 62%,transparent 76%);
  -webkit-mask-size:260% 100%;mask-size:260% 100%;
  -webkit-mask-position:160% 0;mask-position:160% 0;
  -webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;
  transition:-webkit-mask-position 1.15s cubic-bezier(.3,.7,.25,1) .08s,
             mask-position 1.15s cubic-bezier(.3,.7,.25,1) .08s;
}
.roots-section .section-head.in h2,
.roots-section .section-head.reveal.in h2{
  -webkit-mask-position:0 0;mask-position:0 0;
}
.roots-section .section-head p{color:rgba(255,255,255,.7)}
.roots-figure{position:relative;max-width:1090px;margin:0 auto;width:100%}
.roots-svg{overflow:visible;width:100%;height:auto;overflow:visible}

/* ═══════════════════════════════════════════════════════════════════════
   GROWTH — "Rooted in Luxembourg, growing across Europe"
   ═══════════════════════════════════════════════════════════════════════
   The section makes a claim in one sentence, and the figure beneath it should
   be that sentence happening rather than a diagram that fades in. So the whole
   thing is built as a single causal chain, in four acts:

     0  the sentence writes itself, left to right
     1  the ROOT: the Luxembourg tree's trunk rises, then its canopy unfurls
        leaf by leaf. Nothing can grow from a place that does not exist yet,
        so the origin is established before anything leaves it.
     2  the BRANCHES extend outward from the hub
     3  each LEAF unfurls at the exact moment its own branch tip reaches it,
        and its label follows a beat later. The cities come last, growing off
        the countries they belong to — never off the hub, because that is not
        where they are attached.

   Two rules do almost all the work of making it read as growth:

   · CONSTANT SPEED. Every branch's duration is proportional to its own
     measured length, so the growing tip moves at one velocity across the whole
     map. The reach to Canada genuinely takes longer than the reach to Belgium.
     The old version gave all 22 spokes the same 1.3s regardless of length,
     which meant the long ones raced and the short ones crawled — the single
     detail that made it read as 22 lines animating rather than as one thing
     growing. Same principle as the footer wordmark's nib.
   · NEAREST FIRST. Branches are ranked by length and staggered in that order,
     so the canopy fills outward from the centre. The old stagger followed
     markup order — Canada, Scotland, Ireland — which scattered.

   Every timing below is computed in js/home-effects.js from real geometry and
   written onto each element as --d (delay), --t (duration) and --len (path
   length). CSS holds no hard-coded delays at all: nothing to re-tune by hand
   when a market is added, and nothing that can drift out of step with the
   drawing it describes. The fallbacks in each var() are what a browser sees if
   the script never runs — a sane, if unsequenced, reveal. */

/* ── Act 2: branches ── */
.spoke{
  stroke-dasharray:var(--len,400);
  stroke-dashoffset:var(--len,400);
  opacity:var(--o,.5);
}
.roots-figure.in .spoke{
  animation:growBranch var(--t,1.1s) linear var(--d,.1s) forwards;
}
@keyframes growBranch{ to{stroke-dashoffset:0} }

/* ── Act 3: leaves land where their branch arrives ── */
.rn-leaf .leaf-pin{
  opacity:0;transform:scale(.18) rotate(-12deg);
  transform-box:fill-box;transform-origin:bottom center;
  filter:drop-shadow(0 1px 2px rgba(10,23,40,.4));cursor:pointer;
}
.roots-figure.in .rn-leaf .leaf-pin{
  animation:leafLand .54s cubic-bezier(.2,1,.32,1) var(--d,1.4s) forwards;
}
/* No overshoot. The leaf is arriving at rest, not bouncing into place. */
@keyframes leafLand{
  0%{opacity:0;transform:scale(.18) rotate(-12deg)}
  55%{opacity:1}
  100%{opacity:.96;transform:scale(1) rotate(0)}
}

/* ── Cities: a seed, then the halo opening around it ── */
.rn-city .city-seed{
  fill:var(--gold-bright);opacity:0;transform:scale(0);
  transform-box:fill-box;transform-origin:center;
  filter:drop-shadow(0 1px 2px rgba(10,23,40,.45));
}
.roots-figure.in .rn-city .city-seed{
  animation:seedIn .46s cubic-bezier(.2,1,.32,1) var(--d,1.8s) forwards;
}
@keyframes seedIn{ to{opacity:1;transform:scale(1)} }
.rn-city .city-halo{
  fill:none;stroke:var(--gold);stroke-width:1;opacity:0;transform:scale(.3);
  transform-box:fill-box;transform-origin:center;
}
.roots-figure.in .rn-city .city-halo{
  animation:haloOut .6s cubic-bezier(.2,1,.32,1) var(--dh,1.95s) forwards;
}
@keyframes haloOut{
  0%{opacity:0;transform:scale(.3)}
  40%{opacity:.62}
  100%{opacity:.5;transform:scale(1)}
}

/* Any circle node that is not a city halo (defensive: the markup has none
   today, but the old rule covered them). */
.rn circle:not(.city-halo){
  fill:var(--gold);opacity:0;transform:scale(0);
  transform-box:fill-box;transform-origin:center;
  transition:opacity .45s var(--ease) .7s,transform .45s var(--ease) .7s;
}
.roots-figure.in .rn circle:not(.city-halo){opacity:1;transform:scale(1)}

/* ── Hub: the tree, and nothing else ─────────────────────────────────────
   The medallion plate, gilded ring, travelling arc, label pill and the
   "Luxembourg / Headquarters" text have all been removed. They were five
   stacked layers competing for the centre of a diagram whose whole subject is
   the tree; the legend beneath already names the headquarters, so the label
   was saying twice what the mark says once. What remains is the gold tree at
   nearly double its former size, blooming leaf by leaf as the figure arrives.
   The bloom runs root-to-crown, the same direction and easing as the nav and
   footer marks, so every tree on the site comes alive the same way. */
.rn.hub{isolation:isolate}
/* Positioning lives here, not on a transform attribute: a CSS transform on an
   SVG element REPLACES the element's transform attribute outright, so the
   breathing keyframe below was silently throwing away the translate/scale that
   centres the tree on the hub. Both now live in the same declaration. */
.rn.hub .hub-logo{
  opacity:0;transition:opacity .6s ease .25s;
  transform:translate(-59px,-67.5px) scale(1.35);
}
.roots-figure.in .rn.hub .hub-logo{opacity:1}
.rn.hub .hub-logo path{filter:drop-shadow(0 1px 4px rgba(6,14,26,.55))}

/* Act 1. The trunk rises from its own base — transform-origin bottom — before
   a single branch leaves the hub. */
.rn.hub .hub-trunk{
  transform-box:fill-box;transform-origin:bottom center;
  transform:scaleY(.7);opacity:0;
  transition:transform .72s cubic-bezier(.22,1,.36,1) .32s,opacity .45s ease .32s;
}
.roots-figure.in .rn.hub .hub-trunk{transform:scaleY(1);opacity:1}

.rn.hub .hub-leaf{
  transform-box:fill-box;transform-origin:center;
  transform:scale(.15) rotate(-8deg);opacity:0;
}
.roots-figure.in .rn.hub .hub-leaf{
  animation:hubBloom .82s cubic-bezier(.16,1,.3,1) both;
  animation-delay:calc(.6s + (11 - var(--i)) * .045s);
}
/* Overshoot removed, matching the nav mark: the canopy settles, it does not
   pop. The last leaf lands at about 1.9s, by which time the nearest branches
   are already extending — the two acts overlap so the sequence reads as one
   continuous growth rather than as two things taking turns. */
@keyframes hubBloom{
  0%{transform:scale(.15) rotate(-8deg);opacity:0}
  55%{opacity:1}
  100%{transform:scale(1) rotate(0);opacity:1}
}
/* The breathing loop is gone. A tree that has finished growing should stand
   still — and an infinite scale on a group containing thirteen filtered paths
   was the most expensive animation left on the page, running forever for a 4%
   size change nobody consciously registered. The stillness at the end is also
   what gives the sequence a resolution; a canopy that keeps moving never lets
   the eye leave the centre and read the map around it. */
/* Reduced motion: the whole figure is simply present. Every element that the
   sequence animates is reset to its finished state, including the branches —
   a growth animation with the motion removed is a blank diagram, so it has to
   be the END state that survives, not the start. */
@media (prefers-reduced-motion:reduce){
  .rn.hub .hub-leaf,.roots-figure.in .rn.hub .hub-leaf{animation:none;transform:none;opacity:1}
  .rn.hub .hub-trunk{transform:none;opacity:1;transition:none}
  .roots-figure.in .rn.hub .hub-logo{animation:none}
  .spoke,.roots-figure.in .spoke{animation:none;stroke-dashoffset:0}
  .spoke-city,.roots-figure.in .spoke-city{animation:none;opacity:.58}
  .rn-leaf .leaf-pin,.roots-figure.in .rn-leaf .leaf-pin{animation:none;opacity:.96;transform:none}
  .rn-city .city-seed,.roots-figure.in .rn-city .city-seed{animation:none;opacity:1;transform:none}
  .rn-city .city-halo,.roots-figure.in .rn-city .city-halo{animation:none;opacity:.5;transform:none}
  .rn text,.roots-figure.in .rn text{animation:none;opacity:1}
  .roots-section .section-head h2{-webkit-mask-image:none;mask-image:none}
}

/* Clean, premium text — larger, more presence */
.rn text{fill:rgba(255,255,255,.92);font-family:var(--sans);font-size:20px;font-weight:500;text-anchor:middle;opacity:0}
.rn.hub .hub-name{fill:var(--gold);font-family:var(--serif);font-weight:600;font-size:20px}
.rn-sub{fill:rgba(255,255,255,.5)!important;font-size:13px!important;font-weight:600!important;letter-spacing:.12em;text-transform:uppercase}
/* Glowing gold animation on the hub label */
.rn.hub .hub-glow-text{opacity:0}
.roots-figure.in .rn.hub .hub-glow-text{opacity:1}
.roots-figure.in .rn.hub .hub-name.hub-glow-text{animation:hubTextGlow 4s ease-in-out infinite 1.2s}
@keyframes hubTextGlow{
  0%,100%{filter:drop-shadow(0 0 2px rgba(201,163,78,.25))}
  50%{filter:drop-shadow(0 0 8px rgba(220,183,99,.85))}
}
/* City tier — smaller and italic to stay distinct from countries, but at the
   SAME label opacity so a city name never reads as faded or half-there. */
.rn-city text{font-size:15px;font-style:italic;fill:rgba(255,255,255,.9)}
/* ── City tethers ─────────────────────────────────────────────────────────
   A city's tether was so faint (.9px at 40%) that Vancouver read as unattached
   even when its endpoint sat exactly on the mark, so it is dotted at 1.15px
   now. But a dotted stroke and a drawn-on stroke want the same property: the
   dash pattern IS stroke-dasharray, and the growth animation is a dashoffset
   run against a single dash the length of the path. Setting `3 4` here beat
   `var(--len)` on .spoke, so the pattern repeated the whole way along and every
   city thread was fully painted from the first frame — visible, at .58, sitting
   on the map before the trunk had even started to grow, while everything else
   was still hidden. That is what read as the city lines not fading in.

   They cannot grow and be dotted, so they fade — which is what the rest of the
   figure does anyway. Same --d the script computes for the thread, so a city's
   tether still appears at exactly its own moment in the sequence, after its
   parent country's leaf has landed. */
.spoke-city{
  --o:.58;
  stroke-dasharray:3 4;stroke-dashoffset:0;stroke-width:1.15;
  opacity:0;
}
.roots-figure.in .spoke-city{
  animation:cityThread var(--t,.5s) var(--ease) var(--d,1.6s) forwards;
}
@keyframes cityThread{ from{opacity:0} to{opacity:var(--o)} }
/* The name arrives a beat after its own marker — the place is planted, then it
   is named. --dt is written per node by the script. */
.roots-figure.in .rn text{animation:labelIn .5s var(--ease) var(--dt,1.6s) forwards}
@keyframes labelIn{ to{opacity:1} }

/* Interaction is identical for a city and a country: the same pointer cursor,
   the same eased transition, the same hover growth. Nothing about a city's
   hover behaves differently from a country's. */
.rn-leaf,.rn-city{cursor:pointer}
.rn-leaf .leaf-pin,.rn-city .city-seed,.rn-city .city-halo,.rn circle{
  transition:transform .28s var(--ease-lux),fill .28s var(--ease);
}
.rn:hover circle{transform:scale(1.4)}
.rn-leaf:hover .leaf-pin{transform:scale(1.26)}
.rn-city:hover .city-seed{transform:scale(1.26)}
.rn-city:hover .city-halo{transform:scale(1.26)}

/* ── Hovering a marker ───────────────────────────────────────────────────────
   ONLY the golden line animates. Nothing else on the map dims.

   The rule that used to sit here was `.roots-figure.hovering .rn{opacity:.4}`:
   pointing at any one node faded every OTHER node to 40%, names included. On a
   map whose whole job is to name fourteen markets and four cities, hovering
   made twelve of them illegible — the reader reached for a label and the
   labels went away. The dim is gone entirely.

   What is left is the spoke lighting up, plus the hovered node's own marker
   and name growing a little. The name grows by TRANSFORM about its own centre
   (transform-box:fill-box), not by font-size: SVG text does not reflow, so
   scaling cannot move a neighbour, change a measured width, or shift the
   layout by a pixel. */
.roots-figure.hovering .spoke{opacity:.5;transition:opacity .3s var(--ease)}
.roots-figure.hovering .spoke.lit{opacity:1;stroke:var(--gold-bright);stroke-width:2;filter:drop-shadow(0 0 5px rgba(220,183,99,.6))}
.roots-figure .rn text.named{opacity:1 !important;animation:none !important}
/* No zoom on the label. A name that changes size under the pointer moves its
   own edges while you are reading it, and on a map where labels sit inches
   apart it also closes the gap to its neighbours. The name simply brightens
   to full white; the golden spoke is what answers the hover. */
.roots-figure .rn text{
  transition:fill .26s var(--ease);
}
.rn-leaf:hover text,.rn-city:hover text,
.roots-figure .rn.lit text{fill:#fff}
.roots-figure.hovering .rn.lit circle{transform:scale(1.4);fill:var(--gold-bright)}
.roots-figure.hovering .rn.lit .leaf-pin{transform:scale(1.3)}
.roots-figure.hovering .rn.lit .city-seed{transform:scale(1.3)}
.roots-figure.hovering .rn.lit .city-halo{transform:scale(1.3)}
.roots-legend{display:flex;gap:30px;justify-content:center;margin-top:26px;font-size:.9rem;color:rgba(255,255,255,.68)}
/* ── Legend keyed to the actual marks ────────────────────────────────────
   The legend used three generic icons that appeared nowhere in the diagram.
   These are the diagram's own geometry: the traced tree for the headquarters,
   the leaf-pin for a market, the sparkle for a city. Markets and cities are
   drawn white with a soft gold outline rather than in palette colour, because
   no single palette colour could stand for all fourteen of them; the tree keeps
   its gold so the headquarters still reads as the one gilded thing. */
.rl-item{display:inline-flex;align-items:center;gap:9px;white-space:nowrap}
.rl-mark{width:17px;height:17px;overflow:visible;flex:0 0 auto}
.rl-tree{width:20px;height:22px}
.rl-leaf,.rl-spark{
  fill:#fff;
  stroke:var(--gold);stroke-width:1.1;
  paint-order:stroke fill;
  filter:drop-shadow(0 0 2.5px rgba(220,183,99,.55));
}
.rl-spark{stroke-width:.9}

/* Responsive: scale label text up on smaller desktop windows so it stays legible */
@media (max-width:1100px){
  .rn text{font-size:21px}
  .rn.hub .hub-name{font-size:27px}
  .rn-sub{font-size:14px!important}
}
@media (max-width:820px){
  .roots-figure{max-width:660px}
  .rn text{font-size:24px}
  .rn.hub .hub-name{font-size:30px}
  .rn-sub{font-size:15px!important}
}
/* Mobile label sizes. There used to be a width:134%;margin-left:-17% here as
   well, on the theory that spilling the figure past its column would buy the
   tree some size. It bought a third of the map being clipped off the right-hand
   edge with no way to reach it — Canada, Spain and Monaco simply did not exist
   on a phone. The figure is panned now (see the 720px block further down), so
   the drawing keeps its full width and these are only the type sizes that suit
   the 860px it is held at. */
@media (max-width:600px){
  .rn text{font-size:21px}
  .rn-city text{font-size:17px}
  .rn.hub .hub-name{font-size:25px}
  .roots-legend{gap:18px;font-size:.82rem;flex-wrap:wrap;margin-top:20px}
}


/* =========================================================
   JOIN — with Seal watermark
   ========================================================= */
/* Background comes from .lit-navy in style.css — see the note above. */
.join-section{
  position:relative;z-index:1;
  color:#fff;overflow:hidden;
}
/* The Seal: faint embossed tree/monogram watermark */
.join-seal{
  position:absolute;right:-80px;top:50%;transform:translateY(-50%);
  width:clamp(300px,36vw,480px);height:auto;
  opacity:.04;pointer-events:none;filter:blur(0px);
  /* renders the LFFO logo as a pale crest */
}
.join-canopy{position:absolute;inset:0;pointer-events:none;opacity:.4}
.join-inner{position:relative;z-index:2;max-width:900px;margin-inline:auto;text-align:center}
/* ── The one heading set in the association's own hand ───────────────────────
   Every other H2 on the site is Cormorant. This one is the wordmark face, and
   that is the point: the membership ask is where the association speaks as
   itself, so breaking the pattern here is the pattern.

   Two guards, both learned the hard way. The face is a high-contrast italic, so
   it is set LARGER here than a Cormorant H2 would be — below about 34px its
   hairlines start dropping out. And the element is inside .join-inner, which is
   transformed while it reveals, so it carries padding and an equal negative
   margin: a transformed box paints through a layer sized to that box, and this
   face overruns its box on every side. Without the guard the descenders of the
   p and g would be cut for the whole reveal and then pop in at the end. */
.join-head h2{
  color:#fff;margin-top:14px;
  font-family:"LFFO Wordmark",var(--serif);font-style:italic;font-weight:400;
  font-size:clamp(2.15rem,4.6vw,3.4rem);line-height:1.1;letter-spacing:.004em;
  padding:.34em .26em;margin-inline:-.26em;margin-bottom:-.34em;margin-top:calc(14px - .34em);
}
@media (max-width:720px){
  .join-head h2{font-size:clamp(1.95rem,8.4vw,2.5rem)}
}
.join-head p{color:rgba(255,255,255,.75);font-size:1.1rem;margin-top:14px;max-width:560px;margin-inline:auto}
.join-tiers{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin:44px 0 36px}
/* ── THE TIER PLATES — an inscription, not an arrow ──────────────────────────
   What was here: a "\2192" glyph faded in at the top-right corner and the
   whole card jumped up four pixels. A literal arrow drawn in a text
   character, on a card in a section headed "Join the association shaping the
   profession" — the single most considered moment on the homepage answering
   the reader with the most generic gesture on the web.

   What is here now is an ENGRAVED KEYLINE that inscribes itself around the
   plate. A gold hairline starts at the top-left corner and runs two ways at
   once, right along the top and down the left; a quarter-second later a
   second line starts from the bottom-right and runs back along the bottom
   and up the right, and the two meet at the opposite corners and close the
   frame. Under it, mark 04 lights a soft field behind the price, and mark 08
   fills a rule in beneath the figure itself.

   Three of the seven approved marks composited into one gesture. It takes
   about three-quarters of a second to complete, nothing about the card
   moves, and there is no arrow anywhere in it. */
/* Home tier plates — MINIATURE Membership cards. Each is a small copy of a
   Membership-page tier: a deep colour HEAD (navy for the two premium tiers,
   brown for partner) carrying the gold kind label, the white serif name and the
   white price, over a white BODY with the one-line "who it's for". The same
   card as the Membership page, shrunk — not a pale accent box. Square-cornered
   per the house rule. Interaction is the Membership card's own: a gold inset
   ring + soft lift on tap / hover, never on scroll. */
.jt{
  position:relative;display:flex;flex-direction:column;text-align:left;
  text-decoration:none;color:inherit;cursor:pointer;overflow:hidden;
  background:var(--surface);border:1px solid var(--line);border-radius:0;
  box-shadow:var(--shadow-sm);
  transition:transform .34s var(--ease-lux),box-shadow .34s var(--ease-lux),border-color .3s var(--ease,ease);
}
/* the gold inset ring, on its own layer above the head + body (as .tier::after) */
.jt::after{
  content:"";position:absolute;inset:0;pointer-events:none;z-index:5;
  box-shadow:inset 0 0 0 1.5px transparent;transition:box-shadow .3s var(--ease-lux);
}
.jt-field{display:none}
/* the coloured head — navy for premium, brown for partner */
.jt-head{position:relative;background:var(--navy);color:#fff;padding:20px 22px 17px}
.jt[data-tier-kind="partner"] .jt-head{background:var(--brown)}
.jt-kind{display:block;font-size:.66rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--gold);margin-bottom:9px}
.jt[data-tier-kind="partner"] .jt-kind{color:var(--gold-soft)}
.jt-name{display:block;font-family:var(--serif);font-size:1.16rem;font-weight:600;color:#fff;line-height:1.16;margin-bottom:11px}
.jt-price{display:block;font-family:var(--serif);font-size:1.9rem;font-weight:700;color:#fff;line-height:1}
.jt-price small{font-size:.72rem;font-weight:500;color:rgba(255,255,255,.62);font-family:var(--sans);letter-spacing:.02em}
/* the white body — the one-line "who it's for" */
.jt-body{flex:1;padding:15px 22px 18px}
.jt-for{display:block;font-size:.82rem;line-height:1.5;color:var(--ink-soft)}
/* POINTER hover — guarded so it never fires (or sticks) on a touch screen */
@media (hover:hover){
  .jt:hover{transform:translateY(-6px);box-shadow:var(--shadow-xl);border-color:var(--gold)}
  .jt:hover::after{box-shadow:inset 0 0 0 1.5px var(--gold)}
}
/* TAP — the same lift + gold ring, only while the card is pressed */
.jt:active{transform:translateY(-6px);box-shadow:var(--shadow-xl);border-color:var(--gold)}
.jt:active::after{box-shadow:inset 0 0 0 1.5px var(--gold)}
/* keyboard focus — gold ring */
.jt:focus-visible{outline:none;border-color:var(--gold);box-shadow:0 0 0 3px rgba(201,163,78,.32),var(--shadow-lg)}
.jt:focus-visible::after{box-shadow:inset 0 0 0 1.5px var(--gold)}
.jt-featured .jt-crown{display:none}
@media (prefers-reduced-motion:reduce){
  .jt{transition:none}
  .jt:hover,.jt:active,.jt:focus-visible{transform:none}
}
/* Phone: the miniatures tighten a touch. */
@media (max-width:720px){
  .jt-head{padding:16px 18px 14px}
  .jt-name{font-size:1.06rem}
  .jt-price{font-size:1.7rem}
  .jt-body{padding:13px 18px 15px}
  .jt-for{font-size:.8rem}
}

/* Phone: once the reader has told us which side they are on, the cards that do
   not apply step back rather than disappearing, so the full picture is still
   there if they want it but the relevant one is unmistakable. */
/* The matched / stepped-back states used to exist only under 720px, because
   the only thing that could set them was a stored choice from the Membership
   page. The chooser now lives in this band at every width, so the states do
   too. Muted tiers stay readable and stay clickable — a reader who answers
   "I practise family office" has not lost the right to look at the partner
   tier, they have only been shown which one is theirs. */
.jt-muted{opacity:.42;filter:saturate(.6);transition:opacity .4s var(--ease-lux),filter .4s var(--ease-lux)}
/* Matched tier — the persistent gold ring + border (same as Membership's
   .tier-match), so the reader's tier is marked without any motion. */
.jt-match{border-color:var(--gold)}
.jt-match::after{box-shadow:inset 0 0 0 1.5px var(--gold)}
/* The home band carries the RESET only — no box, no border, no question. It
   is a single text action that appears once a tier has been chosen on the
   Membership page (or here) and disappears again when it is used. */
/* Below the tiers now (see index.html), so the spacing flips: it needs air
   above it to separate it from the row it acts on, and only a little below
   before the primary action. Reserving no height while hidden is deliberate —
   the band should not carry a gap for a control that is not there. */
.join-guide{background:none;border:0;padding:0;margin:0 0 12px;text-align:right;max-width:none;min-height:1.4em}
.join-guide .tg-reset{color:rgba(255,255,255,.72)}
.join-guide .tg-reset > span::before{background:var(--gold-bright)}
.join-guide .tg-reset:hover,.join-guide .tg-reset:focus-visible{color:var(--gold-bright)}
.join-guide .tg-reset[hidden]{display:none}
@media (max-width:720px){
  .jt-muted{pointer-events:auto}
}
.join-actions{display:flex;gap:14px;justify-content:center;flex-wrap:wrap}

/* =========================================================
   Gilded headline underline
   ========================================================= */
/* ── The rule under a heading ────────────────────────────────────────────────
   Not the golden divider system — that one runs the page width and separates
   two movements. This is a heading's own underscore and belongs to the
   heading, so it takes its cues from the heading and from nothing else.

   Three faults it had. It was pinned to left:0 with a fixed 2.2em width, so
   under a CENTRED heading it hung off the bottom-left corner looking detached
   from the words above it — plainly wrong on the homepage's centred section
   heads. Its length was the same 2.2em under a three-word heading and under a
   nine-word one. And at 2px with an 8px gold bloom it was heavier than the
   hairline language everything else on the site now speaks.

   Now: it inherits the heading's own text-align, so it sits under the first
   letter of a left-aligned heading and centred under a centred one; its
   length is a proportion of the heading's own measure, clamped so it can
   never look like a stray dash under a short title or a second rule under a
   long one; and it is drawn at the shared hairline weight with a soft taper
   at both ends instead of a glow. */
.gilded-head{position:relative;display:inline-block}
.gilded-head::after{
  content:"";position:absolute;bottom:-.16em;height:2px;width:0;
  left:0;right:auto;
  background:linear-gradient(90deg,var(--gold-bright),var(--gold) 62%,rgba(201,163,78,.35));
  border-radius:2px;
  transition:width 1.1s var(--ease-lux) .2s;
}
/* Centred heads: the rule grows from the centre outward, not from the left. */
.center .gilded-head::after,
.section-head.center .gilded-head::after,
[style*="text-align:center"] .gilded-head::after{
  left:50%;transform:translateX(-50%);
  background:linear-gradient(90deg,rgba(201,163,78,.35),var(--gold) 22%,var(--gold-bright) 50%,var(--gold) 78%,rgba(201,163,78,.35));
}
.reveal.in .gilded-head::after,.in .gilded-head::after{width:clamp(2.2em,38%,7em)}



/* ═══════════════════════════════════════════════════════════════════════
   HERO BUTTONS — now the same instrument as the rest of the site
   ═══════════════════════════════════════════════════════════════════════
   This block used to restore, verbatim, every button declaration from an
   earlier build: 6px rounded corners, 1.5px borders, a translate on hover, a
   scale on press — scoped under .hero so it outranked the engraved system
   the rest of the site had moved to. The hero was the one place still
   speaking the old language, and it was the FIRST thing anyone saw. Two
   rounded buttons under a serif monument is exactly the tell that separates
   a template from a commissioned identity.

   It is gone. The hero's two controls now inherit the global engraved
   system — square, hairline, still — and only the things that are genuinely
   hero-specific are set here: a size step, and the fact that the primary sits
   on navy rather than on cream. */
.hero .btn-lg{padding:1.05em 2.2em;font-size:.88rem}
/* On the navy ground the gold plate wants a fractionally deeper edge so it
   does not read as a floating swatch, and a shadow with some navy in it. */
.hero .btn-gold{
  border-color:var(--gold-deep);
  box-shadow:0 1px 2px rgba(6,14,26,.28),0 6px 18px rgba(6,14,26,.22);
}
.hero .btn-gold:hover,.hero .btn-gold:focus-visible{
  box-shadow:0 1px 3px rgba(6,14,26,.3),0 0 17px rgba(201,163,78,.26);
}
.hero .btn-sweep{padding-left:0;padding-right:0;margin-left:.5em}

/* gilded button shimmer */
/* The .gild white-sweep shimmer is removed — too flashy. Buttons answer with a
   quiet tone shift and lift; the membership shine remains the one moment of
   moving light, on join actions only. */
.gild{position:relative}
@keyframes shimmer{to{left:130%}}

/* =========================================================
   EYEBROW — line draws left-to-right on scroll entry
   ========================================================= */
.eyebrow{position:relative}
.eyebrow::before{
  content:"";
  display:inline-block;
  width:0;height:1px;
  background:var(--gold);
  vertical-align:middle;
  margin-right:.6em;
  transition:width .7s var(--ease);
}
/* When the parent reveal fires .in, or directly when eyebrow is in a .in parent */
.reveal.in .eyebrow::before,
.in .eyebrow::before,
.eyebrow.drawn::before{
  width:26px;
}
/* Hero eyebrow draws after its fadeUp */
.hero-eyebrow::before{
  transition:width .7s var(--ease) .9s;
}

/* =========================================================
   CARD — gold light sweep on hover (watchmaker finish)
   ========================================================= */
.mission,.event-card,.k-card{overflow:hidden;position:relative}
.mission::after,.event-card::after,.k-card::after{
  content:"";
  position:absolute;inset:0;
  background:linear-gradient(
    115deg,
    transparent 20%,
    rgba(201,163,78,.07) 45%,
    rgba(220,183,99,.13) 50%,
    rgba(201,163,78,.07) 55%,
    transparent 80%
  );
  transform:translateX(-110%);
  transition:none;
  pointer-events:none;
  z-index:4;
}
.mission:hover::after,.event-card:hover::after,.k-card:hover::after{
  animation:goldSweep .7s ease forwards;
}
@keyframes goldSweep{
  to{transform:translateX(110%)}
}

/* =========================================================
   SECTION DIVIDERS
   ---------------------------------------------------------
   The component itself now lives in css/style.css, built to the v2 rebuild
   spec (logo-tree palette, damped-pendulum swing, scaleX hairlines).

   Everything that used to be here was a KILL SWITCH. A previous pass had
   turned the whole component off — `.divider-leaf,.divider-bloom,
   .divider-line{display:none}`, the band collapsed to
   `clamp(12px,2.4vw,30px)`, and both `.to-dark` and `.on-dark` set to
   `display:none` — while leaving the six divider elements in index.html
   markup. The dividers were in the DOM and invisible, which is why a second,
   parallel divider system got built alongside them before anyone noticed the
   first one existed. Both the switch and the duplicate system are gone; there
   is one divider component again, and these six elements are it.

   Only the genuinely page-specific rule is kept below. */

/* The presence map and the join band sit back-to-back. Any per-section glow
   makes the shorter band read brighter than the taller one and they meet in a
   seam, so these two are flat base navy — one continuous field, no edge. The
   soft glow stays on standalone navy bands (interior heroes, seminars). */
#presence.lit-navy::before,
#join.lit-navy::before{background:none}
#presence.lit-navy::after,
#join.lit-navy::after{display:none}

/* Card reveal: stronger rise + subtle scale so staggered reveals read as a wave */
.k-card.reveal,.event-card.reveal,.mission.reveal{
  transform:translateY(40px) scale(.965);
}
.k-card.reveal.in,.event-card.reveal.in,.mission.reveal.in{
  transform:none;
}
/* Gentler card reveal on mobile — less travel, no scale, so they don't feel stuck */
@media (max-width:720px){
  .k-card.reveal,.event-card.reveal,.mission.reveal{transform:translateY(14px)}
}

@media (max-width:960px){
  .missions-branch,.events-grid,.knowledge-grid{grid-template-columns:repeat(2,1fr)}
  .numbers-grid{grid-template-columns:repeat(2,1fr);gap:36px 24px}
  .president-grid{grid-template-columns:1fr;gap:40px}
  .pp-frame{max-width:380px;margin-inline:auto}
  .join-tiers{grid-template-columns:1fr}
  .rn text{font-size:20px}
  .rn.hub text{font-size:22px}
}
@media (max-width:600px){
  .missions-branch,.events-grid,.knowledge-grid{grid-template-columns:1fr}
  .numbers-grid{grid-template-columns:1fr 1fr}
  .hero-actions .btn,.join-actions .btn{width:100%;justify-content:center}
  .hero{min-height:auto}
}

/* ===== Premium mobile spacing refinements ===== */
@media (max-width:720px){
  /* More generous, even vertical rhythm between sections */
  .section{padding-block:clamp(48px,11vw,72px)}
  .section-head{margin-bottom:28px}
  /* Stats: more breathing room between the four figures */
  .numbers-grid{gap:34px 20px;margin-top:8px}
  /* Card stacks: consistent, comfortable gaps */
  .missions-branch,.events-grid,.knowledge-grid,.join-tiers{gap:16px}
  /* Hero: tighten the country band and give the CTAs room */
  .hero-actions{gap:12px}
  .hero-countries{margin-top:40px;padding-top:22px}
  /* ── Map: pan it, do not shrink it ────────────────────────────────────────
     The figure is a 1200 x 760 drawing carrying 23 named nodes. Fitted to a
     350px column that is a 3.4x reduction: the country labels land at about
     6px on screen and the city labels smaller still, which is not small type,
     it is unreadable type — the section became a smear with a legend under it.

     Shrinking the drawing was never going to work, so the phone gets the map at
     a legible size and pans it instead. The figure bleeds to both screen edges,
     the drawing is held at 860px, and the container scrolls horizontally with
     momentum. js/home-effects.js centres it on Luxembourg on load, so the first
     thing on screen is the headquarters with its nearest markets around it, and
     the reader drags outward from there — which is also the one section on the
     page that now has a gesture of its own rather than only a reveal. */
  .roots-figure{margin-top:8px}
  /* The heading was the loudest thing in the section on a phone: 30px of serif
     over two lines, above a map the reader has to work at. It steps down so the
     map is the subject and the heading introduces it. */
  .roots-section .section-head h2{font-size:clamp(1.5rem,6.4vw,1.82rem);line-height:1.2}
  .roots-pan{
    /* The whole map is scaled to fit the screen width rather than held at a
       fixed width and panned, so every edge label (Canada, Ireland, Vancouver,
       Lisbon) stays inside the screen instead of being cut off by it. All the
       labels live inside the 0–1200 viewBox, so fitting the viewBox to the
       column brings them all on-screen at once. */
    margin-inline:0;
    overflow:visible;
  }
  /* As large as it goes without any label crossing the screen: the content sits
     left-of-centre in the viewBox, so the drawing is scaled up (144%) and nudged
     right (-14% left margin) to balance the margins — ~25px clear on both sides
     at every phone width, measured, nothing cut off. */
  .roots-pan .roots-svg{width:144%;max-width:none;margin-left:-14%;flex:initial;overflow:visible;padding-block:6px}
  .roots-legend{gap:16px 20px;margin-top:20px;flex-wrap:wrap;font-size:.85rem}
  /* President block: balanced spacing */
  .president-grid{gap:32px}
  /* Section dividers: no margin (margins would reveal the page background between sections) */
  .section-divider{margin-block:0}
}
/* =========================================================
   Reduced motion
   ========================================================= */
@media (prefers-reduced-motion:reduce){
  .pp-ring{animation:none}
  .hero-eyebrow,.hero-sub,.hero-actions,.hero-countries{animation:none;opacity:1}
  .hero-title .w{transform:none;opacity:1;animation:none}
  .pq-line{opacity:1}
  .root{stroke-dashoffset:0}
  .rn circle,.rn text{opacity:1;transform:none}
  .stat-root{transition:none}
}

/* ---------- Home → Knowledge journey ----------
   Two clear paths out of the Knowledge section (the hub and the full library),
   and the whole teaser card is a target via a stretched link, so entering the
   hub from the homepage takes one obvious click. */
.head-actions{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.k-linked{position:relative}
.k-linked .k-stretch{position:absolute;inset:0;z-index:3;font-size:0;line-height:0;color:transparent;background:transparent;border:0}
.k-linked:focus-within{outline:2px solid var(--gold);outline-offset:3px}

/* Clickable knowledge teaser cards: tactile press */
.k-linked{cursor:pointer}
.k-linked:active{transform:translateY(-2px) scale(.995)}

/* === BEGIN generated: touch-life hover mirror (tools/mirror_hover.py) === */
/* Touch devices only. js/touch-life.js adds .tl-on to a component
   while it sits in the middle band of the screen, so scrolling is the
   gesture that a pointer cannot make. Do not edit by hand. */
.mission.tl-on{transform:translateY(-6px);box-shadow:var(--shadow-lg);border-color:color-mix(in srgb,var(--c) 40%,var(--line))}
.mission.tl-on .mission-index{color:color-mix(in srgb,var(--c) 30%,var(--gold-soft))}
.mission.tl-on .mission-icon{transform:scale(1.08) rotate(-4deg)}
.event-card.tl-on .ev-leaf{transform:rotate(40deg) scale(1.1)}
.event-card.tl-on .ev-link i{transform:translateX(4px)}
/* (Home tier plates no longer use .tl-on — they animate on tap only.) */
.mission.tl-on::after, .event-card.tl-on::after{animation:goldSweep .7s ease forwards;}
/* === END generated: touch-life hover mirror === */
