# -*- coding: utf-8 -*-
from pathlib import Path
from math import pi, sin, cos
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.lib.units import mm
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
from reportlab.pdfbase import pdfmetrics
from reportlab.platypus import Paragraph, Table, TableStyle
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.enums import TA_CENTER

ROOT = Path('/Users/bot1/Volumes/root_for_ai/AI工作区/良渚_商业手册_品牌合作PDF_20260602_1526')
OUT = ROOT / 'deliverables/良渚博物院文创品牌及IP授权合作手册_A4_品牌方直发版_20260602_v3.pdf'
LOG = ROOT / 'work/v3/layout_check_v3.txt'
OUT.parent.mkdir(parents=True, exist_ok=True)
LOG.parent.mkdir(parents=True, exist_ok=True)

pdfmetrics.registerFont(UnicodeCIDFont('STSong-Light'))
FONT = 'STSong-Light'
W, H = A4

BONE = colors.HexColor('#FFFDF3')
BONE2 = colors.HexColor('#F7F3E6')
JADE_PALE = colors.HexColor('#E7F1E9')
JADE_SOFT = colors.HexColor('#C9DED3')
JADE = colors.HexColor('#5E9180')
JADE_DARK = colors.HexColor('#173D35')
JADE_DEEP = colors.HexColor('#102F2A')
GOLD = colors.HexColor('#C59B3C')
GOLD_LIGHT = colors.HexColor('#E8CB7B')
CINNABAR = colors.HexColor('#A74E3F')
INK = colors.HexColor('#173A33')
MUTED = colors.HexColor('#60746A')

warnings = []
page_no = 0

def style(name, size, leading, color, align=None):
    return ParagraphStyle(name, fontName=FONT, fontSize=size, leading=leading, textColor=color, wordWrap='CJK', alignment=align or 0)

BASE_STYLES = {
    'kicker': style('kicker', 8.8, 11.2, GOLD),
    'kicker_d': style('kicker_d', 8.8, 11.2, GOLD_LIGHT),
    'cover': style('cover', 34, 42, BONE),
    'h1': style('h1', 24, 30, INK),
    'h1_d': style('h1_d', 24, 30, BONE),
    'h2': style('h2', 15.2, 20, INK),
    'h2_d': style('h2_d', 15.2, 20, colors.HexColor('#FFF3CD')),
    'lead': style('lead', 12.3, 17.5, INK),
    'lead_d': style('lead_d', 12.3, 17.5, BONE),
    'body': style('body', 9.2, 13.8, colors.HexColor('#3F574E')),
    'body_d': style('body_d', 9.2, 13.8, colors.HexColor('#E8EFE6')),
    'small': style('small', 7.8, 10.5, MUTED),
    'center': style('center', 9.0, 12.5, colors.HexColor('#3F574E'), TA_CENTER),
}

def P(text, sty):
    return Paragraph(str(text).replace('\n','<br/>'), sty)

def fit_style(base_key, w, h, text, min_size=7.2):
    base = BASE_STYLES[base_key]
    size = base.fontSize
    while size >= min_size:
        ratio = size / base.fontSize
        st = style(base.name + f'_{size:.1f}', size, max(size*1.32, base.leading*ratio), base.textColor, base.alignment)
        p = P(text, st)
        _, ph = p.wrap(w, h)
        if ph <= h + 0.2:
            return p, ph, st
        size -= 0.4
    p = P(text, st)
    _, ph = p.wrap(w, h)
    return p, ph, st

def draw_text(c, text, x, y_top, w, h, key='body', context=''):
    p, ph, st = fit_style(key, w, h, text)
    if ph > h + 0.2:
        warnings.append(f'page {page_no} overflow {context}: need {ph/mm:.1f}mm > {h/mm:.1f}mm text={str(text)[:40]}')
    p.drawOn(c, x, y_top - min(ph, h))
    return min(ph, h)

def bg(c, kind='light'):
    if kind == 'dark':
        c.setFillColor(JADE_DEEP); c.rect(0,0,W,H,stroke=0,fill=1)
        c.setFillColor(colors.Color(.12,.34,.29,1)); c.circle(W*.76,H*.82,70*mm,stroke=0,fill=1)
        c.setFillColor(colors.Color(.78,.61,.23,.30)); c.circle(W*1.03,H*.10,82*mm,stroke=0,fill=1)
        c.setFillColor(colors.Color(.78,.92,.84,.12)); c.circle(W*.11,H*.10,62*mm,stroke=0,fill=1)
    elif kind == 'split':
        c.setFillColor(BONE); c.rect(0,0,W,H,stroke=0,fill=1)
        c.setFillColor(JADE_PALE); c.rect(W*.60,0,W*.40,H,stroke=0,fill=1)
        c.setFillColor(colors.Color(.78,.88,.82,.46)); c.circle(W*.96,H*.82,65*mm,stroke=0,fill=1)
        c.setFillColor(colors.Color(.79,.61,.24,.12)); c.circle(W*.11,H*.09,62*mm,stroke=0,fill=1)
    else:
        c.setFillColor(BONE); c.rect(0,0,W,H,stroke=0,fill=1)
        c.setFillColor(JADE_PALE); c.circle(W*.08,H*.10,66*mm,stroke=0,fill=1)
        c.setFillColor(colors.Color(.79,.61,.24,.13)); c.circle(W*.94,H*.90,60*mm,stroke=0,fill=1)

def motif(c, x, y, r, dark=False):
    c.saveState(); c.translate(x,y)
    c.setStrokeColor(colors.Color(1,1,1,.14) if dark else colors.Color(.09,.24,.20,.09))
    c.setLineWidth(.75)
    c.circle(0,0,r,stroke=1,fill=0); c.circle(0,0,r*.62,stroke=1,fill=0)
    for i in range(4):
        a=i*pi/2+pi/4; c.line(cos(a)*r*.23, sin(a)*r*.23, cos(a)*r*.86, sin(a)*r*.86)
    c.restoreState()

def footer(c, dark=False):
    c.setStrokeColor(colors.Color(1,1,1,.22) if dark else colors.Color(.1,.24,.2,.15))
    c.setLineWidth(.35); c.line(17*mm, 15*mm, W-17*mm, 15*mm)
    c.setFont(FONT, 7.3); c.setFillColor(colors.Color(1,1,1,.48) if dark else colors.Color(.1,.24,.2,.42))
    c.drawRightString(W-17*mm, 9.5*mm, f'{page_no:02d}')

def start(c, kicker, title, kind='light'):
    global page_no
    page_no += 1
    bg(c, kind); dark = kind == 'dark'
    draw_text(c, kicker, 17*mm, H-22*mm, 170*mm, 9*mm, 'kicker_d' if dark else 'kicker', 'kicker')
    draw_text(c, title, 17*mm, H-38*mm, 160*mm, 34*mm, 'h1_d' if dark else 'h1', 'title')
    motif(c, W-29*mm, H-28*mm, 15*mm, dark)
    footer(c, dark)

def finish(c):
    c.showPage()

def card(c, x, y_top, w, h, title, body, tag=None, dark=False, fill=None):
    y = y_top-h
    c.setFillColor(fill if fill else (colors.Color(1,1,1,.80) if not dark else colors.Color(1,1,1,.09)))
    c.setStrokeColor(colors.Color(.10,.28,.24,.10) if not dark else colors.Color(1,1,1,.16))
    c.roundRect(x,y,w,h,6*mm,stroke=1,fill=1)
    pad=4.6*mm; cur=y_top-pad
    remain=h-2*pad
    if tag:
        used=draw_text(c, tag, x+pad, cur, w-2*pad, 7.5*mm, 'kicker_d' if dark else 'kicker', f'card tag {tag}')
        cur -= used + 2*mm; remain -= used + 2*mm
    used=draw_text(c, title, x+pad, cur, w-2*pad, min(20*mm, remain*.38), 'h2_d' if dark else 'h2', f'card title {title}')
    cur -= used + 2*mm; remain -= used + 2*mm
    if body:
        draw_text(c, body, x+pad, cur, w-2*pad, max(5*mm, remain), 'body_d' if dark else 'body', f'card body {title}')

def stat(c, x, y_top, w, h, number, label, body=''):
    y=y_top-h
    c.setFillColor(colors.Color(1,1,1,.82)); c.setStrokeColor(colors.Color(.10,.28,.24,.10))
    c.roundRect(x,y,w,h,6*mm,stroke=1,fill=1)
    c.setFont(FONT, 20); c.setFillColor(JADE_DARK); c.drawCentredString(x+w/2, y_top-13*mm, number)
    c.setFont(FONT, 8.8); c.setFillColor(GOLD); c.drawCentredString(x+w/2, y_top-23*mm, label)
    if body:
        draw_text(c, body, x+4*mm, y_top-31*mm, w-8*mm, h-33*mm, 'center', f'stat {label}')

def table(c, data, x, y_top, widths, context='table'):
    pdata=[[P(cell, BASE_STYLES['body']) for cell in row] for row in data]
    t=Table(pdata, colWidths=widths, repeatRows=1)
    t.setStyle(TableStyle([
        ('FONTNAME',(0,0),(-1,-1),FONT),('FONTSIZE',(0,0),(-1,-1),8.0),
        ('VALIGN',(0,0),(-1,-1),'TOP'),
        ('BACKGROUND',(0,0),(-1,0),colors.Color(.79,.61,.24,.16)),
        ('TEXTCOLOR',(0,0),(-1,0),colors.HexColor('#76571A')),
        ('BACKGROUND',(0,1),(-1,-1),colors.Color(1,1,1,.78)),
        ('GRID',(0,0),(-1,-1),.25,colors.Color(.10,.28,.24,.13)),
        ('LEFTPADDING',(0,0),(-1,-1),5),('RIGHTPADDING',(0,0),(-1,-1),5),
        ('TOPPADDING',(0,0),(-1,-1),5),('BOTTOMPADDING',(0,0),(-1,-1),5),
    ]))
    tw,th=t.wrap(sum(widths),H)
    t.drawOn(c,x,y_top-th)
    return th

def bullet_panel(c, x, y_top, w, title, items, dark=False):
    h = 18*mm + len(items)*17*mm
    c.setFillColor(colors.Color(1,1,1,.80) if not dark else colors.Color(1,1,1,.09))
    c.setStrokeColor(colors.Color(.10,.28,.24,.10) if not dark else colors.Color(1,1,1,.16))
    c.roundRect(x,y_top-h,w,h,6*mm,stroke=1,fill=1)
    draw_text(c, title, x+5*mm, y_top-5*mm, w-10*mm, 14*mm, 'h2_d' if dark else 'h2', f'bullet title {title}')
    y=y_top-23*mm
    for i,it in enumerate(items,1):
        c.setFillColor(GOLD); c.circle(x+7*mm,y-3*mm,3.2*mm,stroke=0,fill=1)
        c.setFillColor(colors.white); c.setFont(FONT,6.5); c.drawCentredString(x+7*mm,y-5.1*mm,str(i))
        draw_text(c, it, x+13*mm, y+2*mm, w-19*mm, 14*mm, 'body_d' if dark else 'body', f'bullet {title} {i}')
        y-=17*mm

c=canvas.Canvas(str(OUT), pagesize=A4)

# 1 cover
page_no += 1
bg(c,'dark')
draw_text(c,'LIANGZHU MUSEUM · CULTURAL CREATIVE BRAND & IP LICENSING',17*mm,H-24*mm,170*mm,10*mm,'kicker_d','cover kicker')
draw_text(c,'良渚博物院\n文创品牌及IP授权\n合作手册',17*mm,H-58*mm,146*mm,122*mm,'cover','cover title')
c.setStrokeColor(GOLD_LIGHT); c.setLineWidth(1.2); c.line(17*mm,H-142*mm,91*mm,H-142*mm)
draw_text(c,'世界遗产 · 文明圣地 · 国家平台',17*mm,H-156*mm,150*mm,20*mm,'lead_d','cover lead')
draw_text(c,'活化文化遗产，赋能当代生活',17*mm,H-176*mm,150*mm,18*mm,'body_d','cover sub')
for x,y,r in [(158*mm,93*mm,25*mm),(178*mm,68*mm,13*mm),(143*mm,57*mm,10*mm)]: motif(c,x,y,r,True)
c.setFont(FONT,8.2); c.setFillColor(colors.Color(1,1,1,.58)); c.drawString(17*mm,21*mm,'良渚博物院文创品牌及IP授权合作手册')
footer(c,True); finish(c)

# 2 cultural basics
start(c,'01 · 良渚文化基本情况','中华五千多年文明史的重要标识','light')
card(c,17*mm,H-78*mm,176*mm,60*mm,'良渚文化','良渚文化是新石器时代晚期中国长江下游环太湖流域的一支考古学文化，距今约5300年—4300年，是迄今发现的中华大地上最早的国家文明，也是东亚地区最早的文明遗迹。')
card(c,17*mm,H-150*mm,176*mm,58*mm,'良渚古城遗址','作为良渚文化的权力与信仰中心，良渚古城遗址于2019年7月6日成功列入《世界遗产名录》，在世界范围内为中华五千多年文明史树立了重要标识，被誉为“实证中华五千年文明史的圣地”。')
stat(c,17*mm,H-223*mm,40*mm,45*mm,'5300+','距今年代','约5300年—4300年')
stat(c,63*mm,H-223*mm,40*mm,45*mm,'2019','列入世遗','列入《世界遗产名录》')
stat(c,109*mm,H-223*mm,40*mm,45*mm,'1+3','展示格局','博物院联动三大遗址公园')
stat(c,155*mm,H-223*mm,38*mm,45*mm,'国家级','文旅地标','彰显中华五千年文明底蕴')
finish(c)

# 3 1+3 overview
start(c,'02 · “1+3”全域遗产价值展示格局','良渚博物院联动三大遗址公园','split')
card(c,17*mm,H-83*mm,84*mm,62*mm,'良渚博物院','集收藏、研究、展示和宣传良渚文化功能为一体的考古遗址博物馆，全面、立体、真实地展示良渚文化的文化面貌和良渚古城遗址的遗产价值。','核心展示窗口')
card(c,109*mm,H-83*mm,84*mm,62*mm,'良渚古城遗址公园','良渚古城遗址厚重历史文化最典型、最为直接的物质载体，是体验和感悟“中华五千多年文明”的重要场所。','遗址现场')
card(c,17*mm,H-159*mm,84*mm,55*mm,'瑶山遗址公园','依托自然山丘而建，是一处祭坛和高等级墓地组成的复合遗址，营建于良渚文化早期。','祭坛与墓地')
card(c,109*mm,H-159*mm,84*mm,55*mm,'老虎岭遗址公园','目前良渚古城遗址唯一一处向公众展示水利系统剖面结构的遗址点。','水利系统')
card(c,17*mm,H-232*mm,176*mm,40*mm,'全域遗产价值','当前，良渚博物院联动良渚古城、瑶山、老虎岭等遗址公园，统筹构建“1+3”全域遗产价值展示格局，系统打造彰显中华五千年文明底蕴的国家级标杆文旅地标。')
finish(c)

# 4 important honors and spaces
start(c,'03 · 重要展示窗口','国家一级博物馆与重要遗址现场','light')
card(c,17*mm,H-85*mm,176*mm,62*mm,'良渚博物院','良渚博物院被评为“国家一级博物馆”、第二届全国文博百强文创产品单位，被授予“印记——中华文明文化传播标识”。基本陈列展览主题是“良渚是实证中华五千多年文明史的圣地”。')
card(c,17*mm,H-165*mm,84*mm,66*mm,'良渚古城遗址公园','规划总面积14.33平方公里，分城址区、瑶山遗址区、平原低坝—山前长堤区和谷口高坝区4个片区。城址区展示面积3.66平方公里。','14.33平方公里')
card(c,109*mm,H-165*mm,84*mm,66*mm,'遗址展示内容','设置有城门与城墙、河道与作坊、莫角山宫殿、反山王陵等遗址展示区，呈现良渚古城向心式三重布局结构。','城址区展示')
card(c,17*mm,H-242*mm,176*mm,30*mm,'遗产价值呈现','良渚文化空间体系为文化展示、文旅体验、品牌联名、文创开发和文化传播提供了坚实的内容基础。')
finish(c)

# 5 water/yaoshan
start(c,'04 · 遗址价值延展','祭祀礼制与水利文明','light')
card(c,17*mm,H-91*mm,176*mm,70*mm,'瑶山遗址公园','瑶山遗址公园依托自然山丘而建，是一处祭坛和高等级墓地组成的复合遗址，营建于良渚文化早期。其礼制、信仰与高等级墓葬内涵，为良渚文化的精神世界与社会结构提供重要展示维度。')
card(c,17*mm,H-188*mm,176*mm,76*mm,'老虎岭遗址公园','老虎岭遗址公园是目前良渚古城遗址唯一一处向公众展示水利系统剖面结构的遗址点。良渚古城外围水利系统作为良渚遗址成功申遗的重要组成部分，是中国迄今发现最早的大型水利工程遗址，也是目前已发现的世界上最早的堤坝系统之一。')
finish(c)

# 6 cultural creative industry
start(c,'05 · 良渚文化创意产业','文物资源活态化传承','light')
card(c,17*mm,H-82*mm,176*mm,52*mm,'产业定位','良渚博物院深耕文物资源活态化传承，体系化推进品牌IP培育及载体，推动良渚文明实现可观、可触、可品、可感的深度传播，持续为中华五千年文明血脉注入时代动能。')
stat(c,17*mm,H-150*mm,40*mm,45*mm,'11','覆盖品类','日用家居、贵金属等')
stat(c,63*mm,H-150*mm,40*mm,45*mm,'800+','在线产品','在线销售产品约800余款')
stat(c,109*mm,H-150*mm,40*mm,45*mm,'4亿+','销售规模','2025年总销售额已突破4亿元')
stat(c,155*mm,H-150*mm,38*mm,45*mm,'多项','行业荣誉','红点设计奖、“中国礼物”金奖等')
card(c,17*mm,H-224*mm,176*mm,50*mm,'“良渚+”品牌生态矩阵','现已构建“良渚+”品牌生态矩阵，持续迭代推出兼具亲民属性、精工品质、独特辨识度与市场竞争力的标杆文创产品。')
finish(c)

# 7 IP development positioning
start(c,'06 · 良渚文化IP资源开发','从文化资本到经济资本','dark')
card(c,17*mm,H-86*mm,176*mm,62*mm,'IP资源开发','良渚博物院IP资源授权工作通过特定品类授权、联合开发、跨界联名等方式，开发了系列“文化资本”向“经济资本”转化的经典案例，不仅印证良渚文化IP强大的市场吸引力，更推动文化价值与商业价值的有效协同与良性互促。','IP RESOURCE DEVELOPMENT',True)
card(c,17*mm,H-175*mm,176*mm,66*mm,'品牌定位','良渚文化品牌以“世界遗产、文明圣地、国家平台”三重价值为战略基点，秉持“活化文化遗产，赋能当代生活”的使命担当，聚焦“五千年中国看良渚”的叙事主线，塑造兼具深厚历史底蕴与鲜明东方文明标识度的超级文化品牌。','BRAND POSITION',True)
finish(c)

# 8 brand architecture
start(c,'07 · 品牌架构','三级分众化品牌体系','split')
card(c,17*mm,H-86*mm,176*mm,45*mm,'知识产权保护基础','为保障品牌IP的规范发展和知识产权保护，在顶层设计上搭建了层次清晰、覆盖广泛的三级分众化品牌体系，累计完成600余件作品的标准化确权。')
card(c,30*mm,H-143*mm,150*mm,36*mm,'良渚文化','一级品牌，即“良渚文化”为总品牌，传递鲜明的世界遗产标识。','一级品牌')
card(c,30*mm,H-188*mm,150*mm,36*mm,'良渚博物院 / 良渚古城','二级品牌，代表文化展示、文旅体验的重要展示窗口。','二级品牌')
card(c,30*mm,H-233*mm,150*mm,36*mm,'多元化子品牌','三级品牌，面向各个生活场景，实现文化与市场的无缝衔接。','三级品牌')
finish(c)

# 9 color library
start(c,'08 · 品牌素材资源库（一）','良渚色彩资源库','light')
card(c,17*mm,H-93*mm,176*mm,72*mm,'良渚色彩资源库','完整呈现良渚文化色彩系统研究成果，包含1100余组色彩数据、396种良渚特有颜色、8个良渚核心色、39个良渚原创色名，降低了跨领域品牌开发文创的学术门槛，提升开发效率。','COLOR SYSTEM')
colors_data=[('1100+','色彩数据'),('396','特有颜色'),('8','核心色'),('39','原创色名')]
for i,(num,lab) in enumerate(colors_data): stat(c,(17+i*46)*mm,H-163*mm,40*mm,43*mm,num,lab)
# palette separated from text
palette=[(JADE_DARK,'璧青'),(JADE,'玉绿'),(JADE_SOFT,'浅玉'),(GOLD,'琮黄'),(CINNABAR,'玉沁')]
for i,(col,name) in enumerate(palette):
    x=(31+i*31)*mm; y=H-220*mm
    c.setFillColor(col); c.roundRect(x,y,21*mm,21*mm,4*mm,stroke=0,fill=1)
    c.setFont(FONT,8); c.setFillColor(INK); c.drawCentredString(x+10.5*mm,y-7*mm,name)
finish(c)

# 10 pattern library
start(c,'09 · 品牌素材资源库（二）','良渚纹样基因库','light')
card(c,17*mm,H-96*mm,176*mm,78*mm,'良渚纹样基因库','经科学系统性梳理、标准化提取与数字化建档的良渚纹样专有矢量数据库。近百组良渚纹样数据均包含器型图、器型展开图、线稿、色板、单体纹样、高清图片、纹样属性信息等全套信息。','PATTERN SYSTEM')
bullet_panel(c,17*mm,H-196*mm,84*mm,'纹样数据内容',['器型图与器型展开图','线稿、色板与单体纹样','高清图片与纹样属性信息'])
bullet_panel(c,109*mm,H-196*mm,84*mm,'可支持开发环节',['产品开发与包装设计','礼盒视觉与空间陈列','文创衍生与品牌传播'])
finish(c)

# 11 authorization forms
start(c,'10 · 品牌授权形式','特定品类授权、联合开发、跨界联名','light')
card(c,17*mm,H-86*mm,176*mm,48*mm,'特定品类授权','开放特定品类版权授权，合作方依托良渚IP设计、生产与市场化运作，借力品牌影响力赋能产品市场竞争力与商业价值提升。代表性案例：良渚博物院授予周大福贵金属品类独家IP授权，联合打造良渚文化系列饰品。','01')
card(c,17*mm,H-153*mm,176*mm,48*mm,'联合开发','以双方资源整合、优势互补为基础，共同投入要素开展项目共创，实行风险共担、成果共享机制，通过协同创新实现品牌价值跃升。代表性案例：良渚玉器精灵系列盲盒、良渚·萌兽探琮-毛绒盲盒等产品荣获“文博会礼物·新锐奖”。','02')
card(c,17*mm,H-224*mm,176*mm,54*mm,'跨界联名','合作模式以多品牌跨界协同开展市场运营为主，通过联名产品共创、品牌活动联动，实现客群互通、优势互补与品牌势能叠加。代表性案例：良渚文化×特步联名系列产品，将良渚标志性纹样和色彩融入特步新一代缓震旗舰跑鞋青云2.0及跑服设计。','03')
finish(c)

# 12 examples
start(c,'11 · 代表性合作案例','多元跨界形式让良渚IP与当代生活深度共鸣','split')
card(c,17*mm,H-83*mm,84*mm,62*mm,'周大福贵金属品类独家IP授权','良渚博物院授予周大福贵金属品类独家IP授权，联合打造满足文化收藏价值和实用价值双重属性的良渚文化系列饰品。','贵金属')
card(c,109*mm,H-83*mm,84*mm,62*mm,'良渚玉器精灵 / 萌兽探琮','通过文物“萌化”“生活化”，完成从“文化标识”到“萌符号”的符码转译；相关系列产品荣获“文博会礼物·新锐奖”。','联合开发')
card(c,17*mm,H-165*mm,84*mm,66*mm,'良渚文化 × 特步','提取良渚文化核心视觉基因，将良渚标志性纹样和色彩融入青云2.0及跑服设计，创造兼具东方美学辨识度与专业运动性能的产品。','运动鞋服')
card(c,109*mm,H-165*mm,84*mm,66*mm,'多品类跨界合作','良渚博物院积极联动各界优质品牌，先后与特步、甘之颐、塔牌黄酒、小糊涂仙、慕江南等品牌携手合作。','品牌联动')
finish(c)

# 13 rights and policy
start(c,'12 · 良渚文化IP合作征集','分层权益支持 + 年度奖励激励','light')
card(c,17*mm,H-83*mm,176*mm,56*mm,'良渚文化品牌合作权益清单','围绕“分层权益支持+年度奖励激励”的原则，构建并正式发布《良渚文化品牌合作权益清单》，精准提供差异化支持，以覆盖不同合作层级企业的需求。')
card(c,17*mm,H-152*mm,84*mm,52*mm,'2026年良渚文创共创权益政策','推出2026年良渚文创共创权益政策，给予合作方最高礼遇、实施最好政策、提供最优服务。','权益政策')
card(c,109*mm,H-152*mm,84*mm,52*mm,'全链条赋能','从官方活动的VIP受邀到自有空间的免费使用，从官方渠道的精准宣传到核心美学基因库的全面开放。','支持体系')
table(c,[['权益方向','内容'],['活动礼遇','官方活动VIP受邀'],['空间支持','自有空间免费使用'],['传播支持','官方渠道精准宣传'],['素材支持','核心美学基因库开放']],17*mm,H-225*mm,[45*mm,131*mm],'rights table')
finish(c)

# 14 invitation
start(c,'13 · 良渚文创共创合作征集','共商品牌授权、合作开发、招商入驻等多元合作','dark')
draw_text(c,'良渚文化，是历史的厚重书卷，更是时代的鲜活IP。',17*mm,H-76*mm,168*mm,25*mm,'h2_d','invitation lead')
card(c,17*mm,H-137*mm,176*mm,58*mm,'面向社会广泛征集','良渚文创招募共创合作伙伴，面向社会广泛征集文创合作意向及设计开发方案，向拥有文创梦想的优质企业、高校设计团队及个人发出诚挚邀请，共创兼具文化价值、时代特色、当代审美的文创产品，共绘良渚文创发展新图景。','CO-CREATION',True)
card(c,17*mm,H-209*mm,176*mm,48*mm,'合作方式','欢迎以产品授权、合作开发、联名推广等多种方式加入共创计划，实现资源共享、产品共创、市场共拓、品牌共铸。','JOIN THE PLAN',True)
c.setFillColor(colors.Color(1,1,1,.10)); c.setStrokeColor(colors.Color(1,1,1,.22)); c.roundRect(17*mm,35*mm,176*mm,33*mm,6*mm,stroke=1,fill=1)
draw_text(c,'文创设计、IP联名合作意向可扫描良渚文创二维码联系',25*mm,57*mm,120*mm,14*mm,'lead_d','qr text')
c.setFillColor(colors.Color(1,1,1,.16)); c.roundRect(156*mm,41*mm,20*mm,20*mm,3*mm,stroke=0,fill=1)
for i in range(5):
    for j in range(5):
        if (i*j+i+j)%3==0:
            c.setFillColor(colors.Color(1,1,1,.48)); c.rect((158.5+i*3.2)*mm,(43.5+j*3.2)*mm,1.9*mm,1.9*mm,stroke=0,fill=1)
finish(c)

c.save()
LOG.write_text('\n'.join(warnings) if warnings else 'NO_LAYOUT_WARNINGS', encoding='utf-8')
print(OUT)
print(OUT.exists(), OUT.stat().st_size)
print(LOG)
print(LOG.read_text(encoding='utf-8'))
