Every multi-board template laid its boards out in one long horizontal strip, so opening a seven-board carousel dropped the user onto a canvas they had to pan sideways to survey. Three per row matches the deck kit, and the extra row gap is deliberate: the canvas draws frame names at a fixed screen-space offset, so at fit-to-screen zoom a plain column gap lets the second row's labels sit on top of the boards above them. knowledge-carousel additionally takes hard line breaks in two body paragraphs. Greedy wrapping put a comma at the start of a line and left a lone full stop on the last one, which are both CJK line-break faults; authored breaks remove the engine's freedom to reintroduce them. Claude-Session: https://claude.ai/code/session_01FqKQqNj8exYwopGDpYUU7x
480 lines
21 KiB
Python
480 lines
21 KiB
Python
#!/usr/bin/env python3
|
||
"""toolkit-notebook-carousel.op — 干货合集轮播(6 板 · 1080×1440 · 3:4)
|
||
|
||
叙事类型:**合集**(工具 / 资源 N 选)。合集档的读者目的很单一:**收藏**。
|
||
所以本套的每一板都在为最后那板目录服务 —— 第 6 板把六个工具连页码一起列
|
||
出来,是全套收藏率最高的一页(card-system §4.1 G 族:一套 ≥6 板时 G3 优先
|
||
于 G2)。
|
||
|
||
合集最容易失败的地方是「列了十个,一个都没记住」。本套的解法是**在中间插
|
||
一板对照表**:第 3 板让读者先做一次选择,后面三个工具他才会带着「我该用
|
||
哪个」的问题去读,而不是从头滑到尾。
|
||
|
||
### 主题:T7 荧光笔记 `highlighter-notebook`(亮 / 中性偏大胆 / 干货·学习)
|
||
|
||
**采样 → 收敛 → 论证**(沿用 card-system-0808 §3 T7)
|
||
|
||
- 采样:复印纸白、浅蓝网格线、圆珠笔蓝黑(不是黑)、荧光笔黄/薄荷/粉、
|
||
红笔。
|
||
- 收敛:底 = 近白 L0.985;文字 = 蓝黑序列(H265,带 chroma);高亮三支
|
||
L 0.87-0.92(高明度低对比,因为荧光笔是半透明覆盖);红笔为独立点睛。
|
||
- 论证 1:**荧光色的 chroma 压到 0.06-0.145 而非屏幕荧光的 0.25+** ——
|
||
真实荧光笔在纸上是半透明的,饱和度被纸色稀释。压过的荧光才像「笔迹」,
|
||
不压的是「色块」。**这一条是整套主题成立与否的唯一关键。**
|
||
- 论证 2:**文字用蓝黑 `#212939` 而非纯黑** —— 圆珠笔的墨是蓝黑的,这是
|
||
「手写笔记」与「印刷品」的分野。选它承载干货合集:读者要的就是「别人
|
||
的复习笔记」,那是中文语境里可信度最高的干货形态。
|
||
|
||
**最近邻论证**:库里最近的亮底是本批的 `grid-hanzi`(纯白 #FFFFFF,零装
|
||
饰、零圆角、单支信号红)。两者都近白,分野在 chroma 与装饰:本套底
|
||
`#FAFAF8` 是 L0.985 C0.002 的暖白,且有横格线、页边红线、三支高亮带;那套
|
||
是 L1.0 C0 的纯白加一个红方块。缩略图里一张有横纹一张全空,立刻分得开。
|
||
|
||
### 母版规则(六板的硬约束)
|
||
|
||
**每板固定,不许变**
|
||
1. 画幅 1080×1440,安全边距 左右 80 / 上 96 / 下 128。左侧另留 40px 给
|
||
页边红线的呼吸,正文左界 152。
|
||
2. **横格线**:整板 30 道 48px 间距的浅蓝横线,压在内容之下。它是「这是
|
||
一本笔记」的物理依据,六板一道不差。
|
||
3. **页边红线**:距左缘 1 个列宽(112px)的一条 2px 竖线,贯穿全板。
|
||
4. 页眉:左「工具合集 · 六板」,右「NN / 06」(Inter,Caption 32px)。
|
||
5. 页脚:署名 + 本板提要,贴下安全边距。
|
||
6. 字族:汉字 Noto Sans SC / 数字与页码 Inter。
|
||
7. 一板最多两支高亮色。
|
||
|
||
**允许变,且只有这些能变**
|
||
- 主体区的信息结构(下面六板各用一条配方)。
|
||
- 当板用哪两支高亮色(黄 / 薄荷 / 粉轮转)。
|
||
- **红笔批注**:每板最多一处,且 ≤8 字。
|
||
- **便利贴**:整套只用一次,落在第 4 板的清单顶上。
|
||
|
||
### 配方编排(card-system-0808 §4.2)
|
||
|
||
01 A6 三行阶梯 → 02 C1 编号纵列 → 03 E3 表格两列
|
||
04 C3 勾选清单 → 05 B3 高亮切词 → 06 G3 目录回看
|
||
|
||
首板 A 族、末板 G 族;相邻两板不同族;覆盖 A/C/E/B/G 五族;C 族出现 2 次
|
||
但不相连(第 2、4 板);B 族 1 次且落在后 1/3(第 5 板)。
|
||
|
||
### 负约束(本模板明令不做的事)
|
||
|
||
- **高亮带永远不满行高、不满宽**。它只盖住字的下 55%、左右各多 8px ——
|
||
荧光笔盖住的是字的下半部,盖满全高就变成色块底,整套主题当场失效。
|
||
- **一板最多两支高亮色**。三支齐出就成了彩虹配色,那是本主题的死线。
|
||
- **红笔只用于圈画与短批注(≤8 字),不排正文**。红笔一旦排成句子,它
|
||
就从「批注」变成了「第二种正文」。
|
||
- 不用马克笔粗涂效果、不用手写体排正文、不用便签的立体投影。
|
||
- 不写「N 个神器 / 效率翻倍 / 打工人必备」这类词。合集的说服力来自「什
|
||
么时候用它」,不来自形容词。
|
||
- 每板正文不超过 4 行;工具条目每条注解 ≤1 行。
|
||
|
||
硬契约:
|
||
- 字号下限 32px;单板最多用 4 档字阶。
|
||
- CJK 行高:Display 1.15 / Title 1.3 / Body 1.7 / Caption 1.5。
|
||
- CJK 字距恒为 0。
|
||
- 正文与背景对比度 ≥2.0(实测表见文件末尾)。
|
||
- 顶层 frame 必须显式写 x/y。
|
||
- 文本节点绝不写 height。
|
||
"""
|
||
|
||
import os
|
||
import sys
|
||
|
||
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
||
|
||
from oplib import (Ids, color_vars, frame, group, rect, solid, text,
|
||
write_doc)
|
||
|
||
ids = Ids()
|
||
|
||
VARS = color_vars({
|
||
"c-bg": "#FAFAF8", # paper 复印纸白
|
||
"c-panel": "#EFF2F4", # paper.panel 分区块
|
||
"c-grid": "#D6DFE6", # grid 横格线
|
||
"c-margin": "#E9B5B4", # rule.margin 页边红线
|
||
"c-ink": "#212939", # ink.pen 主文字(圆珠笔蓝黑)
|
||
"c-soft": "#545B6A", # ink.soft 次级文字
|
||
"c-faint": "#69707F", # ink.faint 注释 / 页码
|
||
"c-yellow": "#FBE76B", # hl.yellow 高亮黄
|
||
"c-mint": "#A5F3C0", # hl.mint 高亮薄荷
|
||
"c-pink": "#F8C5CD", # hl.pink 高亮粉
|
||
"c-red": "#C33939", # redpen 红笔批注
|
||
"c-sticky": "#F7E8AF", # sticky 便利贴
|
||
})
|
||
|
||
CJK = "Noto Sans SC"
|
||
NUM = "Inter"
|
||
|
||
W, H, GAP = 1080, 1440, 120
|
||
|
||
# 3 板一行 —— 与 deck 体系(deckkit.BOARDS_PER_ROW)同一约定:多板模板在画布上
|
||
# 分行铺开,而不是拖成一长排。行间距比列间距多 240 不是手滑:画布在帧上方以
|
||
# **屏幕空间**固定偏移画帧名,缩到能整屏看时 120 文档像素只剩十几个屏幕像素,
|
||
# 第二行的帧名会压到上一行的板上。
|
||
BOARDS_PER_ROW = 3
|
||
ROW_GAP = GAP + 240
|
||
EDGE = 80
|
||
MARGIN_X = 112 # 页边红线的位置 = 1 个列宽
|
||
TEXT_EDGE = 152 # 正文左界,留出红线的呼吸
|
||
TOP, BOT = 96, 128
|
||
INNER = W - TEXT_EDGE - EDGE # 848
|
||
COLUMN, GUTTER = 62, 16
|
||
|
||
FS_DISPLAY, FS_T1, FS_T2 = 88, 64, 48
|
||
FS_BODY, FS_CAPTION = 40, 32
|
||
LH_DISPLAY, LH_TITLE, LH_BODY, LH_CAPTION = 1.15, 1.3, 1.7, 1.5
|
||
|
||
SERIES = "工具合集 · 六板"
|
||
TOTAL = 6
|
||
RULE_STEP = 48
|
||
|
||
|
||
# ----------------------------------------------------------------- 结构原语
|
||
def col(name, children, *, gap=16, width="fill_container", align="start",
|
||
height="fit_content", **props):
|
||
node = frame(ids, name, width=width, height=height, layout="vertical",
|
||
gap=gap, alignItems=align, fill=[], **props)
|
||
node["children"] = children
|
||
return node
|
||
|
||
|
||
def row(name, children, *, gap=24, align="center", width="fill_container",
|
||
justify="start", **props):
|
||
node = frame(ids, name, width=width, height="fit_content",
|
||
layout="horizontal", gap=gap, alignItems=align,
|
||
justifyContent=justify, fill=[], **props)
|
||
node["children"] = children
|
||
return node
|
||
|
||
|
||
def caption(name, content, color="$c-faint", *, family=CJK, weight=400,
|
||
width="fit_content", align=None):
|
||
return text(ids, name, content, FS_CAPTION, weight, color, family=family,
|
||
width=width, growth="auto" if width == "fit_content"
|
||
else "fixed-width", line_height=LH_CAPTION, align=align)
|
||
|
||
|
||
def body(name, content, color="$c-soft", *, weight=400,
|
||
width="fill_container"):
|
||
return text(ids, name, content, FS_BODY, weight, color, family=CJK,
|
||
width=width, growth="auto" if width == "fit_content"
|
||
else "fixed-width", line_height=LH_BODY)
|
||
|
||
|
||
# ----------------------------------------------------------------- 笔记语汇
|
||
HL_COVER, HL_INK = 0.55, 0.45 # 高亮带只占行高的下 55%,从上方 45% 处起
|
||
HL_BLEED = 8 # 左右各多出 8px,正是荧光笔划过头的那一点
|
||
|
||
|
||
def highlight(word, size, color, *, weight=700, ink="$c-ink"):
|
||
"""荧光高亮:一段只盖住字下半部的色带,压在字**之下**。
|
||
|
||
这是本主题唯一不能省事的构造。把 `fill` 直接给文字的容器就是满行高的
|
||
色块 —— 那不是荧光笔,是底色。所以退到 `layout:none` 手工叠:色带按行
|
||
盒高度的 45% 起、占 55%,左右各外溢 8px,字压在它上面。
|
||
children[0] 画在最上层,所以顺序是 文字 → 色带。
|
||
"""
|
||
line_box = round(size * 1.0)
|
||
box_w = len(word) * size + HL_BLEED * 2
|
||
box = group(ids, f"高亮 · {word}", width=box_w, height=line_box,
|
||
layout="none", fill=[])
|
||
glyphs = text(ids, "高亮文字", word, size, weight, ink, family=CJK,
|
||
width=len(word) * size, growth="fixed-width",
|
||
line_height=1.0)
|
||
glyphs["x"], glyphs["y"] = HL_BLEED, 0
|
||
band = rect(ids, "荧光带", width=box_w,
|
||
height=round(line_box * HL_COVER), fill=solid(color))
|
||
band["x"], band["y"] = 0, round(line_box * HL_INK)
|
||
box["children"] = [glyphs, band]
|
||
return box
|
||
|
||
|
||
def redpen(note):
|
||
"""红笔批注。≤8 字是硬约束 —— 超过就不是批注,是第二种正文。"""
|
||
assert len(note) <= 8, f"红笔批注 {note!r} 超过 8 字"
|
||
return caption("红笔批注", note, "$c-red", weight=600)
|
||
|
||
|
||
def ruled_paper():
|
||
"""横格线 + 页边红线。六板逐板重建,位置由常量算出。"""
|
||
lines = []
|
||
for i in range(1, H // RULE_STEP):
|
||
line = rect(ids, f"横格 {i}", width=W, height=1,
|
||
fill=solid("$c-grid"))
|
||
line["x"], line["y"] = 0, i * RULE_STEP
|
||
lines.append(line)
|
||
margin = rect(ids, "页边红线", width=2, height=H, fill=solid("$c-margin"))
|
||
margin["x"], margin["y"] = MARGIN_X, 0
|
||
return lines + [margin]
|
||
|
||
|
||
# ----------------------------------------------------------------- 母版部件
|
||
def header(page):
|
||
return row("页眉", [
|
||
caption("系列名", SERIES, "$c-faint"),
|
||
caption("页码", f"{page:02d} / {TOTAL:02d}", "$c-faint", family=NUM),
|
||
], gap=24, justify="space_between")
|
||
|
||
|
||
def footer(note):
|
||
return row("页脚", [
|
||
caption("账号名", "@ 你的账号名", "$c-soft", weight=600),
|
||
caption("本板提要", note, "$c-faint"),
|
||
], gap=24, justify="space_between")
|
||
|
||
|
||
def board(page, name, main, note):
|
||
"""一板。横格纸在最底层,正文压在上面 —— 纸永远不盖字。"""
|
||
content = frame(ids, f"{name} · 内容", width="fill_container",
|
||
height="fill_container", layout="vertical",
|
||
padding=[TOP, EDGE, BOT, TEXT_EDGE], gap=0,
|
||
alignItems="start", fill=[])
|
||
content["children"] = [header(page), main, footer(note)]
|
||
|
||
paper = frame(ids, f"{name} · 横格纸", width="fill_container",
|
||
height="fill_container", layout="none", fill=[])
|
||
paper["children"] = ruled_paper()
|
||
|
||
shell = frame(ids, f"{page:02d} {name}", width=W, height=H, layout="none",
|
||
fill=solid("$c-bg"), clipContent=True)
|
||
shell["children"] = [content, paper]
|
||
shell["x"] = ((page - 1) % BOARDS_PER_ROW) * (W + GAP)
|
||
shell["y"] = ((page - 1) // BOARDS_PER_ROW) * (H + ROW_GAP)
|
||
return shell
|
||
|
||
|
||
def zone(children, *, justify="center", gap=32, pad_y=44):
|
||
node = frame(ids, "主体", width="fill_container", height="fill_container",
|
||
layout="vertical", gap=gap, padding=[pad_y, 0],
|
||
justifyContent=justify, alignItems="start", fill=[])
|
||
node["children"] = children
|
||
return node
|
||
|
||
|
||
# ------------------------------------------------------- 01 封面 · A6 三行阶梯
|
||
def cover():
|
||
"""A6:三行逐行缩进一列,第 2 行被荧光笔划中 —— 缩进 + 高亮双重立层级。"""
|
||
lines = [
|
||
text(ids, "标题行", "整理了半年", FS_DISPLAY, 700, "$c-ink",
|
||
family=CJK, width=INNER, growth="fixed-width",
|
||
line_height=LH_DISPLAY),
|
||
highlight("六个工具", FS_DISPLAY, "$c-yellow"),
|
||
text(ids, "标题行", "只留下这些", FS_DISPLAY, 700, "$c-ink",
|
||
family=CJK, width=INNER - (COLUMN + GUTTER) * 2,
|
||
growth="fixed-width", line_height=LH_DISPLAY),
|
||
]
|
||
ladder = []
|
||
for index, node in enumerate(lines):
|
||
wrap = row(f"阶梯行 {index + 1}", [node], gap=0, align="start")
|
||
if index:
|
||
wrap["padding"] = [0, 0, 0, (COLUMN + GUTTER) * index]
|
||
ladder.append(wrap)
|
||
|
||
main = zone([
|
||
row("眉标行", [
|
||
caption("眉标", "写作 · 阅读 · 归档", "$c-soft", weight=600),
|
||
redpen("先看第 3 板"),
|
||
], gap=20),
|
||
col("三行阶梯", ladder, gap=10),
|
||
body("副标", "每个只讲一句:什么时候该用它。", "$c-soft"),
|
||
], justify="center", gap=34)
|
||
return board(1, "封面 · 三行阶梯", main, "封面")
|
||
|
||
|
||
# ------------------------------------------------------- 02 前三 · C1 编号纵列
|
||
TOOLS_A = [
|
||
("01", "先记后整理的笔记本", "想到什么先扔进去,晚上再归位。"),
|
||
("02", "只做一件事的写作器", "全屏、无栏、不能插图,逼你写完。"),
|
||
("03", "自动归档的稍后读", "存进去就不用管,它按主题替你分。"),
|
||
]
|
||
|
||
|
||
def first_three():
|
||
"""C1:编号 2 列 + 内容 10 列。引导符一板只用一种 —— 这里是数字编号。"""
|
||
items = []
|
||
for no, title, note in TOOLS_A:
|
||
items.append(row("工具", [
|
||
text(ids, "编号", no, FS_T1, 700, "$c-faint", family=NUM,
|
||
width=COLUMN * 2, growth="fixed-width", line_height=1.0,
|
||
spacing=-2),
|
||
col("工具文案", [
|
||
text(ids, "工具名", title, FS_T2, 700, "$c-ink", family=CJK,
|
||
width=INNER - COLUMN * 2 - 24, growth="fixed-width",
|
||
line_height=LH_TITLE),
|
||
body("工具注解", note, "$c-soft",
|
||
width=INNER - COLUMN * 2 - 24),
|
||
], gap=10, width=INNER - COLUMN * 2 - 24),
|
||
], gap=24, align="start"))
|
||
|
||
main = zone([
|
||
text(ids, "小标题", "先说每天都开的三个", FS_T1, 700, "$c-ink",
|
||
family=CJK, line_height=LH_TITLE),
|
||
col("工具列表", items, gap=40),
|
||
], justify="center", gap=40)
|
||
return board(2, "前三 · 编号纵列", main, "工具 1-3")
|
||
|
||
|
||
# ------------------------------------------------------- 03 对照 · E3 表格两列
|
||
TABLE = [
|
||
("想快点开始", "先记后整理", "只做一件事"),
|
||
("怕丢东西", "自动归档", "先记后整理"),
|
||
("要写长文", "只做一件事", "自动归档"),
|
||
]
|
||
|
||
|
||
def compare():
|
||
"""E3:表头 2 列 + 两栏各 5 列,斑马底。
|
||
|
||
E 族硬规则:对比双方的版式必须**完全相同**,只允许一个变量不同。这里
|
||
两栏字号、字重、对齐、内边距全同,唯一的差别是「首选」那一列被荧光笔
|
||
划过 —— 结论位按中文阅读习惯放在右边。
|
||
"""
|
||
head = row("表头", [
|
||
caption("表头 · 场景", "你的情况", "$c-soft", weight=600,
|
||
width=COLUMN * 4, align="left"),
|
||
caption("表头 · 次选", "也行", "$c-soft", weight=600,
|
||
width=COLUMN * 4, align="left"),
|
||
caption("表头 · 首选", "首选", "$c-ink", weight=600,
|
||
width=COLUMN * 4, align="left"),
|
||
], gap=GUTTER, align="center")
|
||
|
||
rows = [head, rect(ids, "表头线", width="fill_container", height=2,
|
||
fill=solid("$c-ink"))]
|
||
for index, (case, second, first) in enumerate(TABLE):
|
||
line = row(f"表行 {index + 1}", [
|
||
caption("场景", case, "$c-ink", width=COLUMN * 4, align="left"),
|
||
caption("次选", second, "$c-faint", width=COLUMN * 4,
|
||
align="left"),
|
||
caption("首选", first, "$c-ink", weight=600, width=COLUMN * 4,
|
||
align="left"),
|
||
], gap=GUTTER, align="center", padding=[18, 14])
|
||
if index % 2 == 0:
|
||
line["fill"] = solid("$c-panel")
|
||
rows.append(line)
|
||
|
||
main = zone([
|
||
text(ids, "小标题", "先选,再往下看", FS_T1, 700, "$c-ink",
|
||
family=CJK, line_height=LH_TITLE),
|
||
col("对照表", rows, gap=0),
|
||
redpen("按场景挑"),
|
||
], justify="center", gap=32)
|
||
return board(3, "对照 · 表格两列", main, "怎么选")
|
||
|
||
|
||
# ------------------------------------------------------- 04 后三 · C3 勾选清单
|
||
TOOLS_B = [
|
||
"04 剪贴板历史:复制过的都还在",
|
||
"05 批量重命名:一次改完一整年",
|
||
"06 定时断网器:到点就切,不商量",
|
||
]
|
||
|
||
|
||
def last_three():
|
||
"""C3:单列勾选框,每条 1 行。便利贴在这里出现整套唯一一次。"""
|
||
items = []
|
||
for line in TOOLS_B:
|
||
box = rect(ids, "勾选框", width=34, height=34, cornerRadius=2,
|
||
fill=[], stroke={"thickness": 3, "fill": solid("$c-ink")})
|
||
items.append(row("清单项", [
|
||
box,
|
||
body("清单文字", line, "$c-ink", width=INNER - 34 - 22 - 60),
|
||
], gap=22, align="center"))
|
||
|
||
sticky = frame(ids, "便利贴", width="fit_content", height="fit_content",
|
||
layout="horizontal", padding=[16, 26], cornerRadius=2,
|
||
alignItems="center", fill=solid("$c-sticky"))
|
||
sticky["children"] = [
|
||
caption("便利贴文字", "这三个装了就忘,属于后台", "$c-ink",
|
||
weight=600),
|
||
]
|
||
|
||
panel = col("清单面板", items, gap=24, padding=[32, 30])
|
||
panel["fill"] = solid("$c-panel")
|
||
|
||
main = zone([
|
||
text(ids, "小标题", "剩下三个装了就忘", FS_T1, 700, "$c-ink",
|
||
family=CJK, line_height=LH_TITLE),
|
||
sticky,
|
||
panel,
|
||
], justify="center", gap=28)
|
||
return board(4, "后三 · 勾选清单", main, "工具 4-6")
|
||
|
||
|
||
# ------------------------------------------------------- 05 原则 · B3 高亮切词
|
||
def principle():
|
||
"""B3:被击中的词先出来,整句在后,注解压到 Caption。
|
||
|
||
这一板换薄荷色 —— 封面用过黄,本板换一支,全套六板每支高亮各出现两次,
|
||
没有哪一支变成第二个主色。
|
||
"""
|
||
main = zone([
|
||
highlight("装得少", FS_DISPLAY, "$c-mint"),
|
||
text(ids, "整句", "工具越多,你花在挑工具上的时间也越多。",
|
||
FS_T1, 700, "$c-ink", family=CJK, width=INNER,
|
||
growth="fixed-width", line_height=LH_TITLE),
|
||
caption("注解", "六个是上限不是目标,能砍到四个更好。", "$c-soft",
|
||
width=INNER),
|
||
], justify="center", gap=38)
|
||
return board(5, "原则 · 高亮切词", main, "复述点")
|
||
|
||
|
||
# ------------------------------------------------------- 06 目录 · G3 目录回看
|
||
INDEX = [
|
||
("02", "先记后整理的笔记本"),
|
||
("02", "只做一件事的写作器"),
|
||
("02", "自动归档的稍后读"),
|
||
("04", "剪贴板历史"),
|
||
("04", "批量重命名"),
|
||
("04", "定时断网器"),
|
||
]
|
||
|
||
|
||
def recap():
|
||
"""G3:单列 11 列,每行「页码 + 标题」。一套 ≥6 板时它优先于三键引导。
|
||
|
||
收藏率最高的一页,所以它必须**可扫**:页码用 Inter 等宽感排在左,标题
|
||
左对齐成一柱,读者截图之后照着找得回去。
|
||
"""
|
||
lines = []
|
||
for page, title in INDEX:
|
||
lines.append(row("目录行", [
|
||
text(ids, "回看页码", f"第 {page} 板", FS_CAPTION, 600,
|
||
"$c-faint", family=NUM, width=COLUMN * 3,
|
||
growth="fixed-width", line_height=LH_CAPTION),
|
||
body("回看标题", title, "$c-ink",
|
||
width=INNER - COLUMN * 3 - 24),
|
||
], gap=24, align="center"))
|
||
|
||
main = zone([
|
||
text(ids, "收束句", "六个,\n照着这张表回看。", FS_DISPLAY, 700,
|
||
"$c-ink", family=CJK, width=INNER, growth="fixed-width",
|
||
line_height=LH_DISPLAY),
|
||
col("目录", lines, gap=18),
|
||
], justify="center", gap=40)
|
||
return board(6, "目录 · 回看", main, "收藏这板")
|
||
|
||
|
||
def build():
|
||
return [cover(), first_three(), compare(), last_three(), principle(),
|
||
recap()]
|
||
|
||
|
||
# 对比度(WCAG 相对亮度比,op-design-lint 门槛 2.0;本表逐对实算):
|
||
# c-ink on c-bg 13.95 c-soft on c-bg 6.52
|
||
# c-faint on c-bg 4.76 c-red on c-bg 5.07
|
||
# c-ink on c-panel 12.96 c-soft on c-panel 6.06
|
||
# c-faint on c-panel 4.42 c-ink on c-yellow 11.62
|
||
# c-ink on c-mint 11.23 c-ink on c-pink 9.62
|
||
# c-ink on c-sticky 11.88 c-grid on c-bg 1.29
|
||
# c-margin on c-bg 1.71
|
||
# 承载正文的最低一对是 c-faint on c-panel 4.42(第 3 板对照表「次选」那一
|
||
# 列的斑马行)—— 那是「次选」,本就该退后半档,仍高出 lint 门槛 2.2 倍;
|
||
# 其余承载正文处最低 4.76,已过 WCAG AA 正文门槛。三支高亮色承载 c-ink 都在 9.6 以上
|
||
# —— 这正是「荧光色压 chroma、保高明度」那条论证的回报:既像笔迹,又不牺
|
||
# 牲一点可读性。c-grid 1.29 与 c-margin 1.71 低于门槛是对的:一个是 1px
|
||
# 横格、一个是 2px 页边线,都属非文字图形,本模板明令它们永不承载文字。
|
||
|
||
if __name__ == "__main__":
|
||
write_doc(sys.argv[1], VARS, build(), "干货合集轮播 · 3:4 六板")
|