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

# A small, entirely modeled underwater portrait.
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
for dat in bpy.data.materials:
    bpy.data.materials.remove(dat)

OUT = "/mnt/data"
os.makedirs(OUT, exist_ok=True)

def material(name, color, roughness=.35, metallic=0.0):
    m = bpy.data.materials.new(name)
    m.use_nodes = True
    p = m.node_tree.nodes.get("Principled BSDF")
    p.inputs["Base Color"].default_value = (*color, 1)
    p.inputs["Roughness"].default_value = roughness
    p.inputs["Metallic"].default_value = metallic
    return m

bodymat = material("Living tangerine • pearlescent skin", (1, .28, .016), .30, .10)
p = bodymat.node_tree.nodes.get("Principled BSDF")
p.inputs["Subsurface Weight"].default_value = .065
p.inputs["Subsurface Radius"].default_value = (1, .42, .18)
p.inputs["Coat Weight"].default_value = .27
p.inputs["Coat Roughness"].default_value = .23
vc = bodymat.node_tree.nodes.new("ShaderNodeVertexColor")
vc.layer_name = "Skin color"
bodymat.node_tree.links.new(vc.outputs["Color"], p.inputs["Base Color"])
noise = bodymat.node_tree.nodes.new("ShaderNodeTexNoise")
noise.inputs["Scale"].default_value = 115
noise.inputs["Detail"].default_value = 2
bump = bodymat.node_tree.nodes.new("ShaderNodeBump")
bump.inputs["Strength"].default_value = .13
bump.inputs["Distance"].default_value = .009
bodymat.node_tree.links.new(noise.outputs["Fac"], bump.inputs["Height"])
bodymat.node_tree.links.new(bump.outputs["Normal"], p.inputs["Normal"])

orange = material("Warm orange lips and fin shoulders", (1, .245, .012), .30, .08)
orange.node_tree.nodes.get("Principled BSDF").inputs["Subsurface Weight"].default_value = .055
gillmat = material("Operculum crease • deep amber", (.51, .085, .009), .4, .08)
gold = material("Eye rim • old gold", (.84, .36, .045), .24, .45)
iris = material("Honey amber iris", (.62, .22, .018), .23, .25)
black = material("Deep liquid pupils", (.006, .012, .013), .115, .08)
black.node_tree.nodes.get("Principled BSDF").inputs["Coat Weight"].default_value = .65
mouthmat = material("Inside the little mouth", (.145, .024, .009), .47)

finmats = []
for i in range(9):
    t = i / 8
    col = (1.0, .225 + .40 * t**1.35, .018 + .24 * t**2)
    m = material("Fin membrane %02d • translucent silk" % i, col, .32, .035)
    pr = m.node_tree.nodes.get("Principled BSDF")
    pr.inputs["Transmission Weight"].default_value = .08 + .29 * t
    pr.inputs["Subsurface Weight"].default_value = .045
    pr.inputs["Subsurface Radius"].default_value = (1, .5, .25)
    pr.inputs["Alpha"].default_value = 1 - .23 * t**1.5
    pr.inputs["Coat Weight"].default_value = .15
    if hasattr(m, "surface_render_method"):
        m.surface_render_method = 'DITHERED'
    m.diffuse_color = (*col, 1 - .23*t**1.5)
    finmats.append(m)
raymat = material("Fine amber fin rays", (1, .38, .045), .31, .16)
edgemat = material("Pale gold terminal filaments", (1, .64, .22), .36, .1)
scalemats = [
    material("Scale crescents • sunlit orange", (1, .365, .035), .34, .23),
    material("Scale crescents • dorsal copper", (.88, .205, .016), .35, .22),
    material("Scale crescents • belly gold", (1, .59, .16), .35, .18),
]

def mesh_object(name, verts, faces, mats, indices=None):
    me = bpy.data.meshes.new(name)
    me.from_pydata(verts, [], faces)
    me.materials.clear()
    for ma in mats:
        me.materials.append(ma)
    me.update()
    ob = bpy.data.objects.new(name, me)
    bpy.context.collection.objects.link(ob)
    for i, po in enumerate(me.polygons):
        po.use_smooth = True
        if indices is not None:
            po.material_index = indices[i]
    return ob

def sphere(name, loc, scale, mat, normal=None, segments=48):
    bpy.ops.mesh.primitive_uv_sphere_add(segments=segments, ring_count=32, location=loc)
    ob = bpy.context.object
    ob.name = name
    ob.scale = scale
    if normal is not None:
        ob.rotation_euler = Vector(normal).to_track_quat('Z', 'Y').to_euler()
    ob.data.materials.append(mat)
    for f in ob.data.polygons:
        f.use_smooth = True
    return ob

# Tubes are real meshes, including the very fine scale relief and fin rays.
def append_tube(verts, faces, points, radii, sides=7):
    start = len(verts)
    points = [Vector(p) for p in points]
    for j, pt in enumerate(points):
        tangent = points[min(j+1, len(points)-1)] - points[max(0, j-1)]
        if tangent.length < 1e-8:
            tangent = Vector((1, 0, 0))
        tangent.normalize()
        ref = Vector((0, 0, 1))
        if abs(tangent.dot(ref)) > .93:
            ref = Vector((0, 1, 0))
        a = tangent.cross(ref).normalized()
        b = tangent.cross(a).normalized()
        radius = radii[j] if hasattr(radii, "__len__") else radii
        for k in range(sides):
            angle = 2*math.pi*k/sides
            verts.append(tuple(pt + radius*(a*math.cos(angle)+b*math.sin(angle))))
    for j in range(len(points)-1):
        for k in range(sides):
            a = start+j*sides+k
            b = start+j*sides+(k+1)%sides
            faces.append((a,b,b+sides,a+sides))
    faces.append(tuple(start+k for k in reversed(range(sides))))
    last = start+(len(points)-1)*sides
    faces.append(tuple(last+k for k in range(sides)))

def tube(name, points, radii, mat, sides=8):
    v, f = [], []
    append_tube(v, f, points, radii, sides)
    return mesh_object(name, v, f, [mat])

profile = [
    (-1.88, .015), (-1.78, .32), (-1.57, .61), (-1.23, .82),
    (-.72, .965), (-.23, .935), (.24, .785), (.69, .54),
    (1.08, .325), (1.43, .188), (1.72, .145)
]

def radius(x):
    if x <= profile[0][0]:
        return profile[0][1]
    if x >= profile[-1][0]:
        return profile[-1][1]
    for j in range(len(profile)-1):
        x0,y0 = profile[j]
        x1,y1 = profile[j+1]
        if x0 <= x <= x1:
            t = (x-x0)/(x1-x0)
            jm = max(0,j-1)
            jp = min(len(profile)-1,j+2)
            m0 = (y1-profile[jm][1])/(x1-profile[jm][0])
            m1 = (profile[jp][1]-y0)/(profile[jp][0]-x0)
            h = x1-x0
            return ((2*t**3-3*t*t+1)*y0 + (t**3-2*t*t+t)*h*m0
                    +(-2*t**3+3*t*t)*y1 +(t**3-t*t)*h*m1)

def cy(x):
    return .22*math.sin((x+1.65)*1.65) - .045*x

def cz(x):
    return .045*math.sin((x+1.5)*1.3)

def surface(x, theta, offset=0):
    r = radius(x)
    return Vector((x, cy(x)+(.79*r+offset)*math.cos(theta),
                   cz(x)+(1.04*r+offset)*math.sin(theta)))

verts, faces, colors = [], [], []
NX, NT = 144, 96
for j in range(NX+1):
    x = -1.88+3.60*j/NX
    for k in range(NT):
        th = 2*math.pi*k/NT
        verts.append(tuple(surface(x,th)))
        h = math.sin(th)
        if h >= 0:
            t = h**1.2
            col = (1-.12*t, .31-.135*t, .018-.008*t)
        else:
            t = (-h)**2
            col = (1, .31+.31*t, .018+.17*t)
        glint = .018*math.sin(x*10+th*7)*math.sin(th*13-x*8)
        colors.append((col[0], max(.02,col[1]+glint), col[2], 1))
for j in range(NX):
    for k in range(NT):
        a = j*NT+k
        b = j*NT+(k+1)%NT
        faces.append((a,b,b+NT,a+NT))
faces.append(tuple(reversed(range(NT))))
faces.append(tuple(NX*NT+k for k in range(NT)))
body = mesh_object("GOLDFISH • rounded S-curved body", verts, faces, [bodymat])
attr = body.data.color_attributes.new(name="Skin color", type='FLOAT_COLOR', domain='POINT')
for i, c in enumerate(colors):
    attr.data[i].color = c

# Shallow, staggered crescents: restrained actual geometry rather than a flat decal.
sv, sf, si = [], [], []
for row in range(17):
    x = -1.02+row*.147
    r = radius(x)
    count = max(12, int(32*r/.96))
    step = 2*math.pi/count
    for k in range(count):
        th = (k+.5*(row%2))*step
        arc = []
        for q in range(13):
            a = -math.pi/2 + math.pi*q/12
            xx = x + (.079 if x < .6 else .059)*math.cos(a)
            tt = th + .49*step*math.sin(a)
            arc.append(surface(xx, tt, .006))
        first = len(sf)
        radii = [.0022+.0015*math.sin(math.pi*q/12) for q in range(13)]
        append_tube(sv, sf, arc, radii, 5)
        mid = 1 if math.sin(th) > .52 else (2 if math.sin(th)<-.55 else 0)
        si.extend([mid]*(len(sf)-first))
mesh_object("Hundreds of delicate overlapping scale crescents", sv, sf, scalemats, si)

# Softly sculpted snout and a genuinely open, puckered little mouth.
sphere("Rounded upper snout", (-1.765, cy(-1.765), -.035),
       (.16, .255, .225), orange)
sphere("Mouth opening", (-1.912, cy(-1.85), -.09),
       (.021, .12, .070), mouthmat)
lip_points = []
for j in range(65):
    a = 2*math.pi*j/64
    lip_points.append((-1.929-.007*math.cos(a),
                       cy(-1.85)+.139*math.cos(a), -.09+.085*math.sin(a)))
tube("Soft oval lips", lip_points, .022, orange, 10)

# Both eyes are built, with a separate metallic iris and polished domed pupil.
for sign, label in [(-1, "near"), (1, "far")]:
    x = -1.355
    z = .305
    r = radius(x)
    yy = math.sqrt(max(0,1-((z-cz(x))/(1.04*r))**2))*.79*r
    pos = Vector((x, cy(x)+sign*yy, z))
    normal = Vector((-.38, sign*.91, .18)).normalized()
    sphere(label+" eye • gold socket", pos+normal*.040,
           (.239,.239,.135), gold, normal)
    sphere(label+" eye • amber iris", pos+normal*.151,
           (.184,.184,.055), iris, normal)
    sphere(label+" eye • dark limbal outline", pos+normal*.182,
           (.143,.143,.045), black, normal)
    sphere(label+" eye • living black pupil", pos+normal*.213,
           (.115,.115,.046), black, normal)

    # The gill cover wraps over the flank, rather than being a drawn flat line.
    pts = []
    for j in range(37):
        t = j/36
        gx = -1.105+.32*math.sin(math.pi*t)
        gz = .64-1.23*t
        gr = radius(gx)
        gy = .79*gr*math.sqrt(max(.02,1-((gz-cz(gx))/(1.04*gr))**2))
        pts.append((gx,cy(gx)+sign*(gy+.012),gz))
    tube(label+" curved gill-cover crease", pts,
         [.006+.006*math.sin(math.pi*j/36) for j in range(37)], gillmat)
    pts2 = [(x+.029,y+sign*.004,z) for x,y,z in pts]
    tube(label+" raised operculum edge", pts2, .009, orange)

# All fins are rippled surfaces with progressive edge translucency and mesh rays.
def make_fin(name, fn, nu=32, nv=48, rays=25, ray_width=.008, edge=True):
    v, f, ids = [], [], []
    for i in range(nu+1):
        u = i/nu
        for j in range(nv+1):
            v.append(tuple(fn(u,j/nv)))
    for i in range(nu):
        for j in range(nv):
            a = i*(nv+1)+j
            f.append((a,a+1,a+nv+2,a+nv+1))
            ids.append(min(8,int(9*((i+.5)/nu))))
    ob = mesh_object(name+" • flowing membrane", v, f, finmats, ids)
    rv, rf = [], []
    for j in range(rays):
        t = j/(rays-1)
        points = [fn(.018+.972*k/31,t) for k in range(32)]
        widths = [ray_width*(1-(.018+.972*k/31))**.65+.0014 for k in range(32)]
        append_tube(rv,rf,points,widths,6)
    mesh_object(name+" • fine supporting rays",rv,rf,[raymat])
    if edge:
        pts = [fn(1,j/100) for j in range(101)]
        tube(name+" • gossamer trailing rim",pts,.004,edgemat,6)
    return ob

for sign,label in [(1,"Far veil"),(-1,"Near veil")]:
    def tail(u,t,sign=sign):
        v = 2*t-1
        av = abs(v)
        endx = 2.63+1.06*math.sin(math.pi*av*.87)
        endx += .028*math.cos(v*math.pi*10)
        endz = 1.52*v+.07*math.sin(2*math.pi*v)
        rootx = 1.48+.13*av
        x = rootx+(endx-rootx)*u
        z = .11*v*(1-u)+endz*u
        z += .13*v*math.sin(math.pi*u)
        y = cy(x)+sign*(.055+.43*u**1.45)
        y += .13*math.sin(math.pi*u)*v
        y += .07*u*u*math.sin(3*math.pi*v+2.2*u)
        return Vector((x,y,z))
    make_fin(label+" • bifurcated fantail",tail,40,72,37,.009)

def dorsal(u,t):
    rootx = -.94+2.35*t
    x = rootx+.30*u*math.sin(math.pi*t*.85)
    base = cz(rootx)+1.04*radius(rootx)-.022
    height = 1.01*math.sin(math.pi*t)**.70
    height += .020*math.sin(t*math.pi*16)*math.sin(math.pi*t)
    z = base+u*height
    y = cy(x)+.085*u*math.sin(2*math.pi*t)
    y += .035*u*u*math.sin(14*math.pi*t)
    return Vector((x,y,z))
make_fin("High swept dorsal", dorsal, 30, 64, 29, .0075)

def catmull(points,t):
    n = len(points)-1
    f = min(t*n,n-1e-8)
    j = int(f)
    q = f-j
    a = Vector(points[max(0,j-1)])
    b = Vector(points[j])
    c = Vector(points[min(n,j+1)])
    d = Vector(points[min(n,j+2)])
    return .5*((2*b)+(-a+c)*q+(2*a-5*b+4*c-d)*q*q+(-a+3*b-3*c+d)*q*q*q)

def fan(name, root, boundary, ripple=.035, raycount=18, width=.007):
    root = Vector(root)
    def fn(u,t):
        end = catmull(boundary,t)
        point = root.lerp(end,u)
        point.x += .11*math.sin(math.pi*u)*math.sin(math.pi*t)
        point.y += ripple*u*u*math.sin(t*math.pi*12+1.5*u)
        point.z += .07*math.sin(math.pi*u)*math.sin(math.pi*t)
        return point
    return make_fin(name,fn,28,48,raycount,width)

for sign,label in [(1,"Far"),(-1,"Near")]:
    fan(label+" broad pectoral fin",
        (-.79,cy(-.79)+sign*.65,-.23),
        [(-.57,sign*.96,-.44),
         (-.20,sign*1.32,-.91),
         (.28,sign*1.38,-1.12),
         (.78,sign*1.04,-.91),
         (.86,sign*.72,-.57)],
        .035,20,.0075)
    fan(label+" pelvic fin",
        (.12,cy(.12)+sign*.43,-.66),
        [(.27,sign*.57,-.79),
         (.55,sign*.78,-1.17),
         (.91,sign*.73,-1.34),
         (1.15,sign*.49,-1.09),
         (1.03,sign*.32,-.68)],
        .027,15,.006)

fan("Trailing anal fin",
    (.83,cy(.83),-.44),
    [(1.04,cy(1.04),-.51),
     (1.39,cy(1.39)-.05,-.88),
     (1.78,cy(1.78)-.08,-1.03),
     (1.89,cy(1.89),-.72),
     (1.57,cy(1.57),-.30)],
    .027,16,.006)

# Quiet turquoise environment; no tank, ornaments, or competing animal.
floor = material("Deep turquoise water backdrop", (.018,.115,.135), .82)
pn = floor.node_tree.nodes.get("Principled BSDF")
tex = floor.node_tree.nodes.new("ShaderNodeTexNoise")
tex.inputs["Scale"].default_value = .16
tex.inputs["Detail"].default_value = 1.3
ramp = floor.node_tree.nodes.new("ShaderNodeValToRGB")
ramp.color_ramp.elements[0].position = .17
ramp.color_ramp.elements[0].color = (.009,.065,.087,1)
ramp.color_ramp.elements[1].position = .83
ramp.color_ramp.elements[1].color = (.037,.20,.213,1)
floor.node_tree.links.new(tex.outputs["Fac"],ramp.inputs[0])
floor.node_tree.links.new(ramp.outputs["Color"],pn.inputs["Base Color"])
bpy.ops.mesh.primitive_plane_add(size=200,location=(0,0,-3.05))
bpy.context.object.name = "Endless calm teal water"
bpy.context.object.data.materials.append(floor)

# A few tiny peripheral air pearls quietly establish the aquatic setting.
bubble = material("Clear water pearls", (.72,.94,.96), .09)
bp = bubble.node_tree.nodes.get("Principled BSDF")
bp.inputs["Transmission Weight"].default_value = 1
bp.inputs["IOR"].default_value = 1.333
bp.inputs["Coat Weight"].default_value = .3
for i,(x,y,z,r) in enumerate([
    (-2.52,.55,.68,.058),(-2.66,.78,1.26,.083),(-2.58,.93,1.91,.042),
    (3.68,.85,1.86,.065),(3.89,1.10,2.30,.036)
]):
    sphere("Quiet rising air pearl %02d"%i,(x,y,z),(r,r,r),bubble,segments=32)

world = bpy.data.worlds.new("Underwater blue ambience")
bpy.context.scene.world = world
world.use_nodes = True
world.node_tree.nodes["Background"].inputs["Color"].default_value = (.085,.22,.27,1)
world.node_tree.nodes["Background"].inputs["Strength"].default_value = .36

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

area("Broad warm daylight through the surface",(-3.8,-4.4,6.5),850,(1,.88,.72),4.6,(0,0,0))
area("Cool soft open-water fill",(-.5,-5,1),300,(.69,.88,1),4.0,(0,0,0))
area("Light through the translucent tail",(3.3,3.3,4.3),1050,(.72,.94,1),3.7,(1.3,0,.2))
area("Long eye catchlight",(-4.2,-2.2,2.3),180,(1,.95,.84),2.4,(-1,0,.1),.75)

bpy.ops.object.camera_add(location=(-4.35,-10.7,3.25))
camera = bpy.context.object
camera.name = "Portrait • the little gold swimmer"
target = Vector((.72,0,.20))
camera.rotation_euler = (target-camera.location).to_track_quat('-Z','Y').to_euler()
camera.data.type = 'ORTHO'
camera.data.ortho_scale = 7.55
camera.data.lens = 55
scene = bpy.context.scene
scene.camera = camera

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.render.filepath = os.path.join(OUT,"goldfish.png")
scene.view_settings.view_transform = 'AgX'
try:
    scene.view_settings.look = 'AgX - Medium High Contrast'
except Exception:
    pass
scene.view_settings.exposure = .35
scene.render.image_settings.color_mode = 'RGBA'
scene.camera.data.dof.use_dof = False
scene.world.color = (.035,.12,.16)

# Set a useful initial solid/material inspection state in addition to the camera.
for screen in bpy.data.screens:
    for ar in screen.areas:
        if ar.type == 'VIEW_3D':
            ar.spaces.active.region_3d.view_distance = 9
            ar.spaces.active.region_3d.view_location = Vector((.7,0,0))
            ar.spaces.active.clip_end = 300
            ar.spaces.active.shading.color_type = 'MATERIAL'

bpy.ops.wm.save_as_mainfile(filepath=os.path.join(OUT,"scene.blend"))

# A modest Cycles preview is saved as well; the complete scene retains final settings.
scene.render.resolution_x = 512
scene.render.resolution_y = 512
scene.cycles.samples = 24
scene.render.filepath = os.path.join(OUT,"preview.png")
bpy.ops.render.render(write_still=True)
scene.render.resolution_x = 1536
scene.render.resolution_y = 1536
scene.cycles.samples = 64
scene.render.filepath = os.path.join(OUT,"goldfish.png")
bpy.ops.wm.save_as_mainfile(filepath=os.path.join(OUT,"scene.blend"))
```