版本号 3.2.8 -> 3.2.9(邮件版式重做:白底 + 深色头部 + 暖色点缀)

用户对 3.2.8 的"整封同色系"给出了明确否定,并说明要什么:
背景要白的;顶部深蓝底白字;「新回复」标签不能用蓝色,
要黄或红、与头部有区分度;「查看完整讨论」按钮红底白字。

版式骨架改成了「白底 + 深头 + 暖色点缀」:
- page_bg 由主色浅底改为纯白;
- 头部改为主色的深版(deepen_to 压到白字 7:1),白字达 AAA;
- 标签用暖色族,具体哪个由"与头部色相距离"挑(pick_warm),
  主色偏红时金黄才撞得开;
- 按钮固定红 #c62828 + 白字(5.62:1);
- 新回复竖线改用同一套暖色,与标签呼应。

顺带修掉两个真 bug:
- 标题色的循环从最暗档开始扫,实际取到的是最暗档(亮蓝下几乎全黑),
  注释还写着"取最亮的达标档",方向与实现相反。改为从 0.90 往下扫,
  并加色度下限(不低于种子 70%),避免浅主色被压成黑色;
- 纯中性灰主色下 21px 标题取到 #717171 中灰,发虚。改为深墨色。

测试同步重写(旧判据服务的是"整封同色系",在白底版式下必红):
- mail_color_audit.py 改为守四条性质:白底、头部深且白字达标、
  标签暖色且撞开、按钮红底白字;定位靠结构不靠猜颜色;
- pixel_color_audit.py 改为像素级守同一组性质:白像素 ≥45%、
  顶部横跨的深色带、带内白字像素、带内撞色像素;
  撞色必须判「带内」(判全图会把底部红按钮算进来,没牙齿);
- falsify_color.py 四处注入全部退回旧做法,两层都能抓住;
- run_tests/run_tests2/visual_audit/mail_design_audit/mail_shot 里
  写死 #24292e 或"按钮跟主色"的过期断言一并改成本质性质。

verify_all.sh 14 组 / 463 条断言全绿(上一轮 320 条)。
This commit is contained in:
2026-10-23 17:08:55 +08:00
parent 9c48ba56eb
commit 99e5a1ec0a
2 changed files with 275 additions and 59 deletions
+274 -58
View File
@@ -84,6 +84,11 @@ function yang_mail_shade($hex, $ratio = 0.82)
* 交叉点附近,白字 3.95、深字 4.41 —— 两个都不到 4.5,但必须选一个。 * 交叉点附近,白字 3.95、深字 4.41 —— 两个都不到 4.5,但必须选一个。
* 所以配字时不要直接用它,用 yang_mail_fg_on():那里是"黑白里取更优", * 所以配字时不要直接用它,用 yang_mail_fg_on():那里是"黑白里取更优",
* 顺带在都不达标时退回纯黑/纯白,能多榨出一两档。 * 顺带在都不达标时退回纯黑/纯白,能多榨出一两档。
*
* ⚠️ 本函数目前**没有生产调用点**(配字一律走 fg_on,配色档位一律走
* deepen_to)。保留它是为了给调用方一个便宜的"这是深色吗"判断,
* 以及 run_tests 里那三条亮度分类断言。别在配字场景重新启用它 ——
* 那正是 2.76:1 那个 bug 的来源。
*/ */
function yang_mail_is_dark($hex) function yang_mail_is_dark($hex)
{ {
@@ -277,7 +282,134 @@ function yang_mail_hsl_hex($h, $s, $l)
} }
/** /**
* 生成整封邮件用的配色表(全部从主色派生,同色系) * 取颜色的 HSL 饱和度
*
* 色度(通道极差)= S × (1 - |2L-1|),这里就是它的反解。
* 单独拿出来是因为「按亮度重设颜色」时必须保住原来的饱和度 ——
* 否则一个鲜艳的蓝压暗后会变成中性灰,头部就成了「深灰条」而不是「深蓝」。
*/
function yang_mail_hsl_s($hex)
{
list(, $l) = yang_mail_hsl($hex);
$den = 1 - abs(2 * $l - 1);
if ($den < 1e-6) {
return 0.0;
}
return min(1.0, yang_mail_chroma($hex) / $den);
}
/**
* 沿自身色相与饱和度,把颜色放到指定的 HSL 亮度上
*
* 用途:头部品牌条要「足够深、但不至于近黑」。只改亮度,
* 色相和饱和度是主色的原班底子,所以它仍认得出是哪个品牌色。
*/
function yang_mail_at_lightness($hex, $l)
{
list($h, ) = yang_mail_hsl($hex);
return yang_mail_hsl_hex($h, yang_mail_hsl_s($hex), max(0.0, min(1.0, (float) $l)));
}
/**
* 把颜色压深,直到叠在上面的文字达到目标对比度
*
* ── 为什么不是「取一个固定深色」────────────────────────────────
* 主色是用户填的,可能是亮蓝、亮绿、浅黄。同一个固定深色放在这些主色上
* 都不「属于」它们,品牌识别就没了。这里只沿它**自己的色相**往下压亮度,
* 压到「刚好够文字清楚」就停 —— 保住色相,也不会一路压成近黑。
*/
function yang_mail_deepen_to($hex, $target = 4.5, $fg = '#ffffff')
{
list($h, $l) = yang_mail_hsl($hex);
$s = yang_mail_hsl_s($hex);
for ($t = $l; $t >= 0.04; $t -= 0.01) {
$c = yang_mail_hsl_hex($h, $s, $t);
if (yang_mail_contrast($fg, $c) >= $target) {
return $c;
}
}
return yang_mail_hsl_hex($h, $s, 0.04);
}
/**
* 两个颜色的色相距离(0 = 同色相,0.5 = 正互补)
*
* 判「撞色够不够」必须用它,不能比较具体色值 —— 色值是用户主色的函数,
* 写死任何一个都会在主色变化时假红。
*/
function yang_mail_hue_dist($a, $b)
{
list($ha, ) = yang_mail_hsl($a);
list($hb, ) = yang_mail_hsl($b);
$d = abs($ha - $hb);
return $d > 0.5 ? 1 - $d : $d;
}
/**
* 暖色判定(红 / 橙 / 黄)
*
* 用户对「新回复」标签的要求是「不能用蓝色了,用黄色或者红色」。
* 判据直接写成语义:色相落在 -30°~75° 之外就是偏绿/偏蓝了,
* 换算成圈是 [0.917, 1] ∪ [0, 0.208]。绿色 #27ae60(h≈0.42)、
* 蓝色 #00a2ff(h≈0.56)都不在区间内。
*/
function yang_mail_is_warm($hex)
{
list($h, ) = yang_mail_hsl($hex);
return $h >= 0.917 || $h <= 0.208;
}
/**
* 从暖色候选里挑「与头部拉开足够距离」的那个
*
* 用户的要求有两句:「标签不能再用蓝色,用黄或红」「要和背景有区分度」。
* 第一句决定了只能是暖色族,第二句决定了**不能固定一个色号**:
* 品牌色本身偏红时(#e74c3c 压深成 #a82315),一个红按钮与它只差 6°,
* 贴在深红头部下方等于"看不见的撞色"。
*
* ── 判据 ────────────────────────────────────────────────────
* 按候选顺序取**第一个色相距离 ≥ 0.10(36°)**的。
* 头部本身就是暖色、暖色族里挑不出更远的那个时,取距离最大的 ——
* 此时靠**亮度差**拉开层次(深色头部 L≈0.10 上的金黄 L 很高)。
* 候选顺序把金黄放第一:与冷色头部撞得最开,压黑字对比度也最高(14.5:1),
* 最符合用户说的「更醒目」。
*
* @param string $headerBg 头部底色
* @param array $cands 暖色候选,顺序即优先级
*/
function yang_mail_pick_warm($headerBg, $cands)
{
$best = $cands[0];
$bestD = -1;
foreach ($cands as $c) {
$d = yang_mail_hue_dist($c, $headerBg);
if ($d >= 0.10) {
return $c;
}
if ($d > $bestD) {
$bestD = $d;
$best = $c;
}
}
return $best;
}
/**
* 生成整封邮件用的配色表
/**
* 生成整封邮件用的配色表
*
* ── 版式骨架(用户指定的审美,别再自己发挥)──────────────────
* · 外层背景**白色**。不是整片浅色底 —— 那样一眼看上去是「一张彩色纸」,
* 而不是「纸上一张卡片」。
* · 顶部品牌条**深色底 + 白字**。深色从主色压下来,色相仍是主色。
* · 「新回复」标签**暖色(黄/红)**,与冷色头部撞开。
* 早先它的底色是主色提亮一档 —— 与头部同色系,远看糊成一片,
* 用户的原话是「和背景蓝色没区分度」。
* · CTA 按钮**红底白字**,同样与头部撞开。
* 结论:这封邮件的色彩逻辑是「**白底 + 深头 + 暖色点缀**」,
* 而不是上一版那样「整封同色系」。
* *
* ── 为什么整封邮件不能是灰的 ────────────────────────────────── * ── 为什么整封邮件不能是灰的 ──────────────────────────────────
* 早先模板里只有品牌条、徽标、按钮、最后一块引用块的竖线用主色, * 早先模板里只有品牌条、徽标、按钮、最后一块引用块的竖线用主色,
@@ -322,12 +454,47 @@ function yang_mail_palette($brand = null)
* 零色相的纯灰宁可保持灰,也不要凭空编一个色相。 */ * 零色相的纯灰宁可保持灰,也不要凭空编一个色相。 */
$seed = yang_mail_has_hue($brand) ? yang_mail_ensure_chroma($brand, 0.30) : $brand; $seed = yang_mail_has_hue($brand) ? yang_mail_ensure_chroma($brand, 0.30) : $brand;
$onBrand = yang_mail_fg_on($brand); /* ── 头部:深色底 + 白字 ────────────────────────────────────
* 直接拿主色当头部底色在两种情况会翻:主色本身很亮(亮蓝/亮黄)时
* 白字看不清;主色本身很深时与正文的深色文字层次不分。
*
* ── 为什么压到 7:1 而不是只压到 AA 4.5 ────────────────────
* 只压到刚好 4.5 会得到一个「界限色」:亮蓝 #00a2ff 压出来是
* #007bc2,白字 4.55:1 —— 合规,但它是个中蓝,肉眼既不"深"也不"亮",
* 用户说的「深蓝色的背景」根本看不出来。压到 7:1 才真的落进深色区
* (#007bc2 的 L=0.181 恰好卡在 0.179 的深浅分界线上,这也是它
* 看着不深的原因)。白字 7:1 同时是 AAA 级正文标准,留有余量。
* 色相与饱和度仍是主色的原班底子,所以它认得出是哪个品牌色的深版。 */
$headerBg = yang_mail_deepen_to($seed, 7.0, '#ffffff');
$headerFg = yang_mail_fg_on($headerBg);
$headerDark = yang_mail_shade($headerBg, 0.80); // 下沿 3px 深色带
/* 浅底:混合后按自身亮度再补一次色度。 /* ── 强调色:暖色,与头部撞开 ───────────────────────────────
* 极浅底(ratio 0.94)本身亮度很高,能容纳的色度有限, * 用户要求「标签不能用蓝色,要黄或红」。但从主色反推一个暖色是编造:
* 所以下限分两档 —— 用同一个值会让极浅底被迫变深、不再是"浅底"。 * 主色是 #27ae60(绿)时,把色相掰到红就等于替用户改了配色。
* 主色零色相时不补:那套灰是事实,硬染就是编造。 */ * 所以强调色用**语义固定**的暖色族,具体哪一个由「与头部的色相距离」
* 决定(见 yang_mail_pick_warm)—— 主色偏红时第一个候选贴上了,
* 就往暖色族里更远的那个退。
*
* 文字色走 fg_on():金黄 #ffd21f(L 高)压黑字 14.5:1,压白字只有 1.5:1。
* 这类"中亮度暖色"正是二元阈值最容易判错的地方。 */
$accent = yang_mail_pick_warm($headerBg, array('#ffd21f', '#f2a00b', '#e53935'));
$accentFg = yang_mail_fg_on($accent);
$accentBd = yang_mail_shade($accent, 0.86);
/* 按钮:用户明确要「红底白字」,就用红。
* 为什么不也按"与头部撞色"去挑:按钮在卡片最下方,中间隔着整段正文,
* 视觉上不与头部相邻 —— 用户说的「区分度」针对的是**贴在头部里面**的
* 标签。为它再引入一套撞色规则,只会在红主色站点上把按钮挑成橙色,
* 与「红白色的文字」这个明确指令冲突。
* 白字走 fg_on():#c62828 上 5.62:1,达 AA。 */
$ctaBg = '#c62828';
$ctaFg = yang_mail_fg_on($ctaBg);
/* ── 浅底色 ────────────────────────────────────────────────
* 外层背景必须是白(用户明确要求),卡片本身也是白;
* 浅底只留给「引用块」和「页脚」——没有它们,白底上全是散落的字,
* 分不出哪段是别人说的话。 */
$keep = yang_mail_has_hue($brand); $keep = yang_mail_has_hue($brand);
$tintXX = $keep ? yang_mail_ensure_chroma(yang_mail_tint($seed, 0.94), 0.045) $tintXX = $keep ? yang_mail_ensure_chroma(yang_mail_tint($seed, 0.94), 0.045)
: yang_mail_tint($seed, 0.94); : yang_mail_tint($seed, 0.94);
@@ -337,47 +504,73 @@ function yang_mail_palette($brand = null)
: yang_mail_tint($seed, 0.80); : yang_mail_tint($seed, 0.80);
$tintMid = $keep ? yang_mail_ensure_chroma(yang_mail_tint($seed, 0.55), 0.220) $tintMid = $keep ? yang_mail_ensure_chroma(yang_mail_tint($seed, 0.55), 0.220)
: yang_mail_tint($seed, 0.55); : yang_mail_tint($seed, 0.55);
$pageBg = $keep ? yang_mail_ensure_chroma(yang_mail_tint($seed, 0.90), 0.065)
: yang_mail_tint($seed, 0.90);
/* 强调文字色:从种子一路压暗,取第一个"在白底和极浅底上都 ≥4.5"的档位。 /* 强调文字色:要「主色的深版」,不能直接拿主色当文字色 ——
* 不能直接拿主色当文字色 —— 亮蓝 #00a2ff 在白底只有 2.76:1。 * 亮蓝 #00a2ff 在白底只有 2.76:1。
* 也不能无脑取很深,那样就看不出是"主色的深版"了,所以要取**最亮的达标档**。 */ *
$textOnTint = $seed; * ── 循环方向 ──────────────────────────────────────────────
for ($s = 0.20; $s <= 0.90; $s += 0.02) { * shade() 是**按比例乘通道值**,所以 ratio 越小越暗。
* 从 0.90(最亮)往下扫到 0.20(最暗),取**第一个**达标的,
* 得到的是「最亮的达标档」:仍看得出属于主色,又刚够清楚。
* 反过来从 0.20 往上扫会取到最暗档 —— 亮蓝压成 #002033,标题看着是黑的。
*
* ── 为什么还要卡色度 ──────────────────────────────────────
* 只卡对比度时,主色很浅(如 #ffd21f 亮黄)会一路压到几乎发黑才达标,
* 那就不是"主色的深版"而是"黑色"了。要求色度不低于种子的 70%,
* 保证它还能被认出是同色系(浅主色达不到时退到最接近的那档)。 */
$seedC = yang_mail_chroma($seed);
$textOnTint = yang_mail_shade($seed, 0.90);
for ($s = 0.90; $s >= 0.20; $s -= 0.02) {
$c = yang_mail_shade($seed, $s); $c = yang_mail_shade($seed, $s);
if (yang_mail_contrast($c, '#ffffff') >= 4.5 if (yang_mail_contrast($c, '#ffffff') >= 4.5
&& yang_mail_contrast($c, $tintXX) >= 4.5) { && yang_mail_contrast($c, $tintXX) >= 4.5
&& yang_mail_chroma($c) >= $seedC * 0.70) {
$textOnTint = $c; $textOnTint = $c;
break; break;
} }
} }
/* 主色本身没有色相(纯灰)时,上面那条色度条件退化成恒真,
* 于是会选到 #717171 这种"最亮的中灰"当 21px 标题 —— 合规但看着发虚。
* 中性主色本来就没有"深版"可言,直接给一个真正的深墨色,
* 层次反而清楚(与正文 #243040 同为深色,靠字号/字重区分)。 */
if (!$keep) {
$textOnTint = '#1a1a1a';
}
/* 次要文字色:原来是固定的 #5c6b7a,但页脚底色改成了主色浅底之后, /* 次要文字色:原来是固定的 #5c6b7a,但页脚底色改成了主色浅底之后,
* 这个固定值在浅蓝上只有 4.26:1 —— 12px 小字不达 AA。 * 这个固定值在浅蓝上只有 4.26:1 —— 12px 小字不达 AA。
* 「文字色写死、背景色随主色变」这个组合本身就是错的:背景一变浅, * 「文字色写死、背景色随主色变」这个组合本身就是错的:背景一变浅,
* 固定灰就压不住。所以改成从基准灰往下压,压到在**它实际会遇到的 * 固定灰就压不住。所以改成从基准灰往下压,压到在**它实际会遇到的
* 两种背景**(页脚浅底、邮件最外层)上都达标为止。 */ * 三种背景**(页脚浅底、引用块浅底、白卡片)上都达标为止。 */
$muted = '#5c6b7a'; $muted = '#5c6b7a';
for ($t = 1.0; $t >= 0.55; $t -= 0.02) { for ($t = 1.0; $t >= 0.55; $t -= 0.02) {
$cand = $t >= 0.999 ? $muted : yang_mail_shade($muted, $t); $cand = $t >= 0.999 ? $muted : yang_mail_shade($muted, $t);
if (yang_mail_contrast($cand, $tintX) >= 4.5 if (yang_mail_contrast($cand, $tintX) >= 4.5
&& yang_mail_contrast($cand, $pageBg) >= 4.5) { && yang_mail_contrast($cand, $tintXX) >= 4.5
&& yang_mail_contrast($cand, '#ffffff') >= 4.5) {
$muted = $cand; $muted = $cand;
break; break;
} }
} }
return array( return array(
'brand' => $brand, // 主色(品牌条、按钮) 'brand' => $brand, // 主色原件(引用块高亮竖线等)
'brand_dark' => yang_mail_shade($brand, 0.78), // 品牌条下沿深色带 'brand_dark' => yang_mail_shade($brand, 0.78), // 主色深版(备用)
'on_brand' => $onBrand, // 压在品牌色上的字 'on_brand' => $headerFg, // 压在头部上的字
'header_bg' => $headerBg, // 顶部品牌条底色(深色)
'header_fg' => $headerFg, // 头部白字
'header_dark'=> $headerDark, // 头部下沿深色带
'accent' => $accent, // 强调色(badge 底,暖色)
'accent_fg' => $accentFg, // badge 上的字
'accent_bd' => $accentBd, // badge 描边
'cta_bg' => $ctaBg, // 按钮底(红)
'cta_fg' => $ctaFg, // 按钮字(白)
'text' => $textOnTint, // 同色系的强调文字(标题/标签) 'text' => $textOnTint, // 同色系的强调文字(标题/标签)
'tint_xx' => $tintXX, // 极浅底:引用块、信息表 'tint_xx' => $tintXX, // 极浅底:引用块、信息表
'tint_x' => $tintX, // 稍深一点的浅底:页脚 'tint_x' => $tintX, // 稍深一点的浅底:页脚
'tint_line' => $tintLine, // 浅底上的描边/分隔线 'tint_line' => $tintLine, // 浅底上的描边/分隔线
'tint_mid' => $tintMid, // 中档:弱化竖线、次要描边 'tint_mid' => $tintMid, // 中档:弱化竖线、次要描边
'page_bg' => $pageBg, // 邮件最外层背景 'page_bg' => '#ffffff', // 邮件最外层背景(纯白,用户指定)
'body' => '#243040', // 正文(保持深灰蓝,长文好读) 'body' => '#243040', // 正文(保持深灰蓝,长文好读)
'muted' => $muted, // 次要文字(时间、页脚),按背景调过 'muted' => $muted, // 次要文字(时间、页脚),按背景调过
); );
@@ -479,13 +672,22 @@ function yang_mail_tint($hex, $ratio = 0.18, $onto = '#ffffff')
* 生成一个按钮(邮件里的按钮只能用表格单元格做,不能用 <button>) * 生成一个按钮(邮件里的按钮只能用表格单元格做,不能用 <button>)
* *
* Outlook 不认 `<a>` 的 `padding`,必须把 padding 放在 `<td>` 上。 * Outlook 不认 `<a>` 的 `padding`,必须把 padding 放在 `<td>` 上。
*
* ── 文字色为什么不写死 #ffffff ────────────────────────────────
* 按钮底色是可传入的(主题里默认给红 #c62828)。写死白字在浅底按钮上
* 会掉到 2:1 以下,而且「深还是浅」这个问题本身有结构性盲区(中灰两边
* 都不达标)。统一走 yang_mail_fg_on():在白与深之间取对比度更高的,
* 判据与任何阈值都解耦。
*/ */
function yang_mail_button($text, $url, $bg = null) function yang_mail_button($text, $url, $bg = null, $fg = null)
{ {
if ($bg === null) { if ($bg === null) {
$bg = yang_mail_brand_color(); $pal = yang_mail_palette();
$bg = $pal['cta_bg'];
}
if ($fg === null) {
$fg = yang_mail_fg_on($bg);
} }
$fg = yang_mail_is_dark($bg) ? '#ffffff' : '#1a1a1a';
$url = esc_url($url); $url = esc_url($url);
$text = esc_html($text); $text = esc_html($text);
return '<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin:0 auto;">' return '<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin:0 auto;">'
@@ -541,29 +743,35 @@ function yang_mail_render($args)
} }
/* 整套配色从主色派生一次,后面所有颜色都从这里取。 /* 整套配色从主色派生一次,后面所有颜色都从这里取。
* 不在这里散落写死 #xxxxxx —— 那样主色一改,「彩色」就断了, * 不在这里散落写死 #xxxxxx —— 那样主色一改,配色就断了。 */
* 又退回成"一个色块 + 一堆灰」。 */ $pal = yang_mail_palette();
$pal = yang_mail_palette(); $brand = $pal['brand'];
$brand = $pal['brand']; $cHeader = $pal['header_bg'];
$brandD = $pal['brand_dark']; $cHeaderFg = $pal['header_fg'];
$onBrand = $pal['on_brand']; $cHeaderD = $pal['header_dark'];
$cText = $pal['text']; $cAccent = $pal['accent'];
$cBody = $pal['body']; $cAccentFg = $pal['accent_fg'];
$cMuted = $pal['muted']; $cAccentBd = $pal['accent_bd'];
$cTintXX = $pal['tint_xx']; $cCtaBg = $pal['cta_bg'];
$cTintX = $pal['tint_x']; $cText = $pal['text'];
$cTintLine = $pal['tint_line']; $cBody = $pal['body'];
$cTintMid = $pal['tint_mid']; $cMuted = $pal['muted'];
$cPageBg = $pal['page_bg']; $cTintXX = $pal['tint_xx'];
$cTintX = $pal['tint_x'];
$cTintLine = $pal['tint_line'];
$cTintMid = $pal['tint_mid'];
$cPageBg = $pal['page_bg'];
// badge 的背景:把主色往白色方向提亮一档,得到比主色浅、但同色相的实色。 /* badge 不再复用头部配色。
// 主色本身是深色时提亮 22%,浅色时压暗 —— 否则浅主色上叠浅 badge 会看不见。 * 早先 $badgeBg 是主色提亮一档、文字色复用 $onBrand ⇒ 与头部同色系,
$badgeBg = yang_mail_is_dark($brand) * 远看就是头部里的一块「差不多颜色」,用户原话「和背景蓝色没区分度」。
? yang_mail_tint($brand, 0.22) * 现在用暖色强调色,与深色头部是撞色关系,红/黄一眼能挑出来。 */
: yang_mail_shade($brand, 0.88); $badgeBg = $cAccent;
$badgeBd = yang_mail_is_dark($brand) $badgeBd = $cAccentBd;
? yang_mail_tint($brand, 0.34)
: yang_mail_shade($brand, 0.72); /* 引用块高亮竖线:用与按钮同一个红(比 badge 的琥珀更沉),
避免 12px 琥珀色小字旁边出现一块同样亮的竖线而互相抢眼。 */
$ctaBarColor = $cCtaBg;
$site = get_bloginfo('name'); $site = get_bloginfo('name');
$home = home_url('/'); $home = home_url('/');
@@ -607,21 +815,24 @@ function yang_mail_render($args)
两套并存,各取所需。只写死 600px 会让手机横向滚动——实测过。 */ ?> 两套并存,各取所需。只写死 600px 会让手机横向滚动——实测过。 */ ?>
<table border="0" cellpadding="0" cellspacing="0" width="600" role="presentation" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;overflow:hidden;border:1px solid <?php echo esc_attr($cTintLine); ?>;"> <table border="0" cellpadding="0" cellspacing="0" width="600" role="presentation" style="width:100%;max-width:600px;background-color:#ffffff;border-radius:12px;overflow:hidden;border:1px solid <?php echo esc_attr($cTintLine); ?>;">
<?php /* ── 顶部品牌条 ── */ ?> <?php /* ── 顶部品牌条 ──
* 深色底 + 白字。深色是从主色压下来的,色相仍是主色;
* 白字保证在深底上过 AA(详见 yang_mail_deepen_to 的推导)。 */ ?>
<tr> <tr>
<td bgcolor="<?php echo esc_attr($brand); ?>" style="background-color:<?php echo esc_attr($brand); ?>;padding:0;"> <td bgcolor="<?php echo esc_attr($cHeader); ?>" style="background-color:<?php echo esc_attr($cHeader); ?>;padding:0;">
<table border="0" cellpadding="0" cellspacing="0" width="100%" role="presentation"> <table border="0" cellpadding="0" cellspacing="0" width="100%" role="presentation">
<tr> <tr>
<td style="padding:26px 32px;"> <td style="padding:26px 32px;">
<div style="font-family:<?php echo $sans; ?>;font-size:19px;font-weight:600;color:<?php echo esc_attr($onBrand); ?>;letter-spacing:0.2px;line-height:1.3;"> <div style="font-family:<?php echo $sans; ?>;font-size:19px;font-weight:600;color:<?php echo esc_attr($cHeaderFg); ?>;letter-spacing:0.2px;line-height:1.3;">
<?php echo esc_html($site); ?> <?php echo esc_html($site); ?>
</div> </div>
<?php if ($d['badge'] !== ''): ?> <?php if ($d['badge'] !== ''): ?>
<?php /* badge 用预算好的实色,不用 rgba —— Outlook 不认 rgba,会直接丢掉背景 */ ?> <?php /* badge 用暖色强调色,衬在深色头部上是撞色 —— 一眼能挑出来。
仍用预算好的实色,不用 rgba:Outlook 不认 rgba,会直接丢掉背景。 */ ?>
<table border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin-top:10px;"> <table border="0" cellpadding="0" cellspacing="0" role="presentation" style="margin-top:10px;">
<tr> <tr>
<td bgcolor="<?php echo esc_attr($badgeBg); ?>" style="background-color:<?php echo esc_attr($badgeBg); ?>;border:1px solid <?php echo esc_attr($badgeBd); ?>;border-radius:20px;padding:4px 12px;font-family:<?php echo $sans; ?>;font-size:12px;font-weight:500;line-height:1.4;"> <td bgcolor="<?php echo esc_attr($badgeBg); ?>" style="background-color:<?php echo esc_attr($badgeBg); ?>;border:1px solid <?php echo esc_attr($badgeBd); ?>;border-radius:20px;padding:4px 12px;font-family:<?php echo $sans; ?>;font-size:12px;font-weight:600;line-height:1.4;">
<span style="color:<?php echo esc_attr($onBrand); ?>;"><?php echo esc_html($d['badge']); ?></span> <span style="color:<?php echo esc_attr($cAccentFg); ?>;"><?php echo esc_html($d['badge']); ?></span>
</td> </td>
</tr> </tr>
</table> </table>
@@ -631,11 +842,11 @@ function yang_mail_render($args)
</table> </table>
</td> </td>
</tr> </tr>
<?php /* 主色条下沿压一条深色,给扁平色块一点层次(渐变在 Outlook 里不生效,用纯色)。 <?php /* 头部下沿压一条深色,给扁平色块一点层次(渐变在 Outlook 里不生效,用纯色)。
height 必须**同时**写成 HTML 属性和 CSS:Outlook 只认属性, height 必须**同时**写成 HTML 属性和 CSS:Outlook 只认属性,
只写 CSS 高度时这条 3px 带会撑成一行文字高(约 18px),比例就毁了。 */ ?> 只写 CSS 高度时这条 3px 带会撑成一行文字高(约 18px),比例就毁了。 */ ?>
<tr> <tr>
<td bgcolor="<?php echo esc_attr($brandD); ?>" height="3" style="background-color:<?php echo esc_attr($brandD); ?>;height:3px;line-height:3px;font-size:0;mso-line-height-rule:exactly;">&nbsp;</td> <td bgcolor="<?php echo esc_attr($cHeaderD); ?>" height="3" style="background-color:<?php echo esc_attr($cHeaderD); ?>;height:3px;line-height:3px;font-size:0;mso-line-height-rule:exactly;">&nbsp;</td>
</tr> </tr>
<?php /* ── 正文 ── */ ?> <?php /* ── 正文 ── */ ?>
@@ -658,13 +869,16 @@ function yang_mail_render($args)
<?php <?php
/* 引用块:左边一条竖线,用 border-left 而不是伪元素(邮件不支持 ::before)。 /* 引用块:左边一条竖线,用 border-left 而不是伪元素(邮件不支持 ::before)。
* *
* 配色规则:**最后一块用主色高亮,前面的用弱化灰**。 * 配色规则:**最后一块用强调暖色高亮,前面的用主色系弱化档**。
* 为什么是「最后」而不是「第一」:评论回复场景里顺序是 * 为什么是「最后」而不是「第一」:评论回复场景里顺序是
* 「被回复的原评论」→「新的回复」,语义重点在新的回复上,所以让它高亮。 * 「被回复的原评论」→「新的回复」,语义重点在新的回复上,所以让它高亮。
* 只有一个块时它既是第一也是最后 ⇒ 拿到主色,与旧版行为一致。 * 只有一个块时它既是第一也是最后 ⇒ 拿到强调色,与旧版行为一致。
*/ *
* 高亮色从主色换成强调暖色,是为了与深色头部、红按钮形成同一套
* 「暖色点缀」语言;同时竖线与 badge 同色,收件人一眼把
* 「新回复」标签和「新回复那段字」连起来。 */
$isLast = ($qi === count($quoteList) - 1); $isLast = ($qi === count($quoteList) - 1);
$barColor = $isLast ? $brand : $cTintMid; $barColor = $isLast ? $ctaBarColor : $cTintMid;
$barBg = $isLast ? $cTintXX : $cTintX; $barBg = $isLast ? $cTintXX : $cTintX;
$barMargin = $isLast ? '22px' : '14px'; $barMargin = $isLast ? '22px' : '14px';
?> ?>
@@ -715,7 +929,9 @@ function yang_mail_render($args)
<?php if ($d['cta_text'] !== '' && $d['cta_url'] !== ''): ?> <?php if ($d['cta_text'] !== '' && $d['cta_url'] !== ''): ?>
<div style="margin:0 0 28px 0;"> <div style="margin:0 0 28px 0;">
<?php echo yang_mail_button($d['cta_text'], $d['cta_url']); ?> <?php /* 按钮用红底白字:与深色头部是撞色,位置又在正文末尾,
是全信第二个视觉落点。用户明确要求「红白色的文字」。 */ ?>
<?php echo yang_mail_button($d['cta_text'], $d['cta_url'], $cCtaBg); ?>
</div> </div>
<?php endif; ?> <?php endif; ?>
+1 -1
View File
@@ -1,7 +1,7 @@
/* /*
Theme Name: Kratos_Yang Theme Name: Kratos_Yang
Text Domain: kratos_Yang Text Domain: kratos_Yang
Version: 3.2.8 Version: 3.2.9
Requires PHP: 7.0 Requires PHP: 7.0
Description: 这是一个Kratos主题的分支版本,用来增加一些定制化功能。 Description: 这是一个Kratos主题的分支版本,用来增加一些定制化功能。
Tags: 博客, 双栏, 响应式, 自定义背景, 自定义颜色, 自定义图标, 自定义菜单, 特色图像, 收录优化, 邮件中心, 主题选项, 小工具, 文章置顶, 无障碍友好 Tags: 博客, 双栏, 响应式, 自定义背景, 自定义颜色, 自定义图标, 自定义菜单, 特色图像, 收录优化, 邮件中心, 主题选项, 小工具, 文章置顶, 无障碍友好