```python
import bpy, math
from mathutils import Vector
from math import radians, sin, cos, pi

# ---------- clear ----------
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
for d in (bpy.data.materials, bpy.data.curves, bpy.data.meshes, bpy.data.cameras, bpy.data.lights):
    pass

# ---------- materials ----------
def mat(name, color, rough=0.5, metallic=0.0, emission=None, estr=0):
    m = bpy.data.materials.new(name)
    m.diffuse_color = (*color, 1)
    m.use_nodes = True
    bs = m.node_tree.nodes.get("Principled BSDF")
    bs.inputs["Base Color"].default_value = (*color, 1)
    bs.inputs["Roughness"].default_value = rough
    bs.inputs["Metallic"].default_value = metallic
    if emission:
        if "Emission Color" in bs.inputs:
            bs.inputs["Emission Color"].default_value = (*emission, 1)
            bs.inputs["Emission Strength"].default_value = estr
        else:
            bs.inputs["Emission"].default_value = (*emission, 1)
            bs.inputs["Emission Strength"].default_value = estr
    return m

red = mat("faded vermillion enamel", (0.48,0.035,0.025), .42)
red_hi = mat("fresh shrine vermillion", (0.78,0.075,0.035), .3)
cream = mat("warm ivory front panel", (0.82,0.74,0.57), .42)
dark = mat("rubber and deep recesses", (0.035,0.028,0.025), .7)
glass = mat("slightly tinted display glass", (0.08,0.18,0.20), .16, emission=(0.18,0.32,0.28), estr=.35)
warm = mat("fluorescent warm interior", (0.98,0.46,0.12), .25, emission=(1.0,.25,.045), estr=5)
white = mat("clean paper", (.95,.91,.77), .7)
paper_red = mat("paper red ink", (.68,.05,.035), .65)
wood = mat("new shrine wood", (.32,.095,.035), .48)
wood_hi = mat("clean wood edges", (.58,.20,.065), .4)
gold = mat("bell brass", (.72,.38,.07), .25, .65)
rust = mat("rust blooms", (.38,.09,.025), .8)
blue = mat("blue dusk metal", (.075,.12,.18), .5)
asphalt = mat("cracked asphalt", (.07,.075,.07), .95)
concrete = mat("old concrete curb", (.34,.36,.33), .8)
grass = mat("grass", (.08,.20,.065), .9)
foxwhite = mat("ceramic fox ivory", (.9,.78,.56), .3)
foxred = mat("fox vermillion markings", (.65,.06,.025), .4)
label_blue = mat("can blue", (.04,.22,.45), .3)
label_green = mat("can green", (.04,.38,.24), .35)
label_yellow = mat("can yellow", (.95,.5,.04), .3)
label_pink = mat("can pink", (.7,.08,.20), .35)
label_purple = mat("can purple", (.27,.08,.4), .35)
label_white = mat("can silver", (.65,.68,.63), .25, .35)
em_button = mat("button illumination", (.9,.3,.08), .25, emission=(1,.12,.015), estr=3)
flagmat = mat("nobori cloth", (.68,.035,.025), .7)
flagcream = mat("nobori lettering", (.95,.78,.48), .6)

# ---------- primitive helpers ----------
def cube(name, loc, scale, material, bevel=0.0, rot=None):
    bpy.ops.mesh.primitive_cube_add(location=loc, rotation=rot or (0,0,0))
    o=bpy.context.object; o.name=name; o.scale=(scale[0]/2,scale[1]/2,scale[2]/2)
    bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    if material: o.data.materials.append(material)
    if bevel:
        mod=o.modifiers.new("soft formed edge","BEVEL"); mod.width=bevel; mod.segments=2
    return o

def cyl(name, loc, radius, depth, material, rot=None, verts=16, bevel=0.0):
    bpy.ops.mesh.primitive_cylinder_add(vertices=verts, radius=radius, depth=depth, location=loc, rotation=rot or (0,0,0))
    o=bpy.context.object; o.name=name
    if material:o.data.materials.append(material)
    if bevel:
        mod=o.modifiers.new("rounded edge","BEVEL"); mod.width=bevel; mod.segments=2
    return o

def uv(name, loc, scale, material):
    bpy.ops.mesh.primitive_uv_sphere_add(segments=16, ring_count=10, location=loc)
    o=bpy.context.object; o.name=name; o.scale=scale; bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    o.data.materials.append(material); return o

def torus(name, loc, major, minor, material, rot=(0,0,0)):
    bpy.ops.mesh.primitive_torus_add(major_radius=major, minor_radius=minor, major_segments=24, minor_segments=8, location=loc, rotation=rot)
    o=bpy.context.object; o.name=name; o.data.materials.append(material); return o

def text_obj(name, body, loc, size, material, rot=(radians(90),0,0), extr=.006, align='CENTER'):
    cu=bpy.data.curves.new(name,'FONT'); cu.body=body; cu.align_x=align; cu.align_y='CENTER'; cu.size=size; cu.extrude=extr; cu.bevel_depth=.001
    o=bpy.data.objects.new(name,cu); bpy.context.collection.objects.link(o); o.location=loc; o.rotation_euler=rot; o.data.materials.append(material); return o

# ---------- machine ----------
cube("cabinet", (0,0,1.02), (1.0,.75,1.83), red, .055)
# chamfered roof cap and lower foot
cube("top metal lip",(0,-.005,1.91),(1.0,.78,.10),red_hi,.035)
cube("bottom plinth",(0,-.015,.12),(1.02,.78,.12),dark,.025)
cube("cream recessed front",(0,-.386,1.02),(.87,.025,1.55),cream,.018)

# display recess, backing and warm glow
cube("display dark recess",(0,-.405,1.48),(.78,.018,.47),dark,.015)
cube("warm display backing",(0,-.417,1.48),(.75,.012,.42),warm,.008)
cube("display glass",(0,-.458,1.48),(.79,.012,.48),glass,.012)

# angled shelves
for z in (1.33,1.54):
    cube("angled can shelf",(0,-.445,z),(.73,.09,.025),dark,.008,rot=(radians(-6),0,0))

# cans, 6 x 2
canm=[label_blue,label_green,label_yellow,label_pink,label_purple,label_white]
for row,z in enumerate((1.42,1.64)):
    for i,x in enumerate([-.30,-.18,-.06,.06,.18,.30]):
        cyl("product sample can",(x,-.485,z),.043,.105,canm[i],rot=(radians(90),0,0),verts=20,bevel=.004)
        cyl("can silver top",(x,-.545,z),.035,.006,label_white,rot=(radians(90),0,0),verts=16)
        cube("can label stripe",(x,-.545,z),(.052,.004,.022),white,.002)

# middle band
cube("selection control band",(0,-.412,1.02),(.79,.026,.30),cream,.012)
# coin and bill hardware
cube("coin slot",( -.29,-.445,1.10),(.12,.018,.07),dark,.008)
cube("coin slit",(-.29,-.458,1.10),(.07,.008,.012),gold,.002)
cube("bill reader",(-.29,-.446,.96),(.13,.018,.065),dark,.008)
cube("bill opening",(-.29,-.459,.96),(.08,.007,.012),blue,.002)
text_obj("coin label","¥",(-.29,-.466,1.145),.045,gold)
# 12 buttons 4x3
for j,z in enumerate([1.10,1.015,.93]):
    for i,x in enumerate([-.08,.05,.18,.31]):
        cube("glowing selection button",(x,-.447,z),(.075,.022,.055),em_button,.014)
        cube("tiny price tag",(x,-.462,z-.038),(.062,.006,.018),white,.002)
        text_obj("price","120", (x,-.467,z-.038), .012, dark, extr=.001)

# bell replacing upper-right-ish button
cyl("brass shrine bell",(.31,-.475,1.10),.035,.035,gold,rot=(radians(90),0,0),verts=20)
torus("bell rim",(.31,-.497,1.10),.035,.006,gold,rot=(radians(90),0,0))
cyl("bell clapper",(.31,-.51,1.055),.009,.045,gold,rot=(0,0,0),verts=10)
# pull cord
cyl("bell red pull cord",(.31,-.525,.91),.008,.28,red_hi,verts=8)
cube("bell pull handle",(.31,-.53,.76),(.055,.025,.04),white,.01)
text_obj("button labels","DRINKS",(.10,-.467,1.185),.035,dark)

# hatch
cube("dispensing lower recess",(0,-.414,.48),(.72,.025,.31),dark,.018)
cube("metal dispensing flap",(0,-.452,.51),(.55,.025,.20),blue,.018)
cube("flap push bar",(0,-.475,.59),(.32,.018,.025),gold,.008)
text_obj("dispense label","TAKE YOUR DRINK", (0,-.476,.405),.027,white)

# ghost sticker outline on right
for loc,sc in [((.28,-.472,.73),(.23,.008,.012)),((.28,-.472,.86),(.23,.008,.012)),((.17,-.472,.795),(.012,.008,.13)),((.39,-.472,.795),(.012,.008,.13))]:
    cube("peeled sticker ghost",loc,sc,blue,.002)

# rain streaks and rust
for x,z,l in [(-.39,1.22,.16),(.41,1.42,.11),(.37,1.18,.20),(-.43,.28,.12),(.43,.32,.16)]:
    cube("rain streak",(x,-.468,z),(.012,.006,l),blue,.003)
for x in [-.43,-.30,.34,.44]:
    uv("rust bloom",(x,-.46,.20+abs(x)*.05),(.035,.012,.045),rust)
for x in [-.42,.42]:
    cyl("rusted bolt",(x,-.48,.91),.018,.012,rust,rot=(radians(90),0,0),verts=12)

# ---------- shimenawa ----------
# rope across display top
cyl("shimenawa rope",(0,-.49,1.76),.025,.72,white,rot=(0,radians(90),0),verts=16)
for x in [-.28,-.14,0,.14,.28]:
    torus("rope twist knot",(x,-.50,1.76),.032,.008,white,rot=(0,radians(90),0))
# shide as angular paper ribbons
def shide(x):
    verts=[(x-.045,-.515,1.73),(x+.015,-.515,1.73),(x-.015,-.515,1.66),(x+.045,-.515,1.66),
           (x+.015,-.515,1.60),(x-.045,-.515,1.60)]
    mesh=bpy.data.meshes.new("zigzag shide mesh"); mesh.from_pydata(verts,[],[[0,1,2,3,4,5]]); mesh.materials.append(white)
    ob=bpy.data.objects.new("paper shide",mesh); bpy.context.collection.objects.link(ob)
for x in [-.22,0,.22]: shide(x)

# ---------- torii on roof ----------
for x in [-.27,.27]:
    cube("torii pillar",(x,0,2.10),(.065,.075,.38),wood_hi,.012)
cube("torii lower crossbeam",(0,0,2.20),(.68,.09,.07),wood_hi,.015)
cube("torii upper lintel",(0,0,2.32),(.82,.11,.075),red_hi,.018)
cube("torii top curved cap",(0,0,2.385),(.92,.13,.07),wood_hi,.025)
# end caps
for x in [-.43,.43]: uv("torii cap",(x,0,2.40),(.055,.07,.035),wood_hi)

# fox figurines facing each other
def fox(x, facing):
    uv("kitsune body",(x,0,2.00),(.105,.08,.14),foxwhite)
    uv("kitsune head",(x,-.015,2.15),(.095,.08,.09),foxwhite)
    # ears
    for dx in [-.05,.05]:
        bpy.ops.mesh.primitive_cone_add(vertices=12,radius1=.035,radius2=0,depth=.11,location=(x+dx,-.015,2.25))
        bpy.context.object.data.materials.append(foxred)
    # red chest and muzzle
    uv("fox red bib",(x,-.078,2.07),(.055,.015,.065),foxred)
    uv("fox muzzle",(x+facing*.055,-.078,2.14),(.045,.025,.035),foxwhite)
    # tail curling upward
    cyl("fox tail",(x-facing*.10,.04,2.07),.035,.16,foxwhite,rot=(0,radians(55),0),verts=12)
fox(-.16,1); fox(.16,-1)

# offering box beside hatch, front left
cube("saisen bako",( -.47,-.50,.48),(.22,.18,.18),wood,.018)
cube("offering box slatted lid",(-.47,-.505,.585),(.24,.19,.035),wood_hi,.008)
for x in [-.54,-.49,-.44,-.39]:
    cube("lid slat",(x,-.605,.60),(.018,.02,.045),wood_hi,.003)
text_obj("offering inscription","賽銭",(-.47,-.598,.50),.035,white)

# ---------- side omikuji rack ----------
cyl("fortune rack vertical",(-.55,-.12,1.10),.012,.72,gold,verts=10)
cyl("fortune rack top",(-.55,-.12,1.45),.012,.32,gold,rot=(0,radians(90),0),verts=10)
for i,(y,z,ang) in enumerate([(-.17,1.34,-18),(-.08,1.23,12),(-.20,1.11,28),(-.06,.98,-15),(-.18,.88,18)]):
    # paper hanging vertically in XZ plane, varied rotations
    o=cube("hand tied omikuji",(-.55,y,z),(.07,.012,.19),white,.006,rot=(0,radians(ang),0))
    text_obj("fortune mark","おみくじ",(-.55,y-.009,z+.01),.015,paper_red,rot=(radians(90),0,0),extr=.001)
    cyl("fortune string",(-.55,y-.01,z+.12),.006,.055,red_hi,verts=8)

# ---------- ground / road ----------
cube("asphalt patch",(0,.18,.015),(2.8,2.0,.06),asphalt,.02)
cube("concrete curb",(0,-.78,.08),(2.7,.18,.16),concrete,.025)
# asphalt crack strips
for x,y,a in [(-.8,-.2,20),(.7,.35,-35),(-.35,.5,55),(.95,-.35,10)]:
    cube("road crack",(x,y,.048),(.25,.012,.006),dark,.002,rot=(0,0,radians(a)))
# grass tufts
for x,y in [(-.58,-.48),(-.48,-.68),(.48,-.50),(.60,-.35),(-.75,-.25)]:
    for k in range(3):
        cube("grass blade",(x+.025*k,y,.13),(.012,.012,.16),grass,.002,rot=(0,radians(-15+10*k),0))

# ---------- nobori flag ----------
cyl("banner pole",(-.88,.02,.95),.018,1.9,wood_hi,verts=12)
cube("vertical nobori flag",(-.88,-.015,1.56),(.34,.025,.68),flagmat,.015)
text_obj("nobori symbol","稲荷",(-.88,-.035,1.60),.16,flagcream,rot=(radians(90),0,0),extr=.003)
cube("flag top tie",(-.88,-.03,1.90),(.39,.035,.025),wood_hi,.006)

# ---------- lighting/world ----------
world=bpy.context.scene.world
world.use_nodes=True
world.node_tree.nodes["Background"].inputs["Color"].default_value=(.018,.035,.075,1)
world.node_tree.nodes["Background"].inputs["Strength"].default_value=.25

def area(name,loc,energy,color,size):
    bpy.ops.object.light_add(type='AREA', location=loc)
    l=bpy.context.object; l.name=name; l.data.energy=energy; l.data.color=color; l.data.shape='DISK'; l.data.size=size
    return l
def point(name,loc,energy,color):
    bpy.ops.object.light_add(type='POINT',location=loc)
    l=bpy.context.object; l.name=name; l.data.energy=energy; l.data.color=color; l.data.shadow_soft_size=.25; return l
area("cool blue hour fill",(-3,-4,4),500,(.18,. thirty if False else .28,.65),5)
point("warm interior spill",(0,-.75,1.45),420,(1.0,.22,.06))
point("button glow",(0,-.7,1.0),90,(1.0,.08,.02))
area("soft moon rim",(3,2,3),650,(.16,.28,.65),4)

# ---------- camera ----------
bpy.ops.object.camera_add(location=(-3.05,-4.8,2.55))
cam=bpy.context.object; cam.name="presentation camera"; bpy.context.scene.camera=cam
cam.data.lens=46
def track(obj, target):
    obj.rotation_euler=(Vector(target)-obj.location).to_track_quat('-Z','Y').to_euler()
track(cam,(0,-.05,1.22))

scene=bpy.context.scene
scene.render.engine='BLENDER_EEVEE_NEXT'
scene.render.resolution_x=1536; scene.render.resolution_y=1536; scene.render.resolution_percentage=100
scene.render.image_settings.file_format='PNG'
scene.render.film_transparent=False
scene.view_settings.look='AgX - Medium High Contrast'
scene.render.filepath='/tmp/japanese_vending_shrine.png'
# cycles-compatible scene settings for benchmark override
scene.cycles.samples=64
scene.cycles.use_denoising=True
# organize
for o in bpy.context.scene.objects:
    o.select_set(False)
bpy.ops.wm.save_as_mainfile(filepath='/tmp/japanese_vending_shrine.blend')
```