Create a 3D topographic map with locations marked on the map using R
I'm going to answer my own question.
The key mistake I made was in not understanding the nature of virtual displacements. When virtual displacements are defined they're usually said to be "consistent with the constraints", and I now think that this phrase is very easy to misunderstand. The way I misunderstand it in my question is when I wrote
and I must show that this holds if $(\delta\mathbf{r_1},\delta\mathbf{r_2})$ satisfy the equation of constraint, meaning the differences in length between the position vectors must match: $$|\mathbf{r_1}+\delta r_1|-|\mathbf{r_1}| = -(|\mathbf{r_2}+\delta r_2|-|\mathbf{r_2}|)$$
The key mistake is in imagining that after being moved by a virtual displacement, the position vectors of the particles must still satisfy the constraint equation. This is wrong. Virtual displacements do not in general leave the system still satisfying the constraints, as a naive reading of "consistent with constraints" would suggest.
A simple illuminating example is a single particle constrained to move on the surface of a sphere. If we consider a virtual displacement of the particle at any given position $\mathbf{r}$, it is not a vector $\delta\mathbf{r}$ such that $\mathbf{r}+\delta\mathbf{r}$ is still on the sphere! No, it is a vector $\delta\mathbf{r}$ lying in the plane tangent to the sphere at point $\mathbf{r}$, so that $\mathbf{r}+\delta\mathbf{r}$ is definitely off the sphere!
The correct way to calculate restrictions on virtual displacements is as follows. For each holonomic equation of constraint of the form $f(\mathbf{r}_1,...,\mathbf{r}_n,t)=0$, the virtual displacements $\delta\mathbf{r}_1,...\delta\mathbf{r}_n$ are restricted by the equation $$\nabla_{r_1}f\cdot\delta\mathbf{r}_1+...+\nabla_{r_n}f\cdot\delta\mathbf{r}_n=0$$ (and not at all by the compleletely wrong equation $f(\mathbf{r}_1+\delta\mathbf{r}_1,...,\mathbf{r}_n+\delta\mathbf{r}_n,t)=0$ I was trying to use in my post).
I will now correct the analysis in my post and show that indeed the forces of constraint do zero virtual work. The holonomic equation of constraint is $$f(\mathbf{r}_1,\mathbf{r}_2) = |\mathbf{r}_1|+|\mathbf{r}_2| -R = 0$$ Let's denote by $x_1,y_1$ the $x,y$ coordinates of the first particle and by $z_2$ (always negative) the $z$-coordinate of the second particle. Then, ignoring the always-vanishing coordinates, we have: $$r_1=|\mathbf{r_1}|=\sqrt{x_1^2+y_1^2}, r_2=|\mathbf{r_2}|=-z_2$$ $$f = \sqrt{x_1^2+y_1^2}-z_2-R=0$$ $$\nabla_{r_1}f = \left(\frac{\partial{f}}{\partial{x_1}},\frac{\partial{f}}{\partial{y_1}}\right)= \left(\frac{x_1}{r_1},\frac{y_1}{r_1}\right)$$ $$\nabla_{r_2}f = \frac{\partial{f}}{\partial{z_2}} = -1$$ And the virtual displacements $\delta\mathbf{r}_1=(\delta x_1,\delta y_1), \delta\mathbf{r}_2=\delta z_2$ must satisfy $$\left(\frac{x_1}{r_1},\frac{y_1}{r_1}\right)\cdot(\delta x_1,\delta y_1) + (-1)\delta z_2 = 0$$ or, back to vectors $$\frac{\mathbf{r}_1\cdot\delta\mathbf{r}_1}{r_1} = \delta z_2$$ But since $\mathbf{r}_1\cdot\delta\mathbf{r}_1 = r_1 \delta r_1 \cos(\phi-\psi)$, where $\phi-\psi$ is precisely the angle between the vectors $\mathbf{r}_1,\delta\mathbf{r}_1$ considered in the post, we arrive at the relation we need to show that the forces of constraint do zero virtual work, as shown in the post: $-\delta r_2 = \delta r_1\cos(\phi-\psi)$ (up to a sign flip I made somewhere, no doubt due to the unfortunate choice of the negative $z$ direction).
I'd go with the answer to HTML in iCal attachment from StackOverflow.
It is not strictly forbidden by the RFC, but DESCRIPTION is not the appropriate property for HTML content.
DESCRIPTION should be the plain text version of your content. The property X-ALT-DESC with a FMTTYPE declaration of text/html is the appropriate property for HTML content.
Combining that with the C# example from Using X-ALT-DESC / Applying HTML to calendar invites in Outlook gives something like the following in Apex:
result += newLine + 'DESCRIPTION:' + description;
string html_body = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">' +
'\n<html>' +
'\n<head>' +
'\n<title></title>' +
'\n</head>' +
'\n<body>';
html_body += '<p>Hello <b>Bold</b> New World</p>';
html_body += '</body>\n</html>';
result += newLine + 'X-ALT-DESC;FMTTYPE=text/html:' + html_body;
result += newLine + 'BEGIN:VALARM';
You might need to experiment with the new line characters a bit.