/* =========================================================
   Anar Events — canopy.css (branch `canopy`, home page only; loaded after site.css)
   ONE tall painted tree, assets/tree/tree-full.webp (1536×3714, transparent), scrolled down over four screens.
   Measured with Pillow (alpha > 40), in art rows (1536 wide):
     row  169  first foliage (the top fruit clusters at the sides; the centre stays open to row ~297 across the
               logo's width, x 376–1160, and to row ~233 across x 300–1236)
     rows 400–950   solid canopy, edge to edge
     row 1098  the last hanging fruit inside the statement column (x 460–1076): the column is open below
     row 1200  the canopy's underside across the full width (trunk inner edges x 196 / 1346)
     rows 1280–1760 the trunk shrubs (the gap narrows to x 331–1210)
     rows 2360–2800 bare trunks, gap x 196–1349 (the band tile, assets/tree/trunk-band.webp, made seamless)
     row 3080  the roots start at the sides;  row 3240 the ground closes the middle
     rows 3241–3584, x 551–1099: the two big ground pomegranates (nothing may cover them)
   The art is drawn in three layers from the same file (canopy / trunk shrubs / ground) with the bare-trunk band
   tiled between them, so the middle stretches to the content at any width and the ground always sits on the footer.
   Screen offsets derive from those rows via --s (one art px in CSS px) and --tree-top. Everything is normal-flow
   geometry: the motion (canopy.js) never changes an offset, so Pause / Play moves nothing.
   ========================================================= */

main.canopy{
  --art-w:1536;
  --art-h:3714;
  --tree-w:100vw;                                  /* phones: 110vw (below) */
  --s:calc(var(--tree-w) / 1536);                  /* one art pixel */
  --vh100:100vh;
  /* the rendered height of the mark's content (logo + descriptor + tag pair, the Persian twin on its own line): a CSS
     estimate (387px at 1440, the measured value), overwritten with the measured .hero__mark height by canopy.js
     fitHero() (with or without the motion), so the hero height below reserves the real text, not a guess */
  --hero-content:387px;
  /* the hero height the content needs: the mark's top is capped at --tree-top + 278 art rows − the content (the
     bottom of the text 18 rows above the first foliage inside the logo's column, row 297) and floored at 100px
     (the 88px bar + 12): both hold when the hero is at least (100px + content − 109 art rows) / .6 tall */
  --hero-min:calc((100px + var(--hero-content) - 109 * var(--s)) / .6);
  /* ONE effective hero height (the 600px minimum and the content reserve included), used for the hero, the video
     box, the tree's top and the statement offset alike, so a short viewport never has the canopy crossing the hero
     text and nothing sits under the fixed bar */
  --hero-h:max(var(--vh100),600px,var(--hero-min));
  /* the tree's top: the first foliage (row 169) lands at 60% of screen 1, so the solid canopy (rows 400–950) fills
     the bottom ~16% of screen 1 and the top ~40% of screen 2 at 1440×900 (966px of canopy at that width);
     the centre of the canopy starts at row ~297, under the logo, the line and the tag pair */
  --tree-top:calc(var(--hero-h) * .6 - 169 * var(--s));
  /* page y where art row 1120 sits: the statement starts there, right under the last fruit inside its column
     (row 1098), so screen 2 reads "canopy overhead, words beneath" */
  --at-under:calc(var(--tree-top) + 1120 * var(--s));
  --ground-h:calc(634 * var(--s));                 /* rows 3080–3714: the roots and the ground */
  --form-reserve:calc(534 * var(--s));             /* rows 3180–3714: the form ends above the central fruit (row 3241) */
  position:relative;
  overflow:clip;
  background:var(--night);
}
@supports (height:1svh){
  main.canopy{--vh100:100svh}
}
/* phones: the trunks sit at the art's outer 13%, so 110vw keeps ~35px of bark at both edges (recognisably bark, not
   a page border) with the 1150-row gap (330px at 390) open for the copy; wider pushes the trunks off the screen.
   The gutter (24–40px, 27px at 390: a 40px gutter left 310px and orphaned "realized." / "minute.") keeps the copy
   clear of the bark */
@media (max-width:768px){
  /* the first foliage lands at 52% of screen 1 (60% on desktop): at 390 the canopy is a 350px pair of shrubs, and it
     needs more of the first screen to read as the one tree overhead it is on desktop.
     The mark is anchored from its bottom (16px above the foliage, below), so its top sits at .52 × hero − 16px −
     content: the hero must be at least (header + 24px + 16px + content) / .52 tall for the text to clear the fixed
     bar by 24px (390×700: 704px; 360×640: ~740px, the hero taller than the viewport, the page simply longer) */
  main.canopy{--tree-w:110vw;--gutter:clamp(24px,7vw,40px);--tree-top:calc(var(--hero-h) * .52 - 169 * var(--s));
    --hero-content:266px;--hero-min:calc((var(--header-h) + 40px + var(--hero-content)) / .52)}
}

/* ---------- the video: behind everything, fixed while the motion runs (desktop), fades out under .hero__deepen
   (canopy.js block 3) as screen 2 arrives, then display:none (canopy.js) so site.js pauses it; absolute (scrolls
   away with screen 1) without motion and on phones ---------- */
.hero__bg{position:absolute;top:0;left:0;width:100%;height:var(--hero-h);z-index:0;overflow:hidden;background:var(--night)}
html.canopy-motion .hero__bg{position:fixed;inset:0;height:auto}
@media (max-width:768px){
  html.canopy-motion .hero__bg{position:absolute;inset:auto;top:0;left:0;height:var(--hero-h)}
}
.hero__bg.is-gone{display:none}
.hero__bg .hero__video,.hero__bg .hero__tint,.hero__bg .hero__deepen{position:absolute;inset:0}

/* ---------- screen 1: the hero section is transparent (the fixed video shows through) ---------- */
.canopy .hero{height:var(--hero-h);min-height:0;overflow:visible;background:transparent}
/* the plain gold logo with the soft cypress halo (site.css .hero__halo, inside .hero__rise: no panel edge), capped so
   the canopy's centre never reaches it on wide screens; the descriptor line and the tag pair sit under it in the open
   centre. top: 28% of the hero, but never so low that the block (≈380px at 1440) runs into the canopy's centre
   (row ~297) on a short viewport (1440×700: 143px) */
.canopy .hero__mark{width:min(51vw,760px);top:clamp(100px,calc(var(--tree-top) + 278 * var(--s) - var(--hero-content)),28%)}
.canopy .hero__fade,.canopy .hero__rise,.canopy .hero__text{position:relative}
/* the halo carries the contrast behind the logo and the descriptor (the full-frame tint is lighter, round 3): .85 at
   the centre, so the thin Persian kashida under ANAR EVENTS reads over the loop's pale roses and the small parchment
   lines never compete with the bright linens. Round 8: the outer reach pulled in (230% → 180% tall, gone at 78% of
   the radius, not 80%), so the loop's midtones read above the logo and below the tag pair; the stops are re-solved so
   the alpha behind the text is unchanged (measured at 1440: tag bottom .57 → .57, the descriptor's ends .10 → .10;
   the same proportions at 390). The dark field now ends ~270px from the centre vertically (was ~355px) */
.canopy .hero__halo{display:none} /* owner 2026-11-03: no dark "spray" behind the logo; readability comes from the even video tint */
/* the top scrim: 180px of cypress (.55 → 0) over the tint, so the bar's links, the number and the envelope sit on
   night at scroll 0, not on the loop's white drapery; the phone tint (site.css) keeps its bottom ramp under it */
.canopy .hero__tint{background:linear-gradient(rgba(27,34,30,.55) 0,rgba(27,34,30,0) 180px),linear-gradient(rgba(27,34,30,.34),rgba(27,34,30,.66))}
/* phones: the bottom ramp reaches solid night at 82 % (round 6: at 100 % the loop's grey table and vase showed through
   the gap between the two canopy shrubs, y ≈ 690–840 at 390×844; the open middle must sit on cypress) */
@media (max-width:768px){
  .canopy .hero__tint{background:linear-gradient(rgba(27,34,30,.55) 0,rgba(27,34,30,0) 180px),linear-gradient(rgba(27,34,30,.42) 0%,rgba(27,34,30,.72) 55%,var(--night) 82%)}
}
/* over the video (before .is-scrolled) the number beside the handset is parchment (the small gold figures lost
   definition on the bright drapery); the icons stay gold, and the solid bar keeps the gold number */
.page-index .site-header:not(.is-scrolled) .nav-icon--tel .nav-icon__num{color:var(--parch)}
/* the logo, line and tag are visible by default. They start from opacity 0 only under html.canopy-ready, the class
   canopy.js adds while its own context is live (block 5 takes the rise to 1; the class goes with the context on
   Pause / failure, and .reduced wins regardless), so a blocked or failed canopy.js never leaves the hero hidden. Both
   scripts run before first paint, so a warm-cache load never flashes the logo before it rises */
html.canopy-ready.anim-ready .canopy .hero__rise{opacity:0}
.reduced .canopy .hero__rise{opacity:1}
/* in flow under the line (relative, not static: it must paint above the absolutely positioned halo); the Persian twin
   on its own line under the English caps at every width, centred (round 6: on desktop the 14px gold caps and the 22px
   parchment Naskh sat shoulder to shoulder on one baseline, two unrelated sizes; stacked they read like the logo's
   own wordmark over its kashida). The English line: each sentence its own nowrap span, so a narrow break falls at
   the full stop ("HONORING THE ROOTS." / "ELEVATING THE VIBE.") */
.canopy .hero__tag{position:relative;right:auto;bottom:auto;justify-content:center;text-align:center;margin-top:clamp(14px,2vh,24px);row-gap:2px;text-shadow:0 1px 12px rgba(27,34,30,.9)}
.canopy .hero__tag-en{display:inline-flex;flex-wrap:wrap;justify-content:center;gap:0 .6em}
.canopy .hero__tag-en > span{white-space:nowrap}
.canopy .hero__tag .fa{flex:0 0 100%;text-align:center}
/* phones: the mark is positioned from its BOTTOM, 16px above the first foliage anywhere across the width (art row
   169 sits at 52% of the hero on phones: bottom = 48% of the hero + 16px), so the rendered logo + descriptor + tag
   block, at any text size, ends above the canopy instead of hoping a blind top:30% leaves room */
@media (max-width:768px){.canopy .hero__mark{width:78vw;top:auto;bottom:calc(var(--hero-h) * .48 + 16px)}.canopy .hero__tag{bottom:auto}}
/* the logo morph (canopy.js block 6): while the hero logo travels up into the bar (0 < progress < 1) the hero's own
   logo is hidden and the fixed .logo-morph copy draws it; the header slot stays EMPTY until the morph docks
   (html.logo-docked, progress 1), then the header logo shows in the same place with no transition (no jump). Without
   the motion (Pause, reduced motion, no JS) these classes never exist and the header logo follows .is-scrolled */
html.logo-morphing .canopy .hero__logo img{visibility:hidden}
/* owner 2026-11-03: "make the logo brighter slightly". The same lift on the hero logo, the morphing copy and the docked
   header logo, so nothing changes tone mid-morph (brightness 1.18: #C99E5C reads as #EDBA6C over the tinted video) */
.canopy .hero__logo img,.page-index .logo-morph img,.page-index .site-header .nav-home img{filter:brightness(1.18)}
html.canopy-motion .page-index .site-header .nav-home{opacity:0;visibility:hidden;transition:none}
html.canopy-motion.logo-docked .page-index .site-header .nav-home{opacity:1;visibility:visible}
/* the open phone drawer covers the hero: the morphing copy (z 51, a sibling after the header) stays under it */
.site-header.nav-open ~ .logo-morph{visibility:hidden}
/* the header over the hero video (before .is-scrolled): the links and the icons carry the same night shadow as
   the hero line, so a bright frame of the loop never washes them out */
.page-index .site-header:not(.is-scrolled) .site-nav a{text-shadow:0 1px 10px rgba(27,34,30,.9)}
.page-index .site-header:not(.is-scrolled) .nav-icon .icon{filter:drop-shadow(0 1px 6px rgba(27,34,30,.9))}

/* ---------- the tree: one absolutely positioned layer the full height of main; canopy.js moves it at 0.9× scroll
   from screen 3 on (desktop only). No permanent will-change on any layer but the canopy (and that only while the
   motion runs, desktop): GSAP (force3D) promotes the sprigs, the fruit and the ground while their tweens run, so no
   large texture sits resident without need.
   ONE PAINTING, NO DOUBLED PIXELS (round 3): every art pixel is drawn by exactly one layer, and every layer junction
   either sits inside opaque bark or is a still edge. Measured with Pillow (alpha > 40):
     rows 1100–1722, x 197–1346: nothing but the hanging fruit (rows 1080–1149, canopy) and the two shrubs
                                 (rows 1275–1750, x 200–460 / 1082–1342); the trunks end at x ≤ 192 / ≥ 1350 there
     row 1722: the trunks step out to x 226 / 1317 (a painted branch base), full width from here down
   So: the canopy (rows 0–1200) sways (±0.25°) about its BOTTOM centre (row 1200: the junction row never moves, the crown
   does) and fades out over rows 1150–1200 on top of the static trunk bark; the static trunk layer (rows 1100–1900)
   is masked to the bark columns above row 1722 (no shrub pixels under the moving copies) and to the full width
   below; each shrub lives ONLY in its sprig crop (rows 1270–1722, masked off inside the bark, pivoting on the
   bottom of the crop at the trunk edge, so its cut edges are still) ---------- */
.screen,.tree,.ground-art{position:relative}
.tree{position:absolute;top:var(--tree-top);bottom:0;left:50%;width:var(--tree-w);margin-left:calc(var(--tree-w) / -2);z-index:1;pointer-events:none}
.tree img,.ground-art img{display:block;width:100%;max-width:none;height:auto}
/* z inside the tree: the lower static bark under the band (which fades in over it), the sprigs, the canopy, the
   static junction bark on top of it, the falling fruit above everything */
.tree__trunk--low{z-index:1}
.tree__band{z-index:2}
.tree__sprig{z-index:3}
.tree__shoot,.tree__leaf{z-index:3}
.tree__canopy{z-index:4}
.tree__bark{z-index:5}
.fruit-drop{z-index:6}

/* the canopy: rows 0–1200 of the ONE connected painting (tree-full; the four tonal-slice layers in assets/tree/layers
   are retired: moved apart they left a dark mark where each fruit had been). Opaque to row 1150 (the last hanging
   fruit ends at 1149) and gone at 1200, over the static bark. It never moves: it is the canopy without JS, under
   reduced motion and on Pause, and until the branch rig (below) has loaded; then it fades out under the rig */
.tree__canopy{position:absolute;top:0;left:0;width:100%;height:calc(1200 * var(--s));overflow:hidden;
  -webkit-mask-image:linear-gradient(to bottom,#000 calc(1150 * var(--s)),transparent calc(1200 * var(--s)));mask-image:linear-gradient(to bottom,#000 calc(1150 * var(--s)),transparent calc(1200 * var(--s)))}
html.rig-on .tree__canopy{opacity:0;visibility:hidden;transition:opacity .6s ease,visibility 0s .6s}

/* ---------- the branch rig (canopy.js block 2; built and placed by docs/council/rig_compose.py, pivots in
   assets/tree/rig/rig.json). The same crown as the painting, in pieces, in art px (--s): back to front the static
   backdrop (the fruit-free foliage U, masked to the approved silhouette: it fills every gap), four back branches
   (brightness .85, blur .5px: depth), the static trunks + big limbs + the crown's two top corners (tree-full as painted, rows 168–1200), four front
   branches carrying six fruit. Each .rig__b is placed so its cut end (--px / --py inside the sprite) sits on the
   trunk at (--x, --y), turned to its rest angle by the CSS `rotate` property (--r) about that point; canopy.js
   writes only `transform` (its wind / gust rotation and the depth parallax), which composes with it about the same
   origin. Each .rig__f hangs by its stem top (--x / --y in its branch's box; --r undoes the branch's rest angle,
   so it hangs plumb) and swings about it. Hidden (display:none: the lazy images are not fetched) until canopy.js
   builds the motion; shown under html.rig-wait at opacity 0 while its images load, faded in under html.rig-on.
   Nothing in it reaches above art row 335 inside the logo's column (x 376–1160) at rest, nor below row 1076
   inside the statement's (x 460–1076): the motion stays within the clearances (measured, rig_compose.py --clear) */
.tree__rig{display:none;position:absolute;top:0;left:0;width:100%;height:calc(1200 * var(--s));z-index:4;opacity:0}
html.rig-wait .tree__rig{display:block}
html.rig-on .tree__rig{opacity:1;transition:opacity .6s ease}
.tree .tree__rig img{position:absolute;display:block;width:100%;height:auto;max-width:none}
.tree .tree__rig .rig__bd{left:0;top:calc(192 * var(--s))}
.tree .tree__rig .rig__limbs{left:0;top:calc(168 * var(--s))}
.rig__b{position:absolute;left:calc((var(--x) - var(--px)) * var(--s));top:calc((var(--y) - var(--py)) * var(--s));
  width:calc(var(--w) * var(--s));height:calc(var(--h) * var(--s));transform-origin:calc(var(--px) * var(--s)) calc(var(--py) * var(--s));rotate:var(--r);will-change:transform}
.tree .tree__rig .rig__b > img{position:static;height:100%}
.rig__b--back > img{filter:brightness(.85) blur(.5px)}
.rig__f{position:absolute;left:calc((var(--x) - var(--px)) * var(--s));top:calc(var(--y) * var(--s));width:calc(var(--w) * var(--s));
  transform-origin:calc(var(--px) * var(--s)) 0;rotate:var(--r);will-change:transform}
.tree .tree__rig .rig__f > img{position:static}
/* the six swaying pieces of the old static limbs layer (owner 2026-11-03): placed like a branch (its pivot --px / --py on
   the trunk at --x / --y), no rest angle; canopy.js 7d writes their sway */
.rig__p{position:absolute;left:calc((var(--x) - var(--px)) * var(--s));top:calc((var(--y) - var(--py)) * var(--s));
  width:calc(var(--w) * var(--s));height:calc(var(--h) * var(--s));transform-origin:calc(var(--px) * var(--s)) calc(var(--py) * var(--s));will-change:transform}
.tree .tree__rig .rig__p > img{position:static;height:100%}
/* desktop: the container is its own layer too (the tree's parallax moves it from screen 3 on) */
@media (min-width:769px){html.rig-wait .tree__rig{will-change:transform}}
/* the static junction bark (rows 1000–1300, above the canopy): the bark columns only (x ≤ 215 / ≥ 1326 — the trunks
   end at x ≤ 201 / ≥ 1341 from row 1090 down, and the shrubs stay outside those columns above row 1300), fading in
   over its first 100 rows so it takes the bark over from the moving layers gradually, and overlapping the lower
   static bark (from row 1272) by 28 rows: two elements meeting at one fractional edge draw a half-covered seam, an
   overlap does not. The leaves and branches keep moving; the trunks under them never do (the moving layers' bark,
   displaced < 1px by the sway, sits hidden beneath it) */
.tree__bark{position:absolute;top:calc(1000 * var(--s));left:0;width:100%;height:calc(300 * var(--s));overflow:hidden;
  -webkit-mask-image:linear-gradient(to right,#000 calc(215 * var(--s)),transparent calc(215 * var(--s)),transparent calc(1326 * var(--s)),#000 calc(1326 * var(--s))),linear-gradient(to bottom,transparent 0,#000 calc(100 * var(--s)));
  -webkit-mask-composite:source-in;
  mask-image:linear-gradient(to right,#000 calc(215 * var(--s)),transparent calc(215 * var(--s)),transparent calc(1326 * var(--s)),#000 calc(1326 * var(--s))),linear-gradient(to bottom,transparent 0,#000 calc(100 * var(--s)));
  mask-composite:intersect}
.tree__bark img{margin-top:calc(-1000 * var(--s))}
/* the lower static bark: rows 1272–1900. Two mask layers, composited as a union (the CSS default): the bark columns
   (x ≤ 198 / ≥ 1340: the trunks end at x ≤ 192 / ≥ 1350, so each column runs 6–10 art px past the bark, under the
   sprig's own fade-in) at every row, plus the full width from row 1697 (offset 425) down, under the sprigs' 25-row fade-out.
   The shrub rectangle between them is left to the sprigs */
.tree__trunk{position:absolute;top:calc(1272 * var(--s));left:0;width:100%;height:calc(628 * var(--s));overflow:hidden;
  -webkit-mask-image:linear-gradient(to right,#000 calc(198 * var(--s)),transparent calc(198 * var(--s)),transparent calc(1340 * var(--s)),#000 calc(1340 * var(--s))),linear-gradient(to bottom,transparent calc(425 * var(--s)),#000 calc(425 * var(--s)));
  -webkit-mask-composite:source-over;
  mask-image:linear-gradient(to right,#000 calc(198 * var(--s)),transparent calc(198 * var(--s)),transparent calc(1340 * var(--s)),#000 calc(1340 * var(--s))),linear-gradient(to bottom,transparent calc(425 * var(--s)),#000 calc(425 * var(--s)));
  mask-composite:add}
.tree__trunk img{margin-top:calc(-1272 * var(--s))}
/* the two shrubs (rows 1270–1722), each its own crop: the moving copy of its pixels. canopy.js sways them about the
   bottom of the crop at the trunk edge (left ±1.2°, right ±1.6°: the tips move ~8–12px, the crop top ~12px), so the
   crop must carry no bark and no hard cut: the mask opens over 8 art px at the trunk edge (x 190 → 198 / 1348 → 1340;
   the trunks end at x ≤ 192 / ≥ 1350 on every row of the crop), over the static column that runs to the same line,
   and fades out over the crop's last 25 rows (1697 → 1722) onto the static full-width copy below. At rest the two
   copies coincide; swayed, the base (the pivot) stays put and nothing but leaf and stem moves. The image inside
   each crop is the full tree width (--tree-w), so the crop registers with the tree */
.tree__sprig{position:absolute;top:calc(1270 * var(--s));width:calc(470 * var(--s));height:calc(452 * var(--s));overflow:hidden}
.tree__sprig img{width:var(--tree-w);margin-top:calc(-1270 * var(--s))}
.tree__sprig--l{left:0;transform-origin:calc(197 * var(--s)) 100%;
  -webkit-mask-image:linear-gradient(to right,transparent calc(190 * var(--s)),#000 calc(198 * var(--s))),linear-gradient(to bottom,#000 calc(427 * var(--s)),transparent calc(452 * var(--s)));-webkit-mask-composite:source-in;
  mask-image:linear-gradient(to right,transparent calc(190 * var(--s)),#000 calc(198 * var(--s))),linear-gradient(to bottom,#000 calc(427 * var(--s)),transparent calc(452 * var(--s)));mask-composite:intersect}
.tree__sprig--r{right:0;transform-origin:calc(100% - 190 * var(--s)) 100%;
  -webkit-mask-image:linear-gradient(to left,transparent calc(188 * var(--s)),#000 calc(196 * var(--s))),linear-gradient(to bottom,#000 calc(427 * var(--s)),transparent calc(452 * var(--s)));-webkit-mask-composite:source-in;
  mask-image:linear-gradient(to left,transparent calc(188 * var(--s)),#000 calc(196 * var(--s))),linear-gradient(to bottom,#000 calc(427 * var(--s)),transparent calc(452 * var(--s)));mask-composite:intersect}
.tree__sprig--r img{margin-left:calc(-1066 * var(--s))}
/* the bare-trunk band: trunk-band.webp (rows 2360–2800, seamless) tiled from row 1800 down to the bottom of main,
   fading in over the opaque trunk layer; phones (no trunk layer) tile it from row 1060, opaque by row 1140, i.e.
   fully under the canopy's fade (rows 1150–1200), so the crossfade happens on bark, not on night */
.tree__band{position:absolute;left:0;width:100%;top:calc(1800 * var(--s));bottom:0;
  /* an inner-edge shade over the tile (round 5): each trunk darkens toward the open middle (the inner edges sit at
     x 196 / 1349 = 12.8% / 87.8%), so the tiled bark reads as two round trunks behind the sprigs, not two flat curtains */
  background:linear-gradient(to right,rgba(27,34,30,0) 9%,rgba(27,34,30,.35) 12.8%,rgba(27,34,30,.35) 87.2%,rgba(27,34,30,0) 91%),url("../tree/trunk-band.webp") center top / 100% auto repeat-y;
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 calc(60 * var(--s)));mask-image:linear-gradient(to bottom,transparent 0,#000 calc(60 * var(--s)))}
@media (max-width:768px){
  .tree__trunk,.tree__sprig,.tree__bark{display:none}
  /* an 80-row soft top mask (22px at 390), the desktop inner-edge shade (round 6: each 35px strip darkens toward the
     open middle, so the two read as round trunks, not a flat brown border around the copy; the inner edges sit at
     12.8 % / 87.2 % of the 110vw tile) in front of a 25% cypress tint over the tile: at 390px the bright bark strips
     read as a wallpaper border against the parchment copy; the tint sits them back into the night. It ramps in from
     0 at the canopy junction (rows 1140–1300), so the untinted canopy bark meets it without a tonal step */
  .tree__band{top:calc(1060 * var(--s));background:linear-gradient(to right,rgba(27,34,30,0) 7%,rgba(27,34,30,.4) 13%,rgba(27,34,30,.4) 87%,rgba(27,34,30,0) 93%),linear-gradient(rgba(27,34,30,0) calc(80 * var(--s)),rgba(27,34,30,.25) calc(240 * var(--s)),rgba(27,34,30,.25)),url("../tree/trunk-band.webp") center top / 100% auto repeat-y;
    -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 calc(80 * var(--s)));mask-image:linear-gradient(to bottom,transparent 0,#000 calc(80 * var(--s)))}
  /* phones: no falling fruit (at 390px it hung over the 21px bark sliver and read as a cut-off disc at the edge) */
  .tree img.fruit-drop{display:none}
}
/* the falling fruit (assets/tree/fruit-drop.webp, 82×91, cut from tile-B): hangs under the left trunk's branch at
   x 150 / row 1000, well left of the statement column, and drops 1.6 screens with scroll (canopy.js), drifting
   30px right (still outside the column) */
.tree img.fruit-drop{position:absolute;left:calc(150 * var(--s));top:calc(1000 * var(--s));width:calc(82 * var(--s));height:auto;transform-origin:50% 50%}

/* the ground: rows 3080–3714 at the bottom of main, outside the parallax layer (the form and the footer sit on it
   exactly); its top 100 rows fade in over the band; rises 40px into place on screen 4 (canopy.js) */
.ground-art{position:absolute;left:50%;bottom:0;width:var(--tree-w);height:var(--ground-h);margin-left:calc(var(--tree-w) / -2);overflow:hidden;z-index:1;pointer-events:none;
  -webkit-mask-image:linear-gradient(to bottom,transparent 0,#000 calc(100 * var(--s)));mask-image:linear-gradient(to bottom,transparent 0,#000 calc(100 * var(--s)))}
.ground-art img{margin-top:0}
/* the whole ground fruit, lifted out of the plate (docs/council/pom_cut.py: the plate under it is repainted, the sprite
   carries the fruit's own dark rim, so a rocked fruit leaves no mark). It rocks on its contact point (canopy.js 7a) */
.ground-art img.pom-rock{position:absolute;left:calc(539 * var(--s));top:calc(158 * var(--s));width:calc(259 * var(--s));height:auto;margin:0;transform-origin:50% 97%}
.ground-art img.pom-rock--half{left:calc(801 * var(--s));top:calc(194 * var(--s));width:calc(237 * var(--s))}
/* the fallen fruit on the moss left of the big pair (x 300 / row 3440), rolls in as the ground arrives (canopy.js);
   its own sprite (assets/tree/fruit-roll.webp): the same canopy fruit, graded in Pillow to the ground pair's measured
   hue / saturation / value with its cast shadow baked in, so no CSS filter (round 5: the filtered copy read magenta) */
.ground-art img.fruit-roll{position:absolute;left:calc(300 * var(--s));top:calc(360 * var(--s));width:calc(70 * var(--s));height:auto;margin:0;transform-origin:50% 50%}

/* ---------- the content screens: normal flow above the art (z 2), the middle kept open ---------- */
.screen{z-index:2}
.screen__col{width:100%;margin-inline:auto;padding-inline:var(--gutter);text-align:center}
.screen .kashida{margin:var(--s2) auto 0}
.screen h2{font-size:clamp(32px,4vw,48px);line-height:1.1;text-wrap:balance}
.screen .eyebrow{margin-bottom:var(--s1)}
/* the Persian eyebrows on the home screens: 20px, the brand's second voice over the 48px h2 (not a footnote) */
.screen .eyebrow .fa{font-size:20px;line-height:1.5}
/* screen 2: starts right under the canopy's underside for its column (row 1120). The block is NOT centred in a
   viewport-derived box: it packs to the top of the column, 40–72px under the canopy clearance boundary, so the
   eyebrow, Reimagined Heritage, the kashida, the sentence and the promises read as one composition directly under
   the foliage (at 1440×900 the whole block is in one viewport once the canopy's solid body has passed the bar). The
   min-height (one viewport minus the header minus 420 art rows) keeps a short tail before the celebrations without
   the old 200px void. The column stays inside the shrub gap (x 331–1210 at the narrowest) */
.screen--statement{padding-top:max(0px,calc(var(--at-under) - var(--hero-h)))}
.screen--statement .screen__col{max-width:min(640px + 2 * var(--gutter),44vw + 2 * var(--gutter));min-height:calc(var(--vh100) - var(--header-h) - 420 * var(--s));display:grid;align-content:start;padding-top:clamp(40px,6vh,72px)}
/* desktop: the same 40–72px under the canopy clearance as the base rule, by the owner's choice (round 6: the round-5
   140–220px was tried and reverted; the statement packs to the top of its column, right under the foliage); the
   column (≤ 640px) stays inside the shrub gap (x 331–1210 = 824px at 1440) at every offset, measured */
@media (min-width:769px){.screen--statement .screen__col{padding-top:clamp(40px,6vh,72px)}}
.screen--statement h2{font-size:clamp(32px,3.3vw,48px)}
.statement__one{margin:var(--s3) auto 0;font-size:clamp(20px,1.8vw,24px);line-height:1.4;max-width:24em;text-wrap:balance}
/* the three promises as three short balanced lines (no rules above them, round 5: the repeated dashes diluted the
   heading kashidas; the spacing carries the structure) */
.promises{display:grid;gap:var(--s2);margin:var(--s3) auto 0;color:var(--parch);font-size:clamp(17px,1.4vw,20px);line-height:1.4}
.promises li{text-wrap:balance}
/* screen 3: the celebrations strip accordion (adapted from the Arch version) in the open gap between the bare trunks
   (x 196–1349 = 1078px at 1440: the column is ≤ 68vw, 979px; on tablets ≤ 72vw, 737px at 1024 inside the 769px gap),
   64–96px under the statement */
.screen--celebrations{padding-top:clamp(64px,10vh,96px)}
.screen--celebrations .screen__col{max-width:min(1000px + 2 * var(--gutter),68vw)}
/* tablets 769–1024px (iPad portrait): the statement column widens to 60vw (its text stays inside the shrub gap, x 172–630
   at 800, with the 48px gutter); the celebrations column to 72vw, still inside the trunk gap (75 % of the width) */
@media (min-width:769px) and (max-width:1024px){
  .screen--statement .screen__col{max-width:min(640px + 2 * var(--gutter),60vw + 2 * var(--gutter))}
  .screen--celebrations .screen__col{max-width:72vw}
}
/* Stacked cards with every body visible are the default at every width: no JS, phones, and short landscape viewports
   (700px tall or less). The strip (one open panel, the rest collapsed behind their overlay triggers) exists only once
   canopy.js has wired its listeners and states (.accordion-ready), from 769px wide AND 701px tall. Night palette: deep
   night under each photo, a cypress gradient over it, parchment text, gold accents, labels and "+" */
.accordion{display:grid;gap:var(--s2);margin-top:clamp(32px,5vh,48px);text-align:left}
.accordion__panel{position:relative;overflow:hidden;background:var(--deep);color:var(--parch);border-radius:2px;min-height:300px}
.accordion__media{position:absolute;inset:0}
.accordion__media img{width:100%;height:100%;object-fit:cover;transition:filter .6s var(--ease),transform .6s var(--ease)}
.accordion__media::after{content:"";position:absolute;inset:0;background:linear-gradient(to top,rgba(18,23,20,.9) 0%,rgba(18,23,20,.35) 55%,rgba(18,23,20,.12) 100%)}
/* the overlay triggers only mean something once canopy.js listens to them */
.accordion__trigger{position:absolute;inset:0;width:100%;text-align:left;z-index:2;background:none;border:0;padding:0;cursor:pointer}
.accordion:not(.accordion-ready) .accordion__trigger{display:none}
.accordion__trigger:focus-visible{outline:2px solid var(--gold);outline-offset:-6px}
.accordion__label{position:absolute;left:var(--s2);top:var(--s2);font-size:14px;line-height:20px;letter-spacing:.14em;text-transform:uppercase;color:var(--gold);z-index:1;display:none;white-space:nowrap}
/* the body sits above the trigger (z 3) but lets the pointer through, except on its title link */
.accordion__body{position:relative;z-index:3;padding:var(--s3) var(--s2) var(--s2);display:grid;gap:var(--s1);min-height:100%;align-content:end;pointer-events:none;text-shadow:0 1px 10px rgba(18,23,20,.8)}
.accordion__body[hidden]{display:none}
.accordion__body a{pointer-events:auto}
.accordion__body .fa{font-size:16px;line-height:24px;color:var(--gold);text-align:left}
.accordion__body h3{font-size:clamp(24px,2.4vw,32px);line-height:1.15}
/* each title links to its section on weddings.html: the quiet 2px gold .45 underline, full gold on hover / focus */
.accordion__body h3 a{display:inline-block;border-bottom:2px solid rgba(201,158,92,.45);padding-bottom:2px;transition:border-color .3s,color .3s}
.accordion__body h3 a:hover,.accordion__body h3 a:focus-visible{border-bottom-color:var(--gold)}
.accordion__body p:last-child{max-width:30em;font-size:16px;line-height:24px;color:var(--parch);opacity:.92;text-wrap:balance}
@media (min-width:769px){
  .accordion__body{padding:var(--s4) var(--s3) var(--s3)}
}
@media (min-width:769px) and (min-height:701px){
  /* the strip's height is its content's (never a viewport-capped height that clips the open body), at least 60vh/560px */
  .accordion.accordion-ready{display:flex;gap:var(--s1);min-height:min(60vh,560px)}
  .accordion-ready .accordion__panel{flex:1 1 0;min-height:0;transition:flex .7s var(--ease)}
  .accordion-ready .accordion__panel.is-open{flex:6 1 0}
  .accordion-ready .accordion__panel:not(.is-open) .accordion__media img{filter:blur(2px);transform:scale(1.04)}
  .accordion-ready .accordion__panel:not(.is-open) .accordion__media::after{background:linear-gradient(to top,rgba(18,23,20,.8) 0%,rgba(18,23,20,.3) 100%)}
  /* a closed body is lifted out of flow, so the strip's height comes from the open body alone (a closed strip is
     ~90px wide: its wrapped text must never set the height) */
  .accordion-ready .accordion__panel:not(.is-open) .accordion__body{position:absolute;inset:0;opacity:0;transition:opacity .25s}
  .accordion-ready .accordion__panel.is-open .accordion__body{opacity:1;transition:opacity .6s .25s}
  .accordion-ready .accordion__panel:not(.is-open) .accordion__label{display:block;writing-mode:vertical-rl;left:auto;right:50%;top:auto;bottom:40px;transform:translateX(50%) rotate(180deg)}
  /* a collapsed strip says it opens: a small gold "+" at its foot, under the vertical label */
  .accordion-ready .accordion__panel:not(.is-open)::after{content:"+";position:absolute;left:50%;bottom:10px;transform:translateX(-50%);z-index:1;color:var(--gold);font-size:20px;line-height:20px;pointer-events:none}
}
/* Pause and reduced motion: the strip still opens, it just does not animate (no blur / scale either) */
.reduced .accordion__panel,.reduced .accordion__media img,.reduced .accordion__body{transition:none!important}
.reduced .accordion-ready .accordion__panel .accordion__media img{transform:none}
@media (prefers-reduced-motion:reduce){
  .accordion__panel,.accordion__media img,.accordion__body{transition:none!important}
  .accordion-ready .accordion__panel .accordion__media img{transform:none}
}
.cel__foot{margin-top:calc(clamp(32px,5vh,48px) + var(--s2));font-size:16px;line-height:24px;color:var(--stone);text-wrap:balance}
/* screen 4: the short form (names, email + phone, message, button) ends above the ground's central fruit; the ground + footer close the page */
/* 64–110px under the photo row (round 5: 96–170 split the form over two scroll stops at 1440×900, the button
   stranded under the bar) */
.screen--inquire{padding-top:clamp(64px,9vh,110px);padding-bottom:var(--form-reserve)}
.screen--inquire .screen__col{max-width:min(680px + 2 * var(--gutter),56vw)}
/* the form on the roots: no panel fill and no gold top rule (the heading's kashida is the one line; a translucent card
   was the one boxy shape on the organic page); the field fills and the gold underlines carry the form; 24px rows */
.screen--inquire .form{margin-top:var(--s3);gap:24px;text-align:left;background:transparent;border-top:0;padding:0}
/* the submit row and the reply-time note are centred like the heading, the kashida and the call line: one axis on
   the roots screen (the labels and helper text stay left-aligned) */
.screen--inquire .form__submit,.screen--inquire .form__note{text-align:center}
/* the call line sits under the kashida, above the form (parents who prefer to speak see it before the fields) */
.inquire__call{margin-top:var(--s3);color:var(--stone);font-size:16px;line-height:24px}
/* the quiet 2px gold .45 underline of the celebrations titles, full gold on hover / focus (round 6: with the kashida, two full gold
   underlines and the first field's rule, four gold rules stacked within 200px on the roots screen) */
.inquire__call a{color:var(--parch);border-bottom:2px solid rgba(201,158,92,.45);padding-bottom:2px;transition:border-color .3s,color .3s}
.inquire__call a:hover,.inquire__call a:focus-visible{color:var(--gold);border-bottom-color:var(--gold)}

/* drifting leaves (site.js block 8 animates every .leaf): screens 2–3, over the trunks at the edges (x ≤ 180 / ≥ 1260
   at 1440), never over the copy or the photo row (which ends 110px inside the trunk edge at 1440, 65px at 1280) */
.screen--statement .leaf--1{right:3vw;top:62%;transform:rotate(12deg)}
.screen--celebrations .leaf--3{left:-48px;top:18%;transform:rotate(-8deg)}
/* (the screen-4 leaf and the screen-3 right leaf are gone, rounds 5 and 6: pasted over the bare trunk, its fruit cut
   by the viewport edge, each read as a sticker, not part of the one painting) */

/* phones: everything centred at full width (40px gutters), the photos stacked, the leaves off */
@media (max-width:768px){
  .screen__col,.screen--statement .screen__col,.screen--celebrations .screen__col,.screen--inquire .screen__col{max-width:none}
  /* the whole canopy (352px at 390) sits inside screen 1 on phones, so the statement is a compact block after it, not a
     viewport-high column; the promises end ≤ 80px above "The celebrations" (40px here + 32–40px below, no void).
     Round 8: the statement starts at the canopy's own clearance, not at the hero's bottom: art row 1150, where the
     canopy is fully opaque for the last time (Pillow, measured on the round-8 four-layer stack with the 1150–1200 mask: the last
     pixel above alpha .16 across the text column, x 206–1330, is row 1148, the hanging fruit), so the section's
     top is --tree-top + 1150 rows (a negative margin into the hero's solid-night bottom ramp; positive where the
     canopy ends below the hero, e.g. 768×1024) and the eyebrow sits 28px under it (≥ 16px clearance with the sway,
     ±1px at the fruit, and the bounce, which lifts). 390×844: fruit 713, eyebrow 741 (was 922, a 209px corridor) */
  .screen--statement{padding-top:0;margin-top:calc(var(--tree-top) + 1150 * var(--s) - var(--hero-h))}
  .screen--statement .screen__col{min-height:0;padding-block:28px 40px}
  .screen--celebrations{padding-top:32px}
  /* the cards clear the bark strips too (the trunks' inner edges sit at 9.03vw from each side of the 110vw tree), 4px in */
  .accordion{margin-inline:max(0px,calc(9.03vw + 4px - var(--gutter)))}
  /* no drifting leaves on phones: the copy runs edge to edge, so a leaf would sit over it (site.js skips hidden leaves) */
  .canopy .leaf{display:none}
  .promises{font-size:18px}
  /* the "How we work +" tab (36px wide, mid-height, right edge; hidden while the hero or the photo row is in view and
     while scrolling, site.js) must never sit over text or a slot: the blocks that can meet it keep 44px of right
     clearance, i.e. the gutter topped up (the centred promises shift a few px, invisible). Not the celebrations
     cards (round 7) and not the inquiry form (round 8): site.js hides the tab while the celebrations accordion, #inquire
     or the footer is in view, so the extra right pad only pushed the cards, the fields and the button off the axis; the form keeps
     equal gutters (27px / 27px at 390) */
  .promises{padding-right:max(0px,44px - var(--gutter))}
}

/* ---------- the trunks' own life (owner 2026-11-03; canopy.js block 7) ----------
   Each shoot: the box placed so its base point (--px / --py inside it) sits on the trunk's inner edge at (--x, --y),
   turned to its rest angle (--r) about that point; canopy.js writes only its sway (transform, same origin). The first
   22 art px fade in from the bark, so the shoot grows out of the trunk with no cut end. A touch darker than the
   canopy (the trunks are in shade). --flip mirrors the painting inside the box (the base stays on the box edge) */
.tree__shoot{position:absolute;left:calc((var(--x) - var(--px)) * var(--s));top:calc((var(--y) - var(--py)) * var(--s));
  width:calc(var(--w) * var(--s));height:calc(var(--h) * var(--s));transform-origin:calc(var(--px) * var(--s)) calc(var(--py) * var(--s));rotate:var(--r);pointer-events:none}
.tree .tree__shoot img{width:100%;height:100%;filter:brightness(.8)}
.tree__shoot--flip img{transform:scaleX(-1)}
.tree__shoot--l{-webkit-mask-image:linear-gradient(to right,transparent 0,#000 calc(22 * var(--s)));mask-image:linear-gradient(to right,transparent 0,#000 calc(22 * var(--s)))}
.tree__shoot--r{-webkit-mask-image:linear-gradient(to left,transparent 0,#000 calc(22 * var(--s)));mask-image:linear-gradient(to left,transparent 0,#000 calc(22 * var(--s)))}
/* the falling leaves: in the side gaps between the trunk and the content columns, invisible until canopy.js lets
   each one drift down (opacity 0 at rest: nothing is ever stuck mid-air on Pause / reduced motion / without JS) */
.tree img.tree__leaf{display:none;position:absolute;left:calc(var(--x) * var(--s));top:calc(var(--y) * var(--s));width:calc(var(--w) * var(--s));height:auto;opacity:0;pointer-events:none}
@media (min-width:769px){html.canopy-motion .tree img.tree__leaf{display:block}}
@media (max-width:768px){.tree__shoot{display:none}}
