```python
import bpy
import math
from mathutils import Vector

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

scene = bpy.context.scene
scene.render.engine = 'CYCLES'
scene.cycles.samples = 64
scene.cycles.use_denoising = True
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.view_transform = 'AgX'

def material(name, color, metal=0.0, rough=0.4):
    m = bpy.data.materials.new(name)
    m.diffuse_color = (*color, 1)
    m.use_nodes = True
    p = m.node_tree.nodes.get('Principled BSDF')
    p.inputs['Base Color'].default_value = (*color, 1)
    p.inputs['Metallic'].default_value = metal
    p.inputs['Roughness'].default_value = rough
    return m

enamel = material('Deep spruce • vitreous enamel', (0.018, 0.073, 0.061), .72, .255)
steel = material('Blackened steel', (.025, .032, .033), .82, .29)
brass = material('Aged satin brass', (.40, .235, .082), .8, .3)
bright = material('Exposed steel edges', (.32, .37, .36), .92, .22)
black = material('Soot-dark burner interior', (.008, .006, .004), .15, .68)
ivory = material('Warm ivory lettering', (.76, .68, .46), .25, .4)

# Very fine surface variation, kept subtle enough to read as manufactured metal.
for m in (enamel, brass):
    nt = m.node_tree
    p = nt.nodes.get('Principled BSDF')
    noise = nt.nodes.new('ShaderNodeTexNoise')
    noise.inputs['Scale'].default_value = 165
    noise.inputs['Detail'].default_value = 2
    bump = nt.nodes.new('ShaderNodeBump')
    bump.inputs['Strength'].default_value = .13
    bump.inputs['Distance'].default_value = .008
    nt.links.new(noise.outputs['Fac'], bump.inputs['Height'])
    nt.links.new(bump.outputs['Normal'], p.inputs['Normal'])

glass = bpy.data.materials.new('Clear, thin hurricane glass')
glass.use_nodes = True
glass.diffuse_color = (.94, .98, .97, .16)
nt = glass.node_tree
nt.nodes.clear()
out = nt.nodes.new('ShaderNodeOutputMaterial')
p = nt.nodes.new('ShaderNodeBsdfPrincipled')
p.inputs['Base Color'].default_value = (.97, .995, .98, 1)
p.inputs['Roughness'].default_value = .045
p.inputs['Transmission Weight'].default_value = 1
p.inputs['IOR'].default_value = 1.46
# Permit the flame's illumination to pass through the clear shade without
# requiring a difficult specular-caustic path.
lp = nt.nodes.new('ShaderNodeLightPath')
trans = nt.nodes.new('ShaderNodeBsdfTransparent')
mix = nt.nodes.new('ShaderNodeMixShader')
nt.links.new(lp.outputs['Is Shadow Ray'], mix.inputs[0])
nt.links.new(p.outputs['BSDF'], mix.inputs[1])
nt.links.new(trans.outputs[0], mix.inputs[2])
nt.links.new(mix.outputs[0], out.inputs['Surface'])

def emission(name, color, strength):
    m = material(name, color, 0, .35)
    p = m.node_tree.nodes.get('Principled BSDF')
    p.inputs['Emission Color'].default_value = (*color, 1)
    p.inputs['Emission Strength'].default_value = strength
    return m

flame_mat = emission('Amber flame envelope', (1.0, .255, .025), 7)
flame_inner = emission('Golden luminous heart', (1.0, .69, .21), 14)

def mesh_obj(name, verts, faces, mat):
    me = bpy.data.meshes.new(name)
    me.from_pydata(verts, [], faces)
    me.update()
    ob = bpy.data.objects.new(name, me)
    bpy.context.collection.objects.link(ob)
    if mat:
        ob.data.materials.append(mat)
    for f in me.polygons:
        f.use_smooth = True
    return ob

def lathe(name, profile, mat, n=128):
    verts = []
    for radius, z in profile:
        for j in range(n):
            a = 2 * math.pi * j / n
            verts.append((radius * math.cos(a), radius * math.sin(a), z))
    faces = []
    for k in range(len(profile)-1):
        for j in range(n):
            q = (j+1) % n
            faces.append((k*n+j, k*n+q, (k+1)*n+q, (k+1)*n+j))
    return mesh_obj(name, verts, faces, mat)

def torus(name, major, minor, z, mat, loc=None, rot=None):
    bpy.ops.mesh.primitive_torus_add(
        major_segments=96, minor_segments=16,
        major_radius=major, minor_radius=minor,
        location=loc or (0, 0, z))
    ob = bpy.context.object
    ob.name = name
    if rot:
        ob.rotation_euler = rot
    ob.data.materials.append(mat)
    for f in ob.data.polygons:
        f.use_smooth = True
    return ob

def cylinder(name, radius, depth, loc, mat, rot=None, vertices=64):
    bpy.ops.mesh.primitive_cylinder_add(vertices=vertices, radius=radius, depth=depth, location=loc)
    ob = bpy.context.object
    ob.name = name
    if rot:
        ob.rotation_euler = rot
    ob.data.materials.append(mat)
    mod = ob.modifiers.new('Soft machined edges', 'BEVEL')
    mod.width = .008
    mod.segments = 3
    ob.modifiers.new('Weighted corner normals', 'WEIGHTED_NORMAL')
    for p in ob.data.polygons:
        p.use_smooth = True
    return ob

def tube(name, points, radius, mat, cyclic=False):
    cu = bpy.data.curves.new(name, 'CURVE')
    cu.dimensions = '3D'
    cu.resolution_u = 20
    cu.bevel_depth = radius
    cu.bevel_resolution = 5
    sp = cu.splines.new('BEZIER')
    sp.bezier_points.add(len(points)-1)
    for b, co in zip(sp.bezier_points, points):
        b.co = co
        b.handle_left_type = 'AUTO'
        b.handle_right_type = 'AUTO'
    sp.use_cyclic_u = cyclic
    ob = bpy.data.objects.new(name, cu)
    bpy.context.collection.objects.link(ob)
    ob.data.materials.append(mat)
    bpy.context.view_layer.objects.active = ob
    ob.select_set(True)
    bpy.ops.object.convert(target='MESH')
    ob.select_set(False)
    return ob

def box(name, loc, scale, mat, bevel=.02):
    bpy.ops.mesh.primitive_cube_add(size=1, location=loc)
    ob = bpy.context.object
    ob.name = name
    ob.dimensions = scale
    bpy.ops.object.transform_apply(location=False, rotation=False, scale=True)
    ob.data.materials.append(mat)
    mod = ob.modifiers.new('Rounded corners', 'BEVEL')
    mod.width = bevel
    mod.segments = 4
    ob.modifiers.new('Weighted normals', 'WEIGHTED_NORMAL')
    return ob

# ---------------------------------------------------------------------
# Fuel reservoir and rolled base
# ---------------------------------------------------------------------
lathe('Spun enamel fuel reservoir', [
    (.001,.075),(.46,.075),(.55,.085),(.592,.12),(.604,.17),
    (.603,.24),(.588,.34),(.565,.43),(.521,.51),(.445,.565),
    (.365,.59),(.30,.615),(.001,.615)
], enamel)
torus('Rolled bottom seam', .582, .026, .115, steel)
torus('Polished edge on foot', .588, .012, .14, bright)
torus('Tank shoulder bead', .479, .014, .548, enamel)

lathe('Burner pedestal', [
    (.001,.595),(.29,.595),(.323,.623),(.326,.655),
    (.30,.675),(.252,.69),(.215,.712),(.001,.712)
], steel)
lathe('Lower glass seat', [
    (.24,.666),(.377,.667),(.413,.694),(.418,.734),
    (.404,.751),(.379,.738),(.367,.70),(.24,.70)
], enamel)
torus('Seat brass rim', .401, .013, .738, brass)

# Fill cap on the sloping front-right shoulder.
cylinder('Fuel filler socket', .114, .052, (.365,-.275,.555), steel)
cylinder('Knurled brass fuel cap', .104, .054, (.365,-.275,.598), brass)
torus('Fuel cap top bead', .086, .009, .629, bright, loc=(.365,-.275,.629))
for i in range(32):
    a = i*2*math.pi/32
    cylinder('Cap grip flute', .006, .038,
             (.365+.102*math.cos(a), -.275+.102*math.sin(a), .598),
             brass, vertices=12)
box('Filler cap screwdriver slot', (.365,-.275,.63), (.102,.014,.004), steel, .004)

# ---------------------------------------------------------------------
# Integral side air tubes, real three-dimensional curved metal
# ---------------------------------------------------------------------
for side in (-1, 1):
    tube(('Left' if side < 0 else 'Right') + ' sweeping air tube', [
        (side*.46, .055,.40),
        (side*.635,.055,.54),
        (side*.743,.055,.83),
        (side*.757,.055,1.36),
        (side*.715,.055,1.86),
        (side*.60,.055,2.11),
        (side*.40,.055,2.225),
        (side*.285,.055,2.23)
    ], .073, enamel)
    cylinder('Bail pivot housing', .097, .115, (side*.727,.016,2.005),
             enamel, (math.pi/2,0,0))
    cylinder('Brass bail pivot', .051, .127, (side*.727,-.002,2.005),
             brass, (math.pi/2,0,0))
    cylinder('Pivot pin', .022, .135, (side*.727,-.007,2.005),
             bright, (math.pi/2,0,0))

# Protective wire hoops and four slim guard uprights.
torus('Lower globe protective hoop', .555, .021, 1.025, steel)
for a in (math.radians(43),math.radians(137),math.radians(223),math.radians(317)):
    tube('Curved globe guard', [
        (.385*math.cos(a), .385*math.sin(a), .742),
        (.515*math.cos(a), .515*math.sin(a), .95),
        (.544*math.cos(a), .544*math.sin(a),1.22),
        (.49*math.cos(a), .49*math.sin(a),1.69),
        (.355*math.cos(a), .355*math.sin(a),2.038)
    ], .014, steel)

# Globe: closed cross-section, actual inner and outer walls.
outer = [
    (.378,.741),(.407,.775),(.451,.84),(.492,.94),(.513,1.065),
    (.517,1.20),(.497,1.40),(.468,1.62),(.416,1.82),
    (.359,1.972),(.343,2.039)
]
inner = [(r-.009,z) for r,z in reversed(outer)]
lathe('Hand-blown hurricane glass — 9 mm wall', outer+inner+[outer[0]], glass)
torus('Glass lip', .339, .008, 2.035, glass)

# ---------------------------------------------------------------------
# Burner, adjustment mechanism and luminous wick
# ---------------------------------------------------------------------
lathe('Brass wick burner', [
    (.001,.706),(.192,.706),(.211,.727),(.209,.778),
    (.18,.802),(.151,.814),(.146,.871),(.126,.896),(.001,.896)
], brass)
torus('Burner rolled flange', .2, .012, .752, brass)
for i in range(28):
    a = i*2*math.pi/28
    cylinder('Burner air opening', .012, .002,
             (.183*math.cos(a),.183*math.sin(a),.797), black, vertices=16)
box('Flat wick guide', (0,0,.893), (.141,.051,.054), steel, .009)
box('Charred cotton wick', (0,0,.927), (.101,.029,.032), black, .004)

cylinder('Wick adjuster spindle', .024, .33, (.19,-.16,.778),
         brass, (0,math.pi/2,0))
cylinder('Wick adjustment thumbwheel', .067, .032, (.358,-.16,.778),
         brass, (0,math.pi/2,0), vertices=48)
for i in range(24):
    a=2*math.pi*i/24
    cylinder('Thumbwheel scallop', .009, .036,
             (.358,-.16+.065*math.cos(a),.778+.065*math.sin(a)),
             brass, (0,math.pi/2,0), vertices=12)

def flame(name, rings, mat):
    verts=[]
    n=48
    for z, r, dx in rings:
        for j in range(n):
            a=2*math.pi*j/n
            verts.append((dx+r*math.cos(a),r*.64*math.sin(a),z))
    faces=[]
    for k in range(len(rings)-1):
        for j in range(n):
            faces.append((k*n+j,k*n+(j+1)%n,(k+1)*n+(j+1)%n,(k+1)*n+j))
    return mesh_obj(name, verts, faces, mat)

flame('Living amber flame', [
    (.928,.016,0),(.96,.047,0),(1.02,.069,.006),
    (1.10,.059,.012),(1.18,.039,.025),(1.26,.023,.035),
    (1.34,.009,.026),(1.385,.001,.008)
], flame_mat)
flame('Bright flame heart', [
    (.933,.008,0),(.96,.03,0),(1.02,.042,.004),
    (1.09,.03,.012),(1.17,.001,.017)
], flame_inner)

# ---------------------------------------------------------------------
# Ventilated chimney and broad rain cap
# ---------------------------------------------------------------------
lathe('Upper glass collar', [
    (.29,1.99),(.362,1.99),(.376,2.013),(.376,2.058),
    (.343,2.079),(.29,2.079),(.29,1.99)
], steel)
torus('Upper collar rolled edge', .365, .012, 2.032, brass)
lathe('Dark internal chimney', [
    (.235,2.018),(.255,2.018),(.255,2.284),(.235,2.284),(.235,2.018)
], black)
lathe('Vent lower rim', [
    (.255,2.058),(.317,2.058),(.326,2.078),(.326,2.102),
    (.305,2.117),(.255,2.117)
], enamel)
# Open gaps between these ribs are genuine ventilation slots.
for i in range(18):
    a=2*math.pi*i/18
    da=.061
    verts=[]
    for z in (2.103,2.27):
        for r in (.29,.322):
            for t in (a-da,a+da):
                verts.append((r*math.cos(t),r*math.sin(t),z))
    faces=[(0,1,3,2),(4,6,7,5),(0,4,5,1),(2,3,7,6),(0,2,6,4),(1,5,7,3)]
    mesh_obj('Chimney vent rib',verts,faces,enamel)

lathe('Spun rain hood', [
    (.001,2.254),(.27,2.254),(.39,2.224),(.53,2.205),
    (.565,2.224),(.568,2.248),(.546,2.268),(.458,2.287),
    (.393,2.333),(.343,2.409),(.294,2.458),
    (.22,2.484),(.001,2.484)
], enamel)
torus('Rain hood rolled rim', .551, .017, 2.241, steel)
lathe('Crown button', [
    (.001,2.48),(.126,2.48),(.137,2.495),(.137,2.515),
    (.112,2.532),(.001,2.535)
], brass)
torus('Small crown hanging eye', .078, .018, 0, steel,
      loc=(0,0,2.592), rot=(math.pi/2,0,0))

# Tall bowed wire bail, anchored at the two shoulder pivots.
tube('Arched carrying bail', [
    (-.727,-.072,2.005),(-.825,-.072,2.12),(-.875,-.05,2.48),
    (-.812,-.025,2.88),(-.605,0,3.22),(-.31,.014,3.405),
    (0,.019,3.459),(.31,.014,3.405),(.605,0,3.22),
    (.812,-.025,2.88),(.875,-.05,2.48),(.825,-.072,2.12),
    (.727,-.072,2.005)
], .029, steel)
# A short brass sleeve makes the grip subtly legible.
tube('Bail grip sleeve', [
    (-.22,.017,3.43),(-.11,.019,3.452),(0,.019,3.459),
    (.11,.019,3.452),(.22,.017,3.43)
], .04, brass)

# Small maker's plate, not a graphic overlay.
box('Brass maker plate', (0,-.573,.378), (.43,.025,.183), brass,.027)
box('Enamel plate inset', (0,-.589,.378), (.39,.009,.148), steel,.018)
for x in (-.176,.176):
    cylinder('Plate rivet', .012, .012, (x,-.599,.378),
             brass, (math.pi/2,0,0), vertices=24)

def text_obj(name, body, loc, size, mat):
    cu=bpy.data.curves.new(name,'FONT')
    cu.body=body
    cu.align_x='CENTER'
    cu.align_y='CENTER'
    cu.size=size
    cu.extrude=.0007
    cu.bevel_depth=.0003
    ob=bpy.data.objects.new(name,cu)
    bpy.context.collection.objects.link(ob)
    ob.location=loc
    ob.rotation_euler=(math.pi/2,0,0)
    ob.data.materials.append(mat)
    bpy.context.view_layer.objects.active=ob
    ob.select_set(True)
    bpy.ops.object.convert(target='MESH')
    ob.select_set(False)

text_obj('Maker lettering','N O R T H',(0,-.596,.401),.047,ivory)
text_obj('Model lettering','No. 07',(0,-.596,.352),.033,ivory)

# ---------------------------------------------------------------------
# Ground, illumination, and product-shot presentation
# ---------------------------------------------------------------------
ground = material('Matte midnight slate', (.025,.034,.042), .05, .72)
nt=ground.node_tree
p=nt.nodes.get('Principled BSDF')
noise=nt.nodes.new('ShaderNodeTexNoise')
noise.inputs['Scale'].default_value=95
noise.inputs['Detail'].default_value=2
bump=nt.nodes.new('ShaderNodeBump')
bump.inputs['Strength'].default_value=.18
bump.inputs['Distance'].default_value=.018
nt.links.new(noise.outputs['Fac'],bump.inputs['Height'])
nt.links.new(bump.outputs['Normal'],p.inputs['Normal'])
bpy.ops.mesh.primitive_plane_add(size=200, location=(0,0,.068))
bpy.context.object.name='Quiet slate ground'
bpy.context.object.data.materials.append(ground)

world=bpy.data.worlds.new('Dark blue studio')
scene.world=world
world.use_nodes=True
world.node_tree.nodes['Background'].inputs['Color'].default_value=(.035,.052,.075,1)
world.node_tree.nodes['Background'].inputs['Strength'].default_value=.22

def point(name, loc, color, power, radius):
    data=bpy.data.lights.new(name,'POINT')
    data.energy=power
    data.color=color
    data.shadow_soft_size=radius
    ob=bpy.data.objects.new(name,data)
    bpy.context.collection.objects.link(ob)
    ob.location=loc
    return ob

point('Flame • warm transmitted illumination',(0,-.012,1.115),(1,.36,.075),32,.115)

def area(name, loc, target, power, color, size, size_y=None):
    data=bpy.data.lights.new(name,'AREA')
    data.energy=power
    data.color=color
    if size_y:
        data.shape='RECTANGLE'
        data.size=size
        data.size_y=size_y
    else:
        data.shape='DISK'
        data.size=size
    ob=bpy.data.objects.new(name,data)
    bpy.context.collection.objects.link(ob)
    ob.location=loc
    ob.rotation_euler=(Vector(target)-ob.location).to_track_quat('-Z','Y').to_euler()
    return ob

area('Large softbox • left edge',(-3.4,-4.0,5.0),(0,0,1.45),420,(.79,.88,1),3.5,4.5)
area('Cool rear rim',(2.7,2.3,4.3),(0,0,1.55),540,(.60,.76,1),2.5,3.8)
area('Gentle frontal card',(1.3,-4.2,2.8),(0,0,1.3),85,(1,.82,.63),2.4,3.2)

bpy.ops.object.camera_add(location=(3.7,-7.8,3.7))
camera=bpy.context.object
camera.name='Hero camera'
target=Vector((0,0,1.72))
camera.rotation_euler=(target-camera.location).to_track_quat('-Z','Y').to_euler()
camera.data.type='ORTHO'
camera.data.ortho_scale=4.45
camera.data.lens=55
scene.camera=camera

# Restrained optical glow, leaving the glass reflections and metal edges crisp.
scene.use_nodes=True
nt=scene.node_tree
nt.nodes.clear()
rl=nt.nodes.new('CompositorNodeRLayers')
gl=nt.nodes.new('CompositorNodeGlare')
gl.glare_type='FOG_GLOW'
gl.quality='HIGH'
gl.threshold=2.0
gl.size=7
gl.mix=-.88
comp=nt.nodes.new('CompositorNodeComposite')
nt.links.new(rl.outputs['Image'],gl.inputs['Image'])
nt.links.new(gl.outputs['Image'],comp.inputs['Image'])

scene.render.filepath='/mnt/data/lantern.png'
bpy.ops.wm.save_as_mainfile(filepath='/mnt/data/scene.blend')
```