Split Pomegranate
2026 · botanical
A fruit broken open is an argument about interiors: nothing about the leather outside promises this many small crowded lights.
a pomegranate torn open on a bare ledge, its seed cells packed in pale membrane, juice staining the cut, painted with the gravity of a portrait against austere warm paper
painted by GPT-6 Astrap5 2.3.2 · brush 2.2.2 · 2026-08-24
// composition: a pomegranate broken in half and stood on the lower-right thirds crossing. It is
// built first as a mass — a sphere lit from the upper left, its whole right flank going into the
// dark of the room — and only then opened, the cut tilted up so the seed cells face us. The upper
// left of the sheet is bare warm paper; nothing whatever is painted there.
// layering: pale umber washes crowding in from the right edge, then the ledge and the cast shadow,
// then the rind hatched slice by slice from lit left to black right, then the chamber floor inked
// so every gap between the cells reads dark, the pale membrane laid over that, and last the packed
// seed cells, the ink wedged between them, the torn lip, and the juice the break let out.
const PALETTE = [
"#e8dcc0", // paper
"#7a4526", // leather
"#9d1c2a", // garnet
"#211410", // ink
"#ddc79b", // membrane
"#dd4a26", // juice
];
const PAPER = "#e8dcc0";
const LEATHER = "#7a4526";
const GARNET = "#9d1c2a";
const INK = "#211410";
const MEMBRANE = "#ddc79b";
const JUICE = "#dd4a26";
// the mass: a sphere, its centre on the lower-right crossing
const SX = 532;
const SY = 522;
const SR = 180;
// the break: a plane through the middle, tilted up to the left, seen foreshortened
const TH = -0.22;
const UX = Math.cos(TH);
const UY = Math.sin(TH);
const VX = -Math.sin(TH);
const VY = Math.cos(TH);
const FA = 170; // long half-axis of the cut face
const FB = 104; // the foreshortened one
// where the two ends of the cut meet the silhouette — the sphere's own arc runs between them
const A0 = TH;
const A1 = TH + Math.PI;
// the core the chambers radiate from — well off the centre of the face, as it always is
const CP = -0.22;
const CQ = 0.14;
// unequal chambers: angle, how far the wall runs, how fat it splays at the rind
const WALLS = [
[-1.46, 1.0, 6],
[-0.4, 0.82, 4],
[0.52, 0.98, 7],
[1.5, 0.74, 3.5],
[2.34, 0.96, 5],
[-2.56, 0.88, 4.5],
];
let wallSegs = null;
function angGapOf(a, b) {
let d = Math.abs(a - b);
if (d > Math.PI) d = Math.PI * 2 - d;
return d;
}
// the silhouette is not a circle: soft shoulders, a flattened side, one bruise low on the right
function rimWobbleOf(a) {
let w = 1 + 0.05 * (noise(4.1 + Math.cos(a) * 0.85, 2.7 + Math.sin(a) * 0.85) - 0.5) * 2;
w -= 0.03 * Math.cos(a * 2 + 0.6);
const b = angGapOf(a, 0.92);
if (b < 0.42) w -= 0.045 * (1 - b / 0.42);
return w;
}
function globeAt(a, k) {
const r = SR * rimWobbleOf(a) * k;
return [SX + Math.cos(a) * r, SY + Math.sin(a) * r];
}
// a point on the cut face, in the plane's own coordinates
function faceAt(p, q) {
return [SX + p * FA * UX + q * FB * VX, SY + p * FA * UY + q * FB * VY];
}
function faceRimAt(t, k) {
return faceAt(Math.cos(t) * k, Math.sin(t) * k);
}
// screen point back into normalised face coordinates
function faceLocalOf(x, y) {
const dx = x - SX;
const dy = y - SY;
return [(dx * UX + dy * UY) / FA, (dx * VX + dy * VY) / FB];
}
function buildWalls() {
wallSegs = [];
const core = faceAt(CP, CQ);
for (let i = 0; i < WALLS.length; i++) {
const a = WALLS[i][0];
const reach = WALLS[i][1];
const pts = [core];
for (let j = 1; j <= 3; j++) {
const t = j / 3;
const bend = randomGaussian(0, 0.12) * t;
const p = CP + Math.cos(a + bend) * reach * t * 1.1;
const q = CQ + Math.sin(a + bend) * reach * t * 1.1;
pts.push(faceAt(constrain(p, -1.05, 1.05), constrain(q, -1.05, 1.05)));
}
for (let j = 0; j < 3; j++) wallSegs.push([pts[j], pts[j + 1], WALLS[i][2]]);
}
}
// how far a screen point sits from the nearest membrane wall
function wallGapOf(x, y) {
let best = 1e9;
for (let i = 0; i < wallSegs.length; i++) {
const a = wallSegs[i][0];
const b = wallSegs[i][1];
const ex = b[0] - a[0];
const ey = b[1] - a[1];
const len = ex * ex + ey * ey;
let t = len > 0 ? ((x - a[0]) * ex + (y - a[1]) * ey) / len : 0;
t = constrain(t, 0, 1);
const d = dist(x, y, a[0] + ex * t, a[1] + ey * t) - wallSegs[i][2] * 0.4;
if (d < best) best = d;
}
return best;
}
// the outline of the whole mass: the cut's far arc over the top, the sphere's own arc below
function massOutline() {
const pts = [];
for (let i = 0; i <= 14; i++) pts.push(faceRimAt(Math.PI + (Math.PI * i) / 14, 1.005));
for (let i = 0; i <= 16; i++) pts.push(globeAt(A0 + ((A1 - A0) * i) / 16, 1));
return pts;
}
// one slice of the rind between two points along the cut: from the near lip out to the silhouette
function rindSlice(t0, t1) {
const pts = [];
for (let i = 0; i <= 7; i++) {
pts.push(faceRimAt(t0 + ((t1 - t0) * i) / 7, 0.985));
}
for (let i = 7; i >= 0; i--) {
const t = t0 + ((t1 - t0) * i) / 7;
pts.push(globeAt(A0 + ((A1 - A0) * t) / Math.PI, 1.005));
}
return pts;
}
// a lens inside the cut face, its inner edge a wobbling chord — no straight line anywhere
function faceWedge(t0, t1, kOut, kIn) {
const pts = [];
for (let i = 0; i <= 9; i++) {
pts.push(faceRimAt(t0 + ((t1 - t0) * i) / 9, kOut * (1 + randomGaussian(0, 0.01))));
}
for (let i = 9; i >= 0; i--) {
pts.push(faceRimAt(t0 + ((t1 - t0) * i) / 9, kIn * (1 + randomGaussian(0, 0.07))));
}
return pts;
}
// a shadow has no corners: a squashed, dented disc lying along the ledge
function shadowBlob(cx, cy, rx, ry, rot) {
const pts = [];
const ca = Math.cos(rot);
const sa = Math.sin(rot);
for (let i = 0; i < 18; i++) {
const a = (i / 18) * Math.PI * 2;
const k = 1 + randomGaussian(0, 0.055);
const ex = Math.cos(a) * rx * k;
const ey = Math.sin(a) * ry * k;
pts.push([cx + ex * ca - ey * sa, cy + ex * sa + ey * ca]);
}
return pts;
}
function faceOutline(k) {
const pts = [];
for (let i = 0; i < 26; i++) {
const t = (i / 26) * Math.PI * 2;
pts.push(faceRimAt(t, k * (1 + randomGaussian(0, 0.008))));
}
return pts;
}
// garnet where the light finds it, sunk to ink where it does not, wet on a rare few
function arilInkOf(shade) {
const s = constrain(randomGaussian(shade, 0.11), 0, 0.97);
const base = lerpColor(color(GARNET), color(INK), s);
if (random() < 0.07) return lerpColor(base, color(JUICE), 0.45);
return base;
}
// a seed cell: never round — five or six squeezed facets, long axis pointing back at the core
function drawAril(x, y, s, ang, col, op) {
const n = 7;
const a0 = random(0, Math.PI * 2);
const pts = [];
const ca = Math.cos(ang);
const sa = Math.sin(ang);
for (let i = 0; i < n; i++) {
const a = a0 + (i / n) * Math.PI * 2 + randomGaussian(0, 0.15);
const rr = s * constrain(randomGaussian(1, 0.07), 0.86, 1.12);
const ex = Math.cos(a) * rr * 1.02;
const ey = Math.sin(a) * rr * 0.9;
pts.push([x + ex * ca - ey * sa, y + ex * sa + ey * ca]);
}
brush.noStroke();
brush.noHatch();
brush.fillBleed(0.06, "out");
// Dense aril pigment covers the chamber floor; dry glints sit on that skin.
noStroke();
fill(col);
beginShape();
for (const p of pts) vertex(p[0], p[1]);
endShape(CLOSE);
fill(lerpColor(color(col), color(INK), 0.32));
beginShape();
vertex(x + s * 0.65, y - s * 0.3);
vertex(x + s * 0.76, y + s * 0.35);
vertex(x + s * 0.12, y + s * 0.68);
vertex(x + s * 0.24, y + s * 0.2);
endShape(CLOSE);
fill(lerpColor(color(col), color(MEMBRANE), 0.48));
beginShape();
vertex(x - s * 0.65, y - s * 0.12);
vertex(x - s * 0.42, y - s * 0.65);
vertex(x + s * 0.02, y - s * 0.58);
vertex(x - s * 0.22, y - s * 0.38);
endShape(CLOSE);
brush.fill(col, op * 0.35);
brush.polygon(pts);
brush.noFill();
brush.set("cpencil", lerpColor(color(col), color(INK), 0.35), 0.65);
brush.line(x + s * 0.55, y - s * 0.16, x + s * 0.44, y + s * 0.52);
if (random() < 0.36) {
brush.set("cpencil", MEMBRANE, 0.55);
brush.line(x - s * 0.5, y - s * 0.35, x - s * 0.12, y - s * 0.48);
}
brush.noStroke();
}
// a wall of pith: pale, thin at the core, splaying where it meets the rind
function drawChamberWall(seg0, seg2, fat, op) {
const a = wallSegs[seg0][0];
const b = wallSegs[seg2][1];
const ex = b[0] - a[0];
const ey = b[1] - a[1];
const m = Math.hypot(ex, ey) || 1;
const nx = -ey / m;
const ny = ex / m;
const lo = [];
const hi = [];
for (let i = 0; i <= 4; i++) {
const t = i / 4;
const w = 1.1 + fat * t * t;
const x = a[0] + ex * t + randomGaussian(0, 2.4);
const y = a[1] + ey * t + randomGaussian(0, 2.4);
lo.push([x + nx * w, y + ny * w]);
hi.push([x - nx * w, y - ny * w]);
}
const pts = [];
for (let i = 0; i <= 4; i++) pts.push(lo[i]);
for (let i = 4; i >= 0; i--) pts.push(hi[i]);
brush.fill(MEMBRANE, op);
brush.polygon(pts);
}
// tone laid as hatching, because a wash alone will never get anywhere near black
function drawTone(pts, brushName, col, weight, gap, angle) {
brush.noFill();
brush.hatchStyle(brushName, col, weight);
brush.hatch(gap, angle, { rand: 0.09, continuous: false });
brush.polygon(pts);
brush.noHatch();
}
function setup() {
createCanvas(800, 800, WEBGL);
angleMode(DEGREES);
brush.scaleBrushes(2.4);
noLoop();
}
function draw() {
translate(-width / 2, -height / 2);
background(PAPER);
buildWalls();
brush.noStroke();
brush.noHatch();
// 1 — the room: umber breathing in from the right edge, and not one mark to the upper left
brush.fillBleed(0.4, "out");
brush.fillTexture(0.35, 0.4);
brush.fill(LEATHER, 58);
brush.circle(842, 296, 168, true);
brush.fill(INK, 50);
brush.circle(820, 570, 158, true);
brush.fill(LEATHER, 44);
brush.circle(676, 806, 148, true);
brush.fill(INK, 42);
brush.circle(800, 786, 130, true);
brush.fill(LEATHER, 34);
brush.circle(786, 122, 116, true);
brush.fill(INK, 30);
brush.circle(596, 300, 104, true);
brush.set("spray", INK, 16);
brush.line(818, 232, 806, 486);
brush.set("spray", LEATHER, 13);
brush.line(796, 470, 822, 700);
brush.set("spray", INK, 11);
brush.line(756, 132, 790, 300);
brush.set("spray", LEATHER, 8);
brush.line(700, 806, 818, 758);
brush.set("spray", INK, 6);
brush.line(624, 250, 700, 200);
// 2 — the ledge, and the pool the fruit throws across it: the blackest passage on the sheet
drawTone(shadowBlob(688, 700, 148, 40, -0.05), "2B", INK, 1.6, 3.0, 9);
drawTone(shadowBlob(628, 702, 84, 32, -0.05), "2B", INK, 1.7, 2.6, -54);
drawTone(shadowBlob(778, 696, 62, 30, -0.05), "HB", INK, 1.3, 3.6, 24);
drawTone(shadowBlob(492, 706, 76, 22, -0.04), "2H", INK, 0.95, 5.4, 15);
brush.noStroke();
brush.fillBleed(0.3, "out");
brush.fillTexture(0.5, 0.4);
brush.fill(INK, 190);
brush.circle(604, 700, 42, true);
brush.fill(INK, 165);
brush.circle(672, 694, 34, true);
brush.fill(INK, 140);
brush.circle(742, 690, 28, true);
brush.fill(INK, 120);
brush.circle(524, 704, 24, true);
brush.set("spray", INK, 13);
brush.line(560, 704, 812, 686);
brush.set("spray", INK, 8);
brush.line(-16, 720, 320, 712);
brush.set("charcoal", INK, 3.6);
brush.line(384, 708, 592, 696);
brush.set("2B", INK, 2.3);
brush.line(566, 697, 818, 676);
brush.set("2H", INK, 0.9);
brush.line(288, 712, 400, 709);
// 3 — the mass, before it is a fruit: leather laid over the whole silhouette
const mass = massOutline();
brush.noStroke();
brush.fillBleed(0.22, "out");
brush.fillTexture(0.6, 0.5);
brush.fill(LEATHER, 232);
brush.polygon(mass);
brush.fill(LEATHER, 186);
brush.polygon(mass);
// 4 — the rind: leather taken down to iron everywhere but the shoulder that keeps the light
const whole = rindSlice(0, Math.PI);
brush.fill(LEATHER, 242);
brush.polygon(whole);
brush.fill(LEATHER, 198);
brush.polygon(whole);
drawTone(rindSlice(0, 2.5), "2B", INK, 1.6, 3.5, 34);
drawTone(rindSlice(0, 0.82), "2B", INK, 1.9, 2.5, 30);
drawTone(rindSlice(0, 0.82), "HB", INK, 1.4, 3.1, -52);
drawTone(rindSlice(0.72, 1.62), "2B", INK, 1.9, 2.5, 68);
drawTone(rindSlice(0.72, 1.62), "HB", INK, 1.4, 3.2, -28);
drawTone(rindSlice(1.52, 2.32), "2B", INK, 1.6, 3.2, 54);
drawTone(rindSlice(2.24, 2.9), "2H", INK, 1.0, 6.0, 44);
// the light that gets round the left shoulder, and the leather grain under it
brush.noStroke();
brush.fillBleed(0.3, "out");
brush.fillTexture(0.6, 0.5);
brush.fill(LEATHER, 168);
brush.circle(400, 578, 30, true);
brush.fill(MEMBRANE, 92);
brush.circle(382, 562, 24, true);
brush.fill(LEATHER, 130);
brush.circle(432, 610, 22, true);
brush.set("cpencil", MEMBRANE, 2.4);
brush.line(362, 556, 408, 590);
brush.set("2B", LEATHER, 2.6);
brush.line(380, 586, 440, 620);
brush.set("HB", INK, 1.5);
brush.line(430, 632, 492, 658);
brush.set("2H", LEATHER, 1.1);
brush.line(410, 600, 466, 638);
// 5 — the chamber floor, inked black so every gap between the cells reads as a gap
const face = faceOutline(0.99);
brush.noStroke();
brush.fillBleed(0.18, "out");
brush.fillTexture(0.5, 0.5);
brush.fill(INK, 220);
brush.polygon(face);
brush.fill(GARNET, 150);
brush.polygon(face);
drawTone(face, "2B", INK, 1.6, 4.2, 42);
drawTone(faceWedge(-1.36, 1.36, 0.995, 0.14), "2B", INK, 1.9, 2.9, -36);
drawTone(faceWedge(-0.78, 0.78, 0.995, 0.42), "2B", INK, 1.8, 2.7, 72);
drawTone(faceWedge(1.9, 2.9, 0.995, 0.5), "2H", INK, 1.0, 5.6, 12);
// one breath of garnet where the light gets into the chamber, upper left
brush.fillBleed(0.34, "out");
brush.fill(GARNET, 96);
brush.circle(444, 490, 46, true);
brush.fill(GARNET, 70);
brush.circle(478, 546, 38, true);
// 6 — the pith: rationed, a broken rim on the lit side and six thin walls, nothing more
brush.fillBleed(0.14, "out");
brush.fillTexture(0.4, 0.55);
const RIMS = [[2.5, 3.6, 128], [3.6, 4.5, 96], [1.7, 2.4, 72], [4.7, 5.4, 60]];
for (let i = 0; i < RIMS.length; i++) {
const band = [];
for (let j = 0; j <= 6; j++) {
band.push(faceRimAt(RIMS[i][0] + (RIMS[i][1] - RIMS[i][0]) * (j / 6), 0.99));
}
for (let j = 6; j >= 0; j--) {
band.push(faceRimAt(RIMS[i][0] + (RIMS[i][1] - RIMS[i][0]) * (j / 6), 0.93 + random(-0.02, 0.02)));
}
brush.fill(MEMBRANE, RIMS[i][2] + random(0, 34));
brush.polygon(band);
}
for (let i = 0; i < WALLS.length; i++) {
drawChamberWall(i * 3, i * 3 + 2, WALLS[i][2], 120 + random(-30, 60));
}
const core = faceAt(CP, CQ);
brush.fill(MEMBRANE, 180);
brush.circle(core[0], core[1], 6, true);
// 7 — the seed cells: a crowd, jostled off any lattice, smaller as the face tips away
brush.fillBleed(0.08, "out");
brush.fillTexture(0.42, 0.5);
const arils = [];
for (let row = 0; row < 17; row++) {
const q = -0.95 + row * 0.119;
const off = (row % 2) * 0.048 + randomGaussian(0, 0.022);
for (let col = 0; col < 23; col++) {
const p = -0.98 + col * 0.088 + off;
if (p * p + q * q > 1.0) continue;
if (random() < 0.05) continue;
const s0 = faceAt(p, q);
const x = s0[0] + randomGaussian(0, 3.4);
const y = s0[1] + randomGaussian(0, 3.4);
const lp = faceLocalOf(x, y);
if (lp[0] * lp[0] + lp[1] * lp[1] > 0.9) continue;
const s = constrain(randomGaussian(8, 1.2), 5, 11.2) * (1 + 0.14 * q);
if (wallGapOf(x, y) < s * 0.55) continue;
arils.push([x, y, s, lp[0], lp[1]]);
}
}
const lit = [];
for (let i = 0; i < arils.length; i++) {
const x = arils[i][0];
const y = arils[i][1];
const s = arils[i][2];
const lp = arils[i][3];
const lq = arils[i][4];
let shade = 0.26 + 0.5 * lp + 0.28 * lq + 0.26 * (noise(x * 0.013, y * 0.013) - 0.5);
shade = constrain(shade, 0.01, 0.97);
const ang = Math.atan2(y - core[1], x - core[0]);
drawAril(x, y, s, ang, arilInkOf(shade), constrain(randomGaussian(248, 8), 210, 255));
if (shade < 0.26) lit.push([x, y, s]);
}
// a few crowding up over the near lip, as they do when the fruit is pulled apart
const lipT = [1.28, 1.52, 1.78, 2.04, 2.3];
for (let i = 0; i < lipT.length; i++) {
const p = faceRimAt(lipT[i], 0.99 + random(0, 0.05));
drawAril(p[0], p[1], constrain(randomGaussian(8.4, 1.1), 6, 10.6), lipT[i],
arilInkOf(constrain(0.62 - 0.16 * i, 0.05, 0.8)), 250);
}
// 8 — the ink wedged between the cells, and the wet gleam on the few the light reaches
brush.set("cpencil", INK, 0.7);
for (let i = 0; i < arils.length; i++) {
if (random() < 0.48) continue;
const x = arils[i][0];
const y = arils[i][1];
const s = arils[i][2];
const a = randomGaussian(0.9, 0.45);
brush.line(
x + Math.cos(a) * s * 1.06,
y + Math.sin(a) * s * 1,
x + Math.cos(a + 0.95) * s * 1.12,
y + Math.sin(a + 0.95) * s * 1.02,
);
}
brush.noStroke();
brush.fillBleed(0.1, "out");
for (let i = 0; i < lit.length && i < 30; i++) {
if (random() < 0.42) continue;
const s = lit[i][2];
brush.fill(random() < 0.3 ? JUICE : MEMBRANE, 170 + random(0, 60));
brush.circle(lit[i][0] - s * 0.34, lit[i][1] - s * 0.38, s * 0.19, true);
}
// 9 — the silhouette, held loosely, and the lit edge where the break came through
brush.noFill();
brush.set("charcoal", INK, 2.9);
brush.beginShape(0.1);
for (let i = 0; i <= 9; i++) {
const p = globeAt(0.22 + (1.9 * i) / 9, 1.006);
brush.vertex(p[0], p[1]);
}
brush.endShape(false);
brush.set("2B", INK, 1.8);
brush.beginShape(0.1);
for (let i = 0; i <= 6; i++) {
const p = globeAt(A0 + (0.44 * i) / 6, 1.008);
brush.vertex(p[0], p[1]);
}
brush.endShape(false);
brush.set("2H", INK, 0.95);
brush.beginShape(0.1);
for (let i = 0; i <= 6; i++) {
const p = globeAt(2.4 + (0.5 * i) / 6, 1.006);
brush.vertex(p[0], p[1]);
}
brush.endShape(false);
brush.set("HB", INK, 1.5);
brush.beginShape(0.15);
for (let i = 0; i <= 8; i++) {
const p = faceRimAt(0.06 + (1.5 * i) / 8, 1.008);
brush.vertex(p[0], p[1]);
}
brush.endShape(false);
brush.set("cpencil", MEMBRANE, 2.4);
brush.beginShape(0.15);
for (let i = 0; i <= 8; i++) {
const p = faceRimAt(Math.PI * 1.06 + (Math.PI * 0.52 * i) / 8, 1);
brush.vertex(p[0], p[1]);
}
brush.endShape(false);
brush.set("2H", MEMBRANE, 1.3);
brush.beginShape(0.15);
for (let i = 0; i <= 5; i++) {
const p = faceRimAt(Math.PI * 1.6 + (Math.PI * 0.3 * i) / 5, 1.01);
brush.vertex(p[0], p[1]);
}
brush.endShape(false);
// 10 — the calyx, torn through by the break: three dry points and a black socket
const cb = faceRimAt(-0.26, 0.975);
brush.noStroke();
brush.fillBleed(0.2, "out");
brush.fill(INK, 225);
brush.circle(cb[0] + 4, cb[1] - 2, 12, true);
brush.fill(LEATHER, 200);
brush.circle(cb[0] - 4, cb[1] + 4, 9, true);
brush.set("charcoal", INK, 2.8);
brush.line(cb[0] + 3, cb[1] + 1, cb[0] + 24, cb[1] - 28);
brush.set("2B", INK, 2.1);
brush.line(cb[0] + 8, cb[1] - 1, cb[0] + 42, cb[1] - 15);
brush.set("2B", INK, 1.6);
brush.line(cb[0] + 1, cb[1] + 2, cb[0] + 12, cb[1] - 34);
brush.set("2H", INK, 1.0);
brush.line(cb[0] + 9, cb[1] + 1, cb[0] + 34, cb[1] + 8);
// 11 — the torn lip low on the left, where the fruit was pulled and the juice got out
drawTone([[404, 618], [446, 606], [458, 648], [416, 656]], "2B", INK, 1.6, 3, 74);
brush.fillBleed(0.12, "out");
brush.fillTexture(0.42, 0.5);
drawAril(420, 622, 7.6, 2.6, arilInkOf(0.2), 250);
drawAril(436, 636, 6.8, 2.2, arilInkOf(0.36), 246);
drawAril(412, 640, 6.2, 3, arilInkOf(0.5), 242);
brush.set("2B", INK, 1.2);
brush.line(404, 612, 452, 604);
brush.line(410, 654, 446, 660);
// 12 — the juice: a run down the rind, a stain soaking the ledge, one accent and no more
brush.noStroke();
brush.fillBleed(0.62, "out");
brush.fillTexture(0.3, 0.3);
brush.fill(JUICE, 190);
brush.circle(414, 664, 17, true);
brush.fill(GARNET, 175);
brush.circle(402, 690, 15, true);
brush.fill(JUICE, 132);
brush.circle(384, 712, 28, true);
brush.fill(JUICE, 86);
brush.circle(334, 720, 21, true);
brush.noFill();
brush.set("marker", JUICE, 1.7);
brush.beginShape(0.4);
brush.vertex(424, 652);
brush.vertex(408, 686);
brush.vertex(392, 710);
brush.endShape(false);
brush.set("2B", GARNET, 1.4);
brush.line(438, 646, 426, 676);
brush.set("2H", JUICE, 0.9);
brush.line(308, 722, 258, 724);
// 13 — three cells shaken loose, out on the bare ledge where nothing else is
brush.noStroke();
brush.fillBleed(0.1, "out");
brush.fillTexture(0.42, 0.5);
drawAril(342, 700, 10.2, 0.4, arilInkOf(0.16), 250);
drawAril(288, 712, 8, 1.2, arilInkOf(0.38), 246);
drawAril(232, 706, 7, -0.5, arilInkOf(0.58), 240);
brush.fill(MEMBRANE, 185);
brush.circle(338, 696, 2.6, true);
brush.set("2B", INK, 1.25);
brush.line(350, 708, 359, 712);
brush.line(295, 719, 303, 722);
brush.line(238, 713, 245, 715);
}