Moved some files around and made cleanup better

This commit is contained in:
2026-09-14 19:01:08 -07:00
parent 50b234104a
commit 97ed7f05c8
866 changed files with 404 additions and 1612 deletions

View File

@@ -0,0 +1,19 @@
# BE-042 — Calling of the First Disciples · v02
**Assembly review.** Artwork approved by the user (“Looks good!”); the smaller title treatment was subsequently approved (“I think that looks and feels pretty good”). Final card approval and moving-light review are pending.
- [Normal, standard size](med/normal/card.png)
- [Four-printing comparison](review/printings-comparison.png)
- [Boundless](med/boundless/card.png), [Borderless](med/borderless/card.png), [Textless](med/textless/card.png)
- [Normal finish mask](med/normal/finish-mask.png) and [text protection](med/normal/text-mask.png)
- [Build validation](review/build-validation.json)
- [Approved title layout](source/typography-layout.json) and [measured fit study](review/title-fit-study.json)
- [Exact generation prompt](source/generation-prompt.txt), [native artwork](source/art-native.png), [fit and approval record](source/art-provenance.json)
All four printings have low (500×700), med (1000×1400), and high (2000×2800) opaque face/finish/text-mask exports. High also retains editable SVGs with real text objects and linked central assets. Textless and Boundless text maps are explicitly black.
The full title is “CALLING OF THE” / “FIRST DISCIPLES”, in shared P052 Bold at 100px master size. Its card-specific taller lettering region stays inside the existing cream panel; shared Uncommon v2 frame/backing geometry is unchanged. Verses and attribution use the shared P052 Medium face; reference format is Matthew 4:19 • NKJV. Inkscape object bounds and independently rendered unclipped glyph bounds pass for each line. The title is reflowed at baselines 176 and 266, with 20 master pixels of clearance from the unchanged header flourish in both Normal and Borderless. Actual rendered ink is checked against the ornament with the clearance margin; the earlier colliding treatment is rejected.
The approved raw-ridges-v1 finish module analyzes the fitted illustration once, then compiles each printing from its actual visible components. The masks retain coherent illustration ink and protect active backings. Text protection derives from actual glyph alpha, with the recorded 12px expanded and 8px feathered master margin. See validation for pinned hashes and tools.
Rebuild this working revision with `python3 build.py`, from any directory. The builder refuses missing artwork approval or an approved/frozen package. No shared frames, fonts, existing v01 exports or harness fixtures were replaced. Final acceptance moves the reviewed revision into artifacts only after explicit final card approval.

View File

@@ -0,0 +1,165 @@
#!/usr/bin/env python3
"""Assemble the approved BE-042 v02 artwork with pinned shared Uncommon assets."""
from pathlib import Path
import json, os, subprocess, sys
from xml.sax.saxutils import escape
import xml.etree.ElementTree as ET
import numpy as np
from PIL import Image, ImageDraw, ImageFont, ImageFilter
ROOT=Path(__file__).resolve().parent
REPO=next(p for p in ROOT.parents if (p/'docs/card-layer-pipeline.md').is_file())
sys.path.insert(0,str(REPO/'artifacts/layers'))
sys.path.insert(0,str(REPO/'tools/card-production'))
from library import load_tier, digest
from card_workspace import refresh, update_index
from finish_masks import prepare_illustration, compile_finish, RECIPE_PATH, RECIPE_SHA256
def save(path,value):path.write_text(json.dumps(value,indent=2)+'\n')
def svg(body):return f'<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="2000" height="2800" viewBox="0 0 2000 2800">{body}</svg>'
def luminance(rgb):
c=np.asarray(rgb,dtype=float)/255
c=np.where(c<=.04045,c/12.92,((c+.055)/1.055)**2.4)
return float(c@np.array([.2126,.7152,.0722]))
def contrast(a,b):
lo,hi=sorted([luminance(a),luminance(b)]);return (hi+.05)/(lo+.05)
def check(condition,message):
if not condition:raise ValueError(message)
def check_decoration_clearance(title_alpha,ornament_alpha,padding):
expanded=title_alpha.filter(ImageFilter.MaxFilter(padding*2+1))
check(not np.any((np.asarray(expanded)>0)&(np.asarray(ornament_alpha)>0)),
'Title overlaps the header ornament or its required breathing room.')
def main():
manifest=json.loads((ROOT/'manifest.json').read_text())
check(manifest['stage']!='approved','Approved cards are frozen; create a working revision.')
card=json.loads((ROOT/'card.json').read_text())
check(bool(card.get('artApproval')),'Explicit artwork approval is required before assembly.')
check(card['cardId']=='BE-042' and card['tier']=='uncommon','Wrong card or tier for this builder.')
shared=load_tier(card['tier'],card['layerVersion']);layout=shared['layout'];assets=shared['assets']
font_dir=REPO/'fonts';fm=json.loads((font_dir/'manifest.json').read_text())
for file,record in fm['files'].items():check(digest(font_dir/file)==record['sha256'],f'Shared font changed: {file}')
review=ROOT/'review';text_dir=ROOT/'source/text';text_dir.mkdir(exist_ok=True)
config=review/'fonts.conf';config.write_text(f'<fontconfig><dir>{font_dir}</dir><cachedir>{review/"font-cache"}</cachedir></fontconfig>')
env=dict(os.environ,FONTCONFIG_FILE=str(config))
def ink(*args):return subprocess.check_output(['inkscape',*map(str,args)],env=env,text=True).strip()
art_path=REPO/card['art'];art=Image.open(art_path).convert('RGBA')
check(art.size==(2000,2800) and art.getchannel('A').getextrema()==(255,255),'Master must be opaque on the common canvas.')
check(digest(art_path)==card['artSHA256'],'Approved artwork bytes changed.')
check(card['referenceDisplay']==f'{card["reference"]} • {card["translation"]}','Reference formatting changed.')
check(' '.join(card['verseLines'])==card['excerpt'],'Verse lines differ from the retained quotation.')
check(' '.join(card['titleLines'])==card['name'],'Title lines differ from the full catalogue title.')
check(len(card['verseLines'])<=layout['maximumVerseLines'],'Too many verse lines.')
check(card['verseBaselines']==layout['baselines']['verseByLineCount'][str(len(card['verseLines']))],'Verse layout differs from pinned template.')
treatment=json.loads((ROOT/'source/typography-layout.json').read_text())
regions=dict(layout['textRegions']);regions['title']=treatment['title']['region']
tx,ty,tw,th=regions['title'];px,py,pw,ph=layout['borderlessBacking'][0]
check(px<=tx and py<=ty and tx+tw<=px+pw and ty+th<=py+ph,'Alternate title region leaves the existing panel.')
sizes=dict(layout['fontSizes']);sizes['title']=treatment['title']['fontSize'];families={'title':'P052','verse':'Sanctification P052','reference':'Sanctification P052'}
rows=[(f'title-{i}','title',line,y) for i,(line,y) in enumerate(zip(card['titleLines'],treatment['title']['baselines']))]
check(len(rows)==len(card['titleLines'])==2,'Reviewed title uses exactly two lines.')
rows += [(f'verse-{i}','verse',line,y) for i,(line,y) in enumerate(zip(card['verseLines'],card['verseBaselines']))]
rows += [('reference','reference',card['referenceDisplay'],layout['baselines']['reference'])]
font_checks=[]
for role in families:
face=fm['productionTypography'][role];file=font_dir/face['file'];style='Bold' if role=='title' else 'Medium'
matched=Path(subprocess.check_output(['fc-match','--format=%{file}',f'{families[role]}:style={style}'],env=env,text=True)).resolve()
check(matched==file.resolve(),f'Font fallback for {role}: {matched}')
ranges=[(int(t.split('-')[0],16),int(t.split('-')[-1],16)) for t in subprocess.check_output(['fc-query','--format=%{charset}',str(file)],text=True).split()]
check(all(any(lo<=ord(c)<=hi for lo,hi in ranges) for row in rows if row[1]==role for c in row[2]),f'Missing glyph in {role}.')
check(sizes[role]>=layout['fontMinimums'][role],f'Font below minimum in {role}.')
font_checks.append({'role':role,'file':str(file.relative_to(REPO)),'sha256':digest(file),'weight':face['weight'],'fallbackUsed':False,'missingGlyphs':[]})
nodes=[f'<text id="{key}" x="1000" y="{y}" font-family="{families[role]}" font-weight="{fm["productionTypography"][role]["weight"]}" font-size="{sizes[role]}">{escape(content)}</text>' for key,role,content,y in rows]
body='<g fill="#263f50" text-anchor="middle">'+''.join(nodes)+'</g>'
source=text_dir/'text.svg';source.write_text(svg(body));text_path=text_dir/'text-2000.png'
ink(source,'--export-type=png',f'--export-filename={text_path}','--export-width=2000','--export-height=2800')
text=Image.open(text_path).convert('RGBA');ta=np.asarray(text.getchannel('A'));bounds={}
for row in ink(source,'--query-all').splitlines():
parts=row.split(',')
if len(parts)==5:bounds[parts[0]]=list(map(float,parts[1:]))
glyphs=[]
for (key,role,content,y),node in zip(rows,nodes):
rx,ry,rw,rh=regions[role];x,yy,w,h=bounds[key]
check(rx<=x and ry<=yy and x+w<=rx+rw and yy+h<=ry+rh,f'Object overflow: {key}: {bounds[key]} against {regions[role]}')
isolated=text_dir/f'{key}-unclipped.svg';isolated.write_text(svg('<g text-anchor="middle" fill="#263f50">'+node+'</g>'))
png=isolated.with_suffix('.png');ink(isolated,'--export-type=png',f'--export-filename={png}')
bb=Image.open(png).getchannel('A').getbbox()
check(bb and rx<=bb[0] and ry<=bb[1] and bb[2]<=rx+rw and bb[3]<=ry+rh,f'Unclipped glyph overflow: {key}: {bb}')
glyphs.append({'id':key,'objectBounds':bounds[key],'unclippedInkBounds':list(bb),'region':regions[role],'pass':True})
decoration_checks=[]
padding=treatment['title']['minimumDecorationClearance']
title_alpha=text.getchannel('A').crop((0,0,2000,360))
for kind in ['normal','borderless']:
ornament_source=shared['directory']/'source'/f'backing-{kind}.svg'
diagnostic=review/f'header-ornament-{kind}.png'
ink(ornament_source,'--export-id=ornament-299','--export-id-only','--export-area-page',
'--export-type=png',f'--export-filename={diagnostic}','--export-width=2000','--export-height=2800')
ornament=Image.open(diagnostic).getchannel('A');ob=ornament.getbbox()
check(bool(ob),'Expected header ornament missing from selected template.')
check_decoration_clearance(title_alpha,ornament.crop((0,0,2000,360)),padding)
last=max(g['unclippedInkBounds'][3] for g in glyphs if g['id'].startswith('title-'))
decoration_checks.append({'printing':kind,'source':str(ornament_source.relative_to(REPO)),
'sourceSHA256':digest(ornament_source),'ornamentInkBounds':list(ob),
'verticalClearance':ob[1]-last,'minimumClearance':padding,
'actualExpandedInkIntersection':False,'pass':True})
protected=text.getchannel('A').filter(ImageFilter.MaxFilter(25)).filter(ImageFilter.GaussianBlur(8))
check(np.min(np.asarray(protected)[ta>=128])>=216,'Text protection does not cover rendered glyphs.')
analysis=prepare_illustration(art)
Image.fromarray(analysis.raw_ridges).save(ROOT/'source/raw-ridges.png')
Image.fromarray(np.rint(analysis.pane_weights*255).astype(np.uint8)).save(ROOT/'source/pane-coverage.png')
report={'status':'pending','cardId':card['cardId'],'revision':manifest['revision'],'artApproval':card['artApproval'],'finalCardApproval':None,
'inputs':{'art':{'path':card['art'],'sha256':digest(art_path)},'fit':json.loads((ROOT/'source/art-provenance.json').read_text()),'cardSHA256':digest(ROOT/'card.json'),'builderSHA256':digest(Path(__file__))},
'sharedLayers':{'tier':card['tier'],'version':shared['version'],'manifestSHA256':shared['manifestSHA256'],'reviewStatus':shared['reviewStatus'],'assets':{k:{'path':str(v.relative_to(REPO)),'sha256':digest(v)} for k,v in assets.items()}},
'sharedFontManifestSHA256':digest(font_dir/'manifest.json'),'typography':{'fonts':font_checks,'glyphs':glyphs,'titleLayout':treatment,'decorationClearance':decoration_checks,'textLayerSHA256':digest(text_path)},
'textMask':{'expansionRadius':12,'gaussianRadius':8,'units':'master pixels','derivation':'Actual rendered text alpha; MaxFilter(25), GaussianBlur(8)','minimumProtectionAtGlyphAlpha128':int(np.min(np.asarray(protected)[ta>=128]))},
'finishRecipe':{'id':'raw-ridges-v1','sha256':RECIPE_SHA256,'path':str(RECIPE_PATH.relative_to(REPO)),'moduleSHA256':digest(REPO/'tools/card-production/finish_masks.py'),'rawRidgeSHA256':digest(ROOT/'source/raw-ridges.png'),'paneCoverageSHA256':digest(ROOT/'source/pane-coverage.png'),'illustrationAnalyses':1},
'tools':{'inkscape':ink('--version'),'pillow':Image.__version__,'numpy':np.__version__},'printings':{},'visualReview':{'static':'pending','movingLight':'not performed'}}
for printing,overlay_key,has_text in [('normal','overlay-normal',True),('boundless',None,False),('borderless','backing-borderless',True),('textless','frame-textless',False)]:
overlay=Image.open(assets[overlay_key]).convert('RGBA') if overlay_key else None
face=art.copy()
if overlay:face=Image.alpha_composite(face,overlay)
if has_text:
check(np.all(np.asarray(overlay.getchannel('A'))[ta>0]==255),'Text outside fully opaque backing.')
face=Image.alpha_composite(face,text)
check(face.getchannel('A').getextrema()==(255,255),'Face has transparency.')
if printing=='boundless':check(np.array_equal(np.asarray(face),np.asarray(art)),'Boundless changed artwork pixels.')
finish=compile_finish(analysis,printing,overlay,text if has_text else None)
if overlay:check(np.all(np.asarray(finish)[np.asarray(overlay.getchannel('A'))==255]==0),'Finish leaks onto opaque overlay.')
tm=protected if has_text else Image.new('L',(2000,2800),0)
exports=[]
for label,width in [('low',500),('med',1000),('high',2000)]:
folder=ROOT/label/printing;folder.mkdir(parents=True,exist_ok=True);size=(width,width*7//5)
f=face if width==2000 else face.resize(size,Image.Resampling.LANCZOS);f.save(folder/'card.png')
for name,m in [('finish-mask.png',finish),('text-mask.png',tm)]:
data=m if width==2000 else m.resize(size,Image.Resampling.BILINEAR)
rgba=data.convert('RGBA');rgba.putalpha(255);rgba.save(folder/name)
exports.append({'resolution':label,'dimensions':list(size),'files':{name:digest(folder/name) for name in ['card.png','finish-mask.png','text-mask.png']}})
editable=ROOT/'high'/printing/'card.svg'
def link(path):return f'<image width="2000" height="2800" xlink:href="{escape(os.path.relpath(path,editable.parent))}"/>'
editable.write_text(svg(link(art_path)+(link(assets[overlay_key]) if overlay_key else '')+(body if has_text else '')))
report['printings'][printing]={'overlay':overlay_key,'text':has_text,'exports':exports}
contrasts=[]
for width in [2000,1000,500]:
scale=width/2000;b=np.asarray(Image.open(shared['directory']/'exports'/f'backing-borderless-{width}.png').convert('RGBA'))
xx=int((layout['borderlessBacking'][0][0]+layout['primaryRuleInset'])*scale);yy=int(180*scale)
ratio=max(contrast(c,b[yy,int(500*scale),:3]) for c in b[yy,max(0,xx-1):xx+2,:3])
check(ratio>=3,f'Backing rule contrast too low at {width}.');contrasts.append({'width':width,'primaryRuleToCream':round(ratio,2),'minimum':3})
report['backingContrast']=contrasts;report['textContrast']=round(contrast([38,63,80],[244,234,212]),2)
check(report['textContrast']>=7,'Text contrast below 7:1.')
# Labeled review sheet keeps annotations outside printing assets.
board=Image.new('RGB',(1200,480),'#11161c');draw=ImageDraw.Draw(board);label_font=ImageFont.truetype(str(font_dir/'P052-Bold.otf'),22)
for i,printing in enumerate(['normal','boundless','borderless','textless']):
draw.text((i*300+10,8),printing.title(),font=label_font,fill='#f4ead4')
im=Image.open(ROOT/'med'/printing/'card.png').convert('RGB').resize((280,392),Image.Resampling.LANCZOS);board.paste(im,(i*300+10,50))
board.save(review/'printings-comparison.png')
report['status']='passed';save(review/'build-validation.json',report)
manifest['stage']='assembly-review';save(ROOT/'manifest.json',manifest)
profile_path=ROOT.parents[1]/'card.json';profile=json.loads(profile_path.read_text());profile['stage']='assembly-review';save(profile_path,profile)
refresh(ROOT);update_index()
print('BE-042 v02: all four printings at low/med/high, glyph bounds, fonts, contrast and data-map checks passed.')
if __name__=='__main__':main()

View File

@@ -0,0 +1,35 @@
{
"cardId": "BE-042",
"title": "Calling of the First Disciples",
"name": "CALLING OF THE FIRST DISCIPLES",
"rarity": "Uncommon",
"folderName": "BE-042-calling-of-the-first-disciples",
"artApproval": {
"by": "user",
"note": "Looks good!",
"scope": "Artwork and provisional two-line title study"
},
"tier": "uncommon",
"layerVersion": "v2",
"subjectType": "Event",
"visibleSubjectType": false,
"verseLines": [
"Then He said to them, \u201cFollow Me,",
"and I will make you fishers of men.\u201d"
],
"excerpt": "Then He said to them, \u201cFollow Me, and I will make you fishers of men.\u201d",
"verseBaselines": [
2370,
2495
],
"reference": "Matthew 4:19",
"translation": "NKJV",
"referenceDisplay": "Matthew 4:19 \u2022 NKJV",
"titleLines": [
"CALLING OF THE",
"FIRST DISCIPLES"
],
"titleTreatmentStatus": "approved-100px-two-line-title",
"art": "in-progress/cards/BE-042-calling-of-the-first-disciples/revisions/v02/source/art-master.png",
"artSHA256": "f51ca54ed1944b5615fd2f15a7fdc22bc65608a6de6b7a0d3c5b1b48e98f5550"
}

View File

@@ -0,0 +1,216 @@
{
"schemaVersion": 1,
"cardId": "BE-042",
"folderName": "BE-042-calling-of-the-first-disciples",
"revision": "v02",
"stage": "assembly-review",
"approval": null,
"content": "card.json",
"files": {
"README.md": {
"sha256": "9e2c697f8b8731c7ed4175dcd08ce5a8233b198fb7551cef1c7c8987e9280b6b"
},
"build.py": {
"sha256": "e679ab29bc6043a13eb0fa8d09af152b35dd53199ad358a439a159bb447ef2e6"
},
"card.json": {
"sha256": "6561e64a6db3ba1588ae062fa23c8b835af074a0b16740c6bf97ebf156db58f8"
},
"high/borderless/card.png": {
"sha256": "a9c909c750263849a3b61999e94f6cfb8b2a24024c56e1cb29552d940de19a62"
},
"high/borderless/card.svg": {
"sha256": "478060515912501be56e083c69bf2c728569bcbec61b84e6319f4e686e3deb52"
},
"high/borderless/finish-mask.png": {
"sha256": "26c2174c24ad3e6d42520ecde01155c151fe991c066f393444f76a4113084b43"
},
"high/borderless/text-mask.png": {
"sha256": "19eb883960f341e446144c4e895e8928cbc11d82ff2a88b9e9ba4cd18a350503"
},
"high/boundless/card.png": {
"sha256": "f56a5fbfbea883a5bc04615271fea9fcb0b305618d7f0edd0063a5f10adfb76f"
},
"high/boundless/card.svg": {
"sha256": "0def68f6693146baf63e07d3fa555a965e344ec9d6af49a1ee8ca3ad44e353bc"
},
"high/boundless/finish-mask.png": {
"sha256": "89234de20ff2e99b19071985983def90f097e939b1e30bd392fa813874f6bf39"
},
"high/boundless/text-mask.png": {
"sha256": "27006d9c9a2ced6159cc5a6a76ef707e22797a800df9b9e19ec1f1783fc6d767"
},
"high/normal/card.png": {
"sha256": "df60c465f5f4dddf71a9124167f83aa7d318a1afec3b7957ae7ace2370e0c1f5"
},
"high/normal/card.svg": {
"sha256": "3f4f072f175124c04048cd6d102bab1d4aef56db92f18846e262d699f1c2eee4"
},
"high/normal/finish-mask.png": {
"sha256": "bb113943bfb1070e706c366ea7740e05426ba4eca0f611510c18ae0153b78204"
},
"high/normal/text-mask.png": {
"sha256": "19eb883960f341e446144c4e895e8928cbc11d82ff2a88b9e9ba4cd18a350503"
},
"high/textless/card.png": {
"sha256": "37a2901a7792dda6619abecb98b9ecededffe522fa1e42bfb6c4855ed6fffb5c"
},
"high/textless/card.svg": {
"sha256": "4cc46d6a1508bfa123b200cffad808462ebd1a00897c18f1cc268a36650f3f33"
},
"high/textless/finish-mask.png": {
"sha256": "3f1ce3d85792d20ed37b2a918a94195cda5f3408f488797071076a436d7d7043"
},
"high/textless/text-mask.png": {
"sha256": "27006d9c9a2ced6159cc5a6a76ef707e22797a800df9b9e19ec1f1783fc6d767"
},
"low/borderless/card.png": {
"sha256": "1f1c3c560376bc5a1f8719733ab7f80858cdf70856acfeed8b123ede0c5eb40b"
},
"low/borderless/finish-mask.png": {
"sha256": "26910c29532b194cb829bb7d1188f4962c294c98a36bc8cedf392793eff77c0d"
},
"low/borderless/text-mask.png": {
"sha256": "f82b995d6c0a1ac89b8b956b3c53c32cdcce68eb13d9cb35489a164b77984abc"
},
"low/boundless/card.png": {
"sha256": "942c245bda3f0e20ff4e477e6c49b05f9fcef20d2c222bbe39589a071f3fe951"
},
"low/boundless/finish-mask.png": {
"sha256": "b23e4f7d0ac28f8fb91cb37c15d98ca5df04eacf5edb7c8ed5fa884fe3d3a2cf"
},
"low/boundless/text-mask.png": {
"sha256": "85fbeb48f81f5fd89c81a79be7e1d4d16837edd786733f593e0a4451be5fa52b"
},
"low/normal/card.png": {
"sha256": "21573a7b212422f4deed68e525ad09d39e6025cdfbeaeff8b53db2517b3f90b1"
},
"low/normal/finish-mask.png": {
"sha256": "1bd3d0fd9e2767c490e64529e46071d2963186a16bb0f495521fee941dba71d5"
},
"low/normal/text-mask.png": {
"sha256": "f82b995d6c0a1ac89b8b956b3c53c32cdcce68eb13d9cb35489a164b77984abc"
},
"low/textless/card.png": {
"sha256": "b8a2a5378dc1f00c5915a2d288abd3d363e71eed6de17a42d8fc648b24ec6862"
},
"low/textless/finish-mask.png": {
"sha256": "3c64c1ab9f982749b14d21f28a83339e0e401a6bd5a4df34a8fbf20ac4e3ed40"
},
"low/textless/text-mask.png": {
"sha256": "85fbeb48f81f5fd89c81a79be7e1d4d16837edd786733f593e0a4451be5fa52b"
},
"med/borderless/card.png": {
"sha256": "62453bc06cb12cf7237ae838e675adf209a646984a218a483ced5bc0b6b91777"
},
"med/borderless/finish-mask.png": {
"sha256": "541f2a39b9f730f4a560495ee985b66939ab64f4e3a7e25f43c6782785eae2ec"
},
"med/borderless/text-mask.png": {
"sha256": "2fa1814867fb7b866b9e0365700da6531be25f447415eefd37f5bb1efbe7c74f"
},
"med/boundless/card.png": {
"sha256": "d7049e9cdb6b75cb003f1dbc3f5cda7e4e59d8798da80d8511fb31c780a52d9e"
},
"med/boundless/finish-mask.png": {
"sha256": "08dc6431c8b05bee33cbfc315e7c2420698ed3e8daeff9d840ee0d1991baa232"
},
"med/boundless/text-mask.png": {
"sha256": "f8732c63feae83b55d064bc73e39904d9158c4e194dfd6d30dbff7864adfd490"
},
"med/normal/card.png": {
"sha256": "c4bae9860dad29dba5868881b598cd0045ca2e86e27fad27a9d7bdf1a086c30b"
},
"med/normal/finish-mask.png": {
"sha256": "5ab8249f157c4ba18b0edafb37e9202c38f0c30f3064479f7fb628f23c99fd0f"
},
"med/normal/text-mask.png": {
"sha256": "2fa1814867fb7b866b9e0365700da6531be25f447415eefd37f5bb1efbe7c74f"
},
"med/textless/card.png": {
"sha256": "84187653b148f5090da213b4d641d5d3958bfd89792f36c6c4f4a040706852ee"
},
"med/textless/finish-mask.png": {
"sha256": "d185564cea26fc43aa5d203b80dca8e96f5dd96b9ee8ee0412badb50ebd2b24c"
},
"med/textless/text-mask.png": {
"sha256": "f8732c63feae83b55d064bc73e39904d9158c4e194dfd6d30dbff7864adfd490"
},
"source/art-master.png": {
"sha256": "f51ca54ed1944b5615fd2f15a7fdc22bc65608a6de6b7a0d3c5b1b48e98f5550"
},
"source/art-native.png": {
"sha256": "a6a1b22431990938eea3d9c536d4590fecb1776570770f0f053dbc5e26a3fbe7"
},
"source/art-provenance.json": {
"sha256": "efe55f6c8c37073a66b936067e7195fc1bba49814a16bbe9f466132648ad43c6"
},
"source/generation-prompt.txt": {
"sha256": "f30c65ba62b35c09bada29a2051ce75288aac72180b79323cd6c8e71253dade9"
},
"source/pane-coverage.png": {
"sha256": "12dd127da2c8d34444f27fa9cd0ccb19f4fb7c9e315a1eef7de2d74ed82dc0c0"
},
"source/raw-ridges.png": {
"sha256": "878d0d01686a48641954e5b2dace6f69fb83c9711d4abdbae77acc07eaf4a68d"
},
"source/scene-brief.md": {
"sha256": "977632d77ae2accddacb5d1ecc95a3f226d488b87c40701a28100a6f5ba8449d"
},
"source/text/reference-unclipped.png": {
"sha256": "83e0b682394e439f5f4661772b045d585fb32d008755bc7c16e1ea578be2d988"
},
"source/text/reference-unclipped.svg": {
"sha256": "81cecae8a4b379b7ccd7286869bd21d9919107789504ff505a33cfbf82285dce"
},
"source/text/text-2000.png": {
"sha256": "fdfd174b13ef13f1866cea9addaabede3208c26a735748a7849397d0eac400d2"
},
"source/text/text.svg": {
"sha256": "d8aca5c09f449ec4e62c40159ce66de512c0b09686a6e81783f34799146c245b"
},
"source/text/title-0-unclipped.png": {
"sha256": "8ca5b0f3730836f6b11d1fd654cae383878eb22b0d9364c5de440d3dfbe40233"
},
"source/text/title-0-unclipped.svg": {
"sha256": "5b591025d5d0c47c20695928159e16120efa3120832ca2ec630431921e5b9e7a"
},
"source/text/title-1-unclipped.png": {
"sha256": "30d558c30808bc355ec1d4e2d5ffef3e4fafb1ccec149c348a0f523219815055"
},
"source/text/title-1-unclipped.svg": {
"sha256": "cc9440139735c239bda52e9a08b4bd4522969d29cf46a193056d60ea6fa04ffe"
},
"source/text/verse-0-unclipped.png": {
"sha256": "7e72461698441193c94d9887e5956451fa6e63bd20662d8d4975f0e0bdecd530"
},
"source/text/verse-0-unclipped.svg": {
"sha256": "36d8fe2db663f0c799f928f0fbd9f15f2b2ac896453b73472c6c98551542f514"
},
"source/text/verse-1-unclipped.png": {
"sha256": "7b4a60183a913d7c7e1162933623ba7e2a427887feccd1e360236617dba7e97b"
},
"source/text/verse-1-unclipped.svg": {
"sha256": "3ee1cd753c5a92182cf7656f98709f23af403870692c09101d0434092066879d"
},
"source/typography-layout.json": {
"sha256": "07843f0a8e651967d5adece167fa47aac225e99bb72d587d801d9a75cc2a38e4"
},
"low/manifest.json": {
"sha256": "9f182106a4beeec6cd455d7cd1fe699f3939d1d81814c00dcdb0af1a3c58b3e5"
},
"med/manifest.json": {
"sha256": "4e61838dce4c597f65a645d51669779ef3d1ee63c4f0de076c053655d4b544c6"
},
"high/manifest.json": {
"sha256": "6defea43293d1e7d5c5129cfbe35ca4fde5205b55aac194788be3c8300cbb4d8"
}
},
"compatibilityAliases": [],
"sharedLayers": {
"tier": "uncommon",
"version": "v2",
"manifestSHA256": "8646a69d5cdc67a45c0a8cd209065dba9b4adb80f0dfda6bbbe25965c007301f"
},
"sharedFontManifestSHA256": "ef68ee6393981d54ca068a950f21c53b374d20e6e46c21c788f36380d3aae178"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 708 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 604 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 803 KiB

View File

@@ -0,0 +1,20 @@
{
"schemaVersion": 1,
"kind": "compact-card-revision",
"cardId": "BE-042",
"folderName": "BE-042-calling-of-the-first-disciples",
"revision": "v02",
"originalStage": "assembly-review",
"approval": null,
"reason": "superseded when v03 was accepted",
"originalManifest": "full-manifest.json",
"originalManifestSHA256": "37927321c54badc7539609f4388cf36b7b65e06eba082ce4924d46a0edc59cde",
"referenceResolution": "low",
"referenceImages": [
"low/borderless/card.png",
"low/boundless/card.png",
"low/normal/card.png",
"low/textless/card.png"
],
"retention": "Text provenance plus one 500 x 700 card face per available printing; full current acceptance lives in artifacts/cards."
}

View File

@@ -0,0 +1,525 @@
{
"status": "passed",
"cardId": "BE-042",
"revision": "v02",
"artApproval": {
"by": "user",
"note": "Looks good!",
"scope": "Artwork and provisional two-line title study"
},
"finalCardApproval": null,
"inputs": {
"art": {
"path": "in-progress/cards/BE-042-calling-of-the-first-disciples/revisions/v02/source/art-master.png",
"sha256": "f51ca54ed1944b5615fd2f15a7fdc22bc65608a6de6b7a0d3c5b1b48e98f5550"
},
"fit": {
"native": "art-native.png",
"nativeDimensions": [
1060,
1484
],
"nativeSHA256": "a6a1b22431990938eea3d9c536d4590fecb1776570770f0f053dbc5e26a3fbe7",
"master": "art-master.png",
"masterDimensions": [
2000,
2800
],
"masterSHA256": "f51ca54ed1944b5615fd2f15a7fdc22bc65608a6de6b7a0d3c5b1b48e98f5550",
"transform": {
"method": "uniform cover; centered crop",
"scale": 1.8867924528301887,
"scaledDimensions": [
2000,
2800
],
"cropOffset": [
0,
0
],
"resampling": "Pillow LANCZOS",
"grading": "none"
},
"generationTool": "built-in image_gen",
"prompt": "generation-prompt.txt",
"promptSHA256": "f30c65ba62b35c09bada29a2051ce75288aac72180b79323cd6c8e71253dade9",
"layoutGuide": "artifacts/layers/uncommon/v2/layout.json",
"sharedLayerManifestSHA256": "8646a69d5cdc67a45c0a8cd209065dba9b4adb80f0dfda6bbbe25965c007301f",
"artApproval": {
"by": "user",
"note": "Looks good!",
"scope": "Artwork and provisional two-line title study"
}
},
"cardSHA256": "6561e64a6db3ba1588ae062fa23c8b835af074a0b16740c6bf97ebf156db58f8",
"builderSHA256": "e679ab29bc6043a13eb0fa8d09af152b35dd53199ad358a439a159bb447ef2e6"
},
"sharedLayers": {
"tier": "uncommon",
"version": "v2",
"manifestSHA256": "8646a69d5cdc67a45c0a8cd209065dba9b4adb80f0dfda6bbbe25965c007301f",
"reviewStatus": "pending-user-visual-review",
"assets": {
"frame-normal": {
"path": "artifacts/layers/uncommon/v2/exports/frame-normal-2000.png",
"sha256": "b7c5437332459d8eec78458e559314ed19f9d2a0d691bc99cf86c24f79284801"
},
"frame-textless": {
"path": "artifacts/layers/uncommon/v2/exports/frame-textless-2000.png",
"sha256": "b7c5437332459d8eec78458e559314ed19f9d2a0d691bc99cf86c24f79284801"
},
"backing-normal": {
"path": "artifacts/layers/uncommon/v2/exports/backing-normal-2000.png",
"sha256": "9b72c47765f097111f992f4ca1415360091d60f2990f531d1a87d40ab6e72cd5"
},
"backing-borderless": {
"path": "artifacts/layers/uncommon/v2/exports/backing-borderless-2000.png",
"sha256": "32851cc69f2bcb82daa60fe254f52da6c04a0d7283ea24a6e5b40e88545d50ef"
},
"overlay-normal": {
"path": "artifacts/layers/uncommon/v2/exports/overlay-normal-2000.png",
"sha256": "617ea13ca14b9cb74e2b5cc61cd476cc02426aeee49e1650c649891708d12bf5"
}
}
},
"sharedFontManifestSHA256": "ef68ee6393981d54ca068a950f21c53b374d20e6e46c21c788f36380d3aae178",
"typography": {
"fonts": [
{
"role": "title",
"file": "fonts/P052-Bold.otf",
"sha256": "ba6503baaf0f9e4e40a69cc4c0e57049fbde313fe183aba8fe823208337a94af",
"weight": 700,
"fallbackUsed": false,
"missingGlyphs": []
},
{
"role": "verse",
"file": "fonts/SanctificationP052-Medium.otf",
"sha256": "1e0e1f7f4a5b2899374de51e40f15446a04a5c0163d6a1943155f964c1ace1fb",
"weight": 500,
"fallbackUsed": false,
"missingGlyphs": []
},
{
"role": "reference",
"file": "fonts/SanctificationP052-Medium.otf",
"sha256": "1e0e1f7f4a5b2899374de51e40f15446a04a5c0163d6a1943155f964c1ace1fb",
"weight": 500,
"fallbackUsed": false,
"missingGlyphs": []
}
],
"glyphs": [
{
"id": "title-0",
"objectBounds": [
565.35,
106.5,
870.3,
71.2
],
"unclippedInkBounds": [
565,
106,
1436,
178
],
"region": [
140,
100,
1720,
200
],
"pass": true
},
{
"id": "title-1",
"objectBounds": [
573.7,
196.5,
850.2,
71.2
],
"unclippedInkBounds": [
573,
196,
1424,
268
],
"region": [
140,
100,
1720,
200
],
"pass": true
},
{
"id": "verse-0",
"objectBounds": [
383.6,
2311.6,
1231.6,
71.2
],
"unclippedInkBounds": [
383,
2311,
1616,
2383
],
"region": [
160,
2260,
1680,
300
],
"pass": true
},
{
"id": "verse-1",
"objectBounds": [
362.6,
2436.44,
1273.28,
81.52
],
"unclippedInkBounds": [
362,
2436,
1636,
2518
],
"region": [
160,
2260,
1680,
300
],
"pass": true
},
{
"id": "reference",
"objectBounds": [
724.662,
2603.39,
550.677,
52.9917
],
"unclippedInkBounds": [
724,
2603,
1276,
2657
],
"region": [
160,
2590,
1680,
80
],
"pass": true
}
],
"titleLayout": {
"sharedTemplate": "artifacts/layers/uncommon/v2/layout.json",
"scope": "Card-specific two-line lettering layout; shared backing/frame unchanged",
"approval": {
"by": "user",
"note": "I think that looks and feels pretty good",
"scope": "100px two-line title preview with unchanged embellishment"
},
"title": {
"lines": [
"CALLING OF THE",
"FIRST DISCIPLES"
],
"region": [
140,
100,
1720,
200
],
"baselines": [
176,
266
],
"fontSize": 100,
"weight": 700,
"centerX": 1000,
"minimumDecorationClearance": 20
},
"previousApproval": {
"by": "user",
"note": "Looks good!"
}
},
"decorationClearance": [
{
"printing": "normal",
"source": "artifacts/layers/uncommon/v2/source/backing-normal.svg",
"sourceSHA256": "c5989d794a2e9e7ec7dd6ad7bbf67404d7b8b64e4a9e15548c34255f2177782b",
"ornamentInkBounds": [
755,
288,
1245,
310
],
"verticalClearance": 20,
"minimumClearance": 20,
"actualExpandedInkIntersection": false,
"pass": true
},
{
"printing": "borderless",
"source": "artifacts/layers/uncommon/v2/source/backing-borderless.svg",
"sourceSHA256": "778c2f09fb9d2da51ecc16eb9467951a6bbf97e6d328078cc725df23f774114e",
"ornamentInkBounds": [
755,
288,
1245,
310
],
"verticalClearance": 20,
"minimumClearance": 20,
"actualExpandedInkIntersection": false,
"pass": true
}
],
"textLayerSHA256": "fdfd174b13ef13f1866cea9addaabede3208c26a735748a7849397d0eac400d2"
},
"textMask": {
"expansionRadius": 12,
"gaussianRadius": 8,
"units": "master pixels",
"derivation": "Actual rendered text alpha; MaxFilter(25), GaussianBlur(8)",
"minimumProtectionAtGlyphAlpha128": 221
},
"finishRecipe": {
"id": "raw-ridges-v1",
"sha256": "23331ce56a717edb4e6f85956d11fdd98397009c4e6dd230d8c334c77571dd18",
"path": "tools/card-production/recipes/raw-ridges-v1.json",
"moduleSHA256": "8d2b5399859570f43d9b222e6d37302372d68d2b589921b3c5b161b47cd18d5c",
"rawRidgeSHA256": "878d0d01686a48641954e5b2dace6f69fb83c9711d4abdbae77acc07eaf4a68d",
"paneCoverageSHA256": "12dd127da2c8d34444f27fa9cd0ccb19f4fb7c9e315a1eef7de2d74ed82dc0c0",
"illustrationAnalyses": 1
},
"tools": {
"inkscape": "Inkscape 1.2.2 (b0a8486541, 2022-12-01)",
"pillow": "10.2.0",
"numpy": "1.26.4"
},
"printings": {
"normal": {
"overlay": "overlay-normal",
"text": true,
"exports": [
{
"resolution": "low",
"dimensions": [
500,
700
],
"files": {
"card.png": "21573a7b212422f4deed68e525ad09d39e6025cdfbeaeff8b53db2517b3f90b1",
"finish-mask.png": "1bd3d0fd9e2767c490e64529e46071d2963186a16bb0f495521fee941dba71d5",
"text-mask.png": "f82b995d6c0a1ac89b8b956b3c53c32cdcce68eb13d9cb35489a164b77984abc"
}
},
{
"resolution": "med",
"dimensions": [
1000,
1400
],
"files": {
"card.png": "c4bae9860dad29dba5868881b598cd0045ca2e86e27fad27a9d7bdf1a086c30b",
"finish-mask.png": "5ab8249f157c4ba18b0edafb37e9202c38f0c30f3064479f7fb628f23c99fd0f",
"text-mask.png": "2fa1814867fb7b866b9e0365700da6531be25f447415eefd37f5bb1efbe7c74f"
}
},
{
"resolution": "high",
"dimensions": [
2000,
2800
],
"files": {
"card.png": "df60c465f5f4dddf71a9124167f83aa7d318a1afec3b7957ae7ace2370e0c1f5",
"finish-mask.png": "bb113943bfb1070e706c366ea7740e05426ba4eca0f611510c18ae0153b78204",
"text-mask.png": "19eb883960f341e446144c4e895e8928cbc11d82ff2a88b9e9ba4cd18a350503"
}
}
]
},
"boundless": {
"overlay": null,
"text": false,
"exports": [
{
"resolution": "low",
"dimensions": [
500,
700
],
"files": {
"card.png": "942c245bda3f0e20ff4e477e6c49b05f9fcef20d2c222bbe39589a071f3fe951",
"finish-mask.png": "b23e4f7d0ac28f8fb91cb37c15d98ca5df04eacf5edb7c8ed5fa884fe3d3a2cf",
"text-mask.png": "85fbeb48f81f5fd89c81a79be7e1d4d16837edd786733f593e0a4451be5fa52b"
}
},
{
"resolution": "med",
"dimensions": [
1000,
1400
],
"files": {
"card.png": "d7049e9cdb6b75cb003f1dbc3f5cda7e4e59d8798da80d8511fb31c780a52d9e",
"finish-mask.png": "08dc6431c8b05bee33cbfc315e7c2420698ed3e8daeff9d840ee0d1991baa232",
"text-mask.png": "f8732c63feae83b55d064bc73e39904d9158c4e194dfd6d30dbff7864adfd490"
}
},
{
"resolution": "high",
"dimensions": [
2000,
2800
],
"files": {
"card.png": "f56a5fbfbea883a5bc04615271fea9fcb0b305618d7f0edd0063a5f10adfb76f",
"finish-mask.png": "89234de20ff2e99b19071985983def90f097e939b1e30bd392fa813874f6bf39",
"text-mask.png": "27006d9c9a2ced6159cc5a6a76ef707e22797a800df9b9e19ec1f1783fc6d767"
}
}
]
},
"borderless": {
"overlay": "backing-borderless",
"text": true,
"exports": [
{
"resolution": "low",
"dimensions": [
500,
700
],
"files": {
"card.png": "1f1c3c560376bc5a1f8719733ab7f80858cdf70856acfeed8b123ede0c5eb40b",
"finish-mask.png": "26910c29532b194cb829bb7d1188f4962c294c98a36bc8cedf392793eff77c0d",
"text-mask.png": "f82b995d6c0a1ac89b8b956b3c53c32cdcce68eb13d9cb35489a164b77984abc"
}
},
{
"resolution": "med",
"dimensions": [
1000,
1400
],
"files": {
"card.png": "62453bc06cb12cf7237ae838e675adf209a646984a218a483ced5bc0b6b91777",
"finish-mask.png": "541f2a39b9f730f4a560495ee985b66939ab64f4e3a7e25f43c6782785eae2ec",
"text-mask.png": "2fa1814867fb7b866b9e0365700da6531be25f447415eefd37f5bb1efbe7c74f"
}
},
{
"resolution": "high",
"dimensions": [
2000,
2800
],
"files": {
"card.png": "a9c909c750263849a3b61999e94f6cfb8b2a24024c56e1cb29552d940de19a62",
"finish-mask.png": "26c2174c24ad3e6d42520ecde01155c151fe991c066f393444f76a4113084b43",
"text-mask.png": "19eb883960f341e446144c4e895e8928cbc11d82ff2a88b9e9ba4cd18a350503"
}
}
]
},
"textless": {
"overlay": "frame-textless",
"text": false,
"exports": [
{
"resolution": "low",
"dimensions": [
500,
700
],
"files": {
"card.png": "b8a2a5378dc1f00c5915a2d288abd3d363e71eed6de17a42d8fc648b24ec6862",
"finish-mask.png": "3c64c1ab9f982749b14d21f28a83339e0e401a6bd5a4df34a8fbf20ac4e3ed40",
"text-mask.png": "85fbeb48f81f5fd89c81a79be7e1d4d16837edd786733f593e0a4451be5fa52b"
}
},
{
"resolution": "med",
"dimensions": [
1000,
1400
],
"files": {
"card.png": "84187653b148f5090da213b4d641d5d3958bfd89792f36c6c4f4a040706852ee",
"finish-mask.png": "d185564cea26fc43aa5d203b80dca8e96f5dd96b9ee8ee0412badb50ebd2b24c",
"text-mask.png": "f8732c63feae83b55d064bc73e39904d9158c4e194dfd6d30dbff7864adfd490"
}
},
{
"resolution": "high",
"dimensions": [
2000,
2800
],
"files": {
"card.png": "37a2901a7792dda6619abecb98b9ecededffe522fa1e42bfb6c4855ed6fffb5c",
"finish-mask.png": "3f1ce3d85792d20ed37b2a918a94195cda5f3408f488797071076a436d7d7043",
"text-mask.png": "27006d9c9a2ced6159cc5a6a76ef707e22797a800df9b9e19ec1f1783fc6d767"
}
}
]
}
},
"visualReview": {
"static": "Updated Normal matches the user-approved 100px preview pixel-for-pixel at every export size. The unchanged decorative backing retains 20 master pixels of actual title clearance in Normal and Borderless.",
"movingLight": "Pending harness review; not performed."
},
"backingContrast": [
{
"width": 2000,
"primaryRuleToCream": 4.66,
"minimum": 3
},
{
"width": 1000,
"primaryRuleToCream": 6.13,
"minimum": 3
},
{
"width": 500,
"primaryRuleToCream": 3.41,
"minimum": 3
}
],
"textContrast": 9.2,
"unchangedNonTextPrintingsPNGHashes": {
"low/boundless/text-mask.png": "85fbeb48f81f5fd89c81a79be7e1d4d16837edd786733f593e0a4451be5fa52b",
"low/boundless/finish-mask.png": "b23e4f7d0ac28f8fb91cb37c15d98ca5df04eacf5edb7c8ed5fa884fe3d3a2cf",
"low/boundless/card.png": "942c245bda3f0e20ff4e477e6c49b05f9fcef20d2c222bbe39589a071f3fe951",
"low/textless/text-mask.png": "85fbeb48f81f5fd89c81a79be7e1d4d16837edd786733f593e0a4451be5fa52b",
"low/textless/finish-mask.png": "3c64c1ab9f982749b14d21f28a83339e0e401a6bd5a4df34a8fbf20ac4e3ed40",
"low/textless/card.png": "b8a2a5378dc1f00c5915a2d288abd3d363e71eed6de17a42d8fc648b24ec6862",
"med/boundless/text-mask.png": "f8732c63feae83b55d064bc73e39904d9158c4e194dfd6d30dbff7864adfd490",
"med/boundless/finish-mask.png": "08dc6431c8b05bee33cbfc315e7c2420698ed3e8daeff9d840ee0d1991baa232",
"med/boundless/card.png": "d7049e9cdb6b75cb003f1dbc3f5cda7e4e59d8798da80d8511fb31c780a52d9e",
"med/textless/text-mask.png": "f8732c63feae83b55d064bc73e39904d9158c4e194dfd6d30dbff7864adfd490",
"med/textless/finish-mask.png": "d185564cea26fc43aa5d203b80dca8e96f5dd96b9ee8ee0412badb50ebd2b24c",
"med/textless/card.png": "84187653b148f5090da213b4d641d5d3958bfd89792f36c6c4f4a040706852ee",
"high/boundless/text-mask.png": "27006d9c9a2ced6159cc5a6a76ef707e22797a800df9b9e19ec1f1783fc6d767",
"high/boundless/finish-mask.png": "89234de20ff2e99b19071985983def90f097e939b1e30bd392fa813874f6bf39",
"high/boundless/card.png": "f56a5fbfbea883a5bc04615271fea9fcb0b305618d7f0edd0063a5f10adfb76f",
"high/textless/text-mask.png": "27006d9c9a2ced6159cc5a6a76ef707e22797a800df9b9e19ec1f1783fc6d767",
"high/textless/finish-mask.png": "3f1ce3d85792d20ed37b2a918a94195cda5f3408f488797071076a436d7d7043",
"high/textless/card.png": "37a2901a7792dda6619abecb98b9ecededffe522fa1e42bfb6c4855ed6fffb5c"
}
}

View File

@@ -0,0 +1,4 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by fontconfig.
# For information about cache directory tags, see:
# http://www.brynosaurus.com/cachedir/

View File

@@ -0,0 +1 @@
<fontconfig><dir>/home/dkzver/docker/sanctification/fonts</dir><cachedir>/home/dkzver/docker/sanctification/in-progress/cards/BE-042-calling-of-the-first-disciples/revisions/v02/review/font-cache</cachedir></fontconfig>

View File

@@ -0,0 +1,53 @@
{
"status": "user-approved-artwork",
"agentStaticAssessment": {
"story": "Open-hand invitation across quiet water; one brother beginning to rise, the other turns attentively. No overflowing catch.",
"glass": "Lead divisions follow sky, hills, robes, boat and water; pane-contained cloudy worked-glass texture is strongest in the environment.",
"rarity": "Uncommon: additional setting and richer but restrained palette, with broad restful sky and water.",
"anatomy": "Readable separate figures and natural shoulder-to-hand connections; no floating props identified.",
"occlusion": "Faces and key gestures clear of the actual top/bottom backing. Seated brother near right focal-guide edge; inspect the provisional guide before locking.",
"styleWatch": "Faces retain some illustrative modeling inside glass forms; user review should judge whether stylization is sufficient."
},
"nativeAndFit": {
"native": "art-native.png",
"nativeDimensions": [
1060,
1484
],
"nativeSHA256": "a6a1b22431990938eea3d9c536d4590fecb1776570770f0f053dbc5e26a3fbe7",
"master": "art-master.png",
"masterDimensions": [
2000,
2800
],
"masterSHA256": "f51ca54ed1944b5615fd2f15a7fdc22bc65608a6de6b7a0d3c5b1b48e98f5550",
"transform": {
"method": "uniform cover; centered crop",
"scale": 1.8867924528301887,
"scaledDimensions": [
2000,
2800
],
"cropOffset": [
0,
0
],
"resampling": "Pillow LANCZOS",
"grading": "none"
},
"generationTool": "built-in image_gen",
"prompt": "generation-prompt.txt",
"promptSHA256": "f30c65ba62b35c09bada29a2051ce75288aac72180b79323cd6c8e71253dade9",
"layoutGuide": "artifacts/layers/uncommon/v2/layout.json",
"sharedLayerManifestSHA256": "8646a69d5cdc67a45c0a8cd209065dba9b4adb80f0dfda6bbbe25965c007301f",
"artApproval": null
},
"title": "Provisional two-line study; shared template unchanged.",
"productionAssembly": "Complete; awaiting final card review",
"runtimeReview": "not performed",
"userApproval": {
"by": "user",
"note": "Looks good!",
"scope": "Artwork and provisional two-line title study"
}
}

View File

@@ -0,0 +1,54 @@
{
"status": "provisional; no production lettering or template changes",
"font": "fonts/P052-Bold.otf",
"fontSHA256": "ba6503baaf0f9e4e40a69cc4c0e57049fbde313fe183aba8fe823208337a94af",
"weight": 700,
"fontSize": 112,
"template": "artifacts/layers/uncommon/v2/layout.json",
"existingTitleRegion": [
140,
130,
1720,
140
],
"existingTopBacking": [
60,
60,
1880,
300
],
"singleLine": {
"title": "CALLING OF THE FIRST DISCIPLES",
"width": 1972.66,
"availableWidth": 1720,
"fits": false
},
"singleLineAtMinimum100": {
"width": 1761.25,
"availableWidth": 1720,
"fits": false
},
"recommendation": {
"lines": [
"CALLING OF THE",
"FIRST DISCIPLES"
],
"inkWidths": [
983,
961
],
"provisionalTitleRegion": [
140,
100,
1720,
200
],
"note": "Two lines at the current size need more vertical space than the standard title region, but fit within the existing 300px backing. Keep frame/backing geometry unchanged. Final baselines and actual renderer glyph bounds need assembly review.",
"provisionalBaselines": [
198.0,
298.0
],
"lineGap": 20,
"blockInkHeight": 180
}
}

View File

@@ -0,0 +1,10 @@
# BE-042 — smaller title preview
P052 Bold remains at weight 700. Title size decreases from 112 to 100 master pixels (10.7%), the current minimum. The same balanced two-line wording is reflowed at baselines 176 and 266 to leave space above the unchanged central flourish. Shared art, backing, frame, verse and reference are unchanged.
- [Full-card comparison](comparison.png)
- [Header comparison](header-comparison.png)
- [Smaller Normal preview, standard size](normal-title-100-1000.png)
- [Validation and exact parameters](validation.json)
Preview only; no production exports, masks, typography defaults or harness fixtures were replaced. Unclipped glyph bounds fit, actual ink remains at least 20 master pixels clear of the ornament, and all decoded pixels below the header match the existing card.

View File

@@ -0,0 +1,4 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by fontconfig.
# For information about cache directory tags, see:
# http://www.brynosaurus.com/cachedir/

View File

@@ -0,0 +1 @@
<fontconfig><dir>/home/dkzver/docker/sanctification/fonts</dir><cachedir>/home/dkzver/docker/sanctification/in-progress/cards/BE-042-calling-of-the-first-disciples/revisions/v02/review/title-size-reduction/font-cache</cachedir></fontconfig>

View File

@@ -0,0 +1,76 @@
{
"status": "passed-preview-only",
"titleFont": "fonts/P052-Bold.otf",
"fontSHA256": "ba6503baaf0f9e4e40a69cc4c0e57049fbde313fe183aba8fe823208337a94af",
"weight": 700,
"previousSize": 112,
"previewSize": 100,
"reductionPercent": 10.7,
"minimumSize": 100,
"lines": [
"CALLING OF THE",
"FIRST DISCIPLES"
],
"baselines": [
176,
266
],
"reason": "Reduce size and reflow the shorter block above the unchanged flourish; keeping the former bottom baseline would retain the collision.",
"glyphs": [
{
"id": "title-0",
"objectBounds": [
565.35,
106.5,
870.3,
71.2
],
"unclippedInkBounds": [
565,
106,
1436,
178
],
"region": [
140,
100,
1720,
200
]
},
{
"id": "title-1",
"objectBounds": [
573.7,
196.5,
850.2,
71.2
],
"unclippedInkBounds": [
573,
196,
1424,
268
],
"region": [
140,
100,
1720,
200
]
}
],
"ornamentInkBounds": [
755,
288,
1245,
310
],
"verticalClearanceMasterPixels": 20,
"actualInkClearanceCheck": "20px expanded title ink does not intersect ornament ink",
"unchanged": "Artwork, shared frame/backing/ornament, verse and reference; decoded pixels below y=360 match the existing Normal card exactly.",
"sharedOverlaySHA256": "617ea13ca14b9cb74e2b5cc61cd476cc02426aeee49e1650c649891708d12bf5",
"existingNormalSHA256": "993676b3207561f8cf19ab3c7f863ebfd4dbf505ce861e365bbf4fc028dd109e",
"previewSHA256": "df60c465f5f4dddf71a9124167f83aa7d318a1afec3b7957ae7ace2370e0c1f5",
"productionExports": "Unchanged; this is a static title-size experiment, without new production masks or fixture installation."
}

View File

@@ -0,0 +1,38 @@
{
"native": "art-native.png",
"nativeDimensions": [
1060,
1484
],
"nativeSHA256": "a6a1b22431990938eea3d9c536d4590fecb1776570770f0f053dbc5e26a3fbe7",
"master": "art-master.png",
"masterDimensions": [
2000,
2800
],
"masterSHA256": "f51ca54ed1944b5615fd2f15a7fdc22bc65608a6de6b7a0d3c5b1b48e98f5550",
"transform": {
"method": "uniform cover; centered crop",
"scale": 1.8867924528301887,
"scaledDimensions": [
2000,
2800
],
"cropOffset": [
0,
0
],
"resampling": "Pillow LANCZOS",
"grading": "none"
},
"generationTool": "built-in image_gen",
"prompt": "generation-prompt.txt",
"promptSHA256": "f30c65ba62b35c09bada29a2051ce75288aac72180b79323cd6c8e71253dade9",
"layoutGuide": "artifacts/layers/uncommon/v2/layout.json",
"sharedLayerManifestSHA256": "8646a69d5cdc67a45c0a8cd209065dba9b4adb80f0dfda6bbbe25965c007301f",
"artApproval": {
"by": "user",
"note": "Looks good!",
"scope": "Artwork and provisional two-line title study"
}
}

View File

@@ -0,0 +1,13 @@
Use case: illustration-story. Generate one new, original full-bleed portrait illustration for the Uncommon Sanctification card CALLING OF THE FIRST DISCIPLES. Output one artwork-only image at a 5:7 aspect ratio. No lettering or card design is part of this image.
SCENE AND EMOTIONAL INTENT
Jesus stands on the shore of the Sea of Galilee calling toward two brothers in one small fishing boat. An open, spacious composition emphasizes the distance between caller and called. Show their response to the invitation: invitation and hopeful anticipation, quiet purpose, and the weight of choosing to follow. The governing moment is a personal invitation, not an overflowing catch or an urgent fishing disaster. Jesus offers one clear, natural open-handed calling gesture. One brother turns and begins to rise, with a hand naturally resting on the boat's gunwale; the other, seated, turns his attentive face toward Jesus. Their expressions convey the dawning realization that this invitation changes their lives. All three figures have coherent, believable arms, hands and clear silhouettes. Simple first-century robes and a modest wooden boat; restrained fishing nets lie in the boat rather than becoming a spectacle. No additional people, supernatural figure, serpent, or allegorical fish-men.
COMPOSITION AND CARD-SAFE PLACEMENT
A full environment fills the entire portrait, including the top and bottom that will later be partly covered by separate card panels. Use an eye-level shoreline view and a gentle diagonal shoreline; Jesus occupies the left middle distance, the boat with both brothers the right middle distance, connected by a readable expanse of quiet water. Keep enough physical space between them to make the invitation across that distance central to the story. Use calm water, a few shore stones and reeds, and understated distant Galilean hills to establish place. Preserve several broad quiet glass areas. At a later 2000 x 2800 canvas, opaque card panels cover y=60..360 and y=2180..2740 and the frame covers the outer 76 pixels. All essential faces, Jesus's calling hand, the brothers' responding gestures and their readable boat must stay within x=160..1840 and y=400..2110 (approximately x=8..92%, y=14..75%). Keep the faces comfortably away from these limits. Plan the scene as a spacious middle-distance composition, not a cropped portrait. Do not generate panels, blank bands, borders, corner ornament or lettering placeholders. Continue the landscape naturally under areas later covered.
SHARED GLASS CONSTRUCTION
Build the entire scene from colored glass segments with coherent dark lead-like divisions following bodies, robes, boat planks, flowing water, rocks and hills. Use varied deliberate curved, elongated and angular panes according to the forms, with broad quiet water and sky segments and selective fine detail in the focal gestures. This is a scene made of glass, not a realistic painting beneath a random cracked-glass overlay. Figures share the stylized glass language: expressive facial planes, brows, eyes and mouth contours, clear bodily proportions, gentle simple modeling; avoid realistic flesh shading. Fine ink illustration inside a pane can preserve faces, hair and hands without turning every feature into a tiny polygon.
WORKED-GLASS SURFACE AND UNCOMMON RESTRAINT
Tactile lightly brushed or etched glass: diffuse cloudy, satin-like variations contained inside individual environmental panes, particularly water, stones, sky and the wooden boat. Texture supports the glass colors and boundaries, never a uniform noise filter. Keep it much gentler on faces, hands and bare arms. Uncommon should feel refined and visibly richer than Common, with selective segmentation and modestly broadened jewel colors: calm teal and sapphire water, muted olive hills, restrained wine-red and warm cream robes, and tiny amber-gold touches in the gentle light. Use gentle value transitions and occasional soft tinted highlights inside selected panes, with plentiful visual rest. Welcoming natural daylight and human warmth rather than a blazing sunrise, gilded spectacle, pervasive white dots, glitter or dramatic magical beams. No photorealistic sky, photorealistic people, fantasy TCG illustration, anime, hyper-dense ornament, cathedral/window arch, watermark, text, title, verse, frame or backing. Overall sacred, beautiful, grounded and readable at card size.

View File

@@ -0,0 +1,19 @@
# BE-042 — Calling of the First Disciples
Uncommon · Event · Matthew 4:19 • NKJV
## User-provided catalogue scene
Jesus stands on the shore calling toward the fishermen in an open, spacious composition; emphasize the distance between caller and called. Reserve the “fishers of men” verse for the card text, and show a response to the invitation rather than an overflowing catch.
## User-provided emotional intent
Invitation and hopeful anticipation; quiet purpose and the weight of choosing to follow. Avoid overwhelming spectacle or the urgency of a fishing disaster.
## Retained verse
Then He said to them, “Follow Me, and I will make you fishers of men.”
## Iteration scope
New artwork with the updated shared glass-construction, worked-glass surface, and Uncommon profile. Preserve v01. Art approval and typography treatment remain pending. No final printings or masks in this revision yet.

View File

@@ -0,0 +1,33 @@
{
"sharedTemplate": "artifacts/layers/uncommon/v2/layout.json",
"scope": "Card-specific two-line lettering layout; shared backing/frame unchanged",
"approval": {
"by": "user",
"note": "I think that looks and feels pretty good",
"scope": "100px two-line title preview with unchanged embellishment"
},
"title": {
"lines": [
"CALLING OF THE",
"FIRST DISCIPLES"
],
"region": [
140,
100,
1720,
200
],
"baselines": [
176,
266
],
"fontSize": 100,
"weight": 700,
"centerX": 1000,
"minimumDecorationClearance": 20
},
"previousApproval": {
"by": "user",
"note": "Looks good!"
}
}