← Back to Gallery

Loading 3D viewer…

Art Nouveau Corner Apothecary (indexed)

by Jorge Barbero

Dimensions
64×48×64
Blocks
63,479
Compute Time
10.7s
Generation Time
2m 36s
Edits
1
Model
claude-opus-5
Created
August 30, 2026
autoevalindexedart_nouveaushopinteriorlayered
Prompt

User Prompt

an Art Nouveau corner apothecary shop: two-storey townhouse with a rounded corner bay, glazed deep-green tile facade with whiplash floral ironwork, tall arched shop windows with a curved glass canopy, upper floor with balcony, mansard slate roof; interior with a wooden counter, apothecary shelf wall of bottles, and a stair up to the flat above

Enhanced Prompt

indexed condition: prepare_build + search_docs({action:"related"}) graph retrieval (roofStair, landing, stairFlight, cylinder min 3 flat blocks, orient facade to +Z/+X, inverted roof pitfall, stairs block state) then read of build-rules Critical Build Rules & Pitfalls. LAYERED placeholder->mask->texture-last process. Written from scratch.

Photos

Exterior
Exteriorexterior
Botica
Boticainterior
Vivienda
Viviendainterior
Escalera
Escalerainterior
CraftScript Source
// === BUILD PLAN ===
// Style: Art Nouveau corner apothecary, corner TURRET bay, mansard slate roof
// ORIENTATION (rule 15): the rounded corner + main door face +X / +Z (max x, max z) = the camera.
// Footprint: 21x19 rect (X18..38, Z16..34), SOUTH-EAST corner rounded r=6 around (32,28)
// Height: floor Y11 / walk Y12 (shop, 5 air) | floor2 Y17 / walk Y18 (flat, 4 air) | wall top Y21
//         mansard Y22 cornice, Y23..26 slate flanks, Y27 deck; corner TURRET cone Y23..30
//
// GROUND (top-down, +X right, +Z down):
//   #####################
//   # bottles shelf wall #
//   #                    #
//   #   tables    counter#
//   #                 ST #     ST = staircase (climbs west, walk12 -> walk18)
//   #                  WWW
//   ##WW           (bay)WW
//     #####WWW###WW#DD###      D = door on the rounded bay, facing +Z
//
// PROCESS: LAYERED (build-rules 14): 1) form in blue_wool/red_wool placeholders
//          2) carve openings with clearMasked(onlyMaterial) 3) TEXTURE LAST via replaceMasked
// MATERIALS PLAN:
//   plinth   : deepslate ramp                                  - WHY: dark base = fake AO, grounds the facade
//   ground   : gradient dark_prismarine->green_terracotta->green_concrete - WHY: glazed-tile green, dark low
//   upper    : gradient brown-> white_terracotta -> smooth_quartz         - WHY: pale stucco CONTRAST over green
//   ironwork : iron_bars fanlights, balcony rail, canopy hangers          - WHY: the whiplash signature
//   roof     : deepslate tile/brick stair noise + turret cone             - WHY: slate shingle variation
// Rooms: shop (counter L, bottle wall, brewing bench, seating) / flat (bed, kitchen nook, sofa, balcony)
// STAIR PLAN: D = 18-12 = 6 -> staircase(34,22,12,18,"west") 7 cells, lands flush at (28,18,22)
// === END PLAN ===

var X0 = 18, X1 = 38, Z0 = 16, Z1 = 34;
var R = 6, CX = X1 - R, CZ = Z1 - R;
var padY = 10, floorY = 11, walkY = 12, floor2Y = 17, walkY2 = 18, wallTopY = 21, roofY = 22;
var PH_WALL = 'blue_wool';

function inside(x, z) {
    if (x < X0 || x > X1 || z < Z0 || z > Z1) return false;
    if (x > CX && z > CZ) {
        var dx = x - CX, dz = z - CZ;
        return (dx * dx + dz * dz) <= (R * R + 0.6);
    }
    return true;
}
function insideK(x, z, k) {
    var i, j;
    for (i = -k; i <= k; i++) for (j = -k; j <= k; j++) if (!inside(x + i, z + j)) return false;
    return true;
}
function ringK(x, z, k) {
    if (!insideK(x, z, k)) return false;
    return !insideK(x + 1, z, k) || !insideK(x - 1, z, k) || !insideK(x, z + 1, k) || !insideK(x, z - 1, k);
}
function shell(x, z) { return ringK(x, z, 0); }
function isArc(x, z) { return x > CX && z > CZ; }

var x, y, z, i, k;

// === 1. TERRAIN (superpowers, flat pad under the build) ===
var land = blob(30, 28, 32, {irregularity:0.4, seed:23});
var hbase = hills({base:8, amp:3, scale:0.04, seed:11});
var pad = flatten(hbase, {x0:X0-7, z0:Z0-7, x1:X1+8, z1:Z1+8}, padY, 8);
var cobblePat = noisePalette([{block:'cobblestone',weight:38},{block:'andesite',weight:26},{block:'stone',weight:26},{block:'gravel',weight:10}], {seed:17, freq:0.22});
var soilPat = patches([{block:'grass_block',w:66},{block:'coarse_dirt',w:22},{block:'moss_block',w:12}], 0.055, 7);
var groundMat = function (gx, gz) {
    if (gx >= X1 + 3 || gz >= Z1 + 3) return cobblePat(gx, 0, gz);   // the two streets, on the camera side
    if (gx >= X1 + 1 || gz >= Z1 + 1) return 'smooth_stone';          // kerb / pavement
    return soilPat(gx, gz);
};
surface(land, pad, groundMat, {sub:'dirt', deep:'stone', depth:4});

// === 2. FORM IN PLACEHOLDERS (layered step 1) ===
fill(X0 - 1, floorY, Z0 - 1, X1 + 1, roofY + 10, Z1 + 1, b('air'));
for (x = X0; x <= X1; x++) for (z = Z0; z <= Z1; z++) {
    if (!inside(x, z)) continue;
    pb(x, floorY, z, 'stone_bricks');                       // structural slab under the shop floor
    if (shell(x, z)) for (y = floorY + 1; y <= wallTopY; y++) pb(x, y, z, PH_WALL);
}

// === 3. CARVE OPENINGS BY MASK (layered step 2) ===
// straight facades: 1-block-thick wall slots, mask keeps the cut inside the wall only
function slotStraight(x1, z1, x2, z2, y1, y2) { clearMasked(x1, y1, z1, x2, y2, z2, onlyMaterial(PH_WALL)); }
// south facade (z=Z1) shop windows + upper windows
slotStraight(21, Z1, 23, Z1, 13, 16); slotStraight(25, Z1, 27, Z1, 13, 16);
slotStraight(21, Z1, 23, Z1, 19, 21); slotStraight(25, Z1, 27, Z1, 19, 21);
// east facade (x=X1) shop + upper
slotStraight(X1, 19, X1, 21, 13, 16); slotStraight(X1, 23, X1, 25, 13, 16);
slotStraight(X1, 19, X1, 21, 19, 21); slotStraight(X1, 23, X1, 25, 19, 21);
// west + north: upper only (service sides)
slotStraight(X0, 21, X0, 23, 19, 21); slotStraight(X0, 26, X0, 28, 19, 21);
slotStraight(23, Z0, 25, Z0, 19, 21); slotStraight(30, Z0, 32, Z0, 19, 21);
// the rounded bay: shopfront glass all the way round, door at the +Z/+X diagonal
var doorX = 35, doorZ = 33, best = 999;
for (x = CX + 1; x <= X1; x++) for (z = CZ + 1; z <= Z1; z++) {
    if (!shell(x, z)) continue;
    var dd = Math.abs(x - (CX + R * 0.62)) + Math.abs(z - (CZ + R * 0.78));
    if (dd < best) { best = dd; doorX = x; doorZ = z; }
}
for (x = CX + 1; x <= X1; x++) for (z = CZ + 1; z <= Z1; z++) {
    if (!shell(x, z)) continue;
    var isDoor = (Math.abs(x - doorX) + Math.abs(z - doorZ) <= 1);
    for (y = 13; y <= 16; y++) pb(x, y, z, 'air');
    for (y = 19; y <= 21; y++) pb(x, y, z, 'air');
    if (isDoor) { pb(x, walkY, z, 'air'); pb(x, walkY + 1, z, 'air'); }
}

// === 4. TEXTURE LAST (layered step 3) ===
var plinthPal = noisePalette([{block:'polished_deepslate',weight:44},{block:'deepslate_tiles',weight:34},{block:'deepslate_bricks',weight:22}], {seed:5, freq:0.17});
var greenPal = gradientPalette(13, 16, [{block:'dark_prismarine',from:0},{block:'green_terracotta',from:0.4},{block:'green_concrete',from:0.78}], {noise:0.22, seed:9});
var creamPal = gradientPalette(18, 21, [{block:'brown_terracotta',from:0},{block:'white_terracotta',from:0.3},{block:'smooth_quartz',from:0.78}], {noise:0.2, seed:12});
replaceMasked(X0 - 1, floorY, Z0 - 1, X1 + 1, walkY, Z1 + 1, plinthPal, onlyMaterial(PH_WALL));
replaceMasked(X0 - 1, walkY + 1, Z0 - 1, X1 + 1, 16, Z1 + 1, greenPal, onlyMaterial(PH_WALL));
replaceMasked(X0 - 1, floor2Y, Z0 - 1, X1 + 1, floor2Y, Z1 + 1, b('dark_prismarine'), onlyMaterial(PH_WALL));  // string course
replaceMasked(X0 - 1, walkY2, Z0 - 1, X1 + 1, wallTopY, Z1 + 1, creamPal, onlyMaterial(PH_WALL));

// glaze the openings (mask: only into the air we just carved, never over the build)
function glazeStraight(x1, z1, x2, z2, y1, y2, blk) { fillMasked(x1, y1, z1, x2, y2, z2, b(blk), onlyAir()); }
glazeStraight(21, Z1, 23, Z1, 13, 15, 'glass'); glazeStraight(25, Z1, 27, Z1, 13, 15, 'glass');
glazeStraight(21, Z1, 23, Z1, 16, 16, 'iron_bars'); glazeStraight(25, Z1, 27, Z1, 16, 16, 'iron_bars');
glazeStraight(X1, 19, X1, 21, 13, 15, 'glass'); glazeStraight(X1, 23, X1, 25, 13, 15, 'glass');
glazeStraight(X1, 19, X1, 21, 16, 16, 'iron_bars'); glazeStraight(X1, 23, X1, 25, 16, 16, 'iron_bars');
glazeStraight(21, Z1, 23, Z1, 19, 20, 'glass_pane'); glazeStraight(25, Z1, 27, Z1, 19, 20, 'glass_pane');
glazeStraight(X1, 19, X1, 21, 19, 20, 'glass_pane'); glazeStraight(X1, 23, X1, 25, 19, 20, 'glass_pane');
glazeStraight(X0, 21, X0, 23, 19, 20, 'glass_pane'); glazeStraight(X0, 26, X0, 28, 19, 20, 'glass_pane');
glazeStraight(23, Z0, 25, Z0, 19, 20, 'glass_pane'); glazeStraight(30, Z0, 32, Z0, 19, 20, 'glass_pane');
glazeStraight(21, Z1, 23, Z1, 21, 21, 'iron_bars'); glazeStraight(25, Z1, 27, Z1, 21, 21, 'iron_bars');
glazeStraight(X1, 19, X1, 21, 21, 21, 'iron_bars'); glazeStraight(X1, 23, X1, 25, 21, 21, 'iron_bars');
glazeStraight(X0, 21, X0, 23, 21, 21, 'iron_bars'); glazeStraight(X0, 26, X0, 28, 21, 21, 'iron_bars');
glazeStraight(23, Z0, 25, Z0, 21, 21, 'iron_bars'); glazeStraight(30, Z0, 32, Z0, 21, 21, 'iron_bars');
// bay glass (curved wall: cell by cell so nothing bleeds off the arc)
for (x = CX + 1; x <= X1; x++) for (z = CZ + 1; z <= Z1; z++) {
    if (!shell(x, z)) continue;
    var dr = (Math.abs(x - doorX) + Math.abs(z - doorZ) <= 1);
    if (!dr) { for (y = 13; y <= 15; y++) pb(x, y, z, 'glass'); pb(x, 16, z, 'iron_bars'); }
    for (y = 19; y <= 20; y++) if (!(dr && y === 19)) pb(x, y, z, 'glass_pane');
    pb(x, 21, z, 'iron_bars');
}
ps(doorX, walkY, doorZ, 'dark_oak_door[facing=south,half=lower,hinge=left]');
ps(doorX, walkY + 1, doorZ, 'dark_oak_door[facing=south,half=upper,hinge=right]');
pb(doorX, 14, doorZ, 'glass'); pb(doorX, 15, doorZ, 'glass'); pb(doorX, 16, doorZ, 'iron_bars');

// === 5. FACADE RELIEF — protruding pilasters, sills, quoins ===
function pilaster(px, pz, dx, dz) {
    var yy;
    for (yy = floorY; yy <= wallTopY; yy++) pb(px + dx, yy, pz + dz, (yy <= walkY || yy >= floor2Y) ? 'polished_deepslate' : 'deepslate_tiles');
    ps(px + dx, floor2Y, pz + dz, 'deepslate_tile_slab[type=top]');
    ps(px + dx, wallTopY + 1, pz + dz, 'deepslate_tile_slab[type=bottom]');
}
pilaster(20, Z1, 0, 1); pilaster(24, Z1, 0, 1); pilaster(28, Z1, 0, 1);
pilaster(X1, 18, 1, 0); pilaster(X1, 22, 1, 0); pilaster(X1, 26, 1, 0);
pilaster(X0, 20, -1, 0); pilaster(X0, 25, -1, 0);
for (y = floorY; y <= wallTopY; y++) {
    pb(X0 - 1, y, Z0, 'polished_deepslate'); pb(X0, y, Z0 - 1, 'polished_deepslate');
    pb(X1 + 1, y, Z0, 'polished_deepslate'); pb(X1, y, Z0 - 1, 'polished_deepslate');
    pb(X0 - 1, y, Z1, 'polished_deepslate'); pb(X0, y, Z1 + 1, 'polished_deepslate');
}
// window sills / lintels on the upper floor
for (x = 21; x <= 27; x++) { ps(x, walkY2 - 0, Z1 + 1, 'smooth_quartz_slab[type=top]'); }
for (z = 19; z <= 25; z++) { ps(X1 + 1, walkY2 - 0, z, 'smooth_quartz_slab[type=top]'); }

// === 6. CURVED GLASS CANOPY + IRON BALCONY (camera side only) ===
for (x = X0 - 1; x <= X1 + 2; x++) for (z = Z0 - 1; z <= Z1 + 2; z++) {
    if (inside(x, z)) continue;
    var touch = inside(x + 1, z) || inside(x - 1, z) || inside(x, z + 1) || inside(x, z - 1);
    if (!touch) continue;
    if (x < X0 || z < Z0) continue;
    pb(x, floor2Y, z, 'glass');
    ps(x, floor2Y - 1, z, 'chain[axis=y]');
    if (isArc(x, z) || (x >= 20 && x <= 28 && z > Z1) || (z >= 18 && z <= 26 && x > X1)) {
        ps(x, walkY2, z, 'smooth_quartz_slab[type=bottom]');
        pb(x, walkY2 + 1, z, 'iron_bars');
    }
}
ps(doorX, walkY2, doorZ, 'dark_oak_door[facing=south,half=lower,hinge=left]');
ps(doorX, walkY2 + 1, doorZ, 'dark_oak_door[facing=south,half=upper,hinge=right]');
pb(doorX, walkY2 + 1, doorZ + 1, 'air');

// === 7. FLOORS + BEAMS ===
var boardPal = noisePalette([{block:'dark_oak_planks',weight:58},{block:'spruce_planks',weight:42}], {seed:19, freq:0.2});
for (x = X0 + 1; x <= X1 - 1; x++) for (z = Z0 + 1; z <= Z1 - 1; z++) {
    if (!insideK(x, z, 1)) continue;
    pb(x, floor2Y, z, boardPal(x, floor2Y, z));
    pb(x, roofY, z, 'dark_oak_planks');                              // attic floor: closes the flat
}
for (x = X0 + 1; x <= X1 - 1; x++) { if (insideK(x, 22, 1)) ps(x, floor2Y - 1, 22, 'stripped_dark_oak_log[axis=x]'); if (insideK(x, 28, 1)) ps(x, floor2Y - 1, 28, 'stripped_dark_oak_log[axis=x]'); }
// shop floor: black/white Art Nouveau tiling
for (x = X0 + 1; x <= X1 - 1; x++) for (z = Z0 + 1; z <= Z1 - 1; z++) {
    if (!insideK(x, z, 1)) continue;
    pb(x, floorY, z, (((x >> 1) + (z >> 1)) % 2 === 0) ? 'polished_diorite' : 'polished_blackstone');
}

// === 8. MANSARD ROOF + CORNER TURRET ===
var slatePal = noisePalette([{block:'deepslate_tiles',weight:48},{block:'polished_deepslate',weight:30},{block:'deepslate_bricks',weight:22}], {seed:27, freq:0.18});
var slateStairPal = noisePalette([{block:'deepslate_tile_stairs',weight:62},{block:'deepslate_brick_stairs',weight:38}], {seed:29, freq:0.2});
for (x = X0 - 1; x <= X1 + 1; x++) for (z = Z0 - 1; z <= Z1 + 1; z++) {
    if (inside(x, z)) continue;
    var tc = inside(x + 1, z) || inside(x - 1, z) || inside(x, z + 1) || inside(x, z - 1);
    if (tc) { pb(x, roofY, z, 'polished_deepslate'); ps(x, roofY + 1, z, 'deepslate_tile_slab[type=bottom]'); }
}
for (x = X0; x <= X1; x++) for (z = Z0; z <= Z1; z++) if (shell(x, z)) pb(x, roofY, z, 'polished_deepslate');
for (k = 0; k <= 3; k++) {
    var ry = roofY + 1 + k;
    for (x = X0; x <= X1; x++) for (z = Z0; z <= Z1; z++) {
        if (!ringK(x, z, k)) continue;
        var oN = !insideK(x, z - 1, k), oS = !insideK(x, z + 1, k), oW = !insideK(x - 1, z, k), oE = !insideK(x + 1, z, k);
        var cnt = (oN?1:0)+(oS?1:0)+(oW?1:0)+(oE?1:0);
        if (cnt > 1) { pb(x, ry, z, slatePal(x, ry, z)); continue; }
        roofStair(x, ry, z, slateStairPal(x, ry, z), oN ? 'north' : (oS ? 'south' : (oW ? 'west' : 'east')));
    }
}
for (x = X0; x <= X1; x++) for (z = Z0; z <= Z1; z++) if (insideK(x, z, 4)) pb(x, roofY + 5, z, slatePal(x, roofY + 5, z));
for (x = X0; x <= X1; x++) for (z = Z0; z <= Z1; z++) if (insideK(x, z, 6)) ps(x, roofY + 6, z, 'deepslate_tile_slab[type=bottom]');
// corner TURRET over the rounded bay (radius >= 4 so every flat side keeps 3+ blocks — rule 6)
makeCylinder(CX, roofY, CZ, slatePal, R - 0.4, 3, true);
makeCone(CX, roofY + 3, CZ, slateStairPal, R - 0.4, 7, false);
pb(CX, roofY + 10, CZ, 'polished_deepslate');
pb(CX, roofY + 11, CZ, 'lightning_rod');
// dormer on the south flank
function dormer(dx, dz) {
    var o, yy;
    for (o = -1; o <= 1; o++) {
        for (yy = roofY + 1; yy <= roofY + 3; yy++) pb(dx + o, yy, dz, (o === 0 && yy > roofY + 1) ? 'glass_pane' : 'polished_deepslate');
        roofStair(dx + o, roofY + 4, dz, 'deepslate_tile_stairs', 'south');
        for (yy = roofY + 1; yy <= roofY + 4; yy++) pb(dx + o, yy, dz - 1, 'deepslate_tiles');
    }
}
dormer(22, Z1); dormer(27, Z1);
// chimney
fill(X0 + 2, floor2Y, Z0 + 1, X0 + 2, roofY + 8, Z0 + 1, noisePalette([{block:'bricks',weight:72},{block:'mud_bricks',weight:28}], {seed:33}));
ps(X0 + 2, roofY + 9, Z0 + 1, 'brick_slab[type=bottom]');

// === 9. STAIR (walk 12 -> walk 18), reserved corridor, nothing decorated inside it ===
var topCell = staircase(34, 22, walkY, walkY2, 'west', {width:1, material:'dark_oak_stairs', rail:true, support:'polished_deepslate'});

// === 10. SHOP INTERIOR ===
for (z = 18; z <= 30; z++) for (y = walkY; y <= walkY + 3; y++) pb(X0 + 1, y, z, ((z + y) % 3 === 0) ? 'chiseled_bookshelf' : 'bookshelf');   // bottle wall
for (z = 19; z <= 29; z += 2) ps(X0 + 1, walkY + 4, z, 'dark_oak_slab[type=top]');
for (z = 25; z <= 31; z++) { pb(34, walkY, z, 'stripped_dark_oak_log[axis=z]'); ps(34, walkY + 1, z, 'dark_oak_stairs[facing=west,half=top]'); }
for (x = 29; x <= 33; x++) { pb(x, walkY, 31, 'stripped_dark_oak_log[axis=x]'); ps(x, walkY + 1, 31, 'dark_oak_stairs[facing=north,half=top]'); }
ps(35, walkY, 26, 'brewing_stand'); ps(35, walkY, 28, 'brewing_stand'); ps(36, walkY, 30, 'cauldron[level=0]');
pb(35, walkY, 30, 'barrel'); pb(36, walkY, 26, 'crafting_table'); ps(36, walkY, 28, 'composter');
ps(32, walkY + 2, 31, 'flower_pot'); ps(30, walkY + 2, 31, 'candle[candles=2]');
for (x = 22; x <= 30; x++) for (z = 20; z <= 27; z++) if (insideK(x, z, 1)) pb(x, walkY, z, 'green_carpet');
pb(24, walkY, 23, 'dark_oak_fence'); ps(24, walkY + 1, 23, 'oak_pressure_plate');
chairStair(23, walkY, 23, 'dark_oak_stairs', 'east'); chairStair(25, walkY, 23, 'dark_oak_stairs', 'west');
pb(28, walkY, 26, 'dark_oak_fence'); ps(28, walkY + 1, 26, 'oak_pressure_plate');
chairStair(27, walkY, 26, 'dark_oak_stairs', 'east'); chairStair(29, walkY, 26, 'dark_oak_stairs', 'west');
var lampsG = [[22, 20], [30, 20], [24, 29], [32, 27]];
for (i = 0; i < lampsG.length; i++) { ps(lampsG[i][0], floor2Y - 1, lampsG[i][1], 'chain[axis=y]'); ps(lampsG[i][0], floor2Y - 2, lampsG[i][1], 'lantern[hanging=true]'); }

// === 11. FLAT INTERIOR (upper) ===
placeBed(21, walkY2, 20, 'light_blue', 'north');
pb(22, walkY2, 19, 'dark_oak_fence'); ps(22, walkY2 + 1, 19, 'oak_pressure_plate'); pb(22, walkY2 + 2, 19, 'lantern');
for (x = 26; x <= 31; x++) for (z = 24; z <= 29; z++) if (insideK(x, z, 1)) pb(x, walkY2, z, 'light_gray_carpet');
pb(28, walkY2, 26, 'dark_oak_fence'); ps(28, walkY2 + 1, 26, 'oak_pressure_plate');
chairStair(27, walkY2, 26, 'spruce_stairs', 'east'); chairStair(29, walkY2, 26, 'spruce_stairs', 'west');
for (i = 0; i < 3; i++) chairStair(31 + i, walkY2, 29, 'spruce_stairs', 'north');
// kitchen nook by the chimney
pb(X0 + 2, walkY2, Z0 + 2, 'stripped_spruce_log[axis=y]'); ps(X0 + 2, walkY2 + 1, Z0 + 2, 'spruce_stairs[facing=south,half=top]');
ps(X0 + 3, walkY2, Z0 + 1, 'furnace[facing=south,lit=false]'); ps(X0 + 3, walkY2 + 1, Z0 + 1, 'iron_trapdoor[facing=south,half=bottom,open=false]');
ps(X0 + 4, walkY2, Z0 + 1, 'water_cauldron[level=3]');
pb(X0 + 2, walkY2, Z0 + 1, 'campfire[lit=true]');
for (x = 30; x <= 33; x++) for (y = walkY2; y <= walkY2 + 1; y++) pb(x, y, Z0 + 1, 'bookshelf');
var lampsU = [[24, 21], [30, 25], [26, 29]];
for (i = 0; i < lampsU.length; i++) { ps(lampsU[i][0], roofY - 1, lampsU[i][1], 'chain[axis=y]'); ps(lampsU[i][0], roofY - 2, lampsU[i][1], 'lantern[hanging=true]'); }

// === 12. STREET & LANDSCAPING (camera side) ===
function streetLamp(lx, lz) {
    var yy;
    pb(lx, padY, lz, 'polished_deepslate');
    for (yy = padY + 1; yy <= padY + 4; yy++) pb(lx, yy, lz, 'dark_oak_fence');
    pb(lx, padY + 5, lz, 'polished_deepslate');
    ps(lx - 1, padY + 5, lz, 'chain[axis=y]'); ps(lx - 1, padY + 4, lz, 'lantern[hanging=true]');
    ps(lx + 1, padY + 5, lz, 'chain[axis=y]'); ps(lx + 1, padY + 4, lz, 'lantern[hanging=true]');
}
streetLamp(41, 30); streetLamp(26, 39);
function planter(px, pz) {
    var a, c;
    for (a = 0; a < 2; a++) for (c = 0; c < 2; c++) {
        pb(px + a, padY, pz + c, 'polished_deepslate');
        pb(px + a, padY + 1, pz + c, ((a + c) % 2 === 0) ? 'flowering_azalea_leaves' : 'moss_block');
    }
}
planter(41, 19); planter(41, 24); planter(19, 37); planter(24, 37);
placeTree(44, padY + 1, 35, 'oak');
placeTree(16, padY + 1, 38, 'birch');
ps(X1 + 1, 15, 22, 'dark_oak_wall_sign[facing=east]');
ps(24, 15, Z1 + 1, 'dark_oak_wall_sign[facing=south]');
for (x = X1 + 2; x <= X1 + 4; x++) for (z = Z1 + 2; z <= Z1 + 4; z++) ps(x, padY, z, 'smooth_stone_slab[type=top]');

// === FIX PASS: make the CORNER TURRET read as its own volume (copper vs slate) ===
var copperPal = noisePalette([{block:'exposed_copper',weight:42},{block:'weathered_copper',weight:34},{block:'cut_copper',weight:24}], {seed:47, freq:0.2});
var copperLight = noisePalette([{block:'cut_copper',weight:55},{block:'exposed_copper',weight:45}], {seed:48, freq:0.22});
// copper drum with a cornice ring, then a copper cone cap
makeCylinder(CX, roofY, CZ, copperLight, R - 0.4, 3, true);
makeCylinder(CX, roofY + 2, CZ, b('cut_copper_slab[type=top]'), R + 0.4, 1, true);
makeCone(CX, roofY + 3, CZ, copperPal, R - 0.4, 8, false);
pb(CX, roofY + 11, CZ, 'cut_copper');
pb(CX, roofY + 12, CZ, 'lightning_rod');
// iron cresting round the base of the cone so the turret has an outline
var fa;
for (fa = 0; fa < 360; fa += 20) {
    var rx = CX + Math.round((R - 1) * Math.cos(fa * Math.PI / 180));
    var rz2 = CZ + Math.round((R - 1) * Math.sin(fa * Math.PI / 180));
    if (rx > X1 || rz2 > Z1) continue;
    pb(rx, roofY + 3, rz2, 'iron_bars');
}
// copper cornice band on the main mansard eave = the two roofs stop being one dark mass
var cx3, cz3;
for (cx3 = X0 - 1; cx3 <= X1 + 1; cx3++) for (cz3 = Z0 - 1; cz3 <= Z1 + 1; cz3++) {
    if (inside(cx3, cz3)) continue;
    var tt2 = inside(cx3 + 1, cz3) || inside(cx3 - 1, cz3) || inside(cx3, cz3 + 1) || inside(cx3, cz3 - 1);
    if (tt2) { pb(cx3, roofY, cz3, copperLight(cx3, roofY, cz3)); ps(cx3, roofY + 1, cz3, 'cut_copper_slab[type=bottom]'); }
}

Static Renders

Art Nouveau Corner Apothecary (indexed) isometric viewisometric
Art Nouveau Corner Apothecary (indexed) front viewfront
Art Nouveau Corner Apothecary (indexed) side viewside
Art Nouveau Corner Apothecary (indexed) back viewback
Art Nouveau Corner Apothecary (indexed) top viewtop