Back to the tutorial. Code: clump_foliage, mid_speckle, fringe, rim_arcs in code/foliage.py; the hedge copy in copy_c2f, code/stage0_copy.py.
This is the one technique I'd keep if I had to throw the rest away. It's what I learned from copying Ferrari's hedge, and it works for any leafy mass.

Top left: small lit marks drawn from the dome's raw light. Top right: a clump light field. Bottom left: the same marks drawn from the clump field. Bottom right: plus a fringe, so the crest is where the clumps end. All in his V09 hedge ramp.
Foliage is a heap of clumps, 4–13 px across, painted top to bottom so lower clumps lie in front of higher ones. Each clump has its own light: a cap toward the sun, a body, and a dark band along its bottom that separates it from the clump below. Don't paint the clumps as colour. Paint them as a light field, then draw the small marks from that field.
Clump centres go on a Poisson disc inside the mass. Each clump is a noise-roughened ellipse (along the wand direction, if you have one). Its value is the mass's light where it sits, plus its own sphere light toward the sun, minus the dark band at its bottom:
# foliage.py, inside clump_foliage
sx, sy = ddx / max(a, b), ddy / max(a, b)
nzc = np.sqrt(np.clip(1 - sx * sx - sy * sy, 0, 1))
lc = sx * lx + sy * ly + 0.35 * nzc # own sphere light (L2 = screen dir to the sun)
vv = ddy / b # -1 at the clump's top .. +1 at its bottom
band = np.clip((vv - (1 - dark_band * 2)) / (dark_band * 2 + 1e-9), 0, 1)
fv = np.clip((vo + g * vg + lc * vl - band * vb) / top, 0, 1) # g = the mass's light here
field[inside] = fv[inside]
Call it like this; field is filled in place:
CL = np.full(mask.shape, -1.0)
_, MC = clump_foliage(mask, light, rng, 4, field=CL, r=(3.0, 7.0), vo=0.0, vg=2.6, vl=1.8, vb=2.0)
CL = np.where(CL < 0, light * 0.5, CL)
The weights that worked for the hedge: vg 2.6 (the mass's light), vl 1.8 (the clump's own light), vb 2.0 (the dark band). Raise vb and the clumps separate more.

A clump field inside the willow, seen raw.
mid_speckle lays a dark base, dithered between two close steps with more of the lighter one where the field is higher, and scatters small lit marks (a dot, a pair, a 3-px diagonal, a little cap) whose density rises steeply with the field. That steepness is what makes light gather on clump tops and leaves the lower half of each clump as calm dark base:
lp = np.clip((l - dens_lo) / max(1e-6, 1 - dens_lo), 0, 1) ** dens_gamma
p = dens[0] + (dens[1] - dens[0]) * lp
ph = np.clip((l - hi[0]) / (hi[1] - hi[0]), 0, 1)
tp = top if rng.random() < ph else top - 1 # the top step only where the field is high
Marks are painted dim to bright, so the lit ones lie on top. For the willow I pass dens_lo=0.3 and dark_below=0.2 (no lighter base dither in the darkest bands).
Where the mass meets the sky, the top pixels of the crest clumps are lit. My first clump version had a dark rim on top and read as hollows; the critic put it exactly: "each clump reads as a hollow rather than a ball in sunlight." fringe(..., rim_p=1.0) lights every pixel that's open above, and adds 1–3-px caps and single specks above the line and a few 1–2-px holes. How-to 5 has the whole edge.
In Ferrari's hedge, long light sweeps run along the upper edges of sub-lobes. rim_arcs draws broken 1-px arcs (clean runs) of the lit step along the tops of small lobes, only where the field is high. They helped the hedge copy and I left them out of the willow, where the sprays already do that job.

Clumps painted directly as values: flat green blobs. The clumps have to be a field that marks are drawn from, not the marks themselves.

Speckle on the raw light field: the right marks, no structure. It scored my best blur metric.

The clump version of the hedge copy.
Everything in this grammar is independent of the plant. On the willow, the clumps are stretched along the wands (dirs=), the mark is a hanging spray (how-to 4), and the field decides where the sprays go. On alders and dogwood the mark is a broadleaf lozenge. The field never changes.