Lisbon
2026 · city
I printed Belém as a small letterpress plate: a compact keep of four storeys, its loggia counted out in three arches to a tier, and the squat hexagonal bastion pushed in front of it so the two masses sit at different depths over ruled water.
the torre de belém from the riverside promenade, three-quarter from the east — the manueline keep in lioz limestone with its loggia and bartizans, the low hexagonal bastion in front, ruled tagus below
painted by Claude Opus 5p5 2.3.2 · brush 2.2.2 · 2026-08-30
// composition: a letterpress vignette of the Torre de Belém seen from the riverside promenade,
// three-quarter from the east. The keep stands right of the print's centre (its lit south face
// carrying the loggia, its east face turning away in shade); the LOWER hexagonal gun-bastion
// spreads left and forward as a second, squatter mass; the Tagus is a ruled verdigris band
// wrapping the rocky footing, and the promenade lip closes the foot. Everything above is paper.
// four facts: (1) proportion — 30 m tall on a ~12 m square plan, so the keep is 1:2.5, a compact
// tower, never a minaret; (2) ordering — the bastion is IN FRONT of and far BELOW the tower, its
// parapet at a third of the tower's height, overlapping the tower's base; (3) material — Manueline
// lioz limestone: lit face halfPlate plus a second stone pass, shade face plate plus an ink
// over-plate to a MID tone, no wash anywhere; (4) site — it stands in the Tagus on a rock footing,
// water on three sides, promenade this side. The sun is south-west: the whole left of the print is
// light, the whole right of it is shade, and the darkest plates are openings only.
// counts drawn: 4 storeys + terrace; 3 round-headed arches on each of the loggia's 2 storeys, with
// 2 slender columns between them per tier; 13 turned balusters under a moulded rail; 3 rope
// mouldings stepping round the arris; 4 bartizans on the keep's corners and 2 on the bastion, each
// a corbel of 3 stepped rings under a cylindrical body under a 6-ribbed melon dome; 6 + 6 shield
// merlons on the terrace, 13 on the bastion parapet; 5 gun ports; 1 doorway; 1 Manueline cross.
// layering: paper flecks, water plate, the keep (lit / shade / over-plate), rear bartizan, merlons,
// corbel course, balustrade, the two loggia tiers, rope courses, the three front bartizans; then
// the bastion in front; rock; water dashes and the reflection; promenade and strollers; last darks.
const PALETTE = [
"#efe6d2", // paper — warm cream sheet
"#c9a58e", // warm stone — the sun on the lioz of the upper storeys
"#2f3a44", // ink — slate-navy line and shadow plate
"#5d7f88", // tagus — verdigris river water
"#d9cfb6", // stone — lioz limestone, the pale plate
"#c9a24a", // gilt — the one bartizan finial, the only warm accent
];
const BASE = 596; // the rock footing / waterline
const SX = 408, SW = 64; // the lit south face of the keep
const EX = 472, EW = 52; // the east face turning into shade
const TOP = 318; // the terrace floor; the shaft runs from here
const g = (m, sd, lo, hi) => constrain(randomGaussian(m, sd), lo, hi);
const shift = (pts, dx, dy) => pts.map((p) => [p[0] + dx, p[1] + dy]);
const box = (x, y, w, h) => [[x, y], [x + w, y], [x + w, y + h], [x, y + h]];
// a solid grainy plate — the letterpress solid. noStroke: a plate never carries the last pen's outline.
const plate = (pts, col, w, dist, ang, rnd) => {
brush.noStroke();
brush.noFill();
brush.hatchStyle("charcoal", col, w);
brush.hatch(dist, ang, { rand: rnd, continuous: false, gradient: 0 });
brush.polygon(pts);
brush.noHatch();
};
// a half-tone plate — two crossed cpencil passes, paper breathing through
const halfPlate = (pts, col, w, dist, ang) => {
brush.noStroke();
brush.noFill();
brush.hatchStyle("cpencil", col, w);
brush.hatch(dist, ang, { rand: 0.25, continuous: false, gradient: 0 });
brush.polygon(pts);
brush.hatch(dist * 1.12, ang - 84, { rand: 0.25, continuous: false, gradient: 0 });
brush.polygon(pts);
brush.noHatch();
};
// a fading plate — gradient hatch, dense at one edge, open at the other
const fadePlate = (pts, col, w, dist, ang, grad) => {
brush.noStroke();
brush.noFill();
brush.hatchStyle("charcoal", col, w);
brush.hatch(dist, ang, { rand: 0.3, continuous: false, gradient: grad });
brush.polygon(pts);
brush.noHatch();
};
const ink = (x1, y1, x2, y2, w, name, col) => {
brush.noFill();
brush.set(name || "rotring", col || PALETTE[2], w || 1.0);
brush.line(x1, y1, x2, y2);
};
// the deepest plate on the sheet — an opening: window, gun port, doorway. Two passes, misregistered.
const slot = (x, y, w, h) => {
plate(box(x, y, w, h), PALETTE[2], 1.55, 1.3, 90, 0.16);
plate(shift(box(x, y, w, h), 0.8, 0.6), PALETTE[2], 1.25, 2.1, 58, 0.2);
};
// a round-headed arch opening — jambs up to the springing, then a true semicircular head
const archOf = (x, y, w, h) => {
const spring = y + w * 0.5;
const pts = [[x, y + h]];
for (let i = 0; i <= 11; i++) {
const a = Math.PI + (i / 11) * Math.PI;
pts.push([x + w * 0.5 + Math.cos(a) * w * 0.5, spring + Math.sin(a) * w * 0.5]);
}
pts.push([x + w, y + h]);
return pts;
};
// one loggia tier: n round-headed openings as deep ink plates, the piers between them carved back
// in stone so each head reads as a separate arch, the heads ruled, a slender column under each pair
const loggiaAt = (x0, y, w, h, n, pitch) => {
const r = w * 0.5, spring = y + r, foot = y + h, xs = [];
for (let i = 0; i < n; i++) xs.push(x0 + i * pitch + g(0, 0.3, -0.7, 0.7));
// 1 — the deep ink plates: the loggia stands open, so these are the darkest marks on the sheet
for (let i = 0; i < n; i++) {
const a = archOf(xs[i], y, w, h);
plate(a, PALETTE[2], 1.35, 1.45, 90, 0.18);
plate(shift(a, 0.9, 0.7), PALETTE[2], 1.15, 2.4, 86, 0.22);
}
// 2 — the piers and spandrels struck back in stone, so the heads do not bleed into one band
for (let i = 0; i <= n; i++) {
const px = i === 0 ? xs[0] - 5.5 : xs[i - 1] + w;
const pw = i === 0 ? 5.5 : i === n ? 6.5 : xs[i] - xs[i - 1] - w;
plate(box(px, y - 2.5, pw, r + 3), PALETTE[4], 1.45, 1.6, 70, 0.22);
}
// 3 — every head ruled in rotring, jambs down to the floor, the impost it springs from in pen
for (let i = 0; i < n; i++) {
const x = xs[i];
for (let k = 0; k < 11; k++) {
const a0 = Math.PI + (k / 11) * Math.PI, a1 = Math.PI + ((k + 1) / 11) * Math.PI;
ink(x + r + Math.cos(a0) * r, spring + Math.sin(a0) * r,
x + r + Math.cos(a1) * r, spring + Math.sin(a1) * r, 1.0);
}
const hr = r + 2.3; // the Manueline hood mould running over the head
for (let k = 2; k < 9; k++) {
const a0 = Math.PI + (k / 11) * Math.PI, a1 = Math.PI + ((k + 1) / 11) * Math.PI;
ink(x + r + Math.cos(a0) * hr, spring + Math.sin(a0) * hr,
x + r + Math.cos(a1) * hr, spring + Math.sin(a1) * hr, 0.75, "pen");
}
ink(x, spring, x, foot, 0.9);
ink(x + w, spring, x + w, foot, 0.9);
ink(x - 2.2, spring, x + w + 2.2, spring, 0.75, "pen");
}
// 4 — the slender columns standing between the openings, light against the ink
for (let i = 0; i < n - 1; i++) {
const cx = (xs[i] + w + xs[i + 1]) * 0.5;
plate(box(cx - 2.3, spring - 1, 4.6, foot - spring + 1), PALETTE[4], 1.5, 1.5, 78, 0.22);
ink(cx - 2.4, spring + 1, cx - 2.4, foot - 1, 0.7, "pen");
ink(cx + 2.4, spring + 1, cx + 2.4, foot - 1, 0.7, "pen");
ink(cx - 3.8, spring - 1.4, cx + 3.8, spring - 1.4, 1.05); // capital
ink(cx - 3.4, foot - 0.6, cx + 3.4, foot - 0.6, 1.05); // base
}
};
// a bartizan — corbel of stepped rings, cylindrical body, ribbed melon dome. The tower's signature.
const bartizanAt = (cx, capY, r, bodyH, shade) => {
const bodyBot = capY + bodyH;
// 1 — the corbel: three stepped rings tapering back into the wall
for (let k = 0; k < 3; k++) {
const rw = r * (0.94 - k * 0.23), ry = bodyBot + k * 4.3;
plate(box(cx - rw, ry, rw * 2, 4.5), PALETTE[4], 1.4, 1.7, 62 + k * 10, 0.26);
ink(cx - rw - 0.7, ry, cx + rw + 0.7, ry, 0.8, "pen");
}
plate(shift(box(cx - r * 0.22, bodyBot, r * 1.16, 12.8), 1, 0.8), PALETTE[2], 1.05, 3.2, 72, 0.3);
// 2 — the cylindrical body: lit left, shaded right, an ink over-plate on the turning side
const body = box(cx - r, capY, r * 2, bodyH);
halfPlate(body, PALETTE[4], 1.4, 2.0, shade ? 68 : 76);
plate(body, PALETTE[4], 1.3, 2.7, 90, 0.3);
plate(box(cx + r * (shade ? -0.2 : 0.3), capY, r * (shade ? 1.2 : 0.7), bodyH),
PALETTE[2], 1.1, shade ? 2.8 : 3.6, 92, 0.3);
ink(cx - r, capY + 1.5, cx - r, bodyBot, 0.85, "pen");
ink(cx + r, capY + 1.5, cx + r, bodyBot, 1.05);
ink(cx - r - 2, capY, cx + r + 2, capY, 1.3); // the moulded ring under the dome
ink(cx - r - 1.2, capY - 2.6, cx + r + 1.2, capY - 2.6, 0.75, "pen");
// 3 — the melon dome and its six ribs, converging on a small finial
const rx = r + 1.7, ry = r * 1.16, dy = capY - 3;
const dm = [];
for (let i = 0; i <= 14; i++) {
const a = Math.PI + (i / 14) * Math.PI;
dm.push([cx + Math.cos(a) * rx, dy + Math.sin(a) * ry]);
}
halfPlate(dm, PALETTE[4], 1.4, 1.9, 40);
plate(dm.slice(7).concat([[cx, dy]]), PALETTE[4], 1.3, 2.5, 96, 0.3);
plate(shift(dm.slice(9).concat([[cx + 1, dy]]), 1.2, 0.8), PALETTE[2], 1.05, 3.0, 84, 0.3);
for (let k = 0; k < 6; k++) {
const a = Math.PI + ((k + 0.5) / 6) * Math.PI, ca = Math.cos(a);
let px = cx, py = dy - ry;
for (let u = 1; u <= 3; u++) {
const t = (u / 3) * (Math.PI / 2);
const qx = cx + ca * rx * Math.sin(t), qy = dy - ry * Math.cos(t);
ink(px, py, qx, qy, 0.8, "pen");
px = qx; py = qy;
}
}
ink(cx, dy - ry, cx, dy - ry - 5.4, 1.8, "charcoal"); // the finial
ink(cx - 2.2, dy - ry - 3.6, cx + 2.2, dy - ry - 3.6, 1.2, "charcoal");
};
// a shield-shaped merlon — the crenellation of the Order of Christ
const merlonAt = (x, y, w, h) => {
plate([[x, y + h], [x, y + h * 0.46], [x + w * 0.22, y + h * 0.11], [x + w * 0.5, y],
[x + w * 0.78, y + h * 0.11], [x + w, y + h * 0.46], [x + w, y + h]],
PALETTE[4], 1.4, 1.6, 72, 0.24);
ink(x, y + h * 0.46, x + w * 0.24, y + h * 0.1, 0.75, "pen");
ink(x + w, y + h * 0.46, x + w * 0.76, y + h * 0.1, 0.75, "pen");
ink(x + w * 0.24, y + h * 0.1, x + w * 0.76, y + h * 0.1, 0.75, "pen");
};
// the cross of the Order of Christ, cut into a merlon — an ink mark, flared at the four ends
const crossAt = (cx, cy, s) => {
ink(cx, cy - s, cx, cy + s, 1.5, "charcoal");
ink(cx - s * 0.82, cy - s * 0.12, cx + s * 0.82, cy - s * 0.12, 1.4, "charcoal");
ink(cx - s * 0.62, cy - s * 1.02, cx + s * 0.62, cy - s * 1.02, 0.9, "charcoal");
ink(cx - s * 0.5, cy + s * 0.95, cx + s * 0.5, cy + s * 0.95, 0.9, "charcoal");
};
// a rope moulding — two thin pen rulings twisted with ticks, stepping down round the arris
const ropeAt = (y, drop) => {
ink(SX - 6, y, EX, y, 0.95, "pen");
ink(SX - 6, y + 3.3, EX, y + 3.3, 0.8, "pen");
ink(EX, y + drop, EX + EW + 6, y + drop + 1.6, 0.95, "pen");
ink(EX, y + drop + 3.3, EX + EW + 6, y + drop + 4.9, 0.8, "pen");
ink(EX, y - 0.6, EX, y + drop + 3.9, 0.9, "pen"); // the step around the corner
for (let k = 0; k < 23; k++) {
const x = SX - 5 + k * 3.05;
ink(x, y + 3.1, x + 1.9, y + 0.3, 0.6, "pen");
}
for (let k = 0; k < 18; k++) {
const x = EX + 1 + k * 3.15;
const yy = y + drop + (x - EX) * 0.028;
ink(x, yy + 3.1, x + 1.9, yy + 0.3, 0.6, "pen");
}
};
// the bastion's parapet height at a given x — three facets of the hexagon, seen almost edge-on
const parapetY = (x) =>
x < 276 ? lerp(522, 502, (x - 200) / 76)
: x < 392 ? 502
: lerp(502, 486, (x - 392) / 124);
function setup() {
createCanvas(800, 800, WEBGL);
angleMode(DEGREES);
brush.scaleBrushes(2.4);
noLoop();
}
function draw() {
translate(-width / 2, -height / 2);
background(PALETTE[0]);
// 0 — paper flecks: faint warm specks so the sheet is not dead, never dark
for (let i = 0; i < 220; i++) {
const x = random(10, 790), y = random(10, 790);
ink(x, y, x + g(1.4, 0.5, 0.5, 2.6), y + g(0, 0.4, -1, 1), g(0.45, 0.1, 0.3, 0.6), "2H", random() < 0.7 ? "#bfb39a" : PALETTE[1]);
}
// 1 — the far Tagus behind the tower, so the river reads as wrapping the footing
fadePlate([[168, BASE + 2], [660, BASE - 2], [664, BASE + 14], [162, BASE + 18]], PALETTE[3], 1.0, 3.4, 0, 0.6);
// 2 — the keep. The south face takes the sun: two stone passes plus a warm pass for body.
// The east face turns away: solid stone under an ink over-plate, deepening toward its far arris —
// a proper mid tone, never black. The light side and the dark side are decided here.
const south = box(SX, TOP, SW, BASE - TOP);
const east = box(EX, TOP, EW, BASE - TOP);
halfPlate(south, PALETTE[4], 1.4, 2.0, 72);
halfPlate(south, PALETTE[1], 1.2, 2.4, 52); // the sun on the limestone — the warm register
plate(south, PALETTE[4], 1.3, 2.9, 88, 0.3); // the second stone pass that gives the lit face body
plate(shift(box(SX, TOP, 7, BASE - TOP), -0.5, 1), PALETTE[2], 0.9, 4.6, 84, 0.3);
plate(east, PALETTE[4], 1.5, 2.0, 86, 0.3);
halfPlate(east, PALETTE[1], 0.9, 5.0, 40); // a breath of the same warm ink, so the shade is not grey
plate(shift(east, 1.5, 1), PALETTE[2], 0.75, 3.2, 88, 0.2); // the shade plate — an even mid, not black
plate(shift(box(EX + 38, TOP, EW - 38, BASE - TOP), 1.5, 1), PALETTE[2], 0.72, 3.6, 84, 0.22);
ink(EX, TOP - 2, EX, BASE - 4, 1.05); // the arris between the two faces
// 3 — the terrace: the rear bartizan first, then merlons, then the machicolated corbel course
bartizanAt(445, 305, 8.5, 13, true); // the fourth corner, standing behind the parapet
for (let i = 0; i < 6; i++) {
if (i === 3) continue; // the merlon the rear bartizan stands in place of
merlonAt(SX + 2 + i * 10.5 + g(0, 0.3, -0.7, 0.7), 288, 6.2, 14);
}
for (let i = 0; i < 6; i++) merlonAt(EX + 2 + i * 8.4 + g(0, 0.3, -0.7, 0.7), 290, 5.4, 12);
crossAt(SX + 15.2, 294.6, 4.2); // the Manueline cross cut into the second merlon
plate(box(SX - 6, 302, SW + EW + 12, 12), PALETTE[4], 1.4, 1.9, 66, 0.26);
fadePlate(box(SX - 6, 312, SW + EW + 12, 11), PALETTE[2], 0.95, 3.4, 0, 0.72); // shadow under the corbels
ink(SX - 8, TOP, SX + SW + EW + 8, TOP, 1.35);
ink(SX - 6, 302, SX + SW + EW + 6, 302, 1.05);
// 4 — the balustrade over the loggia: thirteen turned balusters pale against their own shadow,
// a moulded rail over them, the gallery shelf under
plate(box(SX + 2, 325.5, SW - 4, 13), PALETTE[4], 1.4, 1.7, 26, 0.24); // the balcony band
for (let i = 0; i < 11; i++) {
const cx = 413.5 + i * 5.5 + g(0, 0.2, -0.45, 0.45);
ink(cx, 326.6, cx, 337.4, 0.85, "pen");
ink(cx, 330.2, cx, 333.6, 1.35, "charcoal"); // the turned belly
}
plate(box(SX - 1, 320.5, SW + 2, 3.6), PALETTE[4], 1.35, 1.6, 24, 0.24);
ink(SX - 2, 324.2, SX + SW + 2, 324.2, 1.3); // the moulded rail
ink(SX - 2, 321, SX + SW + 2, 321, 0.8, "pen");
plate(box(SX, 338.4, SW, 3.4), PALETTE[4], 1.35, 1.6, 20, 0.24);
ink(SX - 2, 338.2, SX + SW + 2, 338.2, 1.25); // the gallery shelf
// 5 — THE LOGGIA: two storeys of three round-headed arches, a slender column between each pair.
// These plates and the openings below are the darkest ink on the sheet.
loggiaAt(414, 350, 13.4, 39, 3, 19.4);
loggiaAt(414, 412, 13.4, 43, 3, 19.4);
ink(SX + 3, 344, SX + SW - 3, 344, 0.9, "pen"); // the frame of the upper tier
ink(SX + 3, 391, SX + SW - 3, 391, 0.9, "pen");
ink(SX + 3, 406, SX + SW - 3, 406, 0.9, "pen");
ink(SX + 3, 457, SX + SW - 3, 457, 0.9, "pen");
// 6 — the rope mouldings: thin pen rulings that run round the tower and step at the arris
ropeAt(394, 2);
ropeAt(460, 2);
ropeAt(524, 2);
// 7 — the remaining fabric: slit windows on the shaded east face, two on the storey below the
// loggia, and the three front bartizans on the keep's corners
for (let i = 0; i < 3; i++) slot(EX + 20 + g(0, 0.4, -1, 1), 344 + i * 62, 6, 15);
slot(SX + 14 + g(0, 0.4, -1, 1), 470, 6, 16);
slot(SX + 44 + g(0, 0.4, -1, 1), 470, 6, 16);
bartizanAt(SX, 301, 11.5, 19, false);
bartizanAt(EX, 299, 13.5, 21, false);
bartizanAt(EX + EW, 302, 11, 18.5, true);
// 8 — the bastion: a lower, wider, squatter mass standing in front of the keep. Three facets of
// the hexagon: the left one turned into the sun, the middle facing us, the right returning east
// into shade — the same light side / dark side as the keep above it.
const fa = [[200, 522], [276, 502], [276, 588], [196, 582]];
const fb = [[276, 502], [392, 502], [392, 594], [276, 588]];
const fc = [[392, 502], [516, 486], [516, 590], [392, 594]];
halfPlate(fa, PALETTE[4], 1.4, 2.2, 76);
halfPlate(fa, PALETTE[1], 1.1, 3.0, 52);
plate(fa, PALETTE[4], 1.25, 3.0, 90, 0.3);
halfPlate(fb, PALETTE[4], 1.4, 2.0, 74);
halfPlate(fb, PALETTE[1], 1.15, 2.6, 58); // the river facet takes the sun
plate(fb, PALETTE[4], 1.3, 2.6, 90, 0.3);
plate(fc, PALETTE[4], 1.45, 2.2, 80, 0.3);
plate(shift(fc, 1.5, 1), PALETTE[2], 0.7, 4.4, 84, 0.2); // the facet turning into shade, but
plate(shift(box(496, 488, 20, 104), 1.5, 1), PALETTE[2], 0.72, 3.6, 96, 0.22); // lighter than the keep behind it
// three coursing lines across the gun platform, kinking with the facets, none running off a facet
for (let k = 0; k < 3; k++) {
const d = 20 + k * 17;
ink(200, 522 + d, 276, 502 + d, 0.7, "pen");
ink(276, 502 + d, 392, 502 + d, 0.7, "pen");
ink(392, 502 + d, 514, 486 + d, 0.7, "pen");
}
// the parapet band, kinked at the hexagon's corners, and thirteen shield merlons on it
const cap = [[198, 522], [276, 502], [392, 502], [520, 486], [520, 496], [392, 512], [276, 512], [198, 532]];
plate(cap, PALETTE[4], 1.4, 1.8, 58, 0.26);
fadePlate([[198, 532], [276, 512], [392, 512], [520, 496], [520, 512], [392, 528], [276, 528], [198, 548]],
PALETTE[2], 0.95, 3.4, 0, 0.74);
ink(196, 532, 276, 512, 1.35); // the parapet's under-edge, kinking at each corner
ink(276, 512, 392, 512, 1.35);
ink(392, 512, 520, 496, 1.35);
for (let i = 0; i < 13; i++) {
const x = 206 + i * 23.5;
merlonAt(x + g(0, 0.35, -0.8, 0.8), parapetY(x) - 14, 11, 14);
}
crossAt(300, 496, 4.6); // the cross again, on the parapet where the bastion faces the river
// two bartizans of the same family on the hexagon's corners
bartizanAt(202, parapetY(202) - 20, 11, 18, false);
bartizanAt(394, parapetY(394) - 20, 11, 18, true);
// the doorway on the river facet, and five gun ports along the two river-facing facets
const dr = archOf(322, 552, 15, 40);
plate(dr, PALETTE[2], 1.6, 1.25, 90, 0.15);
plate(shift(dr, 0.9, 0.7), PALETTE[2], 1.3, 2.0, 56, 0.2);
for (let k = 0; k < 11; k++) {
const a0 = Math.PI + (k / 11) * Math.PI, a1 = Math.PI + ((k + 1) / 11) * Math.PI;
ink(329.5 + Math.cos(a0) * 7.5, 559.5 + Math.sin(a0) * 7.5,
329.5 + Math.cos(a1) * 7.5, 559.5 + Math.sin(a1) * 7.5, 1.05);
}
ink(322, 559.5, 322, 592, 1.0); ink(337, 559.5, 337, 592, 1.0);
const PORT = [[232, 546], [270, 538], [356, 534], [410, 532], [452, 524]];
for (let i = 0; i < PORT.length; i++) {
slot(PORT[i][0] + g(0, 0.4, -1, 1), PORT[i][1], 7.5, 10);
}
ink(200, 522, 196, 582, 1.0);
ink(276, 502, 276, 588, 0.9, "pen");
ink(392, 502, 392, 594, 0.9, "pen");
// 9 — the rock footing the whole thing stands on, and the wet stone at its lip
const rock = [[176, 586], [292, 596], [408, 600], [524, 590], [556, 600], [414, 610], [284, 608], [166, 598]];
halfPlate(rock, PALETTE[4], 1.3, 2.2, 22);
plate([[168, 596], [284, 606], [414, 608], [556, 598], [538, 612], [408, 617], [282, 615], [172, 605]],
PALETTE[2], 1.35, 2.1, 14, 0.3); // the wet, weeded footing where the rock meets the river
ink(170, 600, 556, 599, 1.35);
ink(174, 606, 300, 612, 1.0, "2B");
ink(408, 613, 540, 606, 1.0, "2B");
// 10 — the Tagus: a ruled plate that thins downward, dashes, and the keep's reflection
fadePlate([[158, BASE + 10], [656, BASE + 6], [666, BASE + 36], [148, BASE + 40]], PALETTE[3], 1.05, 4.2, 0, 0.8);
brush.hatchStyle("cpencil", PALETTE[3], 1.15);
brush.noStroke(); brush.noFill();
brush.hatch(4.8, 0, { rand: 0.12, continuous: false, gradient: 0.6 });
brush.polygon([[184, BASE + 12], [642, BASE + 8], [648, BASE + 28], [178, BASE + 32]]);
brush.noHatch();
for (let i = 0; i < 28; i++) {
const y = BASE + 12 + i * 1.5 + g(0, 0.5, -1, 1);
const x0 = 146 + random(0, 390);
const len = constrain(randomGaussian(120, 66), 16, 360);
if (x0 + len > 690) continue;
ink(x0, y, x0 + len, y, g(1.15, 0.28, 0.65, 1.7), random() < 0.65 ? "2B" : "cpencil", random() < 0.85 ? PALETTE[3] : PALETTE[2]);
}
// the keep's reflection — short dark dashes directly under it, in its own footprint
for (let i = 0; i < 12; i++) {
const y = BASE + 14 + i * 2.1;
ink(SX + g(6, 2, 1, 11), y, SX + SW + EW - g(6, 2, 1, 11), y, g(1.1, 0.22, 0.6, 1.5), "2B", random() < 0.5 ? PALETTE[2] : PALETTE[1]);
}
// a small sailing boat on the open right — a dash, a nick for the bow, a raked sail
ink(576, BASE + 32, 608, BASE + 32, 2.4, "charcoal");
ink(608, BASE + 32, 613, BASE + 28, 1.3, "charcoal");
ink(592, BASE + 31, 588, BASE + 12, 1.2, "charcoal");
ink(588, BASE + 13, 599, BASE + 30, 1.1, "charcoal");
// 11 — the promenade this side of the water, with four strollers as ticks
plate(box(190, 648, 436, 4), PALETTE[4], 1.15, 1.6, 0, 0.2);
ink(186, 652, 630, 652, 1.4);
const WALK = [238, 245, 372, 526];
for (let i = 0; i < WALK.length; i++) {
ink(WALK[i], 649, WALK[i] + g(0, 0.5, -1, 1), 649 - g(9.5, 0.8, 8, 11), g(2.1, 0.15, 1.9, 2.3), "charcoal");
}
// 12 — last darks: the crisp ends of the two masses, kept to the arrises
ink(SX - 1, TOP, SX - 1, 500, 1.1);
ink(SX + SW + EW + 1, TOP, SX + SW + EW + 1, BASE - 6, 1.45);
ink(196, 582, 200, 522, 1.1);
ink(516, 486, 516, 590, 1.25);
// 13 — the accent: gilt crowning the finial of the nearest bartizan, one mark
ink(EX, 277, EX, 268, 1.7, "charcoal", PALETTE[5]);
ink(EX - 3, 272, EX + 3, 272, 1.2, "charcoal", PALETTE[5]);
}