diff --git a/src/main/resources/templates/themes/agri-forest/README.md b/src/main/resources/templates/themes/agri-forest/README.md
new file mode 100644
index 0000000..0813669
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/README.md
@@ -0,0 +1,58 @@
+# agri-forest · 农林绿
+
+云海 CMS 皮肤包。fork 自 `default`(数据契约、模板 th:* 绑定与 default 完全一致),视觉层按农林院校门户语言全部重写,设计语言参考信阳农林学院官网(仅学语言,不复制实现)。
+
+## 风格定位
+
+- **气质词**:庄重、质朴、农林学府。
+- **配色**:墨绿 `#1C6E19` 主导(通栏导航/日期方块/页脚主底),加深端 `#14510F`(页脚/标题条),提亮端 `#3FA43A`(当前导航项/hover),麦穗金 `#C8A45C` 只做装饰线与角标(栏目标题下划线、导航当前项下杠、日期方块 hover 金线、置顶角标)。
+- **结构**:白色页头(左校徽+校名,右工具行:今日日期 + 校园直通车下拉 + 站内搜索)→ 墨绿通栏主导航(白字,当前栏目提亮绿底+金下杠,导航下方与 banner 无缝)→ 通栏轮播(左下墨绿标题条带金边)→ 首页区块 → 墨绿多列页脚(更深底条)。
+- **工艺**:小圆角 4px;间距刻度 4/8/12/16/24/32/48;字号阶梯 12/13/14/15/16/18/20/24/28/32;hover 过渡 0.2s ease;正文行高 1.75;无渐变堆砌、无粉紫、无玻璃拟态;图标一律内联 SVG。
+
+## 参数取值建议(theme.json,13 项)
+
+| key | cssVar | 默认 | 建议 |
+| --- | --- | --- | --- |
+| primary | `--af-primary` | `#1C6E19` | 主色。换季校庆可微调为 `#1F7A1B`,勿低于 `#14510F` 明度(导航白字对比) |
+| primaryDark | `--af-primary-dark` | `#14510F` | 页脚主底/轮播标题条。与 primary 保持同色相 1~2 档差 |
+| primaryLight | `--af-primary-light` | `#3FA43A` | 当前导航项/hover。需要更醒目可用 `#4DB548`,过亮会刺眼 |
+| accent | `--af-accent` | `#C8A45C` | 麦穗金装饰线/角标。庄重场合可降饱和为 `#B8934A` |
+| navBg | `--af-nav-bg` | `#1C6E19` | 主导航底色。默认与 primary 一致;要"导航深一档"配 `#14510F` |
+| footerBg | `--af-footer-bg` | `#14510F` | 页脚主底;底条固定更深一档(`--af-primary-deep`,非参数) |
+| text / textLight | `--af-text` / `--af-text-light` | `#2A3327` / `#6C7A67` | 正文/次要文字,偏绿灰 |
+| bg | `--af-bg` | `#F5F8F3` | 页面底色,带一点绿调的暖白 |
+| cardBg | `--af-card-bg` | `#FFFFFF` | 卡片底,建议保持纯白 |
+| border | `--af-border` | `#DDE8DA` | 边框/分隔线,绿灰调 |
+| linkGreen | `--af-link` | `#277428` | 正文链接绿,介于主色深浅之间 |
+| listLayout | —(select) | `date` | 列表页形态:`date`=46px 日期方块行(农林官网典型);`plain`=通栏行式(日期右置),信息密度更高 |
+
+微调优先级:站点 `theme_params`(本表参数)→ 站点 `custom_css` → 本包 main.css(契约 §6)。
+
+## 首页九段形态表(fragments/home-blocks.html)
+
+站点配 `home_layout` 时首页正文由本包 fragment 渲染(换肤必须连正文一起换):
+
+| fragment | 触发 | 形态 |
+| --- | --- | --- |
+| `news_grid` | article_list + homeStyle=news_grid | 三图焦点(横排 3 封面卡)+ 双列要闻行式列表;支持站点背景带(news_bg_image,画在卡片之下) |
+| `media_focus` | article_list + homeStyle=media_focus | 学术动态:双列密行 + 墨绿来源徽标 |
+| `compact` | article_list + homeStyle=compact | 通知公告:46px 墨绿日期方块(日大号+年月小号),行 hover 出金线 |
+| `image_wall` | article_list + homeStyle=image_wall | 四列图片墙(仅有封面条目),悬浮标题 |
+| `card` | article_list 其他/未设 | 默认卡:头条图文(有封面则图文)+ 行式列表 |
+| `ticker` | type=ticker | 要闻速递横条:墨绿底、金色分隔、单行不塌列 |
+| `gallery` | type=gallery | 校园映像:居中标题+副题+四列图墙+悬浮标题 |
+| `links` | type=links | 专题网站:4 列缩略卡(绿标题条+金下杠+圆徽),分组拉平 |
+| `empty` | 各形态 items 为空 | 空态「栏目暂无内容」(守卫包在外层 th:block,th:replace 优先级 100 先于 th:if 300) |
+
+未知类型回落 `themes/common` 通用骨架;`:root` 已把 `--af-*` 别名到契约变量(`--primary/--text/--card-bg/--border/--bg/--radius`),兜底骨架与 themeVarsCss 换色可穿透。
+
+## 纪律要点
+
+- URL 一律 `url.*` 生成,无硬编码绝对地址;非转义输出仅契约七处白名单。
+- 中文防塌列:`.af-ticker-list{min-width:0;white-space:nowrap}`、`.af-ticker-item{flex:none;text-overflow:ellipsis}`、`.af-block-item-title{min-width:0;overflow:hidden;text-overflow:ellipsis}`。
+- 网格一律 `minmax(0,1fr)`;≤768px 单列、导航横滚、子菜单静态平铺。
+- 背景带层序:`.af-sec-bg` z-index:0,其后 `.af-block` z-index:1。
+
+## 截图说明
+
+`assets/screenshot.png` 为按本皮肤设计语言绘制的门户结构示意图(非浏览器实拍)。管理端选择器如需实拍图,起服后截首页替换即可(记入遗留项)。
diff --git a/src/main/resources/templates/themes/agri-forest/assets/css/main.css b/src/main/resources/templates/themes/agri-forest/assets/css/main.css
new file mode 100644
index 0000000..71a30a6
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/assets/css/main.css
@@ -0,0 +1,1555 @@
+/* =====================================================================
+ agri-forest · 农林绿(基座 default,设计语言参考信阳农林学院官网)
+ 设计语言:白色页头(校徽+校名 / 右工具行)+ 墨绿通栏主导航(当前项 primaryLight 底)
+ + 通栏轮播(左下墨绿标题条)+ 三图焦点新闻 + 带图标栏目标题(麦穗金装饰线)
+ + 46px 日期方块通知列表 + 学术来源徽标 + 专题缩略卡 + 校园映像四列图墙
+ + 墨绿多列页脚(更深底条)
+ 色彩令牌全部走 CSS 变量,theme.json color 参数经 :root 覆盖真实生效。
+ 工艺约定:间距 4/8/12/16/24/32/48 · 字号 12/13/14/15/16/18/20/24/28/32
+ · hover 过渡 0.2s ease · 小圆角 4px · 正文行高 1.75 · 禁渐变堆砌/粉紫/玻璃拟态
+ ===================================================================== */
+
+/* 1. 设计令牌(与 theme.json params 一一对应,禁止出现未消费的声明) */
+:root {
+ --af-primary: #1C6E19; /* 主色:墨绿,主导航/标题/强调 */
+ --af-primary-dark: #14510F; /* 主色加深:页脚主底/hover 深端/标题条 */
+ --af-primary-light: #3FA43A; /* 主色提亮:当前导航项/hover 链接 */
+ --af-accent: #C8A45C; /* 麦穗金:栏目标题装饰线/角标/日期方块 hover 金线 */
+ --af-nav-bg: #1C6E19; /* 主导航条底色(墨绿通栏) */
+ --af-footer-bg: #14510F; /* 页脚主底 */
+ --af-text: #2A3327; /* 正文 */
+ --af-text-light: #6C7A67; /* 次要文字 */
+ --af-bg: #F5F8F3; /* 页面底色 */
+ --af-card-bg: #FFFFFF; /* 卡片底 */
+ --af-border: #DDE8DA; /* 边框/分隔线 */
+ --af-link: #277428; /* 链接绿 */
+
+ /* —— 派生令牌(非参数,供组件消费)—— */
+ --af-primary-deep: #0E3D0B; /* 页脚底条(比页脚主底更深一档) */
+ --af-tint: #EAF3E8; /* 浅绿面(行 hover/侧栏激活/占位面) */
+ --af-tint-strong: #DCEBDA; /* 浅绿面加深(分隔带/表头) */
+ --af-accent-soft: #F7F0DF; /* 金浅底(徽标浅衬) */
+ --af-on-dark: #FFFFFF; /* 深底主文字 */
+ --af-on-dark-soft: rgba(255,255,255,.78);
+ --af-on-dark-faint: rgba(255,255,255,.55);
+ --af-shadow-color: rgba(20,81,15,.10);
+ --af-shadow-sm: 0 1px 4px var(--af-shadow-color);
+ --af-shadow-md: 0 6px 18px rgba(20,81,15,.13);
+ --af-shadow-lg: 0 14px 32px rgba(20,81,15,.18);
+ --af-scrim: rgba(14,61,11,.55); /* 轮播标题条投影端 */
+
+ /* —— 字号阶梯(12/13/14/15/16/18/20/24/28/32)—— */
+ --af-fs-12: 12px;
+ --af-fs-13: 13px;
+ --af-fs-14: 14px;
+ --af-fs-15: 15px;
+ --af-fs-16: 16px;
+ --af-fs-18: 18px;
+ --af-fs-20: 20px;
+ --af-fs-24: 24px;
+ --af-fs-28: 28px;
+ --af-fs-32: 32px;
+
+ /* —— 间距刻度(4/8/12/16/24/32/48)—— */
+ --af-sp-1: 4px;
+ --af-sp-2: 8px;
+ --af-sp-3: 12px;
+ --af-sp-4: 16px;
+ --af-sp-6: 24px;
+ --af-sp-8: 32px;
+ --af-sp-12: 48px;
+
+ /* —— 圆角 / 过渡 / 层级 / 栅格 —— */
+ --af-radius: 4px;
+ --af-speed: .2s ease;
+ --af-z-dropdown: 110;
+ --af-max-width: 1200px;
+ --af-gutter: 24px;
+ --af-font: "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", "Helvetica Neue", Arial, sans-serif;
+
+ /* 皮肤契约别名:common 兜底骨架与 themeVarsCss 换色只认契约变量(--primary/--text/--…),
+ 不别名过去,换肤就只换了页头页脚、首页区块仍是骨架内置色。 */
+ --primary: var(--af-primary);
+ --primary-dark: var(--af-primary-dark);
+ --primary-light: var(--af-primary-light);
+ --text: var(--af-text);
+ --text-light: var(--af-text-light);
+ --bg: var(--af-bg);
+ --card-bg: var(--af-card-bg);
+ --border: var(--af-border);
+ --radius: var(--af-radius);
+}
+
+/* 2. Reset 与基础 */
+* { box-sizing: border-box; }
+html { -webkit-text-size-adjust: 100%; }
+body {
+ margin: 0;
+ font-family: var(--af-font);
+ font-size: var(--af-fs-14);
+ line-height: 1.75;
+ color: var(--af-text);
+ background: var(--af-bg);
+ word-break: break-word;
+}
+h1, h2, h3, h4, h5, h6 { margin: 0; line-height: 1.35; color: var(--af-text); }
+p { margin: 0 0 var(--af-sp-3); }
+ul, ol { margin: 0; padding: 0; list-style: none; }
+a { color: var(--af-link); text-decoration: none; transition: color var(--af-speed); }
+a:hover { color: var(--af-primary-light); }
+a:focus-visible,
+button:focus-visible,
+input:focus-visible { outline: 2px solid var(--af-primary-light) outline-offset: 2px }
+img { max-width: 100%; height: auto; display: block; border: 0; }
+button { font-family: inherit; }
+time { color: var(--af-text-light); font-size: var(--af-fs-13); }
+::selection { background: var(--af-tint-strong); color: var(--af-primary-dark); }
+
+/* 跳过链接(无障碍) */
+.af-skip-link {
+ position: absolute;
+ left: -9999px;
+ top: 0;
+ z-index: 200;
+ background: var(--af-primary);
+ color: var(--af-on-dark);
+ padding: var(--af-sp-2) var(--af-sp-4);
+ border-radius: 0 0 var(--af-radius) 0;
+}
+.af-skip-link:focus { left: 0; color: var(--af-on-dark); }
+
+/* 3. 白色页头:左校徽+校名 / 右工具行(日期 + 校园直通车 + 搜索) */
+.af-header { background: var(--af-card-bg); }
+.af-head { border-bottom: 1px solid var(--af-border); }
+.af-head-inner {
+ max-width: var(--af-max-width);
+ margin: 0 auto;
+ padding: var(--af-sp-4) var(--af-gutter);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--af-sp-6);
+}
+.af-brand { display: flex; align-items: center; gap: var(--af-sp-3); min-width: 0; }
+.af-logo { height: 60px; width: auto; flex: none; }
+.af-sitename {
+ font-size: var(--af-fs-28);
+ font-weight: 700;
+ color: var(--af-primary-dark);
+ letter-spacing: 2px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.af-sitename:hover { color: var(--af-primary); }
+
+/* 工具行 */
+.af-head-side { display: flex; align-items: center; gap: var(--af-sp-4); flex: none; }
+.af-date { color: var(--af-text-light); font-size: var(--af-fs-13); white-space: nowrap; }
+
+/* 校园直通车(专业院系)下拉:悬停/聚焦展开 */
+.af-colleges { position: relative; }
+.af-colleges-toggle {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--af-sp-1);
+ padding: var(--af-sp-1) var(--af-sp-2);
+ border: 1px solid var(--af-border);
+ border-radius: var(--af-radius);
+ cursor: pointer;
+ color: var(--af-text-light);
+ font-size: var(--af-fs-13);
+ white-space: nowrap;
+ transition: color var(--af-speed), border-color var(--af-speed);
+}
+.af-colleges-toggle:hover { color: var(--af-primary); border-color: var(--af-primary-light); }
+.af-colleges-arrow { font-style: normal; font-size: 11px; transition: transform var(--af-speed); }
+.af-colleges:hover .af-colleges-arrow { transform: rotate(180deg); }
+.af-colleges-menu {
+ display: none;
+ position: absolute;
+ top: 100%;
+ right: 0;
+ min-width: 200px;
+ max-height: 420px;
+ overflow-y: auto;
+ padding: var(--af-sp-1) 0;
+ background: var(--af-card-bg);
+ border: 1px solid var(--af-border);
+ border-top: 3px solid var(--af-accent);
+ border-radius: 0 0 var(--af-radius) var(--af-radius);
+ box-shadow: var(--af-shadow-md);
+ z-index: var(--af-z-dropdown);
+}
+.af-colleges:hover .af-colleges-menu,
+.af-colleges:focus-within .af-colleges-menu { display: block; }
+.af-colleges-menu li a {
+ display: block;
+ padding: var(--af-sp-2) var(--af-sp-4);
+ color: var(--af-text);
+ white-space: nowrap;
+ font-size: var(--af-fs-14);
+}
+.af-colleges-menu li a:hover { background: var(--af-tint); color: var(--af-primary); }
+.af-colleges-menu li.active a { color: var(--af-primary); font-weight: 600; }
+
+/* 站内搜索(工具行右端) */
+.af-search { display: flex; flex: none; }
+.af-search input {
+ border: 1px solid var(--af-border);
+ border-right: none;
+ border-radius: var(--af-radius) 0 0 var(--af-radius);
+ padding: var(--af-sp-1) var(--af-sp-3);
+ width: 200px;
+ font-size: var(--af-fs-13);
+ font-family: inherit;
+ color: var(--af-text);
+ background: var(--af-card-bg);
+ outline: none;
+ transition: border-color var(--af-speed), box-shadow var(--af-speed);
+}
+.af-search input::placeholder { color: var(--af-text-light); }
+.af-search input:focus { border-color: var(--af-primary); box-shadow: 0 0 0 3px var(--af-tint-strong); }
+.af-search button {
+ border: none;
+ background: var(--af-primary);
+ color: var(--af-on-dark);
+ padding: var(--af-sp-1) var(--af-sp-4);
+ font-size: var(--af-fs-13);
+ border-radius: 0 var(--af-radius) var(--af-radius) 0;
+ cursor: pointer;
+ transition: background var(--af-speed);
+}
+.af-search button:hover { background: var(--af-primary-dark); }
+
+/* 4. 墨绿通栏主导航:白字,当前栏目 primaryLight 底;导航下方不留缝 */
+.af-nav { background: var(--af-nav-bg); box-shadow: var(--af-shadow-sm); }
+.af-nav ul {
+ max-width: var(--af-max-width);
+ margin: 0 auto;
+ padding: 0 var(--af-gutter);
+ list-style: none;
+ display: flex;
+ flex-wrap: wrap;
+}
+.af-nav > ul > li { position: relative; }
+.af-nav li a {
+ display: block;
+ padding: var(--af-sp-3) var(--af-sp-6);
+ color: var(--af-on-dark);
+ font-size: var(--af-fs-16);
+ position: relative;
+ transition: background var(--af-speed);
+}
+.af-nav li a:hover,
+.af-nav li.active > a { background: var(--af-primary-light); color: var(--af-on-dark); }
+
+/* 麦穗金下杠:当前项/悬停项底部金线 */
+.af-nav li a::after {
+ content: "";
+ position: absolute;
+ left: var(--af-sp-6);
+ right: var(--af-sp-6);
+ bottom: 0;
+ height: 3px;
+ background: var(--af-accent);
+ transform: scaleX(0);
+ transition: transform var(--af-speed);
+}
+.af-nav li.active > a::after,
+.af-nav li:hover > a::after { transform: scaleX(1); }
+
+/* 二级下拉:白底面板 + 金顶线 */
+.af-nav li.has-sub > a .af-caret {
+ font-style: normal;
+ font-size: 11px;
+ margin-left: var(--af-sp-1);
+ opacity: .8;
+}
+.af-nav ul.af-sub-nav {
+ display: none;
+ position: absolute;
+ top: 100%;
+ left: 0;
+ min-width: 176px;
+ padding: var(--af-sp-1) 0;
+ background: var(--af-card-bg);
+ border: 1px solid var(--af-border);
+ border-top: 3px solid var(--af-accent);
+ border-radius: 0 0 var(--af-radius) var(--af-radius);
+ box-shadow: var(--af-shadow-md);
+ z-index: var(--af-z-dropdown);
+}
+.af-nav li:hover > ul.af-sub-nav,
+.af-nav li:focus-within > ul.af-sub-nav { display: block; }
+.af-nav .af-sub-nav li a {
+ padding: var(--af-sp-2) var(--af-sp-4);
+ color: var(--af-text);
+ white-space: nowrap;
+ background: none;
+ font-size: var(--af-fs-14);
+}
+.af-nav .af-sub-nav li a::after { display: none; }
+.af-nav .af-sub-nav li a:hover { background: var(--af-tint); color: var(--af-primary); }
+.af-nav .af-sub-nav li.active a { color: var(--af-primary); font-weight: 600; }
+
+/* 5. 首页轮播(通栏 1920×560):干净切图 + 左下墨绿标题条 */
+.af-banner { position: relative; overflow: hidden; background: var(--af-primary-deep); }
+.af-banner-slides { position: relative; aspect-ratio: 1920 / 560; max-height: 560px; }
+.af-banner-slide { display: none; position: absolute; inset: 0; }
+.af-banner-slide.active { display: block; }
+.af-banner-slide img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ display: block;
+}
+.af-banner-title {
+ position: absolute;
+ left: max(var(--af-gutter), calc((100% - var(--af-max-width)) / 2 + var(--af-gutter)));
+ bottom: var(--af-sp-6);
+ max-width: min(72%, 680px);
+ padding: var(--af-sp-3) var(--af-sp-6);
+ background: var(--af-primary-dark);
+ border-left: 4px solid var(--af-accent);
+ border-radius: 0 var(--af-radius) var(--af-radius) 0;
+ box-shadow: var(--af-shadow-md);
+ color: var(--af-on-dark);
+ font-size: var(--af-fs-20);
+ font-weight: 600;
+ line-height: 1.5;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+.af-banner-dots {
+ position: absolute;
+ bottom: var(--af-sp-4);
+ right: max(var(--af-gutter), calc((100% - var(--af-max-width)) / 2 + var(--af-gutter)));
+ display: flex;
+ gap: var(--af-sp-2);
+ z-index: 20;
+}
+.af-banner-dots button {
+ width: 10px;
+ height: 10px;
+ padding: 0;
+ border: none;
+ border-radius: 999px;
+ background: var(--af-on-dark-faint);
+ cursor: pointer;
+ transition: width .2s ease, background .2s ease;
+}
+.af-banner-dots button.active { width: 28px; background: var(--af-accent); }
+.af-banner-arrow {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 44px;
+ height: 44px;
+ border: none;
+ border-radius: 50%;
+ background: var(--af-scrim);
+ color: var(--af-on-dark);
+ font-size: 22px;
+ line-height: 1;
+ cursor: pointer;
+ opacity: .55;
+ transition: opacity var(--af-speed), background var(--af-speed);
+ z-index: 20;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0;
+}
+.af-banner-arrow:hover { opacity: 1; background: var(--af-primary); }
+.af-banner-arrow.prev { left: max(var(--af-gutter), calc((100% - var(--af-max-width)) / 2)); }
+.af-banner-arrow.next { right: max(var(--af-gutter), calc((100% - var(--af-max-width)) / 2)); }
+
+/* 6. 容器 / 分节 / 背景带层序 */
+.af-home, .af-page { display: block; }
+.af-container { max-width: var(--af-max-width) margin: 0 auto padding: 0 var(--af-gutter) }
+.af-section { margin: var(--af-sp-12) 0; }
+.af-section:first-of-type { margin-top: var(--af-sp-8); }
+
+/* 新闻背景带:绝对定位层必须压 z-index:0,其后第一个卡片抬到 z-index:1(否则带图糊在卡片正面) */
+.af-sec-bg {
+ position: absolute;
+ inset: 0;
+ z-index: 0;
+ background-color: var(--af-tint);
+ background-size: cover;
+ background-position: center;
+}
+.af-sec-bg + .af-block { position: relative; z-index: 1; }
+.af-section--news { position: relative; padding: var(--af-sp-8) 0; margin: var(--af-sp-8) 0; }
+
+/* 7. 区块卡与栏目标题(内联 SVG 小图标 + 麦穗金装饰线 + 右侧「更多」) */
+.af-block {
+ background: var(--af-card-bg);
+ border: 1px solid var(--af-border);
+ border-radius: var(--af-radius);
+ box-shadow: var(--af-shadow-sm);
+ padding: var(--af-sp-6);
+ transition: box-shadow var(--af-speed);
+}
+.af-block:hover { box-shadow: var(--af-shadow-md); }
+.af-block-head {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--af-sp-4);
+ margin-bottom: var(--af-sp-4);
+}
+.af-block-title {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--af-sp-2);
+ padding-bottom: var(--af-sp-2);
+ border-bottom: 3px solid var(--af-accent); /* 麦穗金装饰线 */
+}
+.af-block-title h2 {
+ font-size: var(--af-fs-20);
+ font-weight: 700;
+ color: var(--af-text);
+ letter-spacing: 1px;
+ white-space: nowrap;
+}
+.af-block-icon {
+ flex: none;
+ width: 28px;
+ height: 28px;
+ border-radius: var(--af-radius);
+ background: var(--af-primary);
+ color: var(--af-on-dark);
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+}
+.af-more {
+ flex: none;
+ font-size: var(--af-fs-13);
+ color: var(--af-text-light);
+ white-space: nowrap;
+ transition: color var(--af-speed);
+}
+.af-more:hover { color: var(--af-link); }
+.af-section-title {
+ font-size: var(--af-fs-18);
+ position: relative;
+ padding-left: var(--af-sp-3);
+ margin: 0 0 var(--af-sp-3);
+}
+.af-section-title::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 4px;
+ bottom: 4px;
+ width: 4px;
+ border-radius: 2px;
+ background: var(--af-primary);
+}
+
+/* 8. 行式列表(要闻/学术/默认卡的公共行)与徽标 */
+.af-block-list { list-style: none; }
+.af-block-list--two {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: 0 var(--af-sp-8);
+}
+.af-line {
+ display: flex;
+ align-items: center;
+ gap: var(--af-sp-3);
+ padding: 10px var(--af-sp-2);
+ margin: 0 calc(-1 * var(--af-sp-2));
+ border-bottom: 1px dashed var(--af-border);
+ border-radius: var(--af-radius);
+ transition: background var(--af-speed);
+}
+.af-line:last-child { border-bottom-color: transparent; }
+.af-line:hover { background: var(--af-tint); }
+
+/* 中文防塌列:行标题让出收缩权并超长省略 */
+.af-block-item-title {
+ flex: 1;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-size: var(--af-fs-15);
+ color: var(--af-text);
+ transition: color var(--af-speed);
+}
+.af-block-item-title:hover { color: var(--af-link); }
+.af-item-date { flex: none; color: var(--af-text-light); font-size: var(--af-fs-13); }
+
+/* 置顶角标:麦穗金 */
+.af-top-badge {
+ flex: none;
+ background: var(--af-accent);
+ color: var(--af-primary-dark);
+ font-size: var(--af-fs-12);
+ font-weight: 700;
+ line-height: 1;
+ padding: 3px var(--af-sp-2);
+ border-radius: var(--af-radius);
+}
+
+/* 来源徽标(学术动态):墨绿描边小徽 */
+.af-src {
+ flex: none;
+ max-width: 9em;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-size: var(--af-fs-12);
+ color: var(--af-primary);
+ background: var(--af-tint);
+ border: 1px solid var(--af-tint-strong);
+ border-radius: var(--af-radius);
+ padding: 1px var(--af-sp-2);
+ line-height: 1.7;
+}
+
+/* 46px 日期方块(通知公告):日大号 + 年月小号,墨绿底白字,hover 金线 */
+.af-date-chip {
+ flex: none;
+ width: 46px;
+ min-height: 46px;
+ padding: var(--af-sp-1) 0;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background: var(--af-primary);
+ color: var(--af-on-dark);
+ border-radius: var(--af-radius);
+ box-shadow: inset 0 -3px 0 transparent;
+ transition: box-shadow var(--af-speed);
+}
+.af-date-chip b { font-size: var(--af-fs-18); font-weight: 700; line-height: 1.15; }
+.af-date-chip i { font-style: normal; font-size: var(--af-fs-12); line-height: 1.3; opacity: .82; }
+.af-line:hover .af-date-chip { box-shadow: inset 0 -3px 0 var(--af-accent); }
+.af-notice-list .af-line { padding-top: var(--af-sp-2); padding-bottom: var(--af-sp-2); }
+
+/* 9. 三图焦点(news_grid 前排 / 首页图片新闻):横排 3 卡 */
+.af-trio {
+ list-style: none;
+ display: grid;
+ grid-template-columns: repeat(3, minmax(0, 1fr));
+ gap: var(--af-sp-4);
+}
+.af-trio-item > a { display: block; }
+.af-trio-cover {
+ display: block;
+ position: relative;
+ aspect-ratio: 4 / 3;
+ overflow: hidden;
+ border-radius: var(--af-radius);
+ background: var(--af-tint);
+ border: 1px solid var(--af-border);
+}
+.af-trio-cover img {
+ width: 100%;
+ height: 100%;
+ object-fit: cover;
+ display: block;
+ transition: transform .2s ease;
+}
+.af-trio-item:hover .af-trio-cover img { transform: scale(1.04); }
+
+/* 无封面时的绿面叶纹占位(不造假图) */
+.af-trio-ph {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--af-primary-light);
+ background: var(--af-tint);
+}
+.af-trio-cap { display: block; padding: var(--af-sp-2) var(--af-sp-1) 0; }
+.af-trio-title {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ font-size: var(--af-fs-15);
+ font-weight: 600;
+ color: var(--af-text);
+ line-height: 1.6;
+ transition: color var(--af-speed);
+}
+.af-trio-item:hover .af-trio-title { color: var(--af-link); }
+.af-trio-meta { display: flex; align-items: center; gap: var(--af-sp-2); margin-top: var(--af-sp-1); }
+.af-news-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--af-sp-6); }
+
+/* 10. 头条图文(默认卡/回落栏目区块的区块头条) */
+.af-feat,
+.af-feat-row { padding-bottom: var(--af-sp-4); border-bottom: 1px solid var(--af-border); }
+.af-feat > a,
+.af-feat-row > a { display: flex; gap: var(--af-sp-4); align-items: flex-start; }
+.af-feat-cover {
+ flex: none;
+ display: block;
+ width: 200px;
+ aspect-ratio: 16 / 9;
+ border-radius: var(--af-radius);
+ overflow: hidden;
+ background: var(--af-tint);
+ border: 1px solid var(--af-border);
+}
+.af-feat-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
+.af-feat-body { min-width: 0; flex: 1; display: flex; flex-direction: column; }
+.af-feat-title {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ font-size: var(--af-fs-18);
+ font-weight: 700;
+ color: var(--af-primary-dark);
+ line-height: 1.5;
+ transition: color var(--af-speed);
+}
+.af-feat > a:hover .af-feat-title,
+.af-feat-row > a:hover .af-feat-title { color: var(--af-link); }
+.af-feat-summary {
+ color: var(--af-text-light);
+ font-size: var(--af-fs-13);
+ line-height: 1.7;
+ margin-top: var(--af-sp-2);
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+.af-feat-meta { margin-top: auto; padding-top: var(--af-sp-2); display: flex; gap: var(--af-sp-3); align-items: center; }
+
+/* 11. 四列图片墙(image_wall / 校园映像 gallery):悬浮标题 */
+.af-wall {
+ list-style: none;
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: var(--af-sp-4);
+}
+.af-wall-item > a {
+ display: block;
+ position: relative;
+ border-radius: var(--af-radius);
+ overflow: hidden;
+ background: var(--af-tint);
+ border: 1px solid var(--af-border);
+ box-shadow: var(--af-shadow-sm);
+ transition: box-shadow var(--af-speed), transform var(--af-speed);
+}
+.af-wall-item > a:hover { box-shadow: var(--af-shadow-md) transform: translateY(-2px) }
+.af-wall-item img {
+ width: 100%;
+ aspect-ratio: 3 / 2;
+ object-fit: cover;
+ display: block;
+ transition: transform .2s ease;
+}
+.af-wall-item > a:hover img { transform: scale(1.05); }
+.af-wall-cap {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ padding: var(--af-sp-2) var(--af-sp-3);
+ background: var(--af-scrim);
+ color: var(--af-on-dark);
+ font-size: var(--af-fs-13);
+ line-height: 1.5;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ transform: translateY(100%);
+ transition: transform .2s ease;
+}
+.af-wall-item > a:hover .af-wall-cap,
+.af-wall-item > a:focus-visible .af-wall-cap { transform: translateY(0); }
+
+/* 校园映像:居中标题 + 副题 */
+.af-gallery { text-align: left; }
+.af-gallery-head { text-align: center; margin-bottom: var(--af-sp-6); }
+.af-gallery-title { margin: 0 auto; }
+.af-gallery-sub {
+ margin: var(--af-sp-2) 0 0;
+ color: var(--af-text-light);
+ font-size: var(--af-fs-13);
+ letter-spacing: .18em;
+}
+
+/* 12. 要闻速递横条(ticker):墨绿底 + 金色分隔 */
+.af-ticker { background: var(--af-primary); color: var(--af-on-dark); }
+.af-ticker-inner {
+ display: flex;
+ align-items: center;
+ gap: var(--af-sp-4);
+ padding-top: var(--af-sp-3);
+ padding-bottom: var(--af-sp-3);
+}
+.af-ticker-label {
+ flex: none;
+ display: inline-flex;
+ align-items: center;
+ gap: var(--af-sp-1);
+ font-size: var(--af-fs-15);
+ font-weight: 700;
+ letter-spacing: 2px;
+ padding-right: var(--af-sp-4);
+ border-right: 2px solid var(--af-accent);
+}
+
+/* 中文防塌列:速递列表单行可收缩、条目不被压缩 */
+.af-ticker-list {
+ display: flex;
+ gap: var(--af-sp-8);
+ flex: 1;
+ min-width: 0;
+ overflow: hidden;
+ white-space: nowrap;
+}
+.af-ticker-list li { flex: none; min-width: 0; }
+.af-ticker-item {
+ display: block;
+ flex: none;
+ max-width: 300px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ color: var(--af-on-dark-soft);
+ font-size: var(--af-fs-14);
+ transition: color var(--af-speed);
+}
+.af-ticker-item:hover { color: var(--af-on-dark); }
+
+/* 13. 专题网站缩略卡(links):4 列卡片,绿标题条 + 金下杠 */
+.af-topic-grid {
+ list-style: none;
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: var(--af-sp-4);
+}
+.af-topic > a {
+ display: flex;
+ flex-direction: column;
+ background: var(--af-card-bg);
+ border: 1px solid var(--af-border);
+ border-radius: var(--af-radius);
+ overflow: hidden;
+ text-align: center;
+ box-shadow: var(--af-shadow-sm);
+ transition: box-shadow var(--af-speed), transform var(--af-speed), border-color var(--af-speed);
+}
+.af-topic > a:hover {
+ box-shadow: var(--af-shadow-md);
+ transform: translateY(-2px);
+ border-color: var(--af-primary-light);
+}
+.af-topic-bar {
+ height: 52px;
+ background: var(--af-primary);
+ border-bottom: 3px solid var(--af-accent);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--af-on-dark-soft);
+}
+.af-topic-glyph {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--af-primary);
+ margin: var(--af-sp-4) auto var(--af-sp-2);
+ width: 44px;
+ height: 44px;
+ border-radius: 50%;
+ background: var(--af-tint);
+}
+.af-topic-name {
+ display: block;
+ padding: 0 var(--af-sp-3) var(--af-sp-4);
+ font-size: var(--af-fs-14);
+ color: var(--af-text);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ transition: color var(--af-speed);
+}
+.af-topic > a:hover .af-topic-name { color: var(--af-link); }
+
+/* 14. 空态(与正常态同等用心,不塌陷) */
+.af-empty {
+ text-align: center;
+ padding: var(--af-sp-12) var(--af-sp-4);
+ color: var(--af-text-light);
+ font-size: var(--af-fs-15);
+}
+.af-empty p { margin: 0; }
+.af-empty::before {
+ content: "";
+ display: block;
+ width: 72px;
+ height: 54px;
+ margin: 0 auto var(--af-sp-4);
+ border: 2px solid var(--af-border);
+ border-radius: var(--af-radius);
+ background:
+ linear-gradient(var(--af-tint-strong) 60%, transparent 60%) 12px 10px / 40px 6px no-repeat,
+ linear-gradient(var(--af-tint-strong) 62%, transparent 62%) 12px 22px / 28px 6px no-repeat,
+ linear-gradient(var(--af-border) 100%, transparent 100%) 0 38px / 64px 2px no-repeat;
+}
+.af-empty-hint { font-size: var(--af-fs-13); margin-top: var(--af-sp-1); }
+
+/* 15. 首页回落:头条推荐(大标题左 + 密行右) */
+.af-headline-body {
+ display: grid;
+ grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
+ gap: var(--af-sp-8);
+ align-items: start;
+}
+.af-headline-lead { padding-bottom: var(--af-sp-2); }
+.af-lead-title {
+ display: -webkit-box;
+ -webkit-line-clamp: 3;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ font-size: var(--af-fs-24);
+ font-weight: 700;
+ color: var(--af-primary-dark);
+ line-height: 1.5;
+ transition: color var(--af-speed);
+}
+.af-lead-title:hover { color: var(--af-link); }
+.af-lead-meta { display: flex; gap: var(--af-sp-3); align-items: center; margin-top: var(--af-sp-2); }
+
+/* 首页回落:栏目区块两列 */
+.af-blocks {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: var(--af-sp-6);
+ align-items: start;
+}
+
+/* 16. 列表页 / 单页 / 详情页骨架:左侧栏 + 主卡 */
+.af-page { margin: var(--af-sp-8) auto var(--af-sp-12); }
+.af-cols { display: flex; align-items: flex-start; gap: var(--af-sp-6); }
+.af-cols .af-page-card { flex: 1; min-width: 0; }
+
+/* 左侧栏目导航(docs/11) */
+.af-side-nav {
+ flex: none;
+ width: 220px;
+ background: var(--af-card-bg);
+ border: 1px solid var(--af-border);
+ border-radius: var(--af-radius);
+ box-shadow: var(--af-shadow-sm);
+ overflow: hidden;
+}
+.af-side-nav-head {
+ background: var(--af-primary);
+ border-bottom: 3px solid var(--af-accent);
+ color: var(--af-on-dark);
+ font-size: var(--af-fs-18);
+ font-weight: 700;
+ text-align: center;
+ padding: var(--af-sp-3) var(--af-sp-2);
+ letter-spacing: 2px;
+}
+.af-side-nav-list { list-style: none; margin: 0; padding: var(--af-sp-1) 0; }
+.af-side-nav-item + .af-side-nav-item { border-top: 1px dashed var(--af-border); }
+.af-side-nav-item a {
+ display: block;
+ position: relative;
+ padding: var(--af-sp-3) var(--af-sp-4);
+ color: var(--af-text);
+ font-size: var(--af-fs-15);
+ transition: background var(--af-speed), color var(--af-speed);
+}
+.af-side-nav-item a::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 8px;
+ bottom: 8px;
+ width: 3px;
+ border-radius: 0 2px 2px 0;
+ background: transparent;
+ transition: background var(--af-speed);
+}
+.af-side-nav-item a:hover { color: var(--af-primary); background: var(--af-tint); }
+.af-side-nav-item.active a { background: var(--af-tint); color: var(--af-primary); font-weight: 600; }
+.af-side-nav-item.active a::before { background: var(--af-accent); }
+
+/* 主卡 */
+.af-page-card {
+ background: var(--af-card-bg);
+ border: 1px solid var(--af-border);
+ border-radius: var(--af-radius);
+ box-shadow: var(--af-shadow-sm);
+ padding: var(--af-sp-8) var(--af-sp-6);
+}
+
+/* 面包屑 */
+.af-crumb {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: var(--af-sp-2);
+ margin-bottom: var(--af-sp-4);
+ color: var(--af-text-light);
+ font-size: var(--af-fs-13);
+}
+.af-crumb a { color: var(--af-text-light); }
+.af-crumb a:hover { color: var(--af-link); }
+.af-crumb-sep { color: var(--af-border); }
+.af-crumb-current { color: var(--af-text); font-weight: 500; }
+
+/* 页标题:左绿杠 + 金短线 */
+.af-page-title {
+ position: relative;
+ font-size: var(--af-fs-24);
+ font-weight: 700;
+ padding: 0 0 var(--af-sp-3) var(--af-sp-3);
+ margin: 0 0 var(--af-sp-6);
+ border-bottom: 1px solid var(--af-border);
+}
+.af-page-title::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 6px;
+ bottom: calc(var(--af-sp-3) + 6px);
+ width: 4px;
+ border-radius: 2px;
+ background: var(--af-primary);
+}
+.af-page-title::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ bottom: -2px;
+ width: 64px;
+ height: 3px;
+ background: var(--af-accent);
+}
+
+/* 17. 列表页文章行:图文行 / 日期方块行(plain 形态切通栏行式) */
+.af-article-list { list-style: none; }
+.af-article-list > li { padding: var(--af-sp-4) 0 border-bottom: 1px dashed var(--af-border) }
+.af-article-list > li:last-child { border-bottom: none; }
+.af-article-row { display: flex; gap: var(--af-sp-4); align-items: flex-start; }
+.af-item-cover {
+ flex: none;
+ display: block;
+ width: 200px;
+ aspect-ratio: 16 / 9;
+ border-radius: var(--af-radius);
+ overflow: hidden;
+ background: var(--af-tint);
+ border: 1px solid var(--af-border);
+}
+.af-item-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
+.af-item-body { min-width: 0; flex: 1; display: flex; flex-direction: column; gap: var(--af-sp-1); }
+.af-item-title { font-size: var(--af-fs-18); font-weight: 600; line-height: 1.5; }
+.af-item-title a { color: var(--af-text); }
+.af-item-title a:hover { color: var(--af-link); }
+.af-item-summary {
+ color: var(--af-text-light);
+ font-size: var(--af-fs-14);
+ line-height: 1.75;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+.af-item-meta { display: flex; gap: var(--af-sp-3); align-items: center; margin-top: auto; }
+
+/* 无封面行:46px 日期方块 + 标题(date 形态,默认) */
+.af-article-line {
+ display: flex;
+ align-items: center;
+ gap: var(--af-sp-4);
+ padding: var(--af-sp-2) var(--af-sp-2);
+ margin: 0 calc(-1 * var(--af-sp-2));
+ border-radius: var(--af-radius);
+ transition: background var(--af-speed);
+}
+.af-article-line:hover { background: var(--af-tint); }
+.af-line-main { flex: 1; min-width: 0; }
+.af-line-main .af-item-summary { margin-top: var(--af-sp-1); font-size: var(--af-fs-13); }
+.af-line-side { flex: none; display: flex; align-items: center; gap: var(--af-sp-3); }
+
+/* plain 形态(themeParams.listLayout=plain):隐藏日期方块,日期右置 */
+.af-page--plainlist .af-article-line .af-date-chip { display: none; }
+.af-line-date { display: none; color: var(--af-text-light); font-size: var(--af-fs-13); white-space: nowrap; }
+.af-page--plainlist .af-article-line .af-line-date { display: inline; }
+
+/* 18. 分页 */
+.af-pagination {
+ display: flex;
+ gap: var(--af-sp-2);
+ justify-content: center;
+ align-items: center;
+ padding: var(--af-sp-8) 0 var(--af-sp-2);
+ flex-wrap: wrap;
+}
+.af-pagination a {
+ min-width: 36px;
+ text-align: center;
+ padding: var(--af-sp-1) var(--af-sp-3);
+ border: 1px solid var(--af-border);
+ background: var(--af-card-bg);
+ border-radius: var(--af-radius);
+ font-size: var(--af-fs-14);
+ color: var(--af-text-light);
+ transition: border-color var(--af-speed), color var(--af-speed), background var(--af-speed);
+}
+.af-pagination a:hover {
+ border-color: var(--af-primary);
+ color: var(--af-link);
+ background: var(--af-tint);
+}
+.af-pagination a.active {
+ background: var(--af-primary);
+ color: var(--af-on-dark);
+ border-color: var(--af-primary);
+ font-weight: 600;
+}
+.af-pagination a.disabled { opacity: .4; pointer-events: none; }
+
+/* 19. 详情 / 单页正文 */
+.af-article { display: block; }
+.af-article-title {
+ margin: var(--af-sp-2) 0 var(--af-sp-4);
+ font-size: var(--af-fs-28);
+ font-weight: 700;
+ text-align: center;
+ line-height: 1.5;
+}
+.af-article-meta {
+ display: flex;
+ gap: var(--af-sp-4);
+ justify-content: center;
+ flex-wrap: wrap;
+ color: var(--af-text-light);
+ font-size: var(--af-fs-13);
+ padding: var(--af-sp-2) 0 var(--af-sp-4);
+ border-bottom: 1px solid var(--af-border);
+}
+.af-article-content {
+ line-height: 1.75;
+ font-size: var(--af-fs-16);
+ color: var(--af-text);
+ padding-top: var(--af-sp-6);
+ word-break: break-word;
+}
+.af-article-content p { text-indent: 2em; margin: 0 0 var(--af-sp-3); }
+.af-article-content p:has(img), .af-article-content figure p { text-indent: 0; text-align: center; }
+.af-article-content p > img:only-child { display: inline-block; }
+.af-article-content img { height: auto; border-radius: var(--af-radius); }
+.af-article-content figure { margin: var(--af-sp-4) auto; text-align: center; text-indent: 0; }
+.af-article-content figcaption { font-size: var(--af-fs-13); color: var(--af-text-light); margin-top: var(--af-sp-2); }
+.af-article-content h2, .af-article-content h3 { margin: var(--af-sp-6) 0 var(--af-sp-3); }
+.af-article-content h2 { font-size: var(--af-fs-20); }
+.af-article-content h3 { font-size: var(--af-fs-18); }
+.af-article-content ul, .af-article-content ol { margin: 0 0 var(--af-sp-3) 2em; text-indent: 0; list-style: disc; }
+.af-article-content ol { list-style: decimal; }
+.af-article-content li { margin-bottom: var(--af-sp-1); }
+.af-article-content blockquote {
+ margin: var(--af-sp-4) 0;
+ padding: var(--af-sp-3) var(--af-sp-4);
+ border-left: 4px solid var(--af-accent);
+ background: var(--af-tint);
+ border-radius: 0 var(--af-radius) var(--af-radius) 0;
+ color: var(--af-text-light);
+ text-indent: 0;
+}
+.af-article-content table {
+ border-collapse: collapse;
+ width: 100%;
+ margin: var(--af-sp-4) 0;
+ font-size: var(--af-fs-14);
+}
+.af-article-content table td, .af-article-content table th { border: 1px solid var(--af-border) padding: var(--af-sp-2) var(--af-sp-3) }
+.af-article-content table th { background: var(--af-tint); font-weight: 600; }
+.af-article-content table tbody tr:nth-child(even) { background: var(--af-tint); }
+.af-article-content table tbody tr:hover { background: var(--af-tint-strong); }
+
+/* 上下篇 */
+.af-sibling {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: var(--af-sp-4);
+ margin-top: var(--af-sp-8);
+ padding-top: var(--af-sp-6);
+ border-top: 1px solid var(--af-border);
+}
+.af-sibling a {
+ display: flex;
+ flex-direction: column;
+ gap: var(--af-sp-1);
+ padding: var(--af-sp-3) var(--af-sp-4);
+ background: var(--af-card-bg);
+ border: 1px solid var(--af-border);
+ border-radius: var(--af-radius);
+ box-shadow: var(--af-shadow-sm);
+ transition: border-color var(--af-speed), box-shadow var(--af-speed), transform var(--af-speed);
+}
+.af-sibling a:hover {
+ border-color: var(--af-primary-light);
+ box-shadow: var(--af-shadow-md);
+ transform: translateY(-1px);
+}
+.af-sibling a.next { text-align: right; }
+.af-sibling .sib-label { font-size: var(--af-fs-13); color: var(--af-text-light); }
+.af-sibling .sib-title {
+ font-size: var(--af-fs-14);
+ color: var(--af-text);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.af-sibling a:hover .sib-title { color: var(--af-link); }
+.af-sibling .sib-none {
+ display: flex;
+ flex-direction: column;
+ gap: var(--af-sp-1);
+ padding: var(--af-sp-3) var(--af-sp-4);
+ background: var(--af-tint);
+ border: 1px dashed var(--af-border);
+ border-radius: var(--af-radius);
+ color: var(--af-text-light);
+}
+.af-sibling .sib-none.next { text-align: right; }
+
+/* 20. 服务中心 / 事项指南(事项库 R2,docs/10 §3.4 契约的消费端样式) */
+.af-svc-page, .af-svc-guide { display: block; }
+
+/* 筛选区:三组 chip(对象/类别/部门),active 态标记当前勾选,URL 由后端预生成 */
+.af-svc-filters {
+ margin: var(--af-sp-4) 0 var(--af-sp-3);
+ padding: var(--af-sp-3) var(--af-sp-4);
+ background: var(--af-tint);
+ border-radius: var(--af-radius);
+}
+.af-svc-filter-group { display: flex; align-items: flex-start; gap: var(--af-sp-3); padding: var(--af-sp-2) 0; }
+.af-svc-filter-group + .af-svc-filter-group { border-top: 1px dashed var(--af-border); }
+.af-svc-filter-label {
+ flex: none;
+ width: 4.5em;
+ padding-top: var(--af-sp-1);
+ color: var(--af-text-light);
+ font-size: var(--af-fs-13);
+ font-weight: 600;
+}
+.af-svc-filter-options { display: flex; flex-wrap: wrap; gap: var(--af-sp-2); }
+.af-svc-chip {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--af-sp-1);
+ padding: 2px var(--af-sp-3);
+ background: var(--af-card-bg);
+ border: 1px solid var(--af-border);
+ border-radius: 999px;
+ font-size: var(--af-fs-13);
+ color: var(--af-text);
+ transition: border-color var(--af-speed), color var(--af-speed);
+}
+.af-svc-chip:hover { border-color: var(--af-primary); color: var(--af-link); }
+.af-svc-chip em { font-style: normal; color: var(--af-text-light); font-size: var(--af-fs-12); }
+.af-svc-chip.active { background: var(--af-primary); border-color: var(--af-primary); color: var(--af-on-dark); }
+.af-svc-chip.active em { color: var(--af-on-dark-soft); }
+
+/* 工具条:关键词搜索 + 清除筛选 */
+.af-svc-toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--af-sp-3);
+ margin-bottom: var(--af-sp-4);
+}
+.af-svc-search { display: flex; }
+.af-svc-search input {
+ width: 260px;
+ padding: 7px var(--af-sp-3);
+ border: 1px solid var(--af-border);
+ border-right: none;
+ border-radius: var(--af-radius) 0 0 var(--af-radius);
+ font-size: var(--af-fs-14);
+ font-family: inherit;
+ color: var(--af-text);
+ outline: none;
+ transition: border-color var(--af-speed);
+}
+.af-svc-search input:focus { border-color: var(--af-primary); }
+.af-svc-search button {
+ padding: 7px var(--af-sp-4);
+ border: none;
+ border-radius: 0 var(--af-radius) var(--af-radius) 0;
+ background: var(--af-primary);
+ color: var(--af-on-dark);
+ cursor: pointer;
+ font-size: var(--af-fs-14);
+ transition: background var(--af-speed);
+}
+.af-svc-search button:hover { background: var(--af-primary-dark); }
+.af-svc-clear { font-size: var(--af-fs-13); color: var(--af-text-light); }
+.af-svc-clear:hover { color: var(--af-link); }
+
+/* 事项列表:卡片行(有封面出图,无封面纯文字,与文章列表同哲学不造占位图) */
+.af-svc-list { list-style: none; }
+.af-svc-list li { border-bottom: 1px dashed var(--af-border); }
+.af-svc-list li:last-child { border-bottom: none; }
+.af-svc-item { display: flex; gap: var(--af-sp-4); padding: var(--af-sp-4) var(--af-sp-2); }
+.af-svc-list li:hover { background: var(--af-tint); }
+.af-svc-item-cover {
+ flex: none;
+ width: 96px;
+ height: 64px;
+ border-radius: var(--af-radius);
+ overflow: hidden;
+ border: 1px solid var(--af-border);
+ background: var(--af-tint);
+}
+.af-svc-item-cover img { width: 100%; height: 100%; object-fit: cover; display: block; }
+.af-svc-item-body { display: flex; flex-direction: column; gap: var(--af-sp-1); min-width: 0; }
+.af-svc-item-title { display: flex; align-items: center; gap: var(--af-sp-2); flex-wrap: wrap; }
+.af-svc-item-name { font-size: var(--af-fs-16); font-weight: 600; color: var(--af-text); }
+.af-svc-item:hover .af-svc-item-name { color: var(--af-link); }
+.af-svc-tag {
+ flex: none;
+ padding: 1px var(--af-sp-2);
+ border-radius: var(--af-radius);
+ background: var(--af-tint);
+ border: 1px solid var(--af-border);
+ color: var(--af-text-light);
+ font-size: var(--af-fs-12);
+ line-height: 1.6;
+}
+.af-svc-tag.online { background: var(--af-primary); border-color: var(--af-primary); color: var(--af-on-dark); }
+.af-svc-item-summary {
+ color: var(--af-text-light);
+ font-size: var(--af-fs-14);
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+.af-svc-item-meta { display: flex; gap: var(--af-sp-4); color: var(--af-text-light); font-size: var(--af-fs-13); }
+
+/* 指南页 */
+.af-svc-guide-body { display: block; }
+.af-svc-apply { display: flex; align-items: center; gap: var(--af-sp-3); margin: var(--af-sp-4) 0; }
+.af-svc-apply-btn {
+ display: inline-block;
+ padding: var(--af-sp-2) var(--af-sp-8);
+ border-radius: var(--af-radius);
+ background: var(--af-primary);
+ color: var(--af-on-dark);
+ font-size: var(--af-fs-16);
+ font-weight: 600;
+ transition: background var(--af-speed);
+}
+.af-svc-apply-btn:hover { background: var(--af-primary-dark); color: var(--af-on-dark); }
+.af-svc-apply-hint { color: var(--af-text-light); font-size: var(--af-fs-13); }
+.af-svc-summary {
+ padding: var(--af-sp-3) var(--af-sp-4);
+ background: var(--af-tint);
+ border-left: 3px solid var(--af-primary);
+ border-radius: 0 var(--af-radius) var(--af-radius) 0;
+ color: var(--af-text-light);
+}
+.af-svc-info {
+ width: 100%;
+ margin: var(--af-sp-4) 0;
+ border-collapse: collapse;
+ font-size: var(--af-fs-14);
+}
+.af-svc-info th, .af-svc-info td {
+ border: 1px solid var(--af-border);
+ padding: var(--af-sp-2) var(--af-sp-4);
+ text-align: left;
+ vertical-align: top;
+}
+.af-svc-info th {
+ width: 7em;
+ background: var(--af-tint);
+ color: var(--af-text-light);
+ font-weight: 600;
+ white-space: nowrap;
+}
+.af-svc-section { margin: var(--af-sp-6) 0; }
+.af-svc-section h2 {
+ font-size: var(--af-fs-18);
+ padding-bottom: var(--af-sp-2);
+ border-bottom: 2px solid var(--af-primary);
+ margin-bottom: var(--af-sp-3);
+}
+.af-svc-attachments ul { list-style: none; }
+.af-svc-attachments li {
+ display: flex;
+ align-items: center;
+ gap: var(--af-sp-3);
+ padding: var(--af-sp-2) 0;
+ border-bottom: 1px dashed var(--af-border);
+}
+.af-svc-attachments li:last-child { border-bottom: none; }
+.af-svc-attachments a { color: var(--af-link); }
+.af-svc-attachments a:hover { text-decoration: underline; }
+.af-svc-att-size { color: var(--af-text-light); font-size: var(--af-fs-13); }
+.af-svc-links {
+ display: flex;
+ gap: var(--af-sp-3);
+ margin: var(--af-sp-6) 0 0;
+ padding-top: var(--af-sp-4);
+ border-top: 1px dashed var(--af-border);
+}
+.af-svc-links a {
+ padding: var(--af-sp-1) var(--af-sp-4);
+ border: 1px solid var(--af-border);
+ border-radius: var(--af-radius);
+ font-size: var(--af-fs-13);
+ color: var(--af-text-light);
+ transition: border-color var(--af-speed), color var(--af-speed);
+}
+.af-svc-links a:hover { border-color: var(--af-primary); color: var(--af-link); }
+
+/* 相关服务侧区 */
+.af-svc-related { margin-top: var(--af-sp-8); }
+.af-svc-related-list { list-style: none; margin-top: var(--af-sp-3); }
+.af-svc-related-list li { border-bottom: 1px dashed var(--af-border); }
+.af-svc-related-list li:last-child { border-bottom: none; }
+.af-svc-related-list a {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--af-sp-3);
+ padding: var(--af-sp-3) var(--af-sp-2);
+}
+.af-svc-related-list li:hover { background: var(--af-tint); }
+.af-svc-related-name {
+ font-size: var(--af-fs-15);
+ color: var(--af-text);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.af-svc-related-list a:hover .af-svc-related-name { color: var(--af-link); }
+.af-svc-related-meta { display: flex; align-items: center; gap: var(--af-sp-2); flex: none; }
+.af-svc-related-meta > span:not(.af-svc-tag) { color: var(--af-text-light); font-size: var(--af-fs-13); }
+
+/* 21. 页脚:墨绿多列(品牌+社媒 / 地址联系 / 二维码)+ 浅绿友链带 + 更深底条 */
+.af-footer { margin-top: var(--af-sp-12); background: var(--af-footer-bg); color: var(--af-on-dark-soft); }
+.af-footer-main { padding: var(--af-sp-12) 0 var(--af-sp-8); }
+.af-footer-cols {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--af-sp-12);
+ align-items: flex-start;
+ justify-content: space-between;
+}
+.af-footer-brand { max-width: 380px; min-width: 240px; }
+.af-footer-logo-row { display: flex; align-items: center; gap: var(--af-sp-3); margin-bottom: var(--af-sp-4); }
+.af-footer-logo { height: 52px; width: auto; }
+.af-footer-site { font-size: var(--af-fs-20); font-weight: 700; color: var(--af-on-dark); letter-spacing: 1px; }
+
+/* 社媒图标阵列 */
+.af-social { display: flex; gap: var(--af-sp-3); }
+.af-social-icon {
+ width: 36px;
+ height: 36px;
+ border: 1px solid var(--af-on-dark-faint);
+ border-radius: var(--af-radius);
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--af-on-dark-soft);
+ transition: background var(--af-speed), border-color var(--af-speed), color var(--af-speed);
+}
+.af-social-icon:hover { background: var(--af-primary-light); border-color: var(--af-primary-light); color: var(--af-on-dark); }
+
+/* 地址 / 联系 / 版权 / 备案 */
+.af-footer-info { min-width: 260px; font-size: var(--af-fs-13); line-height: 2; }
+.af-footer-info p { margin: 0; }
+.af-footer-addr { list-style: none; margin: 0 0 var(--af-sp-1); }
+.af-footer-addr li { position: relative; padding-left: var(--af-sp-3); }
+.af-footer-addr li::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 12px;
+ width: 5px;
+ height: 5px;
+ background: var(--af-accent);
+ border-radius: 1px;
+}
+
+/* 二维码位 */
+.af-footer-qr { display: flex; gap: var(--af-sp-6); }
+.af-qr { margin: 0; text-align: center; }
+.af-qr img {
+ width: 96px;
+ height: 96px;
+ padding: 6px;
+ background: var(--af-card-bg);
+ border-radius: var(--af-radius);
+ display: block;
+}
+.af-qr figcaption { margin-top: var(--af-sp-2); font-size: var(--af-fs-12); color: var(--af-on-dark-faint); }
+
+/* 友链区(浅绿带;无分组的站整段不渲染) */
+.af-footer-links {
+ background: var(--af-tint);
+ border-top: 1px solid var(--af-border);
+ border-bottom: 1px solid var(--af-border);
+ color: var(--af-text);
+}
+.af-footer-links-inner { padding: var(--af-sp-4) var(--af-gutter); }
+.af-links-group {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--af-sp-2) var(--af-sp-4);
+ align-items: baseline;
+ font-size: var(--af-fs-13);
+}
+.af-links-group + .af-links-group { margin-top: var(--af-sp-2); }
+.af-group-name {
+ font-weight: 700;
+ color: var(--af-primary-dark);
+ margin-right: var(--af-sp-2);
+ position: relative;
+ padding-left: var(--af-sp-3);
+}
+.af-group-name::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 50%;
+ width: 4px;
+ height: 4px;
+ margin-top: -2px;
+ background: var(--af-accent);
+ border-radius: 50%;
+}
+.af-links-row { margin: 0; display: inline; }
+.af-links-row a { color: var(--af-text-light); }
+.af-links-row a:hover { color: var(--af-link); }
+
+/* B4 友链 Logo:与名称并排小图(高度 ~20px,垂直居中;过宽截断不撑破页脚) */
+.af-link-logo {
+ height: 20px;
+ width: auto;
+ max-width: 64px;
+ object-fit: contain;
+ vertical-align: middle;
+ margin-right: var(--af-sp-1);
+ border-radius: 2px;
+}
+
+/* 底条(更深墨绿) */
+.af-footer-bottom { background: var(--af-primary-deep); }
+.af-footer-bottom-inner {
+ padding: var(--af-sp-3) var(--af-gutter);
+ text-align: center;
+ font-size: var(--af-fs-13);
+ color: var(--af-on-dark-faint);
+}
+.af-footer-bottom-inner p { margin: var(--af-sp-1) 0; }
+
+/* 22. 响应式(≤1024 两栏收敛;≤768 单列 + 导航折叠) */
+@media (max-width: 1024px) {
+ .af-headline-body { grid-template-columns: minmax(0, 1fr); }
+ .af-blocks { grid-template-columns: minmax(0, 1fr); }
+ .af-cols { flex-direction: column; }
+ .af-side-nav { width: 100%; }
+ .af-side-nav-list { display: flex; overflow-x: auto; -webkit-overflow-scrolling: touch; }
+ .af-side-nav-item { flex: none; }
+ .af-side-nav-item + .af-side-nav-item { border-top: none; border-left: 1px dashed var(--af-border); }
+ .af-side-nav-item a { white-space: nowrap; padding: var(--af-sp-3) var(--af-sp-4); }
+ .af-footer-cols { gap: var(--af-sp-8); }
+}
+
+@media (max-width: 768px) {
+ :root { --af-gutter: 16px; }
+
+ /* 白色页头折叠:品牌行纵排,工具行换行 */
+ .af-head-inner {
+ flex-direction: column;
+ align-items: stretch;
+ gap: var(--af-sp-3);
+ padding: var(--af-sp-3) var(--af-gutter);
+ }
+ .af-sitename { font-size: var(--af-fs-20); }
+ .af-logo { height: 44px; }
+ .af-head-side { flex-wrap: wrap; justify-content: space-between; }
+ .af-search { flex: 1; }
+ .af-search input { flex: 1; width: auto; }
+
+ /* 主导航:横向滚动 + 子菜单静态平铺(触屏无 hover,不做浮层) */
+ .af-nav ul { overflow-x: auto; flex-wrap: nowrap; }
+ .af-nav li a { padding: var(--af-sp-3) var(--af-sp-4); white-space: nowrap; font-size: var(--af-fs-15); }
+ .af-nav ul.af-sub-nav {
+ display: block;
+ position: static;
+ border: none;
+ box-shadow: none;
+ background: var(--af-primary-dark);
+ border-radius: 0;
+ min-width: 0;
+ padding: 0;
+ }
+ .af-nav .af-sub-nav li a { color: var(--af-on-dark-soft); padding: var(--af-sp-2) var(--af-sp-4) var(--af-sp-2) var(--af-sp-8); }
+ .af-nav .af-sub-nav li a:hover { background: var(--af-primary-deep); color: var(--af-on-dark); }
+ .af-nav .af-sub-nav li.active a { color: var(--af-on-dark); }
+
+ /* 轮播:4:3 切图,隐藏箭头 */
+ .af-banner-slides { aspect-ratio: 4 / 3; max-height: none; }
+ .af-banner-title { font-size: var(--af-fs-15); padding: var(--af-sp-2) var(--af-sp-3); bottom: var(--af-sp-3); }
+ .af-banner-arrow { display: none; }
+
+ /* 首页:全部单列 */
+ .af-trio { grid-template-columns: minmax(0, 1fr); }
+ .af-block-list--two { grid-template-columns: minmax(0, 1fr); gap: 0; }
+ .af-wall { grid-template-columns: repeat(2, minmax(0, 1fr)); }
+ .af-topic-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
+ .af-section { margin: var(--af-sp-6) 0; }
+ .af-block, .af-page-card { padding: var(--af-sp-4) var(--af-sp-3); }
+ .af-feat > a, .af-feat-row > a { flex-direction: column; }
+ .af-feat-cover { width: 100%; }
+
+ /* 列表页:图文行纵排;日期方块行窄屏保持方块形态 */
+ .af-article-row { flex-direction: column; }
+ .af-item-cover { width: 100%; }
+ .af-article-line { align-items: flex-start; }
+ .af-line-side { flex-direction: column; align-items: flex-end; gap: var(--af-sp-1); }
+ .af-sibling { grid-template-columns: minmax(0, 1fr); }
+ .af-ticker-item { max-width: 180px; }
+ .af-footer-cols { flex-direction: column; gap: var(--af-sp-6); }
+ .af-footer-info { min-width: 0; }
+ .af-svc-toolbar { flex-direction: column; align-items: stretch; }
+ .af-svc-search input { width: auto; flex: 1; }
+ .af-svc-filter-group { flex-direction: column; gap: var(--af-sp-1); }
+ .af-svc-filter-label { width: auto; padding-top: 0; }
+ .af-svc-item { flex-direction: column; gap: var(--af-sp-2); }
+ .af-svc-item-cover { width: 100%; height: 120px; }
+ .af-svc-info th { width: 5.5em; }
+ .af-svc-related-list a { flex-direction: column; align-items: flex-start; }
+}
+
+/* 23. 打印样式(公告高频打印场景) */
+@media print {
+ .af-header, .af-head, .af-nav, .af-banner, .af-footer-links, .af-footer,
+ .af-sibling, .af-pagination, .af-skip-link, .af-search, .af-colleges,
+ .af-side-nav, .af-svc-apply, .af-svc-filters, .af-svc-toolbar, .af-svc-related { display: none !important; }
+ body { background: #ffffff; color: #000000; font-size: 12pt; }
+ .af-page-card { border: none; box-shadow: none; padding: 0; margin: 0; max-width: 100%; }
+ .af-article-title { font-size: 20pt; }
+ .af-article-content { font-size: 11.5pt; line-height: 1.75; }
+ .af-article-content p { text-indent: 2em; }
+ a { color: inherit; }
+}
\ No newline at end of file
diff --git a/src/main/resources/templates/themes/agri-forest/assets/favicon.png b/src/main/resources/templates/themes/agri-forest/assets/favicon.png
new file mode 100644
index 0000000..822653c
Binary files /dev/null and b/src/main/resources/templates/themes/agri-forest/assets/favicon.png differ
diff --git a/src/main/resources/templates/themes/agri-forest/assets/js/main.js b/src/main/resources/templates/themes/agri-forest/assets/js/main.js
new file mode 100644
index 0000000..d3482ae
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/assets/js/main.js
@@ -0,0 +1,87 @@
+/* agri-forest 皮肤包脚本:页头日期 + 首页轮播(自动播放/圆点/箭头/悬停暂停/键盘),无任何外部依赖 */
+(function () {
+ /* 页头工具行日期(本地时间,YYYY年M月D日 星期X) */
+ var dateEl = document.getElementById('siteDate');
+ if (dateEl) {
+ var now = new Date();
+ var week = ['日', '一', '二', '三', '四', '五', '六'][now.getDay()];
+ dateEl.textContent = now.getFullYear() + '年' + (now.getMonth() + 1) + '月'
+ + now.getDate() + '日 星期' + week;
+ }
+
+ /* 轮播 */
+ var root = document.querySelector('.af-banner');
+ var slides = document.querySelectorAll('.af-banner-slide');
+ var dots = document.querySelectorAll('.af-banner-dots button');
+ var prevBtn = document.querySelector('.af-banner-arrow.prev');
+ var nextBtn = document.querySelector('.af-banner-arrow.next');
+ if (!slides.length || !root) {
+ return;
+ }
+ var current = 0;
+ var timer = null;
+ var INTERVAL = 5000;
+
+ function show(index) {
+ slides[current].classList.remove('active');
+ if (dots[current]) {
+ dots[current].classList.remove('active');
+ }
+ current = (index + slides.length) % slides.length;
+ slides[current].classList.add('active');
+ if (dots[current]) {
+ dots[current].classList.add('active');
+ }
+ }
+
+ function start() {
+ stop();
+ if (slides.length > 1) {
+ timer = window.setInterval(function () {
+ show(current + 1);
+ }, INTERVAL);
+ }
+ }
+
+ function stop() {
+ if (timer) {
+ window.clearInterval(timer);
+ timer = null;
+ }
+ }
+
+ dots.forEach(function (dot, index) {
+ dot.addEventListener('click', function () {
+ show(index);
+ start();
+ });
+ });
+ if (prevBtn) {
+ prevBtn.addEventListener('click', function () {
+ show(current - 1);
+ start();
+ });
+ }
+ if (nextBtn) {
+ nextBtn.addEventListener('click', function () {
+ show(current + 1);
+ start();
+ });
+ }
+ root.addEventListener('mouseenter', stop);
+ root.addEventListener('mouseleave', start);
+ root.addEventListener('focusin', stop);
+ root.addEventListener('focusout', start);
+ root.setAttribute('tabindex', '-1');
+ root.addEventListener('keydown', function (e) {
+ if (e.key === 'ArrowLeft') {
+ show(current - 1);
+ start();
+ } else if (e.key === 'ArrowRight') {
+ show(current + 1);
+ start();
+ }
+ });
+
+ start();
+})();
diff --git a/src/main/resources/templates/themes/agri-forest/assets/screenshot.png b/src/main/resources/templates/themes/agri-forest/assets/screenshot.png
new file mode 100644
index 0000000..6dc1772
Binary files /dev/null and b/src/main/resources/templates/themes/agri-forest/assets/screenshot.png differ
diff --git a/src/main/resources/templates/themes/agri-forest/detail.html b/src/main/resources/templates/themes/agri-forest/detail.html
new file mode 100644
index 0000000..b210470
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/detail.html
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 文章标题
+
+
+ 作者
+ 来源
+ 浏览量
+
+
+ 正文
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/agri-forest/fragments/footer.html b/src/main/resources/templates/themes/agri-forest/fragments/footer.html
new file mode 100644
index 0000000..27596a2
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/fragments/footer.html
@@ -0,0 +1,92 @@
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/agri-forest/fragments/head.html b/src/main/resources/templates/themes/agri-forest/fragments/head.html
new file mode 100644
index 0000000..7739009
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/fragments/head.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ 页面标题
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/agri-forest/fragments/header.html b/src/main/resources/templates/themes/agri-forest/fragments/header.html
new file mode 100644
index 0000000..34a5721
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/fragments/header.html
@@ -0,0 +1,66 @@
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/agri-forest/fragments/home-blocks.html b/src/main/resources/templates/themes/agri-forest/fragments/home-blocks.html
new file mode 100644
index 0000000..612697d
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/fragments/home-blocks.html
@@ -0,0 +1,257 @@
+
+
+
+
+
+
+
+
+
+
+
+ -
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+ 来源
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+ 01
+ 2026-01
+
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/agri-forest/guide.html b/src/main/resources/templates/themes/agri-forest/guide.html
new file mode 100644
index 0000000..aa96960
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/guide.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
事项服务暂时不可用,请稍后再试
+
事项数据服务暂不可达,稍后刷新即可恢复
+
+
+
+ 事项名称
+
+ 办理部门
+ 办理方式
+
+ 浏览量
+
+
+
+
+
+ 简介
+
+
+ 事项基本信息
+
+
+ | 服务对象 |
+ 服务对象 |
+
+
+ | 事项类别 |
+ 事项类别 |
+
+
+ | 办理地点 |
+ 办理地点 |
+
+
+ | 办理时限 |
+ 办理时限 |
+
+
+ | 承诺时限 |
+ 承诺时限 |
+
+
+ | 咨询电话 |
+ 咨询电话 |
+
+
+ | 监督投诉 |
+ 监督投诉电话 |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/agri-forest/home.html b/src/main/resources/templates/themes/agri-forest/home.html
new file mode 100644
index 0000000..7b54275
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/home.html
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
头条标题
+
+ 置顶
+
+
+
+
+ -
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/agri-forest/list.html b/src/main/resources/templates/themes/agri-forest/list.html
new file mode 100644
index 0000000..6f4c7e7
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/list.html
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
栏目名
+
搜索词
+
+
+
+ -
+
+
+
+
+
+
+
摘要
+
+
+ 置顶
+
+
+
+
+
+ 01
+ 2026-01
+
+
+
+ 置顶
+
+
+
+
+
+
+
未找到相关内容
+
栏目暂无内容
+
换个关键词试试
+
内容发布后将在此展示
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/agri-forest/service.html b/src/main/resources/templates/themes/agri-forest/service.html
new file mode 100644
index 0000000..6d3d3eb
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/service.html
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
服务中心
+
+
+
+
事项服务暂时不可用,请稍后再试
+
事项数据服务暂不可达,稍后刷新即可恢复
+
+
+
+
+
+
+
+
+
未找到符合条件的服务事项
+
服务中心暂未上架事项
+
换个筛选条件或关键词试试
+
事项发布后将在此展示
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/agri-forest/single.html b/src/main/resources/templates/themes/agri-forest/single.html
new file mode 100644
index 0000000..4694399
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/single.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 栏目名
+
+ 单页内容
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/agri-forest/theme.json b/src/main/resources/templates/themes/agri-forest/theme.json
new file mode 100644
index 0000000..454845f
--- /dev/null
+++ b/src/main/resources/templates/themes/agri-forest/theme.json
@@ -0,0 +1,30 @@
+{
+ "specVersion": 1,
+ "name": "agri-forest",
+ "title": "农林绿(agri-forest)",
+ "version": "1.0.0",
+ "author": "yunhai",
+ "description": "墨绿+麦穗金的农林院校风(设计语言参考信阳农林学院官网)。",
+ "screenshot": "assets/screenshot.png",
+ "bannerSize": "1920x560",
+ "params": [
+ { "key": "primary", "cssVar": "--af-primary", "label": "主色(墨绿)", "type": "color", "default": "#1C6E19" },
+ { "key": "primaryDark", "cssVar": "--af-primary-dark", "label": "主色加深", "type": "color", "default": "#14510F" },
+ { "key": "primaryLight", "cssVar": "--af-primary-light","label": "主色提亮", "type": "color", "default": "#3FA43A" },
+ { "key": "accent", "cssVar": "--af-accent", "label": "麦穗金", "type": "color", "default": "#C8A45C" },
+ { "key": "navBg", "cssVar": "--af-nav-bg", "label": "主导航底色", "type": "color", "default": "#1C6E19" },
+ { "key": "footerBg", "cssVar": "--af-footer-bg", "label": "页脚底色", "type": "color", "default": "#14510F" },
+ { "key": "text", "cssVar": "--af-text", "label": "正文文字色", "type": "color", "default": "#2A3327" },
+ { "key": "textLight", "cssVar": "--af-text-light", "label": "次要文字色", "type": "color", "default": "#6C7A67" },
+ { "key": "bg", "cssVar": "--af-bg", "label": "页面底色", "type": "color", "default": "#F5F8F3" },
+ { "key": "cardBg", "cssVar": "--af-card-bg", "label": "卡片底色", "type": "color", "default": "#FFFFFF" },
+ { "key": "border", "cssVar": "--af-border", "label": "边框色", "type": "color", "default": "#DDE8DA" },
+ { "key": "linkGreen", "cssVar": "--af-link", "label": "链接绿", "type": "color", "default": "#277428" },
+ { "key": "listLayout", "label": "列表页形态", "type": "select", "default": "date",
+ "options": [
+ { "value": "date", "label": "日期方块" },
+ { "value": "plain", "label": "通栏行式" }
+ ]
+ }
+ ]
+}
diff --git a/src/main/resources/templates/themes/jade-normal/README.md b/src/main/resources/templates/themes/jade-normal/README.md
new file mode 100644
index 0000000..a48d41b
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/README.md
@@ -0,0 +1,54 @@
+# jade-normal(师大青)
+
+师范院校风皮肤包:以 `default` 为基座派生,设计语言参考信阳师范大学官网(www.xynu.edu.cn,仅学语言不复制实现)——
+翡翠青主色 + 暖橙点缀,人文师范气质、温润轻盈。
+配了 `home_layout` 的站点,首页正文区块由本主题 `fragments/home-blocks.html` 渲染——派生包不自带区块形态时,
+正文会落到 `themes/common` 的通用骨架,换肤就只剩页头页脚(线上事故根因,见《审计验收清单-20260919》)。
+
+## 风格定位
+
+- 主色翡翠青 `#008D3F` / 加深 `#04682E` / 提亮 `#35B371`,点缀暖橙 `#F18D00`(日期徽标数字、强调角标、"我要办理"按钮)。
+- 页头三段式:深青顶条(日期+专业院系)→ 白色品牌行(校徽+校名居左,服务中心入口+圆角搜索居右)→
+ 翡翠青通栏主导航(白字,当前/悬停项 primaryLight 底条,≤768px checkbox 纯 CSS 折叠)。
+- banner 标题用青色底条(非渐变遮罩);列表主打"46px 橙色日期徽标(日大号+年月小号)"语言。
+- 圆角 8/10px、正文行高 1.8、hover 过渡 0.2s ease;无渐变堆砌、无玻璃拟态、无粉紫。
+- 页脚:薄荷友链带 + 翡翠深青 `#04682E` 多列(品牌+社媒图标 / 多校区地址+联系版权备案 / 二维码)+ 深色底条。
+- 全部 12 个颜色参数可在站点 theme_params 微调,另有 1 个 select 布局参数(见下)。
+
+## 参数取值建议(theme_params)
+
+| key | 默认 | 说明 |
+| -- | -- | -- |
+| `primary` | `#008D3F` | 翡翠青主色(导航/标题/链接) |
+| `primaryDark` | `#04682E` | 加深(顶条/页脚/hover) |
+| `primaryLight` | `#35B371` | 提亮(当前栏目底条/描边) |
+| `accent` | `#F18D00` | 暖橙点缀(日期徽标/角标) |
+| `navBg` | `#008D3F` | 主导航条底色(可与主色分离调) |
+| `footerBg` | `#04682E` | 页脚主底色 |
+| `text` / `textLight` | `#2E3A33` / `#6E7F75` | 正文/次要文字 |
+| `bg` / `cardBg` / `border` | `#F4FAF6` / `#FFFFFF` / `#DFEEE5` | 页面底/卡片/边框 |
+| `mintBg` | `#E7F6EE` | 薄荷底(背景带/友链区/hover 面) |
+| `listLayout` | `badge` | 列表页形态:`badge` 橙色日期徽标行 / `plain` 通栏行式(日期右置) |
+
+## 首页区块形态(布局模式与回落模式同构)
+
+| homeStyle | 呈现 | 类名 |
+| -- | -- | -- |
+| `news_grid` | 校园要闻:左图文头条 + 右橙色日期徽标行 + 四图横排;区块背景可取站点 `news_bg_image` | `jn-split` / `jn-date-badge` / `jn-shots` |
+| `compact` | 通知公告:46px「日大号+年月小号」橙色徽标行 | `jn-row-badge` |
+| `media_focus` | 学术交流/媒体聚焦:来源徽标 + 双列密行 | `jn-src` / `jn-block-list--two` |
+| `image_wall` | 教学科研:四列图片墙,青底标题条,hover 抬图 | `jn-wall` |
+| (空/未知) | 整宽区块卡:头条 + 行式列表 | `jn-block--flow` |
+| `ticker` | 翡翠青要闻速递横条(单行不换行、超长省略,中文不塌列) | `jn-ticker*` |
+| `gallery` | 校园映像四图墙 + 「融媒师大」图标行(微信/微博/抖音/B站走 `social_*` 配置,校报/广播台常驻) | `jn-gallery` / `jn-fusion` |
+| `links` | 快捷通道图标宫格(6 列内联 SVG 图标卡,青色描边 hover 青底白字) | `jn-quick` |
+
+## 契约要点
+
+- 结构类前缀 `jn-`,CSS 变量前缀 `--jn-`;`:root` 把 `--jn-*` 别名到皮肤契约变量(`--primary`/`--text`/`--card-bg`/`--border`…),
+ 使 `themes/common` 兜底骨架也能跟随本皮肤着色。
+- 空态文案「栏目暂无内容」只在 `block.items` 为空时出现;守卫必须写在 `th:block` 外层——
+ `th:replace`(优先级 100)先于 `th:if`(300)求值,写在同一标签上等于没写。
+- 页脚消费 docs/12 增强键:`footer_addresses`(经 `site.footerAddressLines` 逐行渲染)、`qr_wechat`/`qr_weibo`、
+ `social_wechat`/`social_weibo`/`social_douyin`/`social_bilibili`——均有值才渲染,空站点优雅降级。
+- 回归防线:`ThemeContractIT`(7 条路由);带 home_layout 的站点首页不落通用骨架(本包 home.html 分发到自家 fragment)。
diff --git a/src/main/resources/templates/themes/jade-normal/assets/css/main.css b/src/main/resources/templates/themes/jade-normal/assets/css/main.css
new file mode 100644
index 0000000..99cd935
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/assets/css/main.css
@@ -0,0 +1,1949 @@
+/* =====================================================================
+ jade-normal · 师大青(基座 default,设计语言参考信阳师范大学官网 xynu.edu.cn)
+ 设计语言:白色页头(校徽+校名居左/搜索与工具居右) + 翡翠青通栏主导航(白字/当前项
+ primaryLight 底条) + 通栏大图 banner(青色底条标题) + 橙色日期徽标列表
+ + 快捷通道图标宫格 + 四图横排 + 融媒图标行 + 翡翠深青多列页脚。
+ 气质:人文师范、温润轻盈——圆角 8/10px、正文行高 1.8、无渐变堆砌、无玻璃拟态。
+ 色彩令牌全部走 CSS 变量(--jn-*),theme.json color 参数经 :root 覆盖真实生效;
+ 品牌衍生色(悬停/阴影/深底文字)一律由变量或中性黑白透明度派生,不另立色值。
+ ===================================================================== */
+
+/* ---------------------------------------------------------------------
+ 1. 设计令牌(与 theme.json params 一一对应,禁止出现未消费的声明)
+ --------------------------------------------------------------------- */
+:root {
+ /* —— 品牌色板(theme.json 12 个 color 参数一一对应)—— */
+ --jn-primary: #008D3F; /* 主色:翡翠青——导航/标题/链接/强调 */
+ --jn-primary-dark: #04682E; /* 主色加深:顶条/页脚/hover 深端 */
+ --jn-primary-light: #35B371; /* 主色提亮:当前栏目底条/亮线条/hover 链接 */
+ --jn-accent: #F18D00; /* 点缀暖橙:日期徽标/强调数字/角标 */
+ --jn-nav-bg: #008D3F; /* 主导航条底色(翡翠青通栏) */
+ --jn-footer-bg: #04682E; /* 页脚主底(翡翠深青) */
+ --jn-text: #2E3A33; /* 正文(青灰墨) */
+ --jn-text-light: #6E7F75; /* 次要文字(青灰) */
+ --jn-bg: #F4FAF6; /* 页面底色(薄荷白) */
+ --jn-card-bg: #FFFFFF; /* 卡片底 */
+ --jn-border: #DFEEE5; /* 边框/分隔线(浅青灰) */
+ --jn-mint-bg: #E7F6EE; /* 薄荷底:背景带/友链区/hover 面 */
+
+ /* —— 深底文字(顶条/导航/页脚;透明度而非新色值,随底色参数自适应)—— */
+ --jn-ink: #ffffff; /* 深底主文字 */
+ --jn-ink-soft: rgba(255, 255, 255, .78); /* 深底次要文字 */
+ --jn-ink-faint: rgba(255, 255, 255, .55); /* 深底弱化文字 */
+ --jn-scrim: rgba(0, 0, 0, .45); /* banner 标题投影衬底(中性) */
+
+ /* —— 阴影(中性墨绿灰,随卡片抬升三档)—— */
+ --jn-shadow-sm: 0 1px 4px rgba(23, 46, 36, .08);
+ --jn-shadow-md: 0 6px 18px rgba(23, 46, 36, .12);
+ --jn-shadow-lg: 0 14px 32px rgba(23, 46, 36, .16);
+
+ /* —— 圆角(温润人文感:8/10px 两档)—— */
+ --jn-radius: 8px;
+ --jn-radius-lg: 10px;
+ --jn-pill: 999px;
+
+ /* —— 动效 —— */
+ --jn-speed: .2s; /* 统一 hover 过渡 0.2s ease */
+ --jn-ease: ease;
+
+ /* —— 字号阶梯(12/13/14/15/16/18/20/24/28/32)—— */
+ --jn-fs-12: 12px;
+ --jn-fs-13: 13px;
+ --jn-fs-14: 14px;
+ --jn-fs-15: 15px;
+ --jn-fs-16: 16px;
+ --jn-fs-18: 18px;
+ --jn-fs-20: 20px;
+ --jn-fs-24: 24px;
+ --jn-fs-28: 28px;
+ --jn-fs-32: 32px;
+
+ /* —— 间距系统(4/8/12/16/24/32/48)—— */
+ --jn-sp-1: 4px;
+ --jn-sp-2: 8px;
+ --jn-sp-3: 12px;
+ --jn-sp-4: 16px;
+ --jn-sp-6: 24px;
+ --jn-sp-8: 32px;
+ --jn-sp-12: 48px;
+
+ /* —— 栅格 —— */
+ --jn-max: 1200px; /* 内容安全宽 */
+ --jn-gutter: 24px; /* 页边距 */
+ --jn-header-h: 48px; /* 主导航条高(移动端折叠按钮对齐用) */
+
+ --jn-font: "PingFang SC", "Microsoft YaHei", "Hiragino Sans GB", "Helvetica Neue", Arial, sans-serif;
+
+ /* —— 皮肤契约别名:站点配了 home_layout 而本包某形态未覆盖时,回落
+ themes/common 兜底骨架只认契约变量(--primary/--text/--card-bg/--border…)。
+ 不别名过去,换肤就只换了页头页脚、正文区块仍是骨架内置蓝灰。 —— */
+ --primary: var(--jn-primary);
+ --primary-dark: var(--jn-primary-dark);
+ --primary-light: var(--jn-primary-light);
+ --text: var(--jn-text);
+ --text-light: var(--jn-text-light);
+ --bg: var(--jn-bg);
+ --card-bg: var(--jn-card-bg);
+ --border: var(--jn-border);
+ --radius: var(--jn-radius);
+}
+
+/* ---------------------------------------------------------------------
+ 2. Reset 与基础
+ --------------------------------------------------------------------- */
+* { box-sizing: border-box; }
+
+html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
+
+body {
+ margin: 0;
+ font-family: var(--jn-font);
+ font-size: var(--jn-fs-14);
+ line-height: 1.8; /* 人文师范:正文行高 1.8 */
+ color: var(--jn-text);
+ background: var(--jn-bg);
+ word-break: break-word;
+}
+
+h1, h2, h3, h4, h5, h6 { margin: 0; line-height: 1.4; color: var(--jn-text); }
+
+p { margin: 0 0 var(--jn-sp-3); }
+
+ul, ol { margin: 0; padding: 0; list-style: none; }
+
+a { color: inherit; text-decoration: none; transition: color var(--jn-speed) var(--jn-ease); }
+
+img { max-width: 100%; height: auto; display: block; border: 0; }
+
+button { font-family: inherit; cursor: pointer; }
+
+input, button, select, textarea { font-size: inherit; color: inherit; }
+
+time { color: var(--jn-text-light); font-size: var(--jn-fs-13); }
+
+::selection { background: var(--jn-primary); color: var(--jn-ink); }
+
+/* 键盘焦点态:全站统一可见(契约 §4 无障碍要求) */
+a:focus-visible,
+button:focus-visible,
+input:focus-visible,
+[tabindex]:focus-visible {
+ outline: 2px solid var(--jn-primary-light);
+ outline-offset: 2px;
+}
+
+/* 跳过链接:仅键盘聚焦时可见 */
+.skip-link {
+ position: absolute;
+ left: -9999px;
+ top: 0;
+ z-index: 300;
+ background: var(--jn-primary);
+ color: var(--jn-ink);
+ padding: var(--jn-sp-2) var(--jn-sp-4);
+ border-radius: 0 0 var(--jn-radius) 0;
+}
+.skip-link:focus { left: 0; color: var(--jn-ink); }
+
+/* ---------------------------------------------------------------------
+ 3. 页头之一 · 顶条(今日日期 + 专业院系切换,翡翠深青底)
+ --------------------------------------------------------------------- */
+.jn-topbar {
+ background: var(--jn-primary-dark);
+ color: var(--jn-ink-soft);
+ font-size: var(--jn-fs-13);
+}
+
+.jn-topbar-inner {
+ max-width: var(--jn-max);
+ margin: 0 auto;
+ padding: var(--jn-sp-1) var(--jn-gutter);
+ min-height: 36px;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--jn-sp-4);
+}
+
+.jn-topbar-date { white-space: nowrap; letter-spacing: .04em; }
+
+.jn-topbar-side { display: flex; align-items: center; gap: var(--jn-sp-4); }
+
+/* 专业院系下拉(无子站整块不渲染;hover/focus-within 展开) */
+.jn-colleges { position: relative; }
+
+.jn-colleges-toggle {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--jn-sp-1);
+ padding: var(--jn-sp-1) 0;
+ color: var(--jn-ink-soft);
+ font-size: var(--jn-fs-13);
+ white-space: nowrap;
+ cursor: pointer;
+}
+.jn-colleges-toggle:hover { color: var(--jn-ink); }
+
+.jn-colleges-arrow {
+ font-style: normal;
+ font-size: 11px;
+ transition: transform var(--jn-speed) var(--jn-ease);
+}
+.jn-colleges:hover .jn-colleges-arrow,
+.jn-colleges:focus-within .jn-colleges-arrow { transform: rotate(180deg); }
+
+.jn-colleges-menu {
+ display: none;
+ position: absolute;
+ top: 100%;
+ right: 0;
+ min-width: 208px;
+ max-height: 420px;
+ overflow-y: auto;
+ padding: var(--jn-sp-1) 0;
+ background: var(--jn-card-bg);
+ border: 1px solid var(--jn-border);
+ border-top: 2px solid var(--jn-accent); /* 暖橙角标呼应日期徽标 */
+ border-radius: 0 0 var(--jn-radius) var(--jn-radius);
+ box-shadow: var(--jn-shadow-md);
+ z-index: 120;
+}
+.jn-colleges:hover .jn-colleges-menu,
+.jn-colleges:focus-within .jn-colleges-menu { display: block; }
+
+.jn-colleges-menu li a {
+ display: block;
+ padding: var(--jn-sp-2) var(--jn-sp-4);
+ color: var(--jn-text);
+ font-size: var(--jn-fs-14);
+ white-space: nowrap;
+ transition: background var(--jn-speed) var(--jn-ease), color var(--jn-speed) var(--jn-ease);
+}
+.jn-colleges-menu li a:hover { background: var(--jn-mint-bg); color: var(--jn-primary); }
+.jn-colleges-menu li.active a { color: var(--jn-primary); font-weight: 600; }
+
+/* ---------------------------------------------------------------------
+ 4. 页头之二 · 品牌行(白色:校徽+校名居左,搜索与工具链接居右)
+ --------------------------------------------------------------------- */
+.jn-brandbar {
+ background: var(--jn-card-bg);
+ border-bottom: 1px solid var(--jn-border);
+}
+
+.jn-brandbar-inner {
+ max-width: var(--jn-max);
+ margin: 0 auto;
+ padding: var(--jn-sp-4) var(--jn-gutter);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--jn-sp-6);
+}
+
+.jn-brand { display: flex; align-items: center; gap: var(--jn-sp-3); min-width: 0; }
+
+.jn-brand-badge {
+ flex: none;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 56px;
+ height: 56px;
+ border-radius: 50%;
+ color: var(--jn-primary);
+}
+
+.jn-logo { height: 52px; width: auto; }
+
+.jn-site-name {
+ font-size: var(--jn-fs-28);
+ font-weight: 700;
+ color: var(--jn-primary-dark);
+ letter-spacing: 2px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.jn-site-name:hover { color: var(--jn-primary); }
+
+/* 工具区:服务中心入口 + 站内搜索 */
+.jn-tools { display: flex; align-items: center; gap: var(--jn-sp-4); flex: none; }
+
+.jn-tool-link {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--jn-sp-1);
+ padding: var(--jn-sp-1) 0;
+ font-size: var(--jn-fs-14);
+ color: var(--jn-text-light);
+ white-space: nowrap;
+}
+.jn-tool-link svg { flex: none; }
+.jn-tool-link:hover { color: var(--jn-primary); }
+
+.jn-search { display: flex; align-items: center; }
+
+.jn-search input {
+ width: 248px;
+ padding: var(--jn-sp-2) var(--jn-sp-4);
+ border: 2px solid var(--jn-primary);
+ border-right: none;
+ border-radius: var(--jn-pill) 0 0 var(--jn-pill);
+ background: var(--jn-card-bg);
+ color: var(--jn-text);
+ font-size: var(--jn-fs-14);
+ outline: none;
+ transition: border-color var(--jn-speed) var(--jn-ease), box-shadow var(--jn-speed) var(--jn-ease);
+}
+.jn-search input::placeholder { color: var(--jn-text-light); }
+.jn-search input:focus {
+ border-color: var(--jn-primary-light);
+ box-shadow: 0 0 0 3px var(--jn-mint-bg);
+}
+
+.jn-search button {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--jn-sp-1);
+ padding: var(--jn-sp-2) var(--jn-sp-4);
+ border: none;
+ border-radius: 0 var(--jn-pill) var(--jn-pill) 0;
+ background: var(--jn-primary);
+ color: var(--jn-ink);
+ font-size: var(--jn-fs-14);
+ transition: background var(--jn-speed) var(--jn-ease);
+}
+.jn-search button:hover { background: var(--jn-primary-dark); }
+
+/* ---------------------------------------------------------------------
+ 5. 页头之三 · 主导航(翡翠青通栏,白字,当前项 primaryLight 底条)
+ --------------------------------------------------------------------- */
+.jn-nav {
+ background: var(--jn-nav-bg);
+ box-shadow: var(--jn-shadow-sm);
+ position: relative;
+ z-index: 110;
+}
+
+.jn-nav > ul {
+ max-width: var(--jn-max);
+ margin: 0 auto;
+ padding: 0 var(--jn-gutter);
+ display: flex;
+ flex-wrap: wrap;
+}
+
+.jn-nav > ul > li { position: relative; }
+
+.jn-nav > ul > li > a {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--jn-sp-1);
+ padding: 0 var(--jn-sp-6);
+ height: var(--jn-header-h);
+ color: var(--jn-ink);
+ font-size: var(--jn-fs-16);
+ position: relative;
+ transition: background var(--jn-speed) var(--jn-ease);
+}
+
+/* 当前栏目 / 悬停:primaryLight 底条(信阳师大导航语言) */
+.jn-nav > ul > li > a::after {
+ content: "";
+ position: absolute;
+ left: var(--jn-sp-6);
+ right: var(--jn-sp-6);
+ bottom: 0;
+ height: 4px;
+ border-radius: 4px 4px 0 0;
+ background: var(--jn-primary-light);
+ transform: scaleX(0);
+ transition: transform var(--jn-speed) var(--jn-ease);
+}
+.jn-nav > ul > li:hover > a { background: var(--jn-primary-dark); }
+.jn-nav > ul > li.active > a { font-weight: 600; }
+.jn-nav > ul > li.active > a::after,
+.jn-nav > ul > li:hover > a::after { transform: scaleX(1); }
+
+.jn-nav .caret {
+ font-style: normal;
+ font-size: 11px;
+ opacity: .8;
+ transition: transform var(--jn-speed) var(--jn-ease);
+}
+.jn-nav > ul > li:hover > a .caret { transform: rotate(180deg); }
+
+/* 二级下拉:白底面板、青色顶边 */
+.jn-sub {
+ display: none;
+ position: absolute;
+ top: 100%;
+ left: 0;
+ min-width: 184px;
+ padding: var(--jn-sp-1) 0;
+ background: var(--jn-card-bg);
+ border: 1px solid var(--jn-border);
+ border-top: 3px solid var(--jn-primary-light);
+ border-radius: 0 0 var(--jn-radius) var(--jn-radius);
+ box-shadow: var(--jn-shadow-md);
+ z-index: 120;
+}
+.jn-nav li:hover > .jn-sub,
+.jn-nav li:focus-within > .jn-sub { display: block; }
+
+.jn-sub li a {
+ display: block;
+ padding: var(--jn-sp-2) var(--jn-sp-4);
+ color: var(--jn-text);
+ font-size: var(--jn-fs-14);
+ white-space: nowrap;
+ transition: background var(--jn-speed) var(--jn-ease), color var(--jn-speed) var(--jn-ease), padding-left var(--jn-speed) var(--jn-ease);
+}
+.jn-sub li a:hover { background: var(--jn-mint-bg); color: var(--jn-primary); padding-left: var(--jn-sp-6); }
+.jn-sub li.active a { color: var(--jn-primary); font-weight: 600; }
+
+/* 移动端导航折叠(纯 CSS:checkbox + label,无 JS) */
+.jn-nav-fold { display: none; }
+.jn-nav-btn {
+ display: none;
+ align-items: center;
+ justify-content: center;
+ gap: var(--jn-sp-2);
+ width: 100%;
+ height: var(--jn-header-h);
+ background: var(--jn-nav-bg);
+ color: var(--jn-ink);
+ font-size: var(--jn-fs-16);
+ cursor: pointer;
+ user-select: none;
+}
+.jn-nav-btn::before { content: "☰"; font-size: var(--jn-fs-18); }
+
+/* ---------------------------------------------------------------------
+ 6. 首页轮播 banner(通栏大图 1920×560,标题青色底条)
+ --------------------------------------------------------------------- */
+.jn-banner {
+ position: relative;
+ overflow: hidden;
+ background: var(--jn-primary-dark);
+}
+
+.jn-banner-slides { position: relative; aspect-ratio: 1920 / 560; max-height: 560px; }
+
+.jn-banner-slide { display: none; position: absolute; inset: 0; }
+.jn-banner-slide.active { display: block; }
+
+.jn-banner-slide img { width: 100%; height: 100%; object-fit: cover; }
+
+/* 标题:青色底条(非渐变遮罩,呼应信阳师大 banner 语言) */
+.jn-banner-title {
+ position: absolute;
+ left: max(var(--jn-gutter), calc((100% - var(--jn-max)) / 2 + var(--jn-gutter)));
+ bottom: var(--jn-sp-8);
+ display: inline-block;
+ max-width: min(72%, 720px);
+ padding: var(--jn-sp-2) var(--jn-sp-6);
+ background: var(--jn-primary);
+ color: var(--jn-ink);
+ font-size: var(--jn-fs-24);
+ font-weight: 600;
+ line-height: 1.5;
+ border-radius: var(--jn-radius);
+ box-shadow: var(--jn-shadow-lg);
+ text-shadow: 0 1px 2px var(--jn-scrim);
+ overflow: hidden;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+}
+
+.jn-banner-dots {
+ position: absolute;
+ bottom: var(--jn-sp-4);
+ right: max(var(--jn-gutter), calc((100% - var(--jn-max)) / 2 + var(--jn-gutter)));
+ display: flex;
+ gap: var(--jn-sp-2);
+ z-index: 20;
+}
+.jn-banner-dots button {
+ width: 10px;
+ height: 10px;
+ padding: 0;
+ border: none;
+ border-radius: var(--jn-pill);
+ background: var(--jn-ink-faint);
+ transition: width var(--jn-speed) var(--jn-ease), background var(--jn-speed) var(--jn-ease);
+}
+.jn-banner-dots button.active { width: 30px; background: var(--jn-ink); }
+
+.jn-banner-arrow {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 44px;
+ height: 44px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0;
+ border: none;
+ border-radius: 50%;
+ background: var(--jn-scrim);
+ color: var(--jn-ink);
+ font-size: 22px;
+ line-height: 1;
+ opacity: .6;
+ transition: opacity var(--jn-speed) var(--jn-ease), background var(--jn-speed) var(--jn-ease);
+ z-index: 20;
+}
+.jn-banner-arrow:hover { opacity: 1; background: var(--jn-primary-dark); }
+.jn-banner-arrow.prev { left: max(var(--jn-gutter), calc((100% - var(--jn-max)) / 2)); }
+.jn-banner-arrow.next { right: max(var(--jn-gutter), calc((100% - var(--jn-max)) / 2)); }
+
+/* ---------------------------------------------------------------------
+ 7. 通用容器与区块骨架
+ --------------------------------------------------------------------- */
+.jn-container {
+ max-width: var(--jn-max);
+ margin: 0 auto;
+ padding: 0 var(--jn-gutter);
+}
+
+.jn-section { margin: var(--jn-sp-8) 0; }
+
+/* 区块标题行:青色底条标题 + 右侧「更多」 */
+.jn-block-head {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+ gap: var(--jn-sp-4);
+ margin-bottom: var(--jn-sp-4);
+ padding-bottom: var(--jn-sp-3);
+ border-bottom: 1px solid var(--jn-border);
+}
+
+.jn-block-head h2,
+.jn-section-title {
+ position: relative;
+ padding: var(--jn-sp-1) 0 var(--jn-sp-1) var(--jn-sp-4);
+ font-size: var(--jn-fs-24);
+ font-weight: 700;
+ color: var(--jn-text);
+ letter-spacing: .02em;
+}
+.jn-block-head h2::before,
+.jn-section-title::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 6px;
+ height: 70%;
+ border-radius: var(--jn-pill);
+ background: var(--jn-primary);
+}
+.jn-block-head h2::after,
+.jn-section-title::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ bottom: -13px;
+ width: 48px;
+ height: 3px;
+ border-radius: var(--jn-pill);
+ background: var(--jn-accent); /* 暖橙短底线:青主橙辅 */
+}
+
+.jn-more {
+ display: inline-flex;
+ align-items: center;
+ gap: 2px;
+ font-size: var(--jn-fs-13);
+ color: var(--jn-primary);
+ white-space: nowrap;
+ transition: color var(--jn-speed) var(--jn-ease);
+}
+.jn-more::after { content: "›"; font-size: var(--jn-fs-15); }
+.jn-more:hover { color: var(--jn-accent); }
+
+/* 区块卡(白底、细边、hover 阴影抬升) */
+.jn-block {
+ background: var(--jn-card-bg);
+ border: 1px solid var(--jn-border);
+ border-radius: var(--jn-radius-lg);
+ box-shadow: var(--jn-shadow-sm);
+ padding: var(--jn-sp-6);
+ transition: box-shadow var(--jn-speed) var(--jn-ease), transform var(--jn-speed) var(--jn-ease);
+}
+.jn-block:hover { box-shadow: var(--jn-shadow-md); }
+
+/* 背景带层序(news_bg_image):带压 z-0、卡抬 z-1,缺一不可 */
+.jn-sec-bg {
+ position: absolute;
+ inset: 0;
+ z-index: 0;
+ background-size: cover;
+ background-position: center;
+}
+.jn-sec-bg + .jn-block {
+ position: relative;
+ z-index: 1;
+}
+
+/* ---------------------------------------------------------------------
+ 8. 日期徽标(46px 橙色数字:日大号 + 年月小号)
+ --------------------------------------------------------------------- */
+.jn-date-badge {
+ flex: none;
+ width: 46px;
+ height: 46px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background: var(--jn-card-bg);
+ border: 1px solid var(--jn-border);
+ border-bottom: 2px solid var(--jn-accent);
+ border-radius: var(--jn-radius);
+ box-shadow: var(--jn-shadow-sm);
+ overflow: hidden;
+}
+.jn-date-badge b {
+ font-size: var(--jn-fs-18);
+ font-weight: 700;
+ line-height: 1.1;
+ color: var(--jn-accent); /* 橙色数字点缀 */
+}
+.jn-date-badge i {
+ font-style: normal;
+ font-size: var(--jn-fs-12);
+ line-height: 1.3;
+ color: var(--jn-text-light);
+ letter-spacing: .02em;
+ transform: scale(.92);
+}
+
+/* 置顶徽标 */
+.jn-top-badge {
+ flex: none;
+ padding: 3px var(--jn-sp-2);
+ border-radius: var(--jn-pill);
+ background: var(--jn-accent);
+ color: var(--jn-ink);
+ font-size: var(--jn-fs-12);
+ font-weight: 600;
+ line-height: 1.4;
+}
+
+/* ---------------------------------------------------------------------
+ 9. 首页 · 回落模式(无 home_layout 时):头条区 + 栏目区块
+ --------------------------------------------------------------------- */
+.jn-home { display: block; }
+
+.jn-headline {
+ display: grid;
+ grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
+ gap: var(--jn-sp-6);
+ align-items: stretch;
+}
+
+.jn-headline-card,
+.jn-focus-card { display: flex; flex-direction: column; }
+
+/* 头条推荐列表 */
+.jn-headline-list li {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--jn-sp-3);
+ padding: var(--jn-sp-3) var(--jn-sp-2);
+ margin: 0 calc(-1 * var(--jn-sp-2));
+ border-bottom: 1px solid var(--jn-border);
+ border-radius: var(--jn-radius);
+ transition: background var(--jn-speed) var(--jn-ease);
+}
+.jn-headline-list li:last-child { border-bottom: none; }
+.jn-headline-list li:hover { background: var(--jn-mint-bg); }
+.jn-headline-list li a {
+ flex: 1;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-size: var(--jn-fs-15);
+}
+.jn-headline-list li a:hover { color: var(--jn-primary); }
+
+.jn-headline-lead {
+ display: block;
+ padding: 0 0 var(--jn-sp-4);
+ margin: 0;
+ border-bottom: 1px solid var(--jn-border);
+ border-radius: 0;
+}
+.jn-headline-lead:hover { background: none; }
+.jn-lead-title {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ font-size: var(--jn-fs-24);
+ font-weight: 700;
+ line-height: 1.4;
+ color: var(--jn-primary-dark);
+ margin-bottom: var(--jn-sp-2);
+ white-space: normal;
+}
+.jn-lead-title:hover { color: var(--jn-primary); }
+.jn-lead-meta { display: flex; align-items: center; gap: var(--jn-sp-3); }
+
+/* 图片新闻卡(右列:大图 + 两行小图) */
+.jn-focus-card .jn-focus-lead { display: block; }
+.jn-focus-cover {
+ display: block;
+ aspect-ratio: 16 / 9;
+ border-radius: var(--jn-radius);
+ overflow: hidden;
+ margin-bottom: var(--jn-sp-3);
+ background: var(--jn-mint-bg);
+}
+.jn-focus-cover img { width: 100%; height: 100%; object-fit: cover; }
+.jn-focus-title {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ font-size: var(--jn-fs-15);
+ font-weight: 600;
+ line-height: 1.6;
+}
+.jn-focus-lead:hover .jn-focus-title { color: var(--jn-primary); }
+
+.jn-focus-rows { margin-top: var(--jn-sp-3); padding-top: var(--jn-sp-3); border-top: 1px solid var(--jn-border); }
+.jn-focus-rows li { border-bottom: 1px solid var(--jn-border); }
+.jn-focus-rows li:last-child { border-bottom: none; }
+.jn-focus-rows a { display: flex; align-items: center; gap: var(--jn-sp-3); padding: var(--jn-sp-3) 0; }
+.jn-row-cover {
+ flex: none;
+ width: 92px;
+ aspect-ratio: 16 / 9;
+ border-radius: var(--jn-radius);
+ overflow: hidden;
+ background: var(--jn-mint-bg);
+}
+.jn-row-cover img { width: 100%; height: 100%; object-fit: cover; }
+.jn-row-title {
+ flex: 1;
+ min-width: 0;
+ font-size: var(--jn-fs-14);
+ line-height: 1.7;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+.jn-focus-rows a:hover .jn-row-title { color: var(--jn-primary); }
+
+/* 栏目区块网格 */
+.jn-blocks {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: var(--jn-sp-6);
+}
+
+.jn-block-list li.jn-block-item {
+ display: flex;
+ align-items: center;
+ gap: var(--jn-sp-3);
+ padding: var(--jn-sp-2) var(--jn-sp-2);
+ margin: 0 calc(-1 * var(--jn-sp-2));
+ border-bottom: 1px solid var(--jn-border);
+ border-radius: var(--jn-radius);
+ transition: background var(--jn-speed) var(--jn-ease);
+}
+.jn-block-list li.jn-block-item:last-child { border-bottom: none; }
+.jn-block-list li.jn-block-item:hover { background: var(--jn-mint-bg); }
+
+.jn-block-item-title {
+ flex: 1;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-size: var(--jn-fs-15);
+}
+.jn-block-item-title:hover { color: var(--jn-primary); }
+
+.jn-item-date { flex: none; color: var(--jn-text-light); font-size: var(--jn-fs-13); }
+
+/* 区块头条(有封面图文 / 无封面纯文摘要) */
+.jn-block-featured { padding-bottom: var(--jn-sp-4); margin-bottom: var(--jn-sp-2); border-bottom: 1px solid var(--jn-border); }
+.jn-block-featured > a { display: flex; gap: var(--jn-sp-4); align-items: flex-start; }
+
+.jn-feat-cover {
+ flex: none;
+ display: block;
+ width: 176px;
+ aspect-ratio: 16 / 9;
+ border-radius: var(--jn-radius);
+ overflow: hidden;
+ background: var(--jn-mint-bg);
+}
+.jn-feat-cover img { width: 100%; height: 100%; object-fit: cover; }
+.jn-feat-cover--row { width: 100%; margin-bottom: var(--jn-sp-3); }
+/* 全宽封面变体:锚点转纵向,否则横向 nowrap 会把正文列压成 0 宽(390px 实测溢出根因) */
+.jn-feat-a--stack { flex-direction: column; align-items: stretch; }
+
+.jn-feat-body { min-width: 0; flex: 1; display: flex; flex-direction: column; }
+.jn-feat-title {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ font-size: var(--jn-fs-16);
+ font-weight: 600;
+ line-height: 1.6;
+}
+.jn-feat-summary {
+ margin-top: var(--jn-sp-2);
+ color: var(--jn-text-light);
+ font-size: var(--jn-fs-13);
+ line-height: 1.7;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+.jn-feat-meta { display: flex; align-items: center; gap: var(--jn-sp-3); margin-top: auto; padding-top: var(--jn-sp-2); }
+.jn-block-featured a:hover .jn-feat-title { color: var(--jn-primary); }
+
+/* ---------------------------------------------------------------------
+ 10. 布局模式 · news_grid(校园要闻:左图文头条 + 右日期徽标行 + 四图横排)
+ --------------------------------------------------------------------- */
+.jn-news-sec { position: relative; }
+
+.jn-split {
+ display: grid;
+ grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
+ gap: var(--jn-sp-6);
+ align-items: stretch;
+}
+
+.jn-split-side { display: flex; flex-direction: column; min-width: 0; }
+
+.jn-split-side .jn-block-list { flex: 1; }
+.jn-split-side .jn-block-item { padding: var(--jn-sp-3) var(--jn-sp-2); }
+
+/* 四图横排(教学科研/校园映像形态的紧凑图组) */
+.jn-shots {
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: var(--jn-sp-4);
+ margin-top: var(--jn-sp-6);
+}
+.jn-shots li { min-width: 0; }
+.jn-shot a { display: block; border-radius: var(--jn-radius); overflow: hidden; }
+.jn-shot img {
+ width: 100%;
+ aspect-ratio: 4 / 3;
+ object-fit: cover;
+ border-radius: var(--jn-radius);
+ background: var(--jn-mint-bg);
+ transition: transform var(--jn-speed) var(--jn-ease);
+}
+.jn-shot-cap {
+ display: block;
+ margin-top: var(--jn-sp-2);
+ font-size: var(--jn-fs-13);
+ color: var(--jn-text);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.jn-shot a:hover img { transform: scale(1.04); }
+.jn-shot a:hover .jn-shot-cap { color: var(--jn-primary); }
+
+/* ---------------------------------------------------------------------
+ 11. 布局模式 · compact(通知公告:橙色日期徽标行)/ media_focus(来源徽标双列)
+ --------------------------------------------------------------------- */
+.jn-block-list li.jn-row-badge { padding: var(--jn-sp-3) var(--jn-sp-2); }
+.jn-row-badge .jn-block-item-title { font-size: var(--jn-fs-15); }
+
+/* 媒体聚焦:双列密行 */
+.jn-block-list--two {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ column-gap: var(--jn-sp-8);
+}
+.jn-block-list--two li.jn-block-item { border-bottom: 1px dashed var(--jn-border); }
+
+/* 来源徽标 */
+.jn-src {
+ flex: none;
+ padding: 1px var(--jn-sp-2);
+ border: 1px solid var(--jn-primary-light);
+ border-radius: var(--jn-radius);
+ color: var(--jn-primary);
+ font-size: var(--jn-fs-12);
+ line-height: 1.6;
+ max-width: 8em;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+/* ---------------------------------------------------------------------
+ 12. 布局模式 · image_wall(四列图片墙)
+ --------------------------------------------------------------------- */
+.jn-wall {
+ display: grid;
+ grid-template-columns: repeat(4, minmax(0, 1fr));
+ gap: var(--jn-sp-4);
+}
+.jn-wall-item { min-width: 0; }
+.jn-wall-item a {
+ position: relative;
+ display: block;
+ border-radius: var(--jn-radius-lg);
+ overflow: hidden;
+ box-shadow: var(--jn-shadow-sm);
+ transition: box-shadow var(--jn-speed) var(--jn-ease), transform var(--jn-speed) var(--jn-ease);
+}
+.jn-wall-item a:hover { box-shadow: var(--jn-shadow-md); transform: translateY(-3px); }
+.jn-wall-item img {
+ width: 100%;
+ aspect-ratio: 4 / 3;
+ object-fit: cover;
+ background: var(--jn-mint-bg);
+ transition: transform var(--jn-speed) var(--jn-ease);
+}
+.jn-wall-item a:hover img { transform: scale(1.05); }
+.jn-wall-cap {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ padding: var(--jn-sp-2) var(--jn-sp-3);
+ background: var(--jn-primary-dark);
+ color: var(--jn-ink);
+ font-size: var(--jn-fs-13);
+ line-height: 1.5;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+/* ---------------------------------------------------------------------
+ 13. 布局模式 · ticker(翡翠青要闻速递横条;中文不塌列三件套)
+ --------------------------------------------------------------------- */
+.jn-ticker {
+ background: var(--jn-primary);
+ color: var(--jn-ink);
+ box-shadow: var(--jn-shadow-sm);
+}
+
+.jn-ticker-inner {
+ max-width: var(--jn-max);
+ margin: 0 auto;
+ padding: var(--jn-sp-2) var(--jn-gutter);
+ display: flex;
+ align-items: center;
+ gap: var(--jn-sp-4);
+ min-width: 0;
+}
+
+.jn-ticker-label {
+ flex: none;
+ display: inline-flex;
+ align-items: center;
+ gap: var(--jn-sp-2);
+ font-size: var(--jn-fs-15);
+ font-weight: 700;
+ letter-spacing: .08em;
+ padding-right: var(--jn-sp-4);
+ border-right: 1px solid var(--jn-ink-faint);
+}
+.jn-ticker-label::before {
+ content: "";
+ width: 6px;
+ height: 6px;
+ border-radius: 50%;
+ background: var(--jn-accent);
+}
+
+/* flex 项自动最小尺寸=min-content,中文可按字断行 → 不锁 nowrap/不收缩就会塌成一字一列 */
+.jn-ticker-list {
+ flex: 1;
+ min-width: 0;
+ display: flex;
+ gap: var(--jn-sp-8);
+ overflow: hidden;
+ white-space: nowrap;
+}
+.jn-ticker-list li { flex: none; min-width: 0; }
+
+.jn-ticker-item {
+ display: block;
+ flex: none;
+ max-width: 280px;
+ color: var(--jn-ink);
+ font-size: var(--jn-fs-14);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ opacity: .92;
+ transition: opacity var(--jn-speed) var(--jn-ease);
+}
+.jn-ticker-item:hover { opacity: 1; text-decoration: underline; color: var(--jn-ink); }
+
+/* ---------------------------------------------------------------------
+ 14. 布局模式 · gallery(校园映像四图 + 融媒师大图标行)
+ --------------------------------------------------------------------- */
+.jn-gallery { text-align: left; }
+
+.jn-gallery-sub {
+ margin: -4px 0 var(--jn-sp-4);
+ color: var(--jn-text-light);
+ font-size: var(--jn-fs-13);
+ letter-spacing: .1em;
+}
+
+/* 融媒体图标行(微信/微博/抖音/B站/校报/广播台,内联 SVG) */
+.jn-fusion {
+ margin-top: var(--jn-sp-8);
+ padding: var(--jn-sp-6);
+ background: var(--jn-mint-bg);
+ border-radius: var(--jn-radius-lg);
+}
+
+.jn-fusion-label {
+ display: flex;
+ align-items: center;
+ gap: var(--jn-sp-2);
+ margin-bottom: var(--jn-sp-4);
+ font-size: var(--jn-fs-16);
+ font-weight: 600;
+ color: var(--jn-primary-dark);
+}
+.jn-fusion-label::before {
+ content: "";
+ width: 5px;
+ height: 5px;
+ border-radius: 50%;
+ background: var(--jn-accent);
+}
+
+.jn-fusion-row {
+ display: grid;
+ grid-template-columns: repeat(6, minmax(0, 1fr));
+ gap: var(--jn-sp-4);
+}
+
+.jn-fusion-item {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: var(--jn-sp-2);
+ padding: var(--jn-sp-4) var(--jn-sp-2);
+ background: var(--jn-card-bg);
+ border: 1px solid var(--jn-border);
+ border-radius: var(--jn-radius-lg);
+ text-align: center;
+ transition: background var(--jn-speed) var(--jn-ease), border-color var(--jn-speed) var(--jn-ease),
+ box-shadow var(--jn-speed) var(--jn-ease), transform var(--jn-speed) var(--jn-ease);
+}
+a.jn-fusion-item:hover {
+ background: var(--jn-card-bg);
+ border-color: var(--jn-primary);
+ box-shadow: var(--jn-shadow-md);
+ transform: translateY(-3px);
+}
+
+.jn-fusion-ico {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 46px;
+ height: 46px;
+ border-radius: 50%;
+ color: var(--jn-primary);
+ background: var(--jn-mint-bg);
+ transition: background var(--jn-speed) var(--jn-ease), color var(--jn-speed) var(--jn-ease);
+}
+a.jn-fusion-item:hover .jn-fusion-ico {
+ background: var(--jn-primary);
+ color: var(--jn-ink);
+}
+
+.jn-fusion-name {
+ font-size: var(--jn-fs-13);
+ color: var(--jn-text);
+ white-space: nowrap;
+}
+a.jn-fusion-item:hover .jn-fusion-name { color: var(--jn-primary); }
+
+/* ---------------------------------------------------------------------
+ 15. 布局模式 · links(快捷通道图标宫格:青色描边、hover 青底白字)
+ --------------------------------------------------------------------- */
+.jn-quick-group {
+ margin: var(--jn-sp-4) 0 var(--jn-sp-2);
+ font-size: var(--jn-fs-13);
+ color: var(--jn-text-light);
+ letter-spacing: .06em;
+}
+.jn-quick-group:not(:first-of-type) { margin-top: var(--jn-sp-6); }
+
+.jn-quick-grid {
+ display: grid;
+ grid-template-columns: repeat(6, minmax(0, 1fr));
+ gap: var(--jn-sp-4);
+}
+
+.jn-quick-item { min-width: 0; }
+
+.jn-quick-item a {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: var(--jn-sp-3);
+ min-height: 108px;
+ padding: var(--jn-sp-4) var(--jn-sp-2);
+ background: var(--jn-card-bg);
+ border: 1px solid var(--jn-primary-light);
+ border-radius: var(--jn-radius-lg);
+ text-align: center;
+ transition: background var(--jn-speed) var(--jn-ease), border-color var(--jn-speed) var(--jn-ease),
+ box-shadow var(--jn-speed) var(--jn-ease), transform var(--jn-speed) var(--jn-ease);
+}
+
+.jn-quick-ico {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--jn-primary); /* 青色描边图标 */
+ transition: color var(--jn-speed) var(--jn-ease), transform var(--jn-speed) var(--jn-ease);
+}
+
+.jn-quick-name {
+ font-size: var(--jn-fs-14);
+ color: var(--jn-text);
+ max-width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ transition: color var(--jn-speed) var(--jn-ease);
+}
+
+/* hover:青底白字(图标描边同步反白) */
+.jn-quick-item a:hover {
+ background: var(--jn-primary);
+ border-color: var(--jn-primary);
+ box-shadow: var(--jn-shadow-md);
+ transform: translateY(-3px);
+}
+.jn-quick-item a:hover .jn-quick-ico { color: var(--jn-ink); transform: scale(1.08); }
+.jn-quick-item a:hover .jn-quick-name { color: var(--jn-ink); }
+
+/* ---------------------------------------------------------------------
+ 16. 空态(与正常态同等用心:CSS 画一枚「空文件夹」,不造占位图)
+ --------------------------------------------------------------------- */
+.jn-empty {
+ padding: var(--jn-sp-12) var(--jn-sp-4);
+ text-align: center;
+ color: var(--jn-text-light);
+ font-size: var(--jn-fs-15);
+}
+.jn-empty::before {
+ content: "";
+ display: block;
+ width: 72px;
+ height: 56px;
+ margin: 0 auto var(--jn-sp-4);
+ border: 2px solid var(--jn-border);
+ border-radius: 0 0 var(--jn-radius) var(--jn-radius);
+ background:
+ var(--jn-mint-bg) 14px 26px / 40px 6px no-repeat,
+ var(--jn-mint-bg) 14px 38px / 26px 6px no-repeat;
+ box-shadow: inset 0 12px 0 -10px var(--jn-border);
+}
+.jn-empty .jn-empty-hint { margin-top: var(--jn-sp-1); font-size: var(--jn-fs-13); color: var(--jn-text-light); opacity: .8; }
+.jn-empty p { margin: 0; }
+
+/* ---------------------------------------------------------------------
+ 17. 列表页 / 搜索页(themeParams.listLayout:badge 日期徽标行 / plain 通栏行式)
+ --------------------------------------------------------------------- */
+.jn-list-main { margin: var(--jn-sp-8) auto; }
+
+.jn-page-cols { display: flex; align-items: flex-start; gap: var(--jn-sp-6); }
+
+/* 左侧栏目导航(docs/11) */
+.jn-side-nav {
+ flex: none;
+ width: 224px;
+ background: var(--jn-card-bg);
+ border: 1px solid var(--jn-border);
+ border-radius: var(--jn-radius-lg);
+ box-shadow: var(--jn-shadow-sm);
+ overflow: hidden;
+}
+.jn-side-nav-head {
+ padding: var(--jn-sp-4) var(--jn-sp-3);
+ background: var(--jn-primary);
+ color: var(--jn-ink);
+ font-size: var(--jn-fs-18);
+ font-weight: 700;
+ text-align: center;
+ letter-spacing: 3px;
+}
+.jn-side-nav-item + .jn-side-nav-item { border-top: 1px dashed var(--jn-border); }
+.jn-side-nav-item a {
+ display: block;
+ padding: var(--jn-sp-3) var(--jn-sp-4);
+ color: var(--jn-text);
+ font-size: var(--jn-fs-15);
+ transition: background var(--jn-speed) var(--jn-ease), color var(--jn-speed) var(--jn-ease),
+ padding-left var(--jn-speed) var(--jn-ease);
+}
+.jn-side-nav-item a:hover { background: var(--jn-mint-bg); color: var(--jn-primary); padding-left: var(--jn-sp-6); }
+.jn-side-nav-item.active a {
+ background: var(--jn-mint-bg);
+ border-left: 3px solid var(--jn-accent);
+ color: var(--jn-primary);
+ font-weight: 600;
+ padding-left: calc(var(--jn-sp-4) - 3px);
+}
+
+/* 内容卡 */
+.jn-page-card {
+ flex: 1;
+ min-width: 0;
+ background: var(--jn-card-bg);
+ border: 1px solid var(--jn-border);
+ border-radius: var(--jn-radius-lg);
+ box-shadow: var(--jn-shadow-sm);
+ padding: var(--jn-sp-8) var(--jn-sp-6);
+}
+
+/* 面包屑 */
+.jn-breadcrumb {
+ display: flex;
+ flex-wrap: wrap;
+ align-items: center;
+ gap: var(--jn-sp-2);
+ margin-bottom: var(--jn-sp-4);
+ color: var(--jn-text-light);
+ font-size: var(--jn-fs-13);
+}
+.jn-breadcrumb a { color: var(--jn-text-light); }
+.jn-breadcrumb a:hover { color: var(--jn-primary); }
+.jn-breadcrumb .crumb-sep { color: var(--jn-border); }
+.jn-breadcrumb .current { color: var(--jn-primary-dark); font-weight: 600; }
+
+.jn-page-title {
+ position: relative;
+ margin: 0 0 var(--jn-sp-6);
+ padding: var(--jn-sp-1) 0 var(--jn-sp-1) var(--jn-sp-4);
+ font-size: var(--jn-fs-28);
+ font-weight: 700;
+ color: var(--jn-text);
+}
+.jn-page-title::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 6px;
+ height: 70%;
+ border-radius: var(--jn-pill);
+ background: var(--jn-primary);
+}
+
+/* 文章列表 */
+.jn-article-list > li { padding: var(--jn-sp-4) 0; border-bottom: 1px solid var(--jn-border); }
+.jn-article-list > li:last-child { border-bottom: none; }
+
+.jn-item { display: flex; gap: var(--jn-sp-4); align-items: flex-start; }
+
+.jn-item-cover {
+ flex: none;
+ width: 176px;
+ aspect-ratio: 16 / 9;
+ border-radius: var(--jn-radius);
+ overflow: hidden;
+ background: var(--jn-mint-bg);
+}
+.jn-item-cover img { width: 100%; height: 100%; object-fit: cover; }
+
+.jn-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--jn-sp-1); }
+.jn-item-title { font-size: var(--jn-fs-18); font-weight: 600; line-height: 1.5; }
+.jn-item-title a:hover { color: var(--jn-primary); }
+
+.jn-item-summary {
+ color: var(--jn-text-light);
+ font-size: var(--jn-fs-14);
+ line-height: 1.7;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+
+.jn-item-meta { display: flex; align-items: center; gap: var(--jn-sp-3); margin-top: auto; color: var(--jn-text-light); font-size: var(--jn-fs-13); }
+
+/* —— 形态一(默认):日期徽标行(无封面条目带 46px 橙徽)—— */
+.jn-list--badge .jn-item--plain {
+ display: grid;
+ grid-template-columns: 46px minmax(0, 1fr);
+ gap: var(--jn-sp-4);
+ align-items: start;
+}
+.jn-list--badge .jn-item--plain .jn-item-time { display: none; } /* 时间并入徽标,不重复 */
+
+/* —— 形态二:通栏行式(日期右置,themeParams.listLayout=plain)—— */
+.jn-list--plain .jn-date-badge { display: none; } /* 徽标让位 */
+.jn-list--plain .jn-item--plain { display: flex; flex-direction: column; gap: var(--jn-sp-1); }
+.jn-list--plain .jn-item--plain .jn-item-title {
+ display: flex;
+ align-items: baseline;
+ justify-content: space-between;
+ gap: var(--jn-sp-4);
+}
+.jn-list--plain .jn-item--plain .jn-item-time { flex: none; }
+.jn-list--plain .jn-item--plain .jn-item-title > a {
+ flex: 1;
+ min-width: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ font-size: var(--jn-fs-16);
+}
+
+/* 分页 */
+.jn-pagination {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--jn-sp-2);
+ justify-content: center;
+ align-items: center;
+ padding: var(--jn-sp-8) 0 var(--jn-sp-2);
+}
+.jn-pagination a {
+ min-width: 36px;
+ padding: var(--jn-sp-1) var(--jn-sp-3);
+ border: 1px solid var(--jn-border);
+ border-radius: var(--jn-radius);
+ background: var(--jn-card-bg);
+ color: var(--jn-text-light);
+ font-size: var(--jn-fs-14);
+ text-align: center;
+ transition: border-color var(--jn-speed) var(--jn-ease), color var(--jn-speed) var(--jn-ease),
+ background var(--jn-speed) var(--jn-ease);
+}
+.jn-pagination a:hover { border-color: var(--jn-primary); color: var(--jn-primary); background: var(--jn-mint-bg); }
+.jn-pagination a.active { background: var(--jn-primary); border-color: var(--jn-primary); color: var(--jn-ink); font-weight: 600; }
+.jn-pagination a.disabled { opacity: .4; pointer-events: none; }
+
+/* ---------------------------------------------------------------------
+ 18. 详情页 / 单页
+ --------------------------------------------------------------------- */
+.jn-detail-main { margin: var(--jn-sp-8) auto; }
+
+.jn-article-title {
+ margin: var(--jn-sp-2) 0 var(--jn-sp-4);
+ font-size: var(--jn-fs-32);
+ font-weight: 700;
+ line-height: 1.4;
+ text-align: center;
+}
+
+.jn-article-meta {
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+ gap: var(--jn-sp-4);
+ padding: var(--jn-sp-2) 0 var(--jn-sp-4);
+ border-bottom: 1px solid var(--jn-border);
+ color: var(--jn-text-light);
+ font-size: var(--jn-fs-13);
+}
+
+.jn-article-content {
+ padding-top: var(--jn-sp-6);
+ font-size: var(--jn-fs-16);
+ line-height: 1.9;
+ color: var(--jn-text);
+ word-break: break-word;
+}
+.jn-article-content p { text-indent: 2em; margin: 0 0 var(--jn-sp-3); }
+.jn-article-content p:has(img), .jn-article-content figure p { text-indent: 0; text-align: center; }
+.jn-article-content p > img:only-child { display: inline-block; }
+.jn-article-content img { height: auto; border-radius: var(--jn-radius); }
+.jn-article-content figure { margin: var(--jn-sp-4) auto; text-align: center; text-indent: 0; }
+.jn-article-content figcaption { margin-top: var(--jn-sp-2); font-size: var(--jn-fs-13); color: var(--jn-text-light); }
+.jn-article-content h2, .jn-article-content h3 { margin: var(--jn-sp-6) 0 var(--jn-sp-3); }
+.jn-article-content h2 { font-size: var(--jn-fs-20); }
+.jn-article-content h3 { font-size: var(--jn-fs-18); }
+.jn-article-content ul, .jn-article-content ol { margin: 0 0 var(--jn-sp-3) 2em; text-indent: 0; list-style: disc; }
+.jn-article-content ol { list-style: decimal; }
+.jn-article-content li { margin-bottom: var(--jn-sp-1); }
+.jn-article-content a { color: var(--jn-primary); }
+.jn-article-content a:hover { text-decoration: underline; }
+.jn-article-content blockquote {
+ margin: var(--jn-sp-4) 0;
+ padding: var(--jn-sp-3) var(--jn-sp-4);
+ border-left: 4px solid var(--jn-accent);
+ border-radius: 0 var(--jn-radius) var(--jn-radius) 0;
+ background: var(--jn-mint-bg);
+ color: var(--jn-text-light);
+ text-indent: 0;
+}
+.jn-article-content table {
+ width: 100%;
+ margin: var(--jn-sp-4) 0;
+ border-collapse: collapse;
+ font-size: var(--jn-fs-14);
+}
+.jn-article-content table td,
+.jn-article-content table th { border: 1px solid var(--jn-border); padding: var(--jn-sp-2) var(--jn-sp-3); }
+.jn-article-content table th { background: var(--jn-mint-bg); font-weight: 600; }
+.jn-article-content table tbody tr:nth-child(even) { background: var(--jn-mint-bg); }
+.jn-article-content table tbody tr:hover { background: var(--jn-border); }
+
+/* 上下篇 */
+.jn-sibling {
+ display: grid;
+ grid-template-columns: repeat(2, minmax(0, 1fr));
+ gap: var(--jn-sp-4);
+ margin-top: var(--jn-sp-8);
+ padding-top: var(--jn-sp-6);
+ border-top: 1px solid var(--jn-border);
+}
+.jn-sibling a {
+ display: flex;
+ flex-direction: column;
+ gap: var(--jn-sp-1);
+ padding: var(--jn-sp-3) var(--jn-sp-4);
+ background: var(--jn-card-bg);
+ border: 1px solid var(--jn-border);
+ border-radius: var(--jn-radius-lg);
+ box-shadow: var(--jn-shadow-sm);
+ transition: border-color var(--jn-speed) var(--jn-ease), box-shadow var(--jn-speed) var(--jn-ease),
+ transform var(--jn-speed) var(--jn-ease);
+}
+.jn-sibling a:hover { border-color: var(--jn-primary); box-shadow: var(--jn-shadow-md); transform: translateY(-2px); }
+.jn-sibling a.next { text-align: right; }
+.jn-sib-label { font-size: var(--jn-fs-13); color: var(--jn-text-light); }
+.jn-sib-title {
+ font-size: var(--jn-fs-14);
+ color: var(--jn-text);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.jn-sibling a:hover .jn-sib-title { color: var(--jn-primary); }
+.jn-sibling .jn-sib-none {
+ display: flex;
+ flex-direction: column;
+ gap: var(--jn-sp-1);
+ padding: var(--jn-sp-3) var(--jn-sp-4);
+ background: var(--jn-mint-bg);
+ border: 1px dashed var(--jn-border);
+ border-radius: var(--jn-radius-lg);
+ color: var(--jn-text-light);
+}
+.jn-sibling .jn-sib-none.next { text-align: right; }
+
+/* ---------------------------------------------------------------------
+ 19. 服务中心 / 事项指南(事项库 R2,契约 docs/10 §3.4 消费端样式)
+ --------------------------------------------------------------------- */
+.jn-svc-page, .jn-svc-guide { display: block; }
+
+.jn-svc-unavailable { margin-top: var(--jn-sp-4); }
+
+/* 筛选区:三组 chip */
+.jn-svc-filters {
+ margin: var(--jn-sp-4) 0 var(--jn-sp-3);
+ padding: var(--jn-sp-3) var(--jn-sp-4);
+ background: var(--jn-mint-bg);
+ border-radius: var(--jn-radius-lg);
+}
+.jn-svc-filter-group { display: flex; align-items: flex-start; gap: var(--jn-sp-3); padding: var(--jn-sp-2) 0; }
+.jn-svc-filter-group + .jn-svc-filter-group { border-top: 1px dashed var(--jn-border); }
+.jn-svc-filter-label {
+ flex: none;
+ width: 4.5em;
+ padding-top: var(--jn-sp-1);
+ color: var(--jn-text-light);
+ font-size: var(--jn-fs-13);
+ font-weight: 600;
+}
+.jn-svc-filter-options { display: flex; flex-wrap: wrap; gap: var(--jn-sp-2); min-width: 0; }
+
+.jn-svc-chip {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--jn-sp-1);
+ padding: 2px var(--jn-sp-3);
+ background: var(--jn-card-bg);
+ border: 1px solid var(--jn-border);
+ border-radius: var(--jn-pill);
+ font-size: var(--jn-fs-13);
+ color: var(--jn-text);
+ transition: border-color var(--jn-speed) var(--jn-ease), color var(--jn-speed) var(--jn-ease);
+}
+.jn-svc-chip:hover { border-color: var(--jn-primary); color: var(--jn-primary); }
+.jn-svc-chip em { font-style: normal; color: var(--jn-text-light); font-size: var(--jn-fs-12); }
+.jn-svc-chip.active { background: var(--jn-primary); border-color: var(--jn-primary); color: var(--jn-ink); }
+.jn-svc-chip.active em { color: var(--jn-ink-soft); }
+
+/* 工具条 */
+.jn-svc-toolbar {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--jn-sp-3);
+ margin-bottom: var(--jn-sp-4);
+}
+.jn-svc-search { display: flex; }
+.jn-svc-search input {
+ width: 260px;
+ padding: 7px var(--jn-sp-3);
+ border: 1px solid var(--jn-border);
+ border-right: none;
+ border-radius: var(--jn-radius) 0 0 var(--jn-radius);
+ font-size: var(--jn-fs-14);
+ font-family: inherit;
+ outline: none;
+}
+.jn-svc-search input:focus { border-color: var(--jn-primary); }
+.jn-svc-search button {
+ padding: 7px var(--jn-sp-4);
+ border: none;
+ border-radius: 0 var(--jn-radius) var(--jn-radius) 0;
+ background: var(--jn-primary);
+ color: var(--jn-ink);
+ font-size: var(--jn-fs-14);
+ transition: background var(--jn-speed) var(--jn-ease);
+}
+.jn-svc-search button:hover { background: var(--jn-primary-dark); }
+.jn-svc-clear { font-size: var(--jn-fs-13); color: var(--jn-text-light); }
+.jn-svc-clear:hover { color: var(--jn-primary); }
+
+/* 事项列表行 */
+.jn-svc-list li { border-bottom: 1px solid var(--jn-border); }
+.jn-svc-list li:last-child { border-bottom: none; }
+.jn-svc-list li:hover { background: var(--jn-mint-bg); }
+.jn-svc-item { display: flex; gap: var(--jn-sp-4); padding: var(--jn-sp-4) var(--jn-sp-2); }
+.jn-svc-item-cover {
+ flex: none;
+ width: 96px;
+ height: 64px;
+ border: 1px solid var(--jn-border);
+ border-radius: var(--jn-radius);
+ overflow: hidden;
+ background: var(--jn-mint-bg);
+}
+.jn-svc-item-cover img { width: 100%; height: 100%; object-fit: cover; }
+.jn-svc-item-body { display: flex; flex-direction: column; gap: var(--jn-sp-1); min-width: 0; }
+.jn-svc-item-title { display: flex; align-items: center; gap: var(--jn-sp-2); flex-wrap: wrap; }
+.jn-svc-item-name { font-size: var(--jn-fs-16); font-weight: 600; color: var(--jn-text); }
+.jn-svc-item:hover .jn-svc-item-name { color: var(--jn-primary); }
+.jn-svc-tag {
+ flex: none;
+ padding: 1px var(--jn-sp-2);
+ border: 1px solid var(--jn-border);
+ border-radius: var(--jn-radius);
+ background: var(--jn-card-bg);
+ color: var(--jn-text-light);
+ font-size: var(--jn-fs-12);
+ line-height: 1.6;
+}
+.jn-svc-tag.online { background: var(--jn-primary); border-color: var(--jn-primary); color: var(--jn-ink); }
+.jn-svc-item-summary {
+ color: var(--jn-text-light);
+ font-size: var(--jn-fs-14);
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+.jn-svc-item-meta { display: flex; gap: var(--jn-sp-4); color: var(--jn-text-light); font-size: var(--jn-fs-13); }
+
+/* 指南页 */
+.jn-svc-guide-body { display: block; }
+.jn-svc-apply { display: flex; align-items: center; gap: var(--jn-sp-3); margin: var(--jn-sp-4) 0; }
+.jn-svc-apply-btn {
+ display: inline-block;
+ padding: var(--jn-sp-2) var(--jn-sp-8);
+ border-radius: var(--jn-pill);
+ background: var(--jn-accent);
+ color: var(--jn-ink);
+ font-size: var(--jn-fs-16);
+ font-weight: 600;
+ transition: background var(--jn-speed) var(--jn-ease), transform var(--jn-speed) var(--jn-ease);
+}
+.jn-svc-apply-btn:hover { background: var(--jn-primary); color: var(--jn-ink); transform: translateY(-1px); }
+.jn-svc-apply-hint { color: var(--jn-text-light); font-size: var(--jn-fs-13); }
+
+.jn-svc-summary {
+ padding: var(--jn-sp-3) var(--jn-sp-4);
+ background: var(--jn-mint-bg);
+ border-left: 3px solid var(--jn-primary);
+ border-radius: 0 var(--jn-radius) var(--jn-radius) 0;
+ color: var(--jn-text-light);
+}
+
+.jn-svc-info { width: 100%; margin: var(--jn-sp-4) 0; border-collapse: collapse; font-size: var(--jn-fs-14); }
+.jn-svc-info th, .jn-svc-info td {
+ border: 1px solid var(--jn-border);
+ padding: var(--jn-sp-2) var(--jn-sp-4);
+ text-align: left;
+ vertical-align: top;
+}
+.jn-svc-info th {
+ width: 7em;
+ background: var(--jn-mint-bg);
+ color: var(--jn-text-light);
+ font-weight: 600;
+ white-space: nowrap;
+}
+
+.jn-svc-section { margin: var(--jn-sp-6) 0; }
+.jn-svc-section h2 {
+ margin-bottom: var(--jn-sp-3);
+ padding-bottom: var(--jn-sp-2);
+ border-bottom: 2px solid var(--jn-primary);
+ font-size: var(--jn-fs-20);
+}
+
+.jn-svc-attachments li {
+ display: flex;
+ align-items: center;
+ gap: var(--jn-sp-3);
+ padding: var(--jn-sp-2) 0;
+ border-bottom: 1px dashed var(--jn-border);
+}
+.jn-svc-attachments li:last-child { border-bottom: none; }
+.jn-svc-attachments a { color: var(--jn-primary); }
+.jn-svc-attachments a:hover { text-decoration: underline; }
+.jn-svc-att-size { color: var(--jn-text-light); font-size: var(--jn-fs-13); }
+
+.jn-svc-links {
+ display: flex;
+ gap: var(--jn-sp-3);
+ margin: var(--jn-sp-6) 0 0;
+ padding-top: var(--jn-sp-4);
+ border-top: 1px dashed var(--jn-border);
+}
+.jn-svc-links a {
+ padding: var(--jn-sp-1) var(--jn-sp-4);
+ border: 1px solid var(--jn-border);
+ border-radius: var(--jn-pill);
+ font-size: var(--jn-fs-13);
+ color: var(--jn-text-light);
+ transition: border-color var(--jn-speed) var(--jn-ease), color var(--jn-speed) var(--jn-ease);
+}
+.jn-svc-links a:hover { border-color: var(--jn-primary); color: var(--jn-primary); }
+
+/* 相关服务侧区 */
+.jn-svc-related { margin-top: var(--jn-sp-8); }
+.jn-svc-related-list { margin-top: var(--jn-sp-3); }
+.jn-svc-related-list li { border-bottom: 1px solid var(--jn-border); }
+.jn-svc-related-list li:last-child { border-bottom: none; }
+.jn-svc-related-list a {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--jn-sp-3);
+ padding: var(--jn-sp-3) var(--jn-sp-2);
+}
+.jn-svc-related-list li:hover { background: var(--jn-mint-bg); }
+.jn-svc-related-name {
+ font-size: var(--jn-fs-15);
+ color: var(--jn-text);
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.jn-svc-related-list a:hover .jn-svc-related-name { color: var(--jn-primary); }
+.jn-svc-related-meta { display: flex; align-items: center; gap: var(--jn-sp-2); flex: none; }
+.jn-svc-related-meta > span:not(.jn-svc-tag) { color: var(--jn-text-light); font-size: var(--jn-fs-13); }
+
+/* ---------------------------------------------------------------------
+ 20. 页脚(薄荷友链带 + 翡翠深青多列主区 + 深色底条)
+ --------------------------------------------------------------------- */
+/* 友链带(浅薄荷底,无分组整段不渲染) */
+.jn-footer-links {
+ margin-top: var(--jn-sp-8);
+ background: var(--jn-mint-bg);
+ border-top: 1px solid var(--jn-border);
+}
+.jn-footer-links-inner {
+ max-width: var(--jn-max);
+ margin: 0 auto;
+ padding: var(--jn-sp-4) var(--jn-gutter);
+ display: flex;
+ flex-direction: column;
+ gap: var(--jn-sp-2);
+}
+.jn-links-group {
+ display: flex;
+ flex-wrap: wrap;
+ gap: var(--jn-sp-2) var(--jn-sp-4);
+ align-items: baseline;
+ font-size: var(--jn-fs-13);
+}
+.jn-group-name {
+ position: relative;
+ margin-right: var(--jn-sp-2);
+ padding-left: var(--jn-sp-3);
+ color: var(--jn-primary-dark);
+ font-weight: 600;
+}
+.jn-group-name::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 50%;
+ width: 5px;
+ height: 5px;
+ margin-top: -2.5px;
+ border-radius: 50%;
+ background: var(--jn-accent);
+}
+.jn-links-group a { color: var(--jn-text-light); }
+.jn-links-group a:hover { color: var(--jn-primary); }
+
+/* B4 友链 Logo:与名称并排小图 */
+.link-logo {
+ height: 20px;
+ width: auto;
+ max-width: 64px;
+ object-fit: contain;
+ vertical-align: middle;
+ margin-right: var(--jn-sp-1);
+ border-radius: 2px;
+ display: inline-block;
+}
+
+/* 主区:翡翠深青 */
+.jn-footer { background: var(--jn-footer-bg); color: var(--jn-ink-soft); }
+
+.jn-footer-inner {
+ max-width: var(--jn-max);
+ margin: 0 auto;
+ padding: var(--jn-sp-8) var(--jn-gutter) var(--jn-sp-6);
+ display: grid;
+ grid-template-columns: minmax(0, 2fr) minmax(0, 3fr) auto;
+ gap: var(--jn-sp-8);
+ align-items: start;
+}
+
+/* 品牌列:校徽 + 站名 + 社媒图标行 */
+.jn-footer-brand { min-width: 0; }
+.jn-footer-logo-row { display: flex; align-items: center; gap: var(--jn-sp-3); margin-bottom: var(--jn-sp-4); }
+.jn-footer-logo { height: 48px; width: auto; }
+.jn-footer-badge {
+ flex: none;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 48px;
+ height: 48px;
+ border-radius: 50%;
+ color: var(--jn-ink);
+ background: rgba(255, 255, 255, .12);
+}
+.jn-footer-site {
+ font-size: var(--jn-fs-20);
+ font-weight: 600;
+ color: var(--jn-ink);
+ letter-spacing: 1px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+/* 社媒图标(config social_*,有值才渲染;描边圆 hover 反白) */
+.jn-social { display: flex; gap: var(--jn-sp-3); }
+.jn-social-icon {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ width: 36px;
+ height: 36px;
+ border: 1px solid var(--jn-ink-faint);
+ border-radius: 50%;
+ color: var(--jn-ink-soft);
+ transition: background var(--jn-speed) var(--jn-ease), color var(--jn-speed) var(--jn-ease),
+ border-color var(--jn-speed) var(--jn-ease);
+}
+.jn-social-icon:hover {
+ background: var(--jn-ink);
+ border-color: var(--jn-ink);
+ color: var(--jn-footer-bg);
+}
+
+/* 信息列:多校区地址 + 联系/版权/备案 */
+.jn-footer-info { font-size: var(--jn-fs-13); line-height: 2; min-width: 0; }
+.jn-footer-addr { margin: 0 0 var(--jn-sp-2); padding: 0; list-style: none; }
+.jn-footer-addr li { display: flex; align-items: baseline; gap: var(--jn-sp-2); color: var(--jn-ink-soft); }
+.jn-footer-addr li::before {
+ content: "";
+ flex: none;
+ width: 5px;
+ height: 5px;
+ border-radius: 50%;
+ background: var(--jn-accent);
+ transform: translateY(-2px);
+}
+.jn-footer-line { margin: 0; color: var(--jn-ink-soft); }
+.jn-footer-info a { color: var(--jn-ink-soft); }
+.jn-footer-info a:hover { color: var(--jn-ink); }
+
+/* 二维码列(config qr_wechat/qr_weibo,hover 轻抬) */
+.jn-footer-qr { display: flex; gap: var(--jn-sp-4); }
+.jn-qr { margin: 0; text-align: center; }
+.jn-qr img {
+ width: 96px;
+ height: 96px;
+ padding: var(--jn-sp-1);
+ background: var(--jn-ink);
+ border-radius: var(--jn-radius);
+ object-fit: contain;
+ transition: transform var(--jn-speed) var(--jn-ease);
+}
+.jn-qr:hover img { transform: translateY(-3px); }
+.jn-qr figcaption { margin-top: var(--jn-sp-2); font-size: var(--jn-fs-12); color: var(--jn-ink-soft); }
+
+/* 底条(中性黑透明叠深,随 footerBg 参数自适应) */
+.jn-footer-bottom { background: rgba(0, 0, 0, .18); }
+.jn-footer-bottom-inner {
+ max-width: var(--jn-max);
+ margin: 0 auto;
+ padding: var(--jn-sp-3) var(--jn-gutter);
+ text-align: center;
+ font-size: var(--jn-fs-13);
+ color: var(--jn-ink-faint);
+}
+.jn-footer-bottom-inner p { margin: var(--jn-sp-1) 0; }
+
+/* ---------------------------------------------------------------------
+ 21. 响应式(≤1024 折中 / ≤768 单列 + 导航折叠)
+ --------------------------------------------------------------------- */
+@media (max-width: 1024px) {
+ .jn-headline { grid-template-columns: minmax(0, 1fr); }
+ .jn-blocks { grid-template-columns: minmax(0, 1fr); }
+ .jn-split { grid-template-columns: minmax(0, 1fr); }
+ .jn-block-list--two { grid-template-columns: minmax(0, 1fr); }
+ .jn-quick-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
+ .jn-fusion-row { grid-template-columns: repeat(4, minmax(0, 1fr)); }
+ .jn-footer-inner { grid-template-columns: minmax(0, 1fr) auto; }
+ .jn-footer-brand { grid-column: 1 / -1; }
+}
+
+@media (max-width: 768px) {
+ :root { --jn-gutter: 16px; }
+
+ /* 顶条:居中收敛 */
+ .jn-topbar-inner { justify-content: center; }
+ .jn-topbar-side { display: none; }
+
+ /* 品牌行:纵向堆叠,搜索通栏 */
+ .jn-brandbar-inner { flex-direction: column; align-items: stretch; gap: var(--jn-sp-3); padding: var(--jn-sp-3) var(--jn-gutter); }
+ .jn-brand { justify-content: center; }
+ .jn-logo { height: 42px; }
+ .jn-site-name { font-size: var(--jn-fs-20); text-align: center; }
+ .jn-tools { justify-content: center; }
+ .jn-search { width: 100%; }
+ .jn-search input { flex: 1; width: auto; min-width: 0; }
+
+ /* 主导航折叠(checkbox 纯 CSS) */
+ .jn-nav-btn { display: flex; }
+ .jn-nav > ul {
+ display: none;
+ flex-direction: column;
+ padding: 0 var(--jn-gutter) var(--jn-sp-2);
+ }
+ .jn-nav-fold:checked ~ ul { display: flex; } /* label 在 ul 前,兄弟选择器展开 */
+ .jn-nav > ul > li > a { width: 100%; height: auto; padding: var(--jn-sp-3) var(--jn-sp-4); font-size: var(--jn-fs-15); }
+ .jn-nav > ul > li > a::after { display: none; }
+ .jn-nav > ul > li:hover > a { background: var(--jn-primary-dark); }
+ /* 触屏无 hover:二级静态平铺 */
+ .jn-sub {
+ display: block;
+ position: static;
+ min-width: 0;
+ padding: 0;
+ background: var(--jn-primary-dark);
+ border: none;
+ border-radius: 0;
+ box-shadow: none;
+ }
+ .jn-sub li a { color: var(--jn-ink-soft); padding: var(--jn-sp-2) var(--jn-sp-4) var(--jn-sp-2) var(--jn-sp-8); }
+ .jn-sub li a:hover { background: rgba(255, 255, 255, .08); color: var(--jn-ink); padding-left: var(--jn-sp-8); }
+ .jn-sub li.active a { color: var(--jn-ink); }
+
+ /* banner:4:3 竖构图收敛 */
+ .jn-banner-slides { aspect-ratio: 4 / 3; max-height: none; }
+ .jn-banner-title { font-size: var(--jn-fs-16); bottom: var(--jn-sp-6); padding: var(--jn-sp-2) var(--jn-sp-4); }
+ .jn-banner-arrow { display: none; }
+
+ /* 首页区块单列 */
+ .jn-wall, .jn-shots { grid-template-columns: repeat(2, minmax(0, 1fr)); }
+ .jn-quick-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
+ .jn-fusion-row { grid-template-columns: repeat(3, minmax(0, 1fr)); }
+ .jn-block, .jn-page-card { padding: var(--jn-sp-4) var(--jn-sp-3); }
+ .jn-block-head h2, .jn-section-title { font-size: var(--jn-fs-20); }
+
+ /* 列表/详情:侧栏置顶横滑 */
+ .jn-page-cols { flex-direction: column; gap: var(--jn-sp-3); }
+ .jn-side-nav { width: 100%; }
+ .jn-side-nav-list { display: flex; overflow-x: auto; -webkit-overflow-scrolling: touch; }
+ .jn-side-nav-item { flex: none; }
+ .jn-side-nav-item + .jn-side-nav-item { border-top: none; border-left: 1px dashed var(--jn-border); }
+ .jn-side-nav-item a { white-space: nowrap; padding: var(--jn-sp-3) var(--jn-sp-4); }
+ .jn-side-nav-item.active a { border-left: none; border-bottom: 3px solid var(--jn-accent); padding-left: var(--jn-sp-4); }
+
+ .jn-item { flex-direction: column; }
+ .jn-item-cover { width: 100%; }
+ .jn-article-title { font-size: var(--jn-fs-24); }
+ .jn-sibling { grid-template-columns: minmax(0, 1fr); }
+
+ /* 服务中心 */
+ .jn-svc-toolbar { flex-direction: column; align-items: stretch; }
+ .jn-svc-search input { width: auto; flex: 1; min-width: 0; }
+ .jn-svc-filter-group { flex-direction: column; gap: var(--jn-sp-1); }
+ .jn-svc-filter-label { width: auto; padding-top: 0; }
+ .jn-svc-item { flex-direction: column; gap: var(--jn-sp-2); }
+ .jn-svc-item-cover { width: 100%; height: 120px; }
+ .jn-svc-info th { width: 5.5em; }
+ .jn-svc-related-list a { flex-direction: column; align-items: flex-start; }
+
+ /* 页脚单列 */
+ .jn-footer-inner { grid-template-columns: minmax(0, 1fr); gap: var(--jn-sp-4); }
+ .jn-footer-brand { grid-column: auto; }
+ .jn-footer-logo-row { justify-content: center; }
+ .jn-footer-qr { justify-content: center; }
+}
+
+/* ---------------------------------------------------------------------
+ 22. 打印样式(公告高频打印场景:去导航/页脚/交互件,正文降噪)
+ --------------------------------------------------------------------- */
+@media print {
+ .jn-topbar, .jn-brandbar, .jn-nav, .jn-banner,
+ .jn-footer-links, .jn-footer, .jn-sibling, .jn-pagination,
+ .jn-side-nav, .jn-search, .jn-colleges, .jn-svc-apply,
+ .jn-svc-filters, .jn-svc-toolbar, .jn-svc-related, .skip-link { display: none !important; }
+
+ body { background: #fff; color: #000; font-size: 12pt; }
+ .jn-page-card { border: none; box-shadow: none; padding: 0; margin: 0; max-width: 100%; }
+ .jn-article-title { font-size: 20pt; }
+ .jn-article-content { font-size: 11.5pt; line-height: 1.8; }
+ .jn-article-content p { text-indent: 2em; }
+ .jn-article-content table th { background: #eee !important; }
+ a { color: inherit; }
+}
diff --git a/src/main/resources/templates/themes/jade-normal/assets/favicon.png b/src/main/resources/templates/themes/jade-normal/assets/favicon.png
new file mode 100644
index 0000000..822653c
Binary files /dev/null and b/src/main/resources/templates/themes/jade-normal/assets/favicon.png differ
diff --git a/src/main/resources/templates/themes/jade-normal/assets/js/main.js b/src/main/resources/templates/themes/jade-normal/assets/js/main.js
new file mode 100644
index 0000000..815d823
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/assets/js/main.js
@@ -0,0 +1,88 @@
+/* jade-normal(师大青)皮肤包脚本:顶条日期 + 首页轮播(自动播放/圆点/箭头/悬停暂停/键盘),无任何外部依赖。
+ 选择器与 main.css / home.html 的 jn-* 类名一一对应;导航折叠由 CSS(checkbox + label)承担,无需 JS。 */
+(function () {
+ /* 顶条日期(本地时间,YYYY年M月D日 星期X) */
+ var dateEl = document.getElementById('siteDate');
+ if (dateEl) {
+ var now = new Date();
+ var week = ['日', '一', '二', '三', '四', '五', '六'][now.getDay()];
+ dateEl.textContent = now.getFullYear() + '年' + (now.getMonth() + 1) + '月'
+ + now.getDate() + '日 星期' + week;
+ }
+
+ /* 轮播(.jn-banner,见 home.html) */
+ var root = document.querySelector('.jn-banner');
+ var slides = document.querySelectorAll('.jn-banner-slide');
+ var dots = document.querySelectorAll('.jn-banner-dots button');
+ var prevBtn = document.querySelector('.jn-banner-arrow.prev');
+ var nextBtn = document.querySelector('.jn-banner-arrow.next');
+ if (!slides.length || !root) {
+ return;
+ }
+ var current = 0;
+ var timer = null;
+ var INTERVAL = 5000;
+
+ function show(index) {
+ slides[current].classList.remove('active');
+ if (dots[current]) {
+ dots[current].classList.remove('active');
+ }
+ current = (index + slides.length) % slides.length;
+ slides[current].classList.add('active');
+ if (dots[current]) {
+ dots[current].classList.add('active');
+ }
+ }
+
+ function start() {
+ stop();
+ if (slides.length > 1) {
+ timer = window.setInterval(function () {
+ show(current + 1);
+ }, INTERVAL);
+ }
+ }
+
+ function stop() {
+ if (timer) {
+ window.clearInterval(timer);
+ timer = null;
+ }
+ }
+
+ dots.forEach(function (dot, index) {
+ dot.addEventListener('click', function () {
+ show(index);
+ start();
+ });
+ });
+ if (prevBtn) {
+ prevBtn.addEventListener('click', function () {
+ show(current - 1);
+ start();
+ });
+ }
+ if (nextBtn) {
+ nextBtn.addEventListener('click', function () {
+ show(current + 1);
+ start();
+ });
+ }
+ root.addEventListener('mouseenter', stop);
+ root.addEventListener('mouseleave', start);
+ root.addEventListener('focusin', stop);
+ root.addEventListener('focusout', start);
+ root.setAttribute('tabindex', '-1');
+ root.addEventListener('keydown', function (e) {
+ if (e.key === 'ArrowLeft') {
+ show(current - 1);
+ start();
+ } else if (e.key === 'ArrowRight') {
+ show(current + 1);
+ start();
+ }
+ });
+
+ start();
+})();
diff --git a/src/main/resources/templates/themes/jade-normal/assets/screenshot.png b/src/main/resources/templates/themes/jade-normal/assets/screenshot.png
new file mode 100644
index 0000000..f3991bc
Binary files /dev/null and b/src/main/resources/templates/themes/jade-normal/assets/screenshot.png differ
diff --git a/src/main/resources/templates/themes/jade-normal/detail.html b/src/main/resources/templates/themes/jade-normal/detail.html
new file mode 100644
index 0000000..f27c7a7
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/detail.html
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 文章标题
+
+
+ 作者
+ 来源
+ 浏览量
+
+
+ 正文
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/jade-normal/fragments/footer.html b/src/main/resources/templates/themes/jade-normal/fragments/footer.html
new file mode 100644
index 0000000..e360e93
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/fragments/footer.html
@@ -0,0 +1,105 @@
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/jade-normal/fragments/head.html b/src/main/resources/templates/themes/jade-normal/fragments/head.html
new file mode 100644
index 0000000..be2097f
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/fragments/head.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+ 页面标题
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/jade-normal/fragments/header.html b/src/main/resources/templates/themes/jade-normal/fragments/header.html
new file mode 100644
index 0000000..0dd0d83
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/fragments/header.html
@@ -0,0 +1,89 @@
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/jade-normal/fragments/home-blocks.html b/src/main/resources/templates/themes/jade-normal/fragments/home-blocks.html
new file mode 100644
index 0000000..0e17cf2
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/fragments/home-blocks.html
@@ -0,0 +1,316 @@
+
+
+
+
+
+
+
+
+
+ -
+
+ 01
+ 2026-01
+
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+ 媒体来源
+ 文章标题
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+ 01
+ 2026-01
+
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
校园映像
+
+
+ Campus Gallery
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/jade-normal/guide.html b/src/main/resources/templates/themes/jade-normal/guide.html
new file mode 100644
index 0000000..c482165
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/guide.html
@@ -0,0 +1,133 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
事项服务暂时不可用,请稍后再试
+
事项数据服务暂不可达,稍后刷新即可恢复
+
+
+
+ 事项名称
+
+ 办理部门
+ 办理方式
+
+ 浏览量
+
+
+
+
+
+ 简介
+
+
+ 事项基本信息
+
+
+ | 服务对象 |
+ 服务对象 |
+
+
+ | 事项类别 |
+ 事项类别 |
+
+
+ | 办理地点 |
+ 办理地点 |
+
+
+ | 办理时限 |
+ 办理时限 |
+
+
+ | 承诺时限 |
+ 承诺时限 |
+
+
+ | 咨询电话 |
+ 咨询电话 |
+
+
+ | 监督投诉 |
+ 监督投诉电话 |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/jade-normal/home.html b/src/main/resources/templates/themes/jade-normal/home.html
new file mode 100644
index 0000000..b7fdb58
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/home.html
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
头条推荐
+
+
+ -
+ 头条标题
+
+ 置顶
+
+
+
+ -
+ 置顶
+ 文章标题
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/jade-normal/list.html b/src/main/resources/templates/themes/jade-normal/list.html
new file mode 100644
index 0000000..57d09d3
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/list.html
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
栏目名
+
搜索词
+
+
+
+ -
+
+
+
+
+
+
+
摘要
+
+
+ 置顶
+
+
+
+
+
+
+
+
未找到相关内容
+
栏目暂无内容
+
换个关键词试试
+
内容发布后将在此展示
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/jade-normal/service.html b/src/main/resources/templates/themes/jade-normal/service.html
new file mode 100644
index 0000000..d766b6d
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/service.html
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
服务中心
+
+
+
+
事项服务暂时不可用,请稍后再试
+
事项数据服务暂不可达,稍后刷新即可恢复
+
+
+
+
+
+
+
+
+
未找到符合条件的服务事项
+
服务中心暂未上架事项
+
换个筛选条件或关键词试试
+
事项发布后将在此展示
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/jade-normal/single.html b/src/main/resources/templates/themes/jade-normal/single.html
new file mode 100644
index 0000000..e63d749
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/single.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 栏目名
+
+ 单页内容
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/jade-normal/theme.json b/src/main/resources/templates/themes/jade-normal/theme.json
new file mode 100644
index 0000000..0fcb53e
--- /dev/null
+++ b/src/main/resources/templates/themes/jade-normal/theme.json
@@ -0,0 +1,30 @@
+{
+ "specVersion": 1,
+ "name": "jade-normal",
+ "title": "师大青(jade-normal)",
+ "version": "1.0.0",
+ "author": "yunhai",
+ "description": "翡翠青+暖橙点缀的师范院校风(设计语言参考信阳师范大学官网)。",
+ "screenshot": "assets/screenshot.png",
+ "bannerSize": "1920x560",
+ "params": [
+ { "key": "primary", "cssVar": "--jn-primary", "label": "主色·翡翠青", "type": "color", "default": "#008D3F" },
+ { "key": "primaryDark", "cssVar": "--jn-primary-dark", "label": "主色加深", "type": "color", "default": "#04682E" },
+ { "key": "primaryLight", "cssVar": "--jn-primary-light","label": "主色提亮", "type": "color", "default": "#35B371" },
+ { "key": "accent", "cssVar": "--jn-accent", "label": "点缀橙·日期徽标", "type": "color", "default": "#F18D00" },
+ { "key": "navBg", "cssVar": "--jn-nav-bg", "label": "主导航条底色", "type": "color", "default": "#008D3F" },
+ { "key": "footerBg", "cssVar": "--jn-footer-bg", "label": "页脚底色", "type": "color", "default": "#04682E" },
+ { "key": "text", "cssVar": "--jn-text", "label": "正文文字色", "type": "color", "default": "#2E3A33" },
+ { "key": "textLight", "cssVar": "--jn-text-light", "label": "次要文字色", "type": "color", "default": "#6E7F75" },
+ { "key": "bg", "cssVar": "--jn-bg", "label": "页面底色", "type": "color", "default": "#F4FAF6" },
+ { "key": "cardBg", "cssVar": "--jn-card-bg", "label": "卡片底色", "type": "color", "default": "#FFFFFF" },
+ { "key": "border", "cssVar": "--jn-border", "label": "边框色", "type": "color", "default": "#DFEEE5" },
+ { "key": "mintBg", "cssVar": "--jn-mint-bg", "label": "薄荷底·背景带", "type": "color", "default": "#E7F6EE" },
+ { "key": "listLayout", "label": "列表页形态", "type": "select", "default": "badge",
+ "options": [
+ { "value": "badge", "label": "日期徽标行(橙色日徽)" },
+ { "value": "plain", "label": "通栏行式(日期右置)" }
+ ]
+ }
+ ]
+}
diff --git a/src/main/resources/templates/themes/poly-blue/README.md b/src/main/resources/templates/themes/poly-blue/README.md
new file mode 100644
index 0000000..2874693
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/README.md
@@ -0,0 +1,56 @@
+# poly-blue(理工蓝)
+
+理工院校风皮肤包:以 `default` 为基座派生,配色与首页区块形态按浙江理工大学官网(www.zstu.edu.cn)设计语言重做
+(仅学设计语言,不复制实现)。配了 `home_layout` 的站点,首页正文区块由本主题 `fragments/home-blocks.html` 渲染——
+派生包不自带区块形态时,正文会落到 `themes/common` 的通用骨架,换肤就只剩页头页脚(线上事故根因,见《审计验收清单-20260919》)。
+
+## 风格定位
+
+- 主色深宝蓝 `#0558a5` + 加深 `#124489` + 提亮 `#258cff` + 活力橙 `#ff7b00`(热词/来源徽标/「更多」与 hover 强调)+ 绿色小标签 `#1c7b46`。
+- 头部为「深宝蓝通栏品牌行(校名 + 受众标签 + 搜索框带热门搜索词)+ 白底吸顶主导航(当前栏目主色下划线)」;
+ 页脚深宝蓝 `#124489` 多列(品牌+社媒 / 多校区地址 / 二维码位)+ 更深色 `#0b2f5c` 底条。
+- 工艺:全局 radius 6px、间距阶梯 4/8/12/16/24/32/48、字号阶梯 12-36、hover 过渡 0.2s ease、
+ 焦点态 outline 2px primaryLight、卡片 hover 阴影抬升;渐变仅 2 处且均为功能性文字遮罩(轮播标题/图片墙标题);
+ 无玻璃拟态、无粉紫、无大圆角。列表无封面行用 46px 日期方块(日大号 + 年月小号,主色底白字)。
+- `headerStyle` select 参数:`banner`(默认,通栏横幅头图完整形态)/ `plain`(收起受众行与热词、压低品牌行的简洁顶栏)。
+
+## 参数取值建议(theme_params,13 个)
+
+| key | 默认 | 建议 |
+| -- | -- | -- |
+| `primary` | `#0558a5` | 品牌行/下划线/日期方块主色;改浅不建议超过 `#1a6cc5`,否则白字对比不足 |
+| `primaryDark` | `#124489` | 页脚主底;与 footerBg 联动改 |
+| `primaryLight` | `#258cff` | hover 链接/焦点描边;与 primary 拉开明度差 |
+| `accent` | `#ff7b00` | 活力橙:热词圆点/来源徽标/更多按钮 hover;可换校方第二识别色(如 `#e60012` 红),保持高饱和 |
+| `secondary` | `#1c7b46` | 绿色小标签(可在线办理等正向态),建议保持绿系 |
+| `navBg` | `#ffffff` | 主导航底色;保持白或极浅色,深色会破坏「白底吸顶」形态 |
+| `footerBg` | `#124489` | 页脚主底;底条为固定更深色 `#0b2f5c`(派生令牌) |
+| `text` / `textLight` | `#2f3a47` / `#708090` | 正文/次要文字 |
+| `bg` | `#f5f8fc` | 页面底色;偏蓝灰的浅底最有「理工」味,可换 `#f7f9fb` 提亮 |
+| `cardBg` / `border` | `#ffffff` / `#e2e8f2` | 卡片底/分隔线 |
+| `headerStyle` | `banner` | 结构开关:`plain` = 简洁顶栏(受众行/热词隐藏、品牌行压低) |
+
+## 首页区块形态(布局模式与回落模式同构)
+
+| homeStyle / type | 呈现 | 类名 |
+| -- | -- | -- |
+| `news_grid` | 双栏要闻:左 3 份大图文头条卡(16:9 封面 + 标题 + 摘要 + 日期/来源元信息)、右 2 份校园经纬紧凑行(圆点 + 日期右对齐);区块背景可取站点 `news_bg_image` | `pb-split` / `pb-news-*` / `pb-brief-*` |
+| `compact` | 通知公告:46px 日期方块(日大号 + 年月小号,主色底白字)+ 标题行 | `pb-notice-item` / `pb-date-chip` |
+| `media_focus` | 媒体理工:来源徽标(活力橙小 tag)+ 双列密行 | `pb-media-*` / `pb-src--tag` |
+| `image_wall` | 四列图片墙:封面 + 底部渐变遮罩标题,hover 抬图 | `pb-wall` |
+| (空/未知) | 整宽区块卡:头条 + 行式列表 | `pb-block--flow` |
+| `ticker` | 主蓝要闻速递横条(单行不换行、超长省略,中文不塌列) | `pb-ticker*` |
+| `gallery` | 线上展厅:居中双语文区头 + 四列图墙 | `pb-gallery` |
+| `links` | 快捷通道:图标宫格卡(主色描边浅底,整卡 hover 反白填色) | `pb-channels` / `pb-channel` |
+
+## 契约要点
+
+- 结构类前缀 `pb-`,CSS 变量前缀 `--pb-`;`:root` 把 `--pb-*` 别名到皮肤契约变量(`--primary`/`--text`/`--card-bg`/`--border`…),
+ 使 `themes/common` 兜底骨架与站点 `theme_params` 换色能穿透到首页区块。
+- 品牌行受众标签(考生/在校生/教职工/校友)为静态标签位:CMS 暂无受众分组数据源,不造空链接;
+ 热门搜索词经 `url.search(词, null)` 生成真实搜索链接。
+- 空态文案「栏目暂无内容」只在 `block.items` 为空时出现;守卫必须写在 `th:block` 外层——
+ `th:replace`(优先级 100)先于 `th:if`(300)求值,写在同一标签上等于没写。
+- 绝对定位背景带层序:`.pb-sec-bg` z-index:0,其后首个 `.pb-block` z-index:1。
+- 响应式:≤992 收起左侧栏并单列;≤768 品牌行纵排 + 汉堡抽屉 + 二级手风琴;网格一律 `minmax(0,1fr)`(390px 不溢出)。
+- 门禁:`ThemeContractIT`(7 条路由)+ `./verify-theme.sh poly-blue`;受众标签/热词为静态文案属预期,非死链。
diff --git a/src/main/resources/templates/themes/poly-blue/assets/css/main.css b/src/main/resources/templates/themes/poly-blue/assets/css/main.css
new file mode 100644
index 0000000..41584cb
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/assets/css/main.css
@@ -0,0 +1,1593 @@
+/* =====================================================================
+ poly-blue · 理工蓝(基座 default,设计语言参考浙江理工大学官网 zstu.edu.cn)
+ 设计语言:深宝蓝通栏品牌行(校名/受众/搜索热词)+ 白底吸顶主导航(当前项主色下划线)
+ + 通栏大图轮播(图上左下角标题渐变遮罩)+ 双栏要闻(左大图头条/右密行)
+ + 46px 日期方块通知 + 媒体来源徽标(活力橙)+ 快捷通道图标宫格
+ + 深宝蓝多列页脚(更深色底条)。
+ 工艺约束:全局 radius 6px;间距阶梯 4/8/12/16/24/32/48px;字号阶梯 12/13/14/15/16/18/20/24/28/36;
+ hover 过渡 0.2s ease;焦点态 outline 2px primaryLight;渐变仅 2 处且均为功能性文字遮罩
+ (轮播标题遮罩 / 图片墙标题遮罩);无玻璃拟态、无粉紫、无大圆角。
+ 色彩令牌全部走 CSS 变量,theme.json color 参数经 :root 覆盖真实生效。
+ ===================================================================== */
+
+/* ---------------------------------------------------------------------
+ 1. 设计令牌(与 theme.json params 一一对应,禁止出现未消费的声明)
+ --------------------------------------------------------------------- */
+:root {
+ --pb-primary: #0558a5; /* 主色:深宝蓝,品牌行/下划线/日期方块/强调 */
+ --pb-primary-dark: #124489; /* 主色加深:页脚主底/深色端 */
+ --pb-primary-light: #258cff; /* 主色提亮:hover 链接/焦点描边/角标 */
+ --pb-accent: #ff7b00; /* 活力橙:热词/来源徽标/hover 强调 */
+ --pb-secondary: #1c7b46; /* 绿色小标签:可在线办理等正向态 */
+ --pb-nav-bg: #ffffff; /* 主导航条底色(白底吸顶) */
+ --pb-footer-bg: #124489; /* 页脚主底 */
+ --pb-text: #2f3a47; /* 正文 */
+ --pb-text-light: #708090; /* 次要文字 */
+ --pb-bg: #f5f8fc; /* 页面底色 */
+ --pb-card-bg: #ffffff; /* 卡片底 */
+ --pb-border: #e2e8f2; /* 边框/分隔线 */
+
+ /* 派生令牌(固定值,不进 theme.json;均由品牌色系推导,非粉紫) */
+ --pb-footer-deep: #0b2f5c; /* 页脚底条更深色 */
+ --pb-nav-ink: var(--pb-primary); /* 导航文字色 */
+ --pb-ink-on-dark: #ffffff; /* 深底主文字 */
+ --pb-ink-on-dark-soft: rgba(255,255,255,.78);
+ --pb-ink-on-dark-faint: rgba(255,255,255,.56);
+ --pb-mask: rgba(4,26,54,.78); /* 图上标题遮罩端色 */
+ --pb-tint: rgba(5,88,165,.07); /* 主色极浅底(区块头部条/悬停底) */
+ --pb-tint-strong: rgba(5,88,165,.14);
+ --pb-accent-tint: rgba(255,123,0,.10);
+ --pb-shadow-sm: 0 1px 4px rgba(9,47,88,.08);
+ --pb-shadow-md: 0 6px 16px rgba(9,47,88,.12);
+ --pb-shadow-lg: 0 12px 28px rgba(9,47,88,.18);
+ --pb-radius: 6px; /* 全局唯一主圆角(禁大圆角) */
+ --pb-radius-sm: 4px;
+ --pb-speed: .2s ease; /* 统一 hover 过渡 */
+ --pb-font: "Microsoft YaHei", "PingFang SC", "Hiragino Sans GB", "Helvetica Neue", Arial, sans-serif;
+
+ /* 间距阶梯(4/8/12/16/24/32/48)与字号阶梯(12/13/14/15/16/18/20/24/28/36) */
+ --pb-sp-1: 4px; --pb-sp-2: 8px; --pb-sp-3: 12px; --pb-sp-4: 16px;
+ --pb-sp-6: 24px; --pb-sp-8: 32px; --pb-sp-12: 48px;
+ --pb-fz-xs: 12px; --pb-fz-sm: 13px; --pb-fz-md: 14px; --pb-fz-lg: 15px;
+ --pb-fz-xl: 16px; --pb-fz-2xl: 18px; --pb-fz-3xl: 20px; --pb-fz-4xl: 24px;
+ --pb-fz-5xl: 28px; --pb-fz-6xl: 36px;
+
+ /* 皮肤契约别名:themes/common 兜底骨架与站点 theme_params 只认契约变量
+ (--primary/--text/--text-light/--card-bg/--border/--bg/--radius)。
+ 不别名过去,换肤就只换了页头页脚、首页区块仍是骨架内置色。 */
+ --primary: var(--pb-primary);
+ --primary-dark: var(--pb-primary-dark);
+ --primary-light: var(--pb-primary-light);
+ --text: var(--pb-text);
+ --text-light: var(--pb-text-light);
+ --bg: var(--pb-bg);
+ --card-bg: var(--pb-card-bg);
+ --border: var(--pb-border);
+ --radius: var(--pb-radius);
+}
+
+/* ---------------------------------------------------------------------
+ 2. Reset 与基础
+ --------------------------------------------------------------------- */
+* { margin: 0; padding: 0; box-sizing: border-box; }
+
+html { -webkit-text-size-adjust: 100%; }
+
+body {
+ font-family: var(--pb-font);
+ font-size: var(--pb-fz-md);
+ line-height: 1.7;
+ color: var(--pb-text);
+ background: var(--pb-bg);
+ word-break: break-word;
+}
+
+ul, ol { list-style: none; }
+
+a { color: var(--pb-primary); text-decoration: none; transition: color var(--pb-speed); }
+a:hover { color: var(--pb-primary-light); }
+
+img { max-width: 100%; display: block; border: 0; }
+
+button { font-family: inherit; cursor: pointer; }
+
+input, button, select, textarea { font-size: inherit; color: inherit; }
+
+::selection { background: var(--pb-primary); color: #fff; }
+
+/* 焦点态可见:键盘聚焦统一 2px 提亮蓝描边 */
+a:focus-visible,
+button:focus-visible,
+input:focus-visible,
+[tabindex]:focus-visible {
+ outline: 2px solid var(--pb-primary-light);
+ outline-offset: 2px;
+}
+
+/* 跳转链接:仅键盘聚焦时可见 */
+.skip-link {
+ position: absolute;
+ left: -999px;
+ top: 0;
+ z-index: 300;
+ background: var(--pb-primary);
+ color: #fff;
+ padding: var(--pb-sp-2) var(--pb-sp-4);
+ border-radius: 0 0 var(--pb-radius-sm) 0;
+}
+.skip-link:focus { left: 0; color: #fff; }
+
+/* ---------------------------------------------------------------------
+ 3. 布局容器
+ --------------------------------------------------------------------- */
+.pb-container { width: 100%; max-width: 1200px; margin: 0 auto; padding: 0 var(--pb-sp-4); }
+
+/* ---------------------------------------------------------------------
+ 4. 头部:深宝蓝通栏品牌行(校名 + 日期 + 专业院系 + 受众标签 + 搜索/热词)
+ --------------------------------------------------------------------- */
+.pb-brandbar { background: var(--pb-primary); color: var(--pb-ink-on-dark); }
+
+.pb-brandbar-inner {
+ max-width: 1200px;
+ margin: 0 auto;
+ padding: var(--pb-sp-4);
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--pb-sp-6);
+}
+
+/* 品牌:校徽徽标 + 校名 */
+.pb-brand { display: flex; align-items: center; gap: var(--pb-sp-3); min-width: 0; }
+
+.pb-brand-badge {
+ flex: none;
+ width: 56px;
+ height: 56px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ background: rgba(255,255,255,.12);
+ border: 1px solid rgba(255,255,255,.28);
+ border-radius: var(--pb-radius);
+ overflow: hidden;
+ transition: border-color var(--pb-speed);
+}
+.pb-brand:hover .pb-brand-badge { border-color: rgba(255,255,255,.6); }
+
+.pb-logo { width: 100%; height: 100%; object-fit: contain; }
+
+.pb-brand-badge--plain { color: var(--pb-ink-on-dark); }
+
+.pb-site-name {
+ color: var(--pb-ink-on-dark);
+ font-size: var(--pb-fz-4xl);
+ font-weight: 700;
+ letter-spacing: 2px;
+ line-height: 1.3;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ position: relative;
+}
+/* 校名下橙色短线:hover 展满(活力橙强调) */
+.pb-site-name::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ bottom: -4px;
+ width: 48px;
+ height: 3px;
+ background: var(--pb-accent);
+ transition: width var(--pb-speed);
+}
+.pb-site-name:hover { color: var(--pb-ink-on-dark); }
+.pb-site-name:hover::after { width: 100%; }
+
+/* 品牌行右侧:上排(日期/院系/受众)+ 下排(搜索/热词) */
+.pb-brand-side { flex: none; display: flex; flex-direction: column; align-items: flex-end; gap: var(--pb-sp-2); }
+
+.pb-brand-tools { display: flex; align-items: center; gap: var(--pb-sp-3); font-size: var(--pb-fz-sm); color: var(--pb-ink-on-dark-soft); }
+
+.pb-date { white-space: nowrap; color: var(--pb-ink-on-dark-faint); }
+
+/* 专业院系下拉(无子站整块不渲染;悬停/键盘焦点展开) */
+.pb-colleges { position: relative; }
+
+.pb-colleges-toggle { display: inline-flex; align-items: center; gap: var(--pb-sp-1); color: var(--pb-ink-on-dark-soft); cursor: pointer; line-height: 1; }
+.pb-colleges-toggle a { color: var(--pb-ink-on-dark-soft); }
+.pb-colleges-toggle a:hover { color: var(--pb-ink-on-dark); }
+
+.pb-colleges-arrow { font-style: normal; font-size: var(--pb-fz-xs); transition: transform var(--pb-speed); }
+.pb-colleges:hover .pb-colleges-arrow { transform: rotate(180deg); }
+
+.pb-colleges-menu {
+ position: absolute;
+ top: 100%;
+ right: 0;
+ min-width: 180px;
+ background: var(--pb-card-bg);
+ border: 1px solid var(--pb-border);
+ border-radius: var(--pb-radius);
+ box-shadow: var(--pb-shadow-md);
+ padding: var(--pb-sp-1) 0;
+ opacity: 0;
+ visibility: hidden;
+ transform: translateY(var(--pb-sp-1));
+ transition: opacity var(--pb-speed), transform var(--pb-speed), visibility var(--pb-speed);
+ z-index: 120;
+}
+.pb-colleges:hover .pb-colleges-menu,
+.pb-colleges:focus-within .pb-colleges-menu { opacity: 1; visibility: visible; transform: translateY(0); }
+
+.pb-colleges-menu li + li { border-top: 1px solid var(--pb-border); }
+
+.pb-colleges-menu a {
+ display: block;
+ padding: var(--pb-sp-2) var(--pb-sp-4);
+ color: var(--pb-text);
+ font-size: var(--pb-fz-sm);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ transition: background var(--pb-speed), color var(--pb-speed), padding-left var(--pb-speed);
+}
+.pb-colleges-menu a:hover { background: var(--pb-tint); color: var(--pb-primary); padding-left: var(--pb-sp-6); }
+.pb-colleges-menu li.active a {
+ color: var(--pb-primary);
+ font-weight: 600;
+ border-left: 3px solid var(--pb-accent);
+ padding-left: calc(var(--pb-sp-4) - 3px);
+}
+
+/* 受众标签(静态标签位:CMS 暂无受众分组数据源,不造空链接) */
+.pb-audience { display: flex; align-items: center; gap: var(--pb-sp-2); padding-left: var(--pb-sp-3); border-left: 1px solid rgba(255,255,255,.22); }
+
+.pb-audience-item { color: var(--pb-ink-on-dark-soft); font-size: var(--pb-fz-sm); position: relative; padding: 0 var(--pb-sp-1); }
+.pb-audience-item + .pb-audience-item::before {
+ content: "";
+ position: absolute;
+ left: -5px;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 1px;
+ height: 10px;
+ background: rgba(255,255,255,.22);
+}
+
+/* 搜索行:白底圆角搜索框 + 热门搜索词(橙点前缀) */
+.pb-search-row { display: flex; align-items: center; gap: var(--pb-sp-3); }
+
+.pb-search {
+ display: flex;
+ align-items: center;
+ width: 280px;
+ background: var(--pb-card-bg);
+ border-radius: var(--pb-radius);
+ overflow: hidden;
+ border: 1px solid transparent;
+ transition: box-shadow var(--pb-speed), border-color var(--pb-speed);
+}
+.pb-search:focus-within { border-color: var(--pb-accent); box-shadow: 0 0 0 3px var(--pb-accent-tint); }
+
+.pb-search input { flex: 1; min-width: 0; border: 0; padding: var(--pb-sp-2) var(--pb-sp-3); font-size: var(--pb-fz-sm); color: var(--pb-text); background: transparent; }
+.pb-search input::placeholder { color: var(--pb-text-light); }
+.pb-search input:focus { outline: none; }
+
+.pb-search button {
+ flex: none;
+ display: inline-flex;
+ align-items: center;
+ gap: var(--pb-sp-1);
+ border: 0;
+ background: var(--pb-accent);
+ color: #fff;
+ font-size: var(--pb-fz-sm);
+ padding: var(--pb-sp-2) var(--pb-sp-4);
+ transition: background var(--pb-speed);
+}
+.pb-search button:hover { background: #ff9430; }
+
+.pb-hotwords { display: flex; align-items: center; gap: var(--pb-sp-2); font-size: var(--pb-fz-xs); color: var(--pb-ink-on-dark-faint); white-space: nowrap; }
+
+.pb-hotwords a { color: var(--pb-ink-on-dark-soft); position: relative; padding-left: var(--pb-sp-2); }
+.pb-hotwords a::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: var(--pb-accent);
+}
+.pb-hotwords a:hover { color: var(--pb-accent); }
+
+/* ---------------------------------------------------------------------
+ 5. 白底吸顶主导航:当前栏目主色下划线高亮;hover 提亮;下拉主色面板
+ --------------------------------------------------------------------- */
+.pb-nav { background: var(--pb-nav-bg); border-bottom: 1px solid var(--pb-border); box-shadow: var(--pb-shadow-sm); }
+
+.pb-nav-inner { max-width: 1200px; margin: 0 auto; padding: 0 var(--pb-sp-4); display: flex; align-items: center; }
+
+/* 汉堡按钮:≤768 显示 */
+.pb-nav-toggle {
+ display: none;
+ flex: none;
+ width: 40px;
+ height: 40px;
+ border: 1px solid var(--pb-border);
+ border-radius: var(--pb-radius-sm);
+ background: transparent;
+ margin: var(--pb-sp-2) 0;
+}
+.pb-nav-toggle span { display: block; width: 18px; height: 2px; margin: 3px auto; background: var(--pb-primary); border-radius: 1px; transition: transform var(--pb-speed), opacity var(--pb-speed); }
+
+.pb-nav-list { display: flex; align-items: stretch; flex-wrap: wrap; min-width: 0; }
+
+.pb-nav-list > li { position: relative; }
+
+.pb-nav-list > li > a {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--pb-sp-1);
+ padding: var(--pb-sp-4) var(--pb-sp-3);
+ color: var(--pb-nav-ink);
+ font-size: var(--pb-fz-lg);
+ font-weight: 600;
+ position: relative;
+ transition: color var(--pb-speed), background var(--pb-speed);
+}
+/* 当前栏目:主色下划线(hover 同步生长) */
+.pb-nav-list > li > a::after {
+ content: "";
+ position: absolute;
+ left: 50%;
+ bottom: 0;
+ width: 0;
+ height: 3px;
+ background: var(--pb-primary);
+ transform: translateX(-50%);
+ transition: width var(--pb-speed);
+}
+.pb-nav-list > li > a:hover { color: var(--pb-primary-light); background: var(--pb-tint); }
+.pb-nav-list > li > a:hover::after,
+.pb-nav-list > li.active > a::after { width: 100%; }
+.pb-nav-list > li.active > a { color: var(--pb-primary); }
+
+.pb-caret { font-style: normal; font-size: var(--pb-fz-xs); color: var(--pb-text-light); transition: transform var(--pb-speed); }
+.pb-nav-list > li:hover .pb-caret { transform: rotate(180deg); color: var(--pb-primary-light); }
+
+/* 二级下拉:主色实底面板 + 顶部橙色亮线;悬停/键盘焦点展开 */
+.pb-sub {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ min-width: 200px;
+ background: var(--pb-primary);
+ border-top: 3px solid var(--pb-accent);
+ border-radius: 0 0 var(--pb-radius) var(--pb-radius);
+ box-shadow: var(--pb-shadow-md);
+ padding: var(--pb-sp-1) 0;
+ opacity: 0;
+ visibility: hidden;
+ transform: translateY(var(--pb-sp-1));
+ transition: opacity var(--pb-speed), transform var(--pb-speed), visibility var(--pb-speed);
+ z-index: 110;
+}
+.pb-nav-list > li:hover > .pb-sub,
+.pb-nav-list > li:focus-within > .pb-sub { opacity: 1; visibility: visible; transform: translateY(0); }
+
+.pb-sub li + li { border-top: 1px solid rgba(255,255,255,.10); }
+
+.pb-sub a {
+ display: block;
+ padding: var(--pb-sp-2) var(--pb-sp-4) var(--pb-sp-2) var(--pb-sp-6);
+ color: var(--pb-ink-on-dark-soft);
+ font-size: var(--pb-fz-sm);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ position: relative;
+}
+.pb-sub a::before {
+ content: "";
+ position: absolute;
+ left: var(--pb-sp-4);
+ top: 50%;
+ transform: translateY(-50%);
+ width: 4px;
+ height: 4px;
+ border-radius: 50%;
+ background: var(--pb-accent);
+ opacity: .65;
+ transition: opacity var(--pb-speed);
+}
+.pb-sub a:hover { color: var(--pb-ink-on-dark); background: var(--pb-primary-light); }
+.pb-sub a:hover::before { opacity: 1; }
+.pb-sub li.active > a { color: var(--pb-ink-on-dark); background: var(--pb-primary-light); font-weight: 600; }
+
+/* 吸顶态(main.js 加 .pb-nav--fixed 并插入等高 .pb-nav-holder 占位) */
+.pb-nav-holder { width: 100%; }
+
+.pb-nav--fixed {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ z-index: 200;
+ box-shadow: var(--pb-shadow-md);
+ animation: pb-nav-drop var(--pb-speed);
+}
+@keyframes pb-nav-drop {
+ from { transform: translateY(-4px); opacity: .6; }
+ to { transform: translateY(0); opacity: 1; }
+}
+
+/* ---------------------------------------------------------------------
+ 6. headerStyle=plain 变体(themeParams select,root class 切换):
+ 收起受众行与热词、压低品牌行高度——简洁顶栏形态
+ --------------------------------------------------------------------- */
+.pb-header--plain .pb-brandbar-inner { padding-top: var(--pb-sp-3); padding-bottom: var(--pb-sp-3); }
+.pb-header--plain .pb-brand-badge { width: 44px; height: 44px; }
+.pb-header--plain .pb-site-name { font-size: var(--pb-fz-3xl); }
+.pb-header--plain .pb-audience,
+.pb-header--plain .pb-hotwords,
+.pb-header--plain .pb-date { display: none; }
+.pb-header--plain .pb-brand-side { gap: 0; }
+.pb-header--plain .pb-search { width: 220px; }
+
+/* ---------------------------------------------------------------------
+ 7. 首页轮播:通栏大图 + 图上左下角标题渐变遮罩(功能性渐变 1/2)
+ --------------------------------------------------------------------- */
+.pb-banner { position: relative; overflow: hidden; background: var(--pb-primary-dark); }
+
+.pb-banner-slides { position: relative; aspect-ratio: 1920 / 560; }
+
+.pb-banner-slide {
+ position: absolute;
+ inset: 0;
+ opacity: 0;
+ visibility: hidden;
+ transition: opacity .45s ease, visibility .45s ease;
+}
+.pb-banner-slide.active { opacity: 1; visibility: visible; position: relative; }
+
+.pb-banner-slide img { width: 100%; height: 100%; object-fit: cover; }
+
+/* 图上左下角标题:功能性渐变遮罩保证白字可读(非装饰渐变) */
+.pb-banner-title {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ padding: var(--pb-sp-12) var(--pb-sp-12) var(--pb-sp-6);
+ background: linear-gradient(to top, var(--pb-mask), rgba(4,26,54,0));
+ color: #fff;
+ font-size: var(--pb-fz-4xl);
+ font-weight: 700;
+ letter-spacing: 1px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.pb-banner-slide:hover .pb-banner-title { color: #fff; }
+
+.pb-banner-arrow {
+ position: absolute;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 48px;
+ height: 48px;
+ border: 0;
+ border-radius: 50%;
+ background: rgba(4,26,54,.42);
+ color: #fff;
+ font-size: var(--pb-fz-4xl);
+ line-height: 1;
+ transition: background var(--pb-speed);
+ z-index: 5;
+}
+.pb-banner-arrow:hover { background: var(--pb-primary); }
+.pb-banner-arrow.prev { left: var(--pb-sp-6); }
+.pb-banner-arrow.next { right: var(--pb-sp-6); }
+
+.pb-banner-dots { position: absolute; right: var(--pb-sp-6); bottom: var(--pb-sp-4); display: flex; gap: var(--pb-sp-2); z-index: 5; }
+.pb-banner-dots button { width: 28px; height: 4px; border: 0; border-radius: 2px; background: rgba(255,255,255,.46); transition: background var(--pb-speed), width var(--pb-speed); }
+.pb-banner-dots button:hover { background: rgba(255,255,255,.8); }
+.pb-banner-dots button.active { background: var(--pb-accent); width: 40px; }
+
+/* ---------------------------------------------------------------------
+ 8. 首页区块公共件:节容器 / 区块卡 / 标题行(色条+底线)/ 更多钩子
+ --------------------------------------------------------------------- */
+.pb-home { padding-bottom: var(--pb-sp-12); }
+
+.pb-section { padding: var(--pb-sp-12) 0 0; position: relative; }
+
+/* 绝对定位背景带层序:背景 z-index:0,其后首个区块 z-index:1(层序契约) */
+.pb-sec-bg { position: absolute; inset: 0; background-size: cover; background-position: center; background-repeat: no-repeat; opacity: .16; z-index: 0; pointer-events: none; }
+.pb-sec-bg + .pb-block { position: relative; z-index: 1; }
+
+/* 结构钩子(模板结构类:基类/容器/变体标记,仅布局语义) */
+.pb-header { position: relative; }
+.pb-block--flow { display: block; width: 100%; }
+.pb-footer-brand { min-width: 0; }
+.pb-hotwords-label { color: var(--pb-ink-on-dark-faint); }
+.pb-svc-guide-body,
+.pb-svc-unavailable { min-width: 0; }
+
+.pb-block { background: var(--pb-card-bg); border: 1px solid var(--pb-border); border-radius: var(--pb-radius); box-shadow: var(--pb-shadow-sm); padding: var(--pb-sp-4) var(--pb-sp-6) var(--pb-sp-6); }
+
+/* 区块标题行:左侧主色竖条 + 标题,右侧「更多 +」钩子(hover 橙) */
+.pb-block-head {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: var(--pb-sp-4);
+ border-bottom: 1px solid var(--pb-border);
+ padding-bottom: var(--pb-sp-3);
+ margin-bottom: var(--pb-sp-4);
+}
+
+.pb-block-head h2 {
+ position: relative;
+ padding-left: var(--pb-sp-3);
+ font-size: var(--pb-fz-3xl);
+ font-weight: 700;
+ color: var(--pb-text);
+ line-height: 1.4;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.pb-block-head h2::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 50%;
+ transform: translateY(-50%);
+ width: 4px;
+ height: 18px;
+ border-radius: 2px;
+ background: var(--pb-primary);
+}
+/* 标题行下橙色短线(活力橙点缀) */
+.pb-block-head h2::after {
+ content: "";
+ position: absolute;
+ left: 0;
+ bottom: -13px;
+ width: 48px;
+ height: 2px;
+ background: var(--pb-accent);
+}
+
+.pb-more {
+ flex: none;
+ font-size: var(--pb-fz-sm);
+ color: var(--pb-text-light);
+ padding: var(--pb-sp-1) var(--pb-sp-2);
+ border: 1px solid var(--pb-border);
+ border-radius: var(--pb-radius-sm);
+ transition: color var(--pb-speed), border-color var(--pb-speed), background var(--pb-speed);
+}
+.pb-more:hover { color: var(--pb-accent); border-color: var(--pb-accent); background: var(--pb-accent-tint); }
+
+/* 小徽标:置顶(主色底白字) */
+.pb-top-badge {
+ flex: none;
+ display: inline-block;
+ background: var(--pb-primary);
+ color: #fff;
+ font-size: var(--pb-fz-xs);
+ line-height: 1;
+ padding: 3px var(--pb-sp-1);
+ border-radius: var(--pb-radius-sm);
+}
+
+/* 来源徽标:正文态(主色文字 + 极浅底);tag 态(媒体理工:橙系小 tag) */
+.pb-src {
+ display: inline-block;
+ font-size: var(--pb-fz-xs);
+ color: var(--pb-primary);
+ background: var(--pb-tint-strong);
+ border-radius: var(--pb-radius-sm);
+ padding: 2px var(--pb-sp-1);
+ line-height: 1.5;
+}
+.pb-src--tag { color: var(--pb-accent); background: var(--pb-accent-tint); border: 1px solid rgba(255,123,0,.28); }
+
+/* 元信息行(日期/来源/置顶) */
+.pb-news-meta { display: flex; align-items: center; gap: var(--pb-sp-2); font-size: var(--pb-fz-xs); color: var(--pb-text-light); flex-wrap: wrap; }
+
+/* 中文防塌列契约(回归测试检查项,照 academic-navy 同款规则) */
+.pb-ticker-list { min-width: 0; white-space: nowrap; }
+.pb-ticker-item { flex: none; text-overflow: ellipsis; }
+.pb-block-item-title { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
+
+/* 空态 */
+.pb-empty { padding: var(--pb-sp-12) var(--pb-sp-4); text-align: center; color: var(--pb-text-light); background: var(--pb-tint); border: 1px dashed var(--pb-border); border-radius: var(--pb-radius); }
+.pb-empty p { font-size: var(--pb-fz-lg); }
+.pb-empty-hint { font-size: var(--pb-fz-sm); margin-top: var(--pb-sp-1); }
+
+/* ---------------------------------------------------------------------
+ 9. 形态一 news_grid:双栏要闻——左 3 份大图文头条卡 / 右 2 份紧凑密行
+ --------------------------------------------------------------------- */
+.pb-split { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--pb-sp-6); align-items: start; }
+
+/* 左:大图文头条卡(16:9 封面 + 标题 + 摘要 + 日期来源元信息) */
+.pb-news-lead > a {
+ display: block;
+ border: 1px solid var(--pb-border);
+ border-radius: var(--pb-radius);
+ overflow: hidden;
+ background: var(--pb-card-bg);
+ transition: box-shadow var(--pb-speed), transform var(--pb-speed), border-color var(--pb-speed);
+}
+.pb-news-lead > a:hover { box-shadow: var(--pb-shadow-md); transform: translateY(-2px); border-color: var(--pb-primary-light); }
+
+.pb-news-cover { display: block; aspect-ratio: 16 / 9; overflow: hidden; background: var(--pb-tint); }
+.pb-news-cover img { width: 100%; height: 100%; object-fit: cover; transition: transform .3s ease; }
+.pb-news-lead > a:hover .pb-news-cover img { transform: scale(1.04); }
+
+.pb-news-body { display: block; padding: var(--pb-sp-3) var(--pb-sp-4) var(--pb-sp-4); }
+
+.pb-news-title {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ font-size: var(--pb-fz-xl);
+ font-weight: 700;
+ color: var(--pb-text);
+ line-height: 1.5;
+ margin-bottom: var(--pb-sp-2);
+ transition: color var(--pb-speed);
+}
+.pb-news-lead > a:hover .pb-news-title { color: var(--pb-primary); }
+
+.pb-news-summary {
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ font-size: var(--pb-fz-sm);
+ color: var(--pb-text-light);
+ line-height: 1.8;
+ margin-bottom: var(--pb-sp-3);
+}
+
+/* 右:校园经纬紧凑列表(圆点前缀 + 日期右对齐) */
+.pb-brief-list {
+ border: 1px solid var(--pb-border);
+ border-radius: var(--pb-radius);
+ background: var(--pb-card-bg);
+ padding: var(--pb-sp-2) var(--pb-sp-4);
+}
+
+.pb-brief-item { display: flex; align-items: center; gap: var(--pb-sp-2); padding: var(--pb-sp-2) 0; min-width: 0; }
+.pb-brief-item + .pb-brief-item { border-top: 1px dashed var(--pb-border); }
+
+.pb-brief-dot { flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--pb-border); transition: background var(--pb-speed), transform var(--pb-speed); }
+.pb-brief-item:hover .pb-brief-dot { background: var(--pb-accent); transform: scale(1.3); }
+
+.pb-brief-item .pb-block-item-title { flex: 1; font-size: var(--pb-fz-sm); color: var(--pb-text); white-space: nowrap; transition: color var(--pb-speed); }
+.pb-brief-item:hover .pb-block-item-title { color: var(--pb-primary-light); }
+
+.pb-item-date { flex: none; font-size: var(--pb-fz-xs); color: var(--pb-text-light); font-variant-numeric: tabular-nums; }
+
+/* ---------------------------------------------------------------------
+ 10. 形态三 compact:通知公告日期方块行(46px「日大号 + 年月小号」,主色底白字)
+ --------------------------------------------------------------------- */
+.pb-date-chip {
+ flex: none;
+ width: 46px;
+ height: 46px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ background: var(--pb-primary);
+ color: #fff;
+ border-radius: var(--pb-radius-sm);
+ line-height: 1.15;
+ transition: background var(--pb-speed);
+}
+.pb-date-chip b { font-size: var(--pb-fz-3xl); font-weight: 700; }
+.pb-date-chip i { font-style: normal; font-size: var(--pb-fz-xs); opacity: .82; }
+
+.pb-notice-list li + li { border-top: 1px dashed var(--pb-border); }
+
+.pb-notice-item { display: flex; align-items: center; gap: var(--pb-sp-3); padding: var(--pb-sp-3) 0; min-width: 0; }
+.pb-notice-item:hover .pb-date-chip { background: var(--pb-primary-light); }
+
+.pb-notice-item .pb-block-item-title { flex: 1; font-size: var(--pb-fz-md); color: var(--pb-text); white-space: nowrap; transition: color var(--pb-speed); }
+.pb-notice-item:hover .pb-block-item-title { color: var(--pb-primary-light); }
+
+/* ---------------------------------------------------------------------
+ 11. 形态四 media_focus:媒体理工——来源徽标(橙系小 tag)+ 双列密行
+ --------------------------------------------------------------------- */
+.pb-media-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: var(--pb-sp-12); }
+
+.pb-media-item { display: flex; align-items: center; gap: var(--pb-sp-2); padding: var(--pb-sp-2) 0; border-bottom: 1px dashed var(--pb-border); min-width: 0; }
+
+.pb-media-item .pb-src--tag { flex: none; max-width: 30%; overflow: hidden; white-space: nowrap; }
+
+.pb-media-item .pb-block-item-title { flex: 1; font-size: var(--pb-fz-sm); color: var(--pb-text); white-space: nowrap; transition: color var(--pb-speed); }
+.pb-media-item:hover .pb-block-item-title { color: var(--pb-accent); }
+
+/* ---------------------------------------------------------------------
+ 12. 形态五 image_wall / gallery:四列图片墙 + 底部渐变遮罩标题(功能性渐变 2/2)
+ --------------------------------------------------------------------- */
+.pb-wall { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--pb-sp-4); }
+
+.pb-wall-item > a {
+ position: relative;
+ display: block;
+ border-radius: var(--pb-radius);
+ overflow: hidden;
+ aspect-ratio: 4 / 3;
+ background: var(--pb-tint);
+ box-shadow: var(--pb-shadow-sm);
+ transition: box-shadow var(--pb-speed), transform var(--pb-speed);
+}
+.pb-wall-item > a:hover { box-shadow: var(--pb-shadow-md); transform: translateY(-3px); }
+
+.pb-wall-item img { width: 100%; height: 100%; object-fit: cover; transition: transform .3s ease; }
+.pb-wall-item > a:hover img { transform: scale(1.05); }
+
+/* 底部渐变遮罩标题:功能性文字保护(非装饰渐变) */
+.pb-wall-cap {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ padding: var(--pb-sp-8) var(--pb-sp-3) var(--pb-sp-2);
+ background: linear-gradient(to top, var(--pb-mask), rgba(4,26,54,0));
+ color: #fff;
+ font-size: var(--pb-fz-sm);
+ line-height: 1.5;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.pb-wall-item > a:hover .pb-wall-cap { color: #fff; }
+
+/* 线上展厅:居中双语文区头 */
+.pb-gallery { text-align: center; }
+
+.pb-gallery-head { margin-bottom: var(--pb-sp-4); }
+
+.pb-gallery-title { justify-content: center; border-bottom: 0; padding-bottom: 0; margin-bottom: var(--pb-sp-1); }
+.pb-gallery-title h2::after { left: 50%; transform: translateX(-50%); bottom: -5px; }
+
+.pb-gallery-sub { font-size: var(--pb-fz-sm); color: var(--pb-text-light); letter-spacing: 2px; }
+
+.pb-wall--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
+
+/* ---------------------------------------------------------------------
+ 13. 布局模式 ticker:要闻速递横条(主色底白字,单行不换行,中文不塌列)
+ --------------------------------------------------------------------- */
+.pb-ticker { margin-top: var(--pb-sp-8); background: var(--pb-primary); color: var(--pb-ink-on-dark); }
+
+.pb-ticker-inner { display: flex; align-items: center; gap: var(--pb-sp-4); padding-top: var(--pb-sp-2); padding-bottom: var(--pb-sp-2); }
+
+.pb-ticker-label {
+ flex: none;
+ position: relative;
+ font-size: var(--pb-fz-lg);
+ font-weight: 700;
+ padding: var(--pb-sp-1) var(--pb-sp-4) var(--pb-sp-1) var(--pb-sp-3);
+ background: var(--pb-accent);
+ border-radius: var(--pb-radius-sm);
+ color: #fff;
+}
+.pb-ticker-label::before,
+.pb-ticker-label::after {
+ content: "";
+ position: absolute;
+ top: 50%;
+ width: 5px;
+ height: 5px;
+ border-radius: 50%;
+ background: #fff;
+ opacity: .85;
+ transform: translateY(-50%);
+}
+.pb-ticker-label::before { left: -3px; }
+.pb-ticker-label::after { right: -3px; }
+
+.pb-ticker-list { display: flex; align-items: center; gap: var(--pb-sp-6); overflow: hidden; flex: 1; }
+.pb-ticker-list li { min-width: 0; }
+
+.pb-ticker-item {
+ flex: none;
+ display: inline-block;
+ max-width: 360px;
+ color: var(--pb-ink-on-dark-soft);
+ font-size: var(--pb-fz-sm);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.pb-ticker-item:hover { color: var(--pb-ink-on-dark); text-decoration: underline; text-underline-offset: 3px; }
+
+/* ---------------------------------------------------------------------
+ 14. 布局模式 links:快捷通道图标宫格(主色描边 hover 填色)
+ --------------------------------------------------------------------- */
+.pb-channel-group { font-size: var(--pb-fz-sm); font-weight: 600; color: var(--pb-text-light); margin: var(--pb-sp-2) 0; }
+.pb-channel-group:first-of-type { margin-top: 0; }
+
+.pb-channels { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: var(--pb-sp-3); }
+
+.pb-channel {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: var(--pb-sp-2);
+ padding: var(--pb-sp-4) var(--pb-sp-2);
+ border: 1px solid var(--pb-border);
+ border-radius: var(--pb-radius);
+ background: var(--pb-card-bg);
+ transition: border-color var(--pb-speed), background var(--pb-speed), box-shadow var(--pb-speed), transform var(--pb-speed);
+}
+.pb-channel:hover { border-color: var(--pb-primary); background: var(--pb-primary); color: #fff; box-shadow: var(--pb-shadow-md); transform: translateY(-2px); }
+
+/* 图标位:主色描边浅底,整卡 hover 反白(描边填色语义) */
+.pb-channel-icon {
+ width: 52px;
+ height: 52px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--pb-primary);
+ border: 1px solid var(--pb-primary);
+ border-radius: var(--pb-radius);
+ background: var(--pb-tint);
+ transition: color var(--pb-speed), background var(--pb-speed), border-color var(--pb-speed);
+}
+.pb-channel:hover .pb-channel-icon { color: var(--pb-primary); background: #fff; border-color: #fff; }
+
+.pb-channel-name {
+ font-size: var(--pb-fz-sm);
+ color: var(--pb-text);
+ max-width: 100%;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ transition: color var(--pb-speed);
+}
+.pb-channel:hover .pb-channel-name { color: #fff; }
+
+/* ---------------------------------------------------------------------
+ 15. 回落模式首页(无 home_layout):头条推荐 + 图片新闻双栏 + 栏目区块网格
+ --------------------------------------------------------------------- */
+.pb-headline { display: grid; grid-template-columns: minmax(0, 3fr) minmax(0, 2fr); gap: var(--pb-sp-6); align-items: start; }
+
+.pb-headline-card,
+.pb-focus-card { background: var(--pb-card-bg); border: 1px solid var(--pb-border); border-radius: var(--pb-radius); box-shadow: var(--pb-shadow-sm); padding: var(--pb-sp-4) var(--pb-sp-6) var(--pb-sp-6); }
+
+.pb-headline-list li { display: flex; align-items: center; gap: var(--pb-sp-2); padding: var(--pb-sp-2) 0; min-width: 0; }
+.pb-headline-list li + li { border-top: 1px dashed var(--pb-border); }
+
+.pb-headline-list a {
+ flex: 1;
+ min-width: 0;
+ color: var(--pb-text);
+ font-size: var(--pb-fz-md);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.pb-headline-list a:hover { color: var(--pb-primary-light); }
+
+.pb-headline-list time { flex: none; font-size: var(--pb-fz-xs); color: var(--pb-text-light); font-variant-numeric: tabular-nums; }
+
+.pb-headline-lead { padding-bottom: var(--pb-sp-3); }
+
+.pb-lead-title { display: block; font-size: var(--pb-fz-xl); font-weight: 700; color: var(--pb-text); line-height: 1.6; }
+.pb-lead-title:hover { color: var(--pb-primary); }
+
+.pb-lead-meta { display: flex; align-items: center; gap: var(--pb-sp-2); margin-top: var(--pb-sp-2); font-size: var(--pb-fz-xs); color: var(--pb-text-light); }
+
+/* 图片新闻:首条大图 + 缩略行 */
+.pb-focus-lead {
+ display: block;
+ border-radius: var(--pb-radius);
+ overflow: hidden;
+ position: relative;
+ aspect-ratio: 16 / 9;
+ background: var(--pb-tint);
+ box-shadow: var(--pb-shadow-sm);
+}
+.pb-focus-lead img { width: 100%; height: 100%; object-fit: cover; }
+.pb-focus-lead:hover img { opacity: .92; }
+
+/* 图片新闻首图封面容器(撑满 16:9 链接位) */
+.pb-focus-cover { display: block; width: 100%; height: 100%; overflow: hidden; }
+
+/* 图上标题用纯色半透明底带(非渐变,保证全文件渐变恰为 2 处功能性遮罩) */
+.pb-focus-title {
+ position: absolute;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ padding: var(--pb-sp-2) var(--pb-sp-3);
+ background: var(--pb-mask);
+ color: #fff;
+ font-size: var(--pb-fz-lg);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.pb-focus-lead:hover .pb-focus-title { color: #fff; }
+
+.pb-focus-rows { margin-top: var(--pb-sp-3); display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--pb-sp-1); }
+
+.pb-focus-rows li + li { border-top: 1px dashed var(--pb-border); }
+
+.pb-focus-rows a { display: flex; align-items: center; gap: var(--pb-sp-2); padding: var(--pb-sp-2) 0; min-width: 0; }
+
+.pb-row-cover { flex: none; width: 84px; height: 56px; border-radius: var(--pb-radius-sm); overflow: hidden; background: var(--pb-tint); }
+.pb-row-cover img { width: 100%; height: 100%; object-fit: cover; }
+
+.pb-row-title {
+ flex: 1;
+ min-width: 0;
+ font-size: var(--pb-fz-sm);
+ color: var(--pb-text);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.pb-focus-rows a:hover .pb-row-title { color: var(--pb-primary-light); }
+
+/* 栏目区块网格(回落模式) */
+.pb-blocks { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--pb-sp-6); }
+
+/* 区块内头条(feat):行式图文 */
+.pb-feat { border-bottom: 1px solid var(--pb-border); padding-bottom: var(--pb-sp-3); margin-bottom: var(--pb-sp-2); }
+
+.pb-feat > a { display: flex; gap: var(--pb-sp-3); min-width: 0; }
+
+.pb-feat-cover { flex: none; width: 160px; aspect-ratio: 16 / 9; border-radius: var(--pb-radius-sm); overflow: hidden; background: var(--pb-tint); }
+.pb-feat-cover img { width: 100%; height: 100%; object-fit: cover; }
+
+.pb-feat-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--pb-sp-1); }
+
+.pb-feat-title {
+ font-size: var(--pb-fz-lg);
+ font-weight: 700;
+ color: var(--pb-text);
+ line-height: 1.5;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+.pb-feat > a:hover .pb-feat-title { color: var(--pb-primary); }
+
+.pb-feat-summary {
+ font-size: var(--pb-fz-sm);
+ color: var(--pb-text-light);
+ line-height: 1.7;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+
+/* 默认卡行式列表(card 形态) */
+.pb-block-list li + li { border-top: 1px dashed var(--pb-border); }
+
+.pb-block-item { display: flex; align-items: center; gap: var(--pb-sp-2); padding: var(--pb-sp-2) 0; min-width: 0; }
+
+.pb-item-tick { flex: none; width: 5px; height: 5px; background: var(--pb-border); transform: rotate(45deg); transition: background var(--pb-speed); }
+.pb-block-item:hover .pb-item-tick { background: var(--pb-accent); }
+
+.pb-block-item .pb-block-item-title { flex: 1; font-size: var(--pb-fz-sm); color: var(--pb-text); white-space: nowrap; transition: color var(--pb-speed); }
+.pb-block-item:hover .pb-block-item-title { color: var(--pb-primary-light); }
+
+.pb-block-item .pb-item-date { font-size: var(--pb-fz-xs); }
+
+/* ---------------------------------------------------------------------
+ 16. 列表/详情/单页/搜索:双栏(左侧栏 + 页卡)与页内组件
+ --------------------------------------------------------------------- */
+.pb-page { padding: var(--pb-sp-6) 0 var(--pb-sp-12); }
+
+.pb-cols { display: grid; grid-template-columns: 220px minmax(0, 1fr); gap: var(--pb-sp-6); align-items: start; }
+
+/* 左侧栏目导航(sideNav 为空不渲染,窄屏栅格降级为单列) */
+.pb-side-nav { background: var(--pb-card-bg); border: 1px solid var(--pb-border); border-radius: var(--pb-radius); overflow: hidden; box-shadow: var(--pb-shadow-sm); }
+
+.pb-side-nav-head { background: var(--pb-primary); color: #fff; font-size: var(--pb-fz-lg); font-weight: 700; padding: var(--pb-sp-3) var(--pb-sp-4); }
+
+.pb-side-nav-list { padding: var(--pb-sp-2) 0; }
+
+.pb-side-nav-item a {
+ display: block;
+ padding: var(--pb-sp-2) var(--pb-sp-4);
+ color: var(--pb-text);
+ font-size: var(--pb-fz-sm);
+ position: relative;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ transition: background var(--pb-speed), color var(--pb-speed), padding-left var(--pb-speed);
+}
+.pb-side-nav-item a:hover { background: var(--pb-tint); color: var(--pb-primary); padding-left: var(--pb-sp-6); }
+.pb-side-nav-item.active a {
+ color: var(--pb-primary);
+ font-weight: 700;
+ background: var(--pb-tint-strong);
+ border-left: 3px solid var(--pb-accent);
+ padding-left: calc(var(--pb-sp-4) - 3px);
+}
+
+/* 页卡 */
+.pb-page-card { background: var(--pb-card-bg); border: 1px solid var(--pb-border); border-radius: var(--pb-radius); box-shadow: var(--pb-shadow-sm); padding: var(--pb-sp-6); min-width: 0; }
+
+/* 面包屑 */
+.pb-crumb {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: var(--pb-sp-2);
+ font-size: var(--pb-fz-sm);
+ color: var(--pb-text-light);
+ padding-bottom: var(--pb-sp-3);
+ border-bottom: 1px solid var(--pb-border);
+ margin-bottom: var(--pb-sp-4);
+}
+.pb-crumb a { color: var(--pb-text-light); }
+.pb-crumb a:hover { color: var(--pb-primary-light); }
+.pb-crumb .crumb-parent { color: var(--pb-text-light); }
+
+.pb-crumb-sep { color: var(--pb-border); }
+
+.pb-crumb-current { color: var(--pb-primary); font-weight: 600; }
+
+.pb-page-title {
+ font-size: var(--pb-fz-3xl);
+ font-weight: 700;
+ color: var(--pb-text);
+ padding-left: var(--pb-sp-3);
+ border-left: 4px solid var(--pb-primary);
+ line-height: 1.4;
+ margin-bottom: var(--pb-sp-6);
+ word-break: break-word;
+}
+
+/* 文章列表:有封面图文行 / 无封面日期方块行 */
+.pb-article-list > li + li { border-top: 1px solid var(--pb-border); }
+
+.pb-article-row { display: flex; gap: var(--pb-sp-4); padding: var(--pb-sp-4) 0; min-width: 0; }
+
+.pb-item-cover { flex: none; width: 200px; aspect-ratio: 16 / 9; border-radius: var(--pb-radius); overflow: hidden; background: var(--pb-tint); }
+.pb-item-cover img { width: 100%; height: 100%; object-fit: cover; transition: transform .3s ease; }
+.pb-article-row:hover .pb-item-cover img { transform: scale(1.04); }
+
+.pb-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--pb-sp-2); }
+
+.pb-item-title a { font-size: var(--pb-fz-xl); font-weight: 600; color: var(--pb-text); line-height: 1.6; transition: color var(--pb-speed); }
+.pb-item-title a:hover { color: var(--pb-primary-light); }
+
+.pb-item-summary {
+ font-size: var(--pb-fz-sm);
+ color: var(--pb-text-light);
+ line-height: 1.8;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+
+.pb-item-meta { display: flex; align-items: center; gap: var(--pb-sp-2); font-size: var(--pb-fz-xs); color: var(--pb-text-light); }
+
+/* 无封面:日期方块行 */
+.pb-article-line { display: flex; align-items: flex-start; gap: var(--pb-sp-3); padding: var(--pb-sp-3) 0; min-width: 0; }
+.pb-article-line .pb-date-chip { margin-top: 2px; }
+
+.pb-line-main { flex: 1; min-width: 0; }
+
+.pb-line-main .pb-block-item-title { display: block; font-size: var(--pb-fz-md); font-weight: 600; color: var(--pb-text); white-space: nowrap; transition: color var(--pb-speed); }
+.pb-article-line:hover .pb-block-item-title { color: var(--pb-primary-light); }
+.pb-article-line:hover .pb-date-chip { background: var(--pb-primary-light); }
+
+.pb-line-main .pb-item-summary { margin-top: var(--pb-sp-1); }
+
+.pb-line-side { flex: none; padding-top: 2px; }
+
+/* 分页 */
+.pb-pagination { display: flex; justify-content: center; align-items: center; flex-wrap: wrap; gap: var(--pb-sp-1); margin-top: var(--pb-sp-8); }
+
+.pb-pagination a {
+ min-width: 32px;
+ height: 32px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ padding: 0 var(--pb-sp-2);
+ border: 1px solid var(--pb-border);
+ border-radius: var(--pb-radius-sm);
+ color: var(--pb-text);
+ font-size: var(--pb-fz-sm);
+ background: var(--pb-card-bg);
+ transition: color var(--pb-speed), border-color var(--pb-speed), background var(--pb-speed);
+}
+.pb-pagination a:hover { color: var(--pb-primary); border-color: var(--pb-primary); }
+.pb-pagination a.active { background: var(--pb-primary); border-color: var(--pb-primary); color: #fff; font-weight: 600; }
+.pb-pagination a.disabled { color: var(--pb-text-light); opacity: .5; pointer-events: none; }
+
+/* ---------------------------------------------------------------------
+ 17. 详情页:标题/元信息/正文排版/上下篇
+ --------------------------------------------------------------------- */
+.pb-article { min-width: 0; }
+
+.pb-article-title {
+ font-size: var(--pb-fz-4xl);
+ font-weight: 700;
+ color: var(--pb-text);
+ line-height: 1.5;
+ text-align: center;
+ margin-bottom: var(--pb-sp-4);
+ word-break: break-word;
+}
+
+.pb-article-meta {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: var(--pb-sp-3);
+ padding: var(--pb-sp-3) 0;
+ border-top: 1px solid var(--pb-border);
+ border-bottom: 1px solid var(--pb-border);
+ font-size: var(--pb-fz-xs);
+ color: var(--pb-text-light);
+ margin-bottom: var(--pb-sp-6);
+}
+
+/* 富文本正文(jsoup 白名单清洗后直出)排版 */
+.pb-article-content { font-size: var(--pb-fz-lg); line-height: 2; color: var(--pb-text); }
+.pb-article-content p { margin: var(--pb-sp-3) 0; }
+.pb-article-content h2,
+.pb-article-content h3,
+.pb-article-content h4 { margin: var(--pb-sp-6) 0 var(--pb-sp-3); color: var(--pb-text); line-height: 1.5; }
+.pb-article-content h2 { font-size: var(--pb-fz-3xl); border-left: 4px solid var(--pb-primary); padding-left: var(--pb-sp-2); }
+.pb-article-content h3 { font-size: var(--pb-fz-xl); }
+.pb-article-content h4 { font-size: var(--pb-fz-lg); }
+.pb-article-content img { margin: var(--pb-sp-3) auto; border-radius: var(--pb-radius-sm); }
+.pb-article-content a { color: var(--pb-primary); text-decoration: underline; text-underline-offset: 3px; }
+.pb-article-content ul,
+.pb-article-content ol { margin: var(--pb-sp-3) 0; padding-left: var(--pb-sp-6); }
+.pb-article-content ul li { list-style: disc; }
+.pb-article-content ol li { list-style: decimal; }
+.pb-article-content blockquote {
+ margin: var(--pb-sp-4) 0;
+ padding: var(--pb-sp-3) var(--pb-sp-4);
+ background: var(--pb-tint);
+ border-left: 4px solid var(--pb-primary-light);
+ border-radius: 0 var(--pb-radius-sm) var(--pb-radius-sm) 0;
+ color: var(--pb-text-light);
+}
+.pb-article-content table { width: 100%; border-collapse: collapse; margin: var(--pb-sp-4) 0; font-size: var(--pb-fz-sm); }
+.pb-article-content th,
+.pb-article-content td { border: 1px solid var(--pb-border); padding: var(--pb-sp-2) var(--pb-sp-3); text-align: left; }
+.pb-article-content th { background: var(--pb-tint); color: var(--pb-text); font-weight: 600; }
+
+/* 上下篇 */
+.pb-sibling { margin-top: var(--pb-sp-8); padding-top: var(--pb-sp-4); border-top: 1px solid var(--pb-border); display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--pb-sp-4); }
+
+.pb-sibling a,
+.pb-sib-none {
+ display: flex;
+ flex-direction: column;
+ gap: var(--pb-sp-1);
+ padding: var(--pb-sp-3) var(--pb-sp-4);
+ border: 1px solid var(--pb-border);
+ border-radius: var(--pb-radius);
+ background: var(--pb-card-bg);
+ transition: border-color var(--pb-speed), box-shadow var(--pb-speed);
+}
+.pb-sibling a:hover { border-color: var(--pb-primary-light); box-shadow: var(--pb-shadow-sm); }
+
+.pb-sibling .next { grid-column: 2; text-align: right; }
+
+.pb-sib-label { font-size: var(--pb-fz-xs); color: var(--pb-primary); font-weight: 600; }
+
+.pb-sib-title { font-size: var(--pb-fz-sm); color: var(--pb-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
+.pb-sibling a:hover .pb-sib-title { color: var(--pb-primary-light); }
+
+.pb-sib-none .pb-sib-title { color: var(--pb-text-light); }
+
+/* ---------------------------------------------------------------------
+ 18. 服务中心 / 事项指南(svc 页族)
+ --------------------------------------------------------------------- */
+.pb-svc-page { min-width: 0; }
+
+.pb-svc-filters { border: 1px solid var(--pb-border); border-radius: var(--pb-radius); padding: var(--pb-sp-3) var(--pb-sp-4); margin-bottom: var(--pb-sp-4); }
+
+.pb-svc-filter-group { display: flex; align-items: flex-start; gap: var(--pb-sp-3); padding: var(--pb-sp-2) 0; }
+.pb-svc-filter-group + .pb-svc-filter-group { border-top: 1px dashed var(--pb-border); }
+
+.pb-svc-filter-label { flex: none; font-size: var(--pb-fz-sm); font-weight: 600; color: var(--pb-text); padding-top: var(--pb-sp-1); }
+
+.pb-svc-filter-options { display: flex; flex-wrap: wrap; gap: var(--pb-sp-2); min-width: 0; }
+
+.pb-chip {
+ display: inline-flex;
+ align-items: center;
+ gap: var(--pb-sp-1);
+ padding: 3px var(--pb-sp-2);
+ border: 1px solid var(--pb-border);
+ border-radius: var(--pb-radius-sm);
+ font-size: var(--pb-fz-sm);
+ color: var(--pb-text);
+ background: var(--pb-card-bg);
+ transition: color var(--pb-speed), border-color var(--pb-speed), background var(--pb-speed);
+}
+.pb-chip em { font-style: normal; font-size: var(--pb-fz-xs); color: var(--pb-text-light); }
+.pb-chip:hover { color: var(--pb-primary); border-color: var(--pb-primary); }
+.pb-chip.active { background: var(--pb-primary); border-color: var(--pb-primary); color: #fff; }
+.pb-chip.active em { color: rgba(255,255,255,.8); }
+
+.pb-svc-toolbar { display: flex; align-items: center; gap: var(--pb-sp-3); margin-bottom: var(--pb-sp-4); }
+
+.pb-svc-search {
+ display: flex;
+ width: min(420px, 100%);
+ border: 1px solid var(--pb-border);
+ border-radius: var(--pb-radius);
+ overflow: hidden;
+ transition: border-color var(--pb-speed), box-shadow var(--pb-speed);
+}
+.pb-svc-search:focus-within { border-color: var(--pb-primary-light); box-shadow: 0 0 0 3px var(--pb-tint-strong); }
+
+.pb-svc-search input { flex: 1; min-width: 0; border: 0; padding: var(--pb-sp-2) var(--pb-sp-3); font-size: var(--pb-fz-sm); }
+.pb-svc-search input:focus { outline: none; }
+
+.pb-svc-search button { border: 0; background: var(--pb-primary); color: #fff; font-size: var(--pb-fz-sm); padding: var(--pb-sp-2) var(--pb-sp-6); transition: background var(--pb-speed); }
+.pb-svc-search button:hover { background: var(--pb-primary-light); }
+
+.pb-svc-clear { font-size: var(--pb-fz-sm); color: var(--pb-text-light); text-decoration: underline; text-underline-offset: 3px; }
+.pb-svc-clear:hover { color: var(--pb-accent); }
+
+/* 事项卡列表 */
+.pb-svc-list > li + li { border-top: 1px solid var(--pb-border); }
+
+.pb-svc-item { display: flex; gap: var(--pb-sp-4); padding: var(--pb-sp-4) 0; min-width: 0; }
+
+.pb-svc-item-cover { flex: none; width: 120px; aspect-ratio: 16 / 9; border-radius: var(--pb-radius-sm); overflow: hidden; background: var(--pb-tint); }
+.pb-svc-item-cover img { width: 100%; height: 100%; object-fit: cover; }
+
+.pb-svc-item-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: var(--pb-sp-2); }
+
+.pb-svc-item-title { display: flex; align-items: center; flex-wrap: wrap; gap: var(--pb-sp-2); min-width: 0; }
+
+.pb-svc-item-name { font-size: var(--pb-fz-lg); font-weight: 600; color: var(--pb-text); transition: color var(--pb-speed); }
+.pb-svc-item:hover .pb-svc-item-name { color: var(--pb-primary-light); }
+
+.pb-tag { flex: none; font-size: var(--pb-fz-xs); color: var(--pb-primary); background: var(--pb-tint-strong); border-radius: var(--pb-radius-sm); padding: 2px var(--pb-sp-1); line-height: 1.5; }
+.pb-tag.online { color: var(--pb-secondary); background: rgba(28,123,70,.10); }
+
+.pb-svc-item-summary {
+ font-size: var(--pb-fz-sm);
+ color: var(--pb-text-light);
+ line-height: 1.7;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+
+.pb-svc-item-meta { display: flex; flex-wrap: wrap; gap: var(--pb-sp-3); font-size: var(--pb-fz-xs); color: var(--pb-text-light); }
+
+/* 指南页 */
+.pb-svc-guide { min-width: 0; }
+
+.pb-svc-apply { display: flex; align-items: center; gap: var(--pb-sp-3); margin-bottom: var(--pb-sp-4); }
+
+.pb-svc-apply-btn {
+ display: inline-flex;
+ align-items: center;
+ background: var(--pb-accent);
+ color: #fff;
+ font-size: var(--pb-fz-lg);
+ font-weight: 600;
+ padding: var(--pb-sp-2) var(--pb-sp-8);
+ border-radius: var(--pb-radius);
+ box-shadow: var(--pb-shadow-sm);
+ transition: background var(--pb-speed), box-shadow var(--pb-speed), transform var(--pb-speed);
+}
+.pb-svc-apply-btn:hover { background: #ff9430; color: #fff; box-shadow: var(--pb-shadow-md); transform: translateY(-1px); }
+
+.pb-svc-apply-hint { font-size: var(--pb-fz-sm); color: var(--pb-text-light); }
+
+.pb-svc-summary {
+ padding: var(--pb-sp-3) var(--pb-sp-4);
+ background: var(--pb-tint);
+ border-left: 4px solid var(--pb-primary-light);
+ border-radius: 0 var(--pb-radius-sm) var(--pb-radius-sm) 0;
+ font-size: var(--pb-fz-sm);
+ color: var(--pb-text-light);
+ margin-bottom: var(--pb-sp-4);
+}
+
+.pb-svc-info { width: 100%; border-collapse: collapse; margin: var(--pb-sp-3) 0 var(--pb-sp-6); font-size: var(--pb-fz-sm); }
+.pb-svc-info th,
+.pb-svc-info td { border: 1px solid var(--pb-border); padding: var(--pb-sp-2) var(--pb-sp-3); text-align: left; vertical-align: top; }
+.pb-svc-info th { width: 120px; background: var(--pb-tint); color: var(--pb-text); font-weight: 600; white-space: nowrap; }
+
+.pb-svc-section { margin-top: var(--pb-sp-6); }
+.pb-svc-section h2 { font-size: var(--pb-fz-xl); color: var(--pb-text); padding-left: var(--pb-sp-3); border-left: 4px solid var(--pb-primary); margin-bottom: var(--pb-sp-3); line-height: 1.5; }
+
+.pb-svc-attachments ul { display: flex; flex-direction: column; gap: var(--pb-sp-2); }
+
+.pb-svc-attachments a { display: inline-flex; align-items: center; gap: var(--pb-sp-1); color: var(--pb-primary); font-size: var(--pb-fz-sm); }
+.pb-svc-attachments a:hover { color: var(--pb-accent); text-decoration: underline; text-underline-offset: 3px; }
+
+.pb-svc-att-size { font-size: var(--pb-fz-xs); color: var(--pb-text-light); margin-left: var(--pb-sp-2); }
+
+.pb-svc-links { display: flex; flex-wrap: wrap; gap: var(--pb-sp-3); margin-top: var(--pb-sp-6); padding-top: var(--pb-sp-4); border-top: 1px dashed var(--pb-border); }
+.pb-svc-links a { font-size: var(--pb-fz-sm); color: var(--pb-primary); padding: var(--pb-sp-1) var(--pb-sp-4); border: 1px solid var(--pb-primary); border-radius: var(--pb-radius-sm); transition: background var(--pb-speed), color var(--pb-speed); }
+.pb-svc-links a:hover { background: var(--pb-primary); color: #fff; }
+
+.pb-svc-related { margin-top: var(--pb-sp-8); }
+
+.pb-svc-related-title { font-size: var(--pb-fz-xl); padding-left: var(--pb-sp-3); border-left: 4px solid var(--pb-primary); margin-bottom: var(--pb-sp-3); line-height: 1.5; }
+
+.pb-svc-related-list > li + li { border-top: 1px dashed var(--pb-border); }
+
+.pb-svc-related-list a { display: flex; align-items: center; justify-content: space-between; gap: var(--pb-sp-3); padding: var(--pb-sp-2) 0; min-width: 0; }
+
+.pb-svc-related-name { flex: 1; min-width: 0; font-size: var(--pb-fz-sm); color: var(--pb-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
+.pb-svc-related-list a:hover .pb-svc-related-name { color: var(--pb-primary-light); }
+
+.pb-svc-related-meta { flex: none; display: inline-flex; align-items: center; gap: var(--pb-sp-2); font-size: var(--pb-fz-xs); color: var(--pb-text-light); }
+
+/* ---------------------------------------------------------------------
+ 19. 页脚:深宝蓝多列(品牌+社媒 / 地址联系 / 二维码)+ 浅色友链层 + 更深色底条
+ --------------------------------------------------------------------- */
+.pb-footer { margin-top: var(--pb-sp-12); background: var(--pb-footer-bg); color: var(--pb-ink-on-dark-soft); }
+
+.pb-footer-main {
+ display: grid;
+ grid-template-columns: minmax(0, 2fr) minmax(0, 2fr) auto;
+ gap: var(--pb-sp-12);
+ padding: var(--pb-sp-12) var(--pb-sp-4) var(--pb-sp-8);
+}
+
+.pb-footer-logo-row { display: flex; align-items: center; gap: var(--pb-sp-3); min-width: 0; }
+
+.pb-footer-logo {
+ width: 52px;
+ height: 52px;
+ object-fit: contain;
+ background: rgba(255,255,255,.12);
+ border: 1px solid rgba(255,255,255,.28);
+ border-radius: var(--pb-radius);
+ padding: var(--pb-sp-1);
+}
+
+.pb-footer-site {
+ font-size: var(--pb-fz-3xl);
+ font-weight: 700;
+ letter-spacing: 2px;
+ color: var(--pb-ink-on-dark);
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.pb-social { display: flex; align-items: center; gap: var(--pb-sp-2); margin-top: var(--pb-sp-4); }
+
+.pb-social-icon {
+ width: 36px;
+ height: 36px;
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ color: var(--pb-ink-on-dark-soft);
+ border: 1px solid rgba(255,255,255,.28);
+ border-radius: var(--pb-radius);
+ transition: color var(--pb-speed), border-color var(--pb-speed), background var(--pb-speed), transform var(--pb-speed);
+}
+.pb-social-icon:hover { color: var(--pb-ink-on-dark); border-color: var(--pb-accent); background: var(--pb-accent); transform: translateY(-2px); }
+
+.pb-footer-info { min-width: 0; }
+
+.pb-footer-addr { display: flex; flex-direction: column; gap: var(--pb-sp-1); margin-bottom: var(--pb-sp-3); font-size: var(--pb-fz-sm); }
+.pb-footer-addr li { position: relative; padding-left: var(--pb-sp-3); }
+.pb-footer-addr li::before {
+ content: "";
+ position: absolute;
+ left: 0;
+ top: 9px;
+ width: 5px;
+ height: 5px;
+ background: var(--pb-accent);
+ transform: rotate(45deg);
+}
+
+.pb-footer-line { display: flex; align-items: baseline; gap: var(--pb-sp-2); font-size: var(--pb-fz-sm); line-height: 1.9; }
+
+.pb-dot { flex: none; width: 5px; height: 5px; border-radius: 50%; background: var(--pb-accent); transform: translateY(-2px); }
+
+.pb-footer-qr { display: flex; gap: var(--pb-sp-4); justify-content: flex-end; }
+
+.pb-qr { display: flex; flex-direction: column; align-items: center; gap: var(--pb-sp-2); }
+
+.pb-qr-frame {
+ display: block;
+ width: 96px;
+ height: 96px;
+ padding: var(--pb-sp-1);
+ background: #fff;
+ border-radius: var(--pb-radius);
+ overflow: hidden;
+ transition: transform var(--pb-speed), box-shadow var(--pb-speed);
+}
+.pb-qr:hover .pb-qr-frame { transform: scale(1.05); box-shadow: var(--pb-shadow-md); }
+.pb-qr-frame img { width: 100%; height: 100%; object-fit: contain; }
+
+.pb-qr figcaption { font-size: var(--pb-fz-xs); color: var(--pb-ink-on-dark-faint); text-align: center; }
+
+/* 友链层:主底之上半透明白覆层(纯色叠加,非渐变) */
+.pb-footer-links { background: rgba(255,255,255,.05); border-top: 1px solid rgba(255,255,255,.12); }
+
+.pb-footer-links-inner { display: flex; flex-wrap: wrap; gap: var(--pb-sp-4) var(--pb-sp-12); padding: var(--pb-sp-4); }
+
+.pb-links-group { min-width: 0; }
+
+.pb-group-name {
+ display: inline-block;
+ font-size: var(--pb-fz-sm);
+ font-weight: 600;
+ color: var(--pb-ink-on-dark);
+ border-left: 3px solid var(--pb-accent);
+ padding-left: var(--pb-sp-2);
+ margin-bottom: var(--pb-sp-2);
+}
+
+.pb-links-row { display: flex; flex-wrap: wrap; gap: var(--pb-sp-2) var(--pb-sp-4); }
+
+.pb-links-row a { display: inline-flex; align-items: center; gap: var(--pb-sp-1); color: var(--pb-ink-on-dark-soft); font-size: var(--pb-fz-sm); transition: color var(--pb-speed); }
+.pb-links-row a:hover { color: var(--pb-accent); }
+
+.pb-link-logo { width: 16px; height: 16px; object-fit: contain; }
+
+/* 底条:更深色 */
+.pb-footer-bottom { background: var(--pb-footer-deep); }
+
+.pb-footer-bottom-inner { display: flex; justify-content: center; padding: var(--pb-sp-3) var(--pb-sp-4); font-size: var(--pb-fz-sm); color: var(--pb-ink-on-dark-faint); }
+
+/* ---------------------------------------------------------------------
+ 20. 响应式:≤1200 收窄 / ≤992 收侧栏 / ≤768 单列 + 汉堡导航 / ≤480 微调
+ (网格一律 minmax(0,1fr),390px 不溢出)
+ --------------------------------------------------------------------- */
+@media (max-width: 1200px) {
+ .pb-brandbar-inner { padding: var(--pb-sp-3) var(--pb-sp-4); }
+ .pb-site-name { font-size: var(--pb-fz-3xl); letter-spacing: 1px; }
+ .pb-search { width: 220px; }
+ .pb-hotwords { display: none; }
+ .pb-channels { grid-template-columns: repeat(4, minmax(0, 1fr)); }
+}
+
+@media (max-width: 992px) {
+ .pb-cols { grid-template-columns: minmax(0, 1fr); }
+ .pb-side-nav { display: none; }
+ .pb-footer-main { grid-template-columns: minmax(0, 1fr); gap: var(--pb-sp-6); }
+ .pb-footer-qr { justify-content: flex-start; }
+ .pb-split,
+ .pb-headline { grid-template-columns: minmax(0, 1fr); }
+ .pb-media-list { grid-template-columns: minmax(0, 1fr); column-gap: 0; }
+ .pb-wall,
+ .pb-wall--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
+ .pb-brand-tools .pb-date { display: none; }
+}
+
+/* ≤768:单列布局 + 品牌行纵排 + 汉堡导航 */
+@media (max-width: 768px) {
+ .pb-brandbar-inner { flex-direction: column; align-items: flex-start; gap: var(--pb-sp-3); padding: var(--pb-sp-3); }
+
+ .pb-brand-side { width: 100%; align-items: stretch; }
+
+ .pb-brand-tools { width: 100%; justify-content: space-between; flex-wrap: wrap; gap: var(--pb-sp-2); }
+
+ .pb-audience { padding-left: 0; border-left: 0; flex-wrap: wrap; }
+
+ .pb-search-row { width: 100%; }
+ .pb-search { flex: 1; width: auto; }
+
+ /* 汉堡导航:按钮显示,列表纵排抽屉 */
+ .pb-nav-toggle { display: block; }
+
+ .pb-nav-list { display: none; flex-direction: column; align-items: stretch; width: 100%; padding-bottom: var(--pb-sp-2); }
+ .pb-nav-list.pb-open { display: flex; }
+
+ .pb-nav-list > li > a { width: 100%; justify-content: space-between; padding: var(--pb-sp-3) var(--pb-sp-4); font-size: var(--pb-fz-md); }
+ .pb-nav-list > li > a::after { display: none; }
+ .pb-nav-list > li.active > a { background: var(--pb-tint-strong); }
+
+ /* 二级:窄屏改手风琴展开(main.js 切换 .pb-sub-open) */
+ .pb-sub {
+ position: static;
+ opacity: 1;
+ visibility: visible;
+ transform: none;
+ display: none;
+ min-width: 0;
+ border-radius: 0;
+ box-shadow: none;
+ margin: 0 calc(var(--pb-sp-4) * -1);
+ }
+ .pb-nav-list > li.pb-sub-open > .pb-sub { display: block; }
+
+ .pb-banner-arrow { display: none; }
+ .pb-banner-title { font-size: var(--pb-fz-lg); padding: var(--pb-sp-8) var(--pb-sp-3) var(--pb-sp-3); }
+ .pb-banner-dots { right: var(--pb-sp-3); bottom: var(--pb-sp-2); }
+
+ .pb-section { padding-top: var(--pb-sp-6); }
+ .pb-block { padding: var(--pb-sp-3) var(--pb-sp-3) var(--pb-sp-4); }
+
+ .pb-news-body { padding: var(--pb-sp-3); }
+ .pb-news-title { font-size: var(--pb-fz-lg); }
+
+ .pb-blocks { grid-template-columns: minmax(0, 1fr); }
+
+ .pb-article-row { flex-direction: column; gap: var(--pb-sp-2); }
+ .pb-item-cover { width: 100%; }
+
+ .pb-feat > a { flex-direction: column; }
+ .pb-feat-cover { width: 100%; }
+
+ .pb-page-card { padding: var(--pb-sp-3); }
+ .pb-article-title { font-size: var(--pb-fz-3xl); }
+ .pb-sibling { grid-template-columns: minmax(0, 1fr); }
+ .pb-sibling .next { grid-column: auto; text-align: left; }
+
+ .pb-ticker-inner { flex-wrap: wrap; gap: var(--pb-sp-2); }
+ .pb-ticker-list { flex-basis: 100%; }
+ .pb-ticker-item { max-width: 100%; }
+
+ .pb-channels { grid-template-columns: repeat(3, minmax(0, 1fr)); }
+ .pb-channel-icon { width: 44px; height: 44px; }
+}
+
+@media (max-width: 480px) {
+ .pb-brand-badge { width: 44px; height: 44px; }
+ .pb-site-name { font-size: var(--pb-fz-xl); }
+ .pb-wall,
+ .pb-wall--4 { grid-template-columns: minmax(0, 1fr); }
+ .pb-channels { grid-template-columns: repeat(2, minmax(0, 1fr)); }
+ .pb-footer-qr { flex-wrap: wrap; }
+ .pb-page-title { font-size: var(--pb-fz-xl); }
+ .pb-banner-title { font-size: var(--pb-fz-md); }
+ .pb-svc-apply-btn { width: 100%; justify-content: center; }
+}
+
+/* ---------------------------------------------------------------------
+ 21. 无障碍与打印微调
+ --------------------------------------------------------------------- */
+@media (prefers-reduced-motion: reduce) {
+ *,
+ *::before,
+ *::after {
+ transition-duration: 0.01ms !important;
+ animation-duration: 0.01ms !important;
+ }
+}
+
+@media print {
+ .pb-nav,
+ .pb-brandbar,
+ .pb-banner-arrow,
+ .pb-banner-dots,
+ .pb-footer-links,
+ .pb-nav-toggle { display: none !important; }
+ body { background: #fff; }
+ .pb-page-card,
+ .pb-block { box-shadow: none; border-color: var(--pb-border); }
+}
diff --git a/src/main/resources/templates/themes/poly-blue/assets/favicon.png b/src/main/resources/templates/themes/poly-blue/assets/favicon.png
new file mode 100644
index 0000000..822653c
Binary files /dev/null and b/src/main/resources/templates/themes/poly-blue/assets/favicon.png differ
diff --git a/src/main/resources/templates/themes/poly-blue/assets/js/main.js b/src/main/resources/templates/themes/poly-blue/assets/js/main.js
new file mode 100644
index 0000000..0e69098
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/assets/js/main.js
@@ -0,0 +1,192 @@
+/* poly-blue(理工蓝)皮肤包脚本:顶条日期 + 首页轮播(自动播放/圆点/箭头/悬停暂停/键盘/触摸)
+ + 白底主导航吸顶 + 移动端抽屉与二级手风琴。与 default 同源逻辑,无任何外部依赖。 */
+(function () {
+ 'use strict';
+
+ /* ---------- 顶条日期(本地时间,YYYY年M月D日 星期X;元素在深宝蓝品牌行) ---------- */
+ var dateEl = document.getElementById('siteDate');
+ if (dateEl) {
+ var now = new Date();
+ var week = ['日', '一', '二', '三', '四', '五', '六'][now.getDay()];
+ dateEl.textContent = now.getFullYear() + '年' + (now.getMonth() + 1) + '月'
+ + now.getDate() + '日 星期' + week;
+ }
+
+ /* ---------- 白底主导航吸顶(桌面端;≤768 不吸顶,交还给抽屉形态) ---------- */
+ var nav = document.getElementById('pbNav');
+ var DESKTOP_MIN = 769;
+ var navBaseTop = 0;
+ var holder = null;
+
+ function unlockNav() {
+ if (nav) { nav.classList.remove('pb-nav--fixed'); }
+ if (holder && holder.parentNode) {
+ holder.parentNode.removeChild(holder);
+ }
+ holder = null;
+ }
+
+ function lockNav() {
+ if (!nav) { return; }
+ if (!nav.classList.contains('pb-nav--fixed')) {
+ holder = document.createElement('div');
+ holder.className = 'pb-nav-holder';
+ holder.style.height = nav.offsetHeight + 'px';
+ nav.parentNode.insertBefore(holder, nav);
+ nav.classList.add('pb-nav--fixed');
+ } else if (holder) {
+ holder.style.height = nav.offsetHeight + 'px';
+ }
+ }
+
+ function measureNavTop() {
+ if (!nav) { return; }
+ unlockNav();
+ navBaseTop = nav.getBoundingClientRect().top + window.pageYOffset;
+ }
+
+ function onScrollNav() {
+ if (window.innerWidth < DESKTOP_MIN) {
+ unlockNav();
+ return;
+ }
+ if (window.pageYOffset > navBaseTop) {
+ lockNav();
+ } else {
+ unlockNav();
+ }
+ }
+
+ if (nav) {
+ measureNavTop();
+ window.addEventListener('scroll', onScrollNav, { passive: true });
+ var resizeTimer = null;
+ window.addEventListener('resize', function () {
+ if (resizeTimer) { window.clearTimeout(resizeTimer); }
+ resizeTimer = window.setTimeout(function () {
+ measureNavTop();
+ onScrollNav();
+ }, 150);
+ });
+ }
+
+ /* ---------- 移动端抽屉 + 二级手风琴 ---------- */
+ var navToggle = document.querySelector('.pb-nav-toggle');
+ var navList = document.querySelector('.pb-nav-list');
+
+ if (navToggle && navList) {
+ navToggle.addEventListener('click', function () {
+ var open = navList.classList.toggle('pb-open');
+ navToggle.setAttribute('aria-expanded', open ? 'true' : 'false');
+ });
+ }
+
+ /* 窄屏下:点击带二级的项先展开面板,再点才跳转;宽屏交还给 CSS hover */
+ if (navList) {
+ navList.addEventListener('click', function (e) {
+ if (window.innerWidth >= DESKTOP_MIN) { return; }
+ var link = e.target.closest ? e.target.closest('a') : null;
+ if (!link) { return; }
+ var li = link.parentElement;
+ if (!li || !li.classList.contains('has-sub')) { return; }
+ var sub = li.querySelector('.pb-sub');
+ if (!sub) { return; }
+ if (!li.classList.contains('pb-sub-open')) {
+ e.preventDefault();
+ li.classList.add('pb-sub-open');
+ }
+ });
+ }
+
+ /* ---------- 首页轮播(自动播放/圆点/箭头/悬停暂停/键盘) ---------- */
+ var root = document.querySelector('.pb-banner');
+ var slides = document.querySelectorAll('.pb-banner-slide');
+ var dots = document.querySelectorAll('.pb-banner-dots button');
+ var prevBtn = document.querySelector('.pb-banner-arrow.prev');
+ var nextBtn = document.querySelector('.pb-banner-arrow.next');
+ if (!slides.length || !root) {
+ return;
+ }
+ var current = 0;
+ var timer = null;
+ var INTERVAL = 5000;
+
+ function show(index) {
+ slides[current].classList.remove('active');
+ if (dots[current]) {
+ dots[current].classList.remove('active');
+ }
+ current = (index + slides.length) % slides.length;
+ slides[current].classList.add('active');
+ if (dots[current]) {
+ dots[current].classList.add('active');
+ }
+ }
+
+ function start() {
+ stop();
+ if (slides.length > 1) {
+ timer = window.setInterval(function () {
+ show(current + 1);
+ }, INTERVAL);
+ }
+ }
+
+ function stop() {
+ if (timer) {
+ window.clearInterval(timer);
+ timer = null;
+ }
+ }
+
+ dots.forEach(function (dot, index) {
+ dot.addEventListener('click', function () {
+ show(index);
+ start();
+ });
+ });
+ if (prevBtn) {
+ prevBtn.addEventListener('click', function () {
+ show(current - 1);
+ start();
+ });
+ }
+ if (nextBtn) {
+ nextBtn.addEventListener('click', function () {
+ show(current + 1);
+ start();
+ });
+ }
+ root.addEventListener('mouseenter', stop);
+ root.addEventListener('mouseleave', start);
+ root.addEventListener('focusin', stop);
+ root.addEventListener('focusout', start);
+ root.setAttribute('tabindex', '-1');
+ root.addEventListener('keydown', function (e) {
+ if (e.key === 'ArrowLeft') {
+ show(current - 1);
+ start();
+ } else if (e.key === 'ArrowRight') {
+ show(current + 1);
+ start();
+ }
+ });
+
+ /* 触摸滑动切页 */
+ var touchX = null;
+ root.addEventListener('touchstart', function (e) {
+ touchX = e.changedTouches[0].clientX;
+ stop();
+ }, { passive: true });
+ root.addEventListener('touchend', function (e) {
+ if (touchX === null) { return; }
+ var dx = e.changedTouches[0].clientX - touchX;
+ if (Math.abs(dx) > 40) {
+ show(dx < 0 ? current + 1 : current - 1);
+ }
+ touchX = null;
+ start();
+ }, { passive: true });
+
+ start();
+})();
diff --git a/src/main/resources/templates/themes/poly-blue/assets/screenshot.png b/src/main/resources/templates/themes/poly-blue/assets/screenshot.png
new file mode 100644
index 0000000..2a59eea
Binary files /dev/null and b/src/main/resources/templates/themes/poly-blue/assets/screenshot.png differ
diff --git a/src/main/resources/templates/themes/poly-blue/detail.html b/src/main/resources/templates/themes/poly-blue/detail.html
new file mode 100644
index 0000000..24be053
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/detail.html
@@ -0,0 +1,76 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 文章标题
+
+
+ 作者
+ 来源
+ 浏览量
+
+
+ 正文
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/poly-blue/fragments/footer.html b/src/main/resources/templates/themes/poly-blue/fragments/footer.html
new file mode 100644
index 0000000..e188562
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/fragments/footer.html
@@ -0,0 +1,101 @@
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/poly-blue/fragments/head.html b/src/main/resources/templates/themes/poly-blue/fragments/head.html
new file mode 100644
index 0000000..c96f24d
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/fragments/head.html
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+ 页面标题
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/poly-blue/fragments/header.html b/src/main/resources/templates/themes/poly-blue/fragments/header.html
new file mode 100644
index 0000000..d120046
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/fragments/header.html
@@ -0,0 +1,109 @@
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/poly-blue/fragments/home-blocks.html b/src/main/resources/templates/themes/poly-blue/fragments/home-blocks.html
new file mode 100644
index 0000000..e659537
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/fragments/home-blocks.html
@@ -0,0 +1,229 @@
+
+
+
+
+
+
+
+
+
+ -
+
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+ 01
+ 2026-01
+
+ 文章标题
+ 置顶
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
线上展厅
+
+
+ Online Exhibition Hall
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/poly-blue/guide.html b/src/main/resources/templates/themes/poly-blue/guide.html
new file mode 100644
index 0000000..fc26d1c
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/guide.html
@@ -0,0 +1,134 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
事项服务暂时不可用,请稍后再试
+
事项数据服务暂不可达,稍后刷新即可恢复
+
+
+
+ 事项名称
+
+ 办理部门
+ 办理方式
+
+ 浏览量
+
+
+
+
+
+ 简介
+
+
+ 事项基本信息
+
+
+ | 服务对象 |
+ 服务对象 |
+
+
+ | 事项类别 |
+ 事项类别 |
+
+
+ | 办理地点 |
+ 办理地点 |
+
+
+ | 办理时限 |
+ 办理时限 |
+
+
+ | 承诺时限 |
+ 承诺时限 |
+
+
+ | 咨询电话 |
+ 咨询电话 |
+
+
+ | 监督投诉 |
+ 监督投诉电话 |
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/poly-blue/home.html b/src/main/resources/templates/themes/poly-blue/home.html
new file mode 100644
index 0000000..2a80827
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/home.html
@@ -0,0 +1,148 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
头条推荐
+
+
+ -
+ 头条标题
+
+ 置顶
+
+
+
+ -
+ 置顶
+ 文章标题
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/poly-blue/list.html b/src/main/resources/templates/themes/poly-blue/list.html
new file mode 100644
index 0000000..4638723
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/list.html
@@ -0,0 +1,106 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
栏目名
+
搜索词
+
+
+
+ -
+
+
+
+
+
+
+
摘要
+
+
+ 置顶
+
+
+
+
+
+ 01
+ 2026-01
+
+
+
+ 置顶
+
+
+
+
+
+
未找到相关内容
+
栏目暂无内容
+
换个关键词试试
+
内容发布后将在此展示
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/poly-blue/service.html b/src/main/resources/templates/themes/poly-blue/service.html
new file mode 100644
index 0000000..23a79db
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/service.html
@@ -0,0 +1,111 @@
+
+
+
+
+
+
+
+
+
+
+
+
服务中心
+
+
+
+
事项服务暂时不可用,请稍后再试
+
事项数据服务暂不可达,稍后刷新即可恢复
+
+
+
+
+
+
+
+
+
未找到符合条件的服务事项
+
服务中心暂未上架事项
+
换个筛选条件或关键词试试
+
事项发布后将在此展示
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/poly-blue/single.html b/src/main/resources/templates/themes/poly-blue/single.html
new file mode 100644
index 0000000..66ffed0
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/single.html
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 栏目名
+
+ 单页内容
+
+
+
+
+
+
+
+
+
+
diff --git a/src/main/resources/templates/themes/poly-blue/theme.json b/src/main/resources/templates/themes/poly-blue/theme.json
new file mode 100644
index 0000000..e34d5ae
--- /dev/null
+++ b/src/main/resources/templates/themes/poly-blue/theme.json
@@ -0,0 +1,29 @@
+{
+ "specVersion": 1,
+ "name": "poly-blue",
+ "title": "理工蓝(poly-blue)",
+ "version": "1.0.0",
+ "author": "yunhai",
+ "description": "深宝蓝+活力橙的理工院校风(设计语言参考浙江理工大学官网)。",
+ "screenshot": "assets/screenshot.png",
+ "bannerSize": "1920x560",
+ "params": [
+ { "key": "primary", "cssVar": "--pb-primary", "label": "主色", "type": "color", "default": "#0558a5" },
+ { "key": "primaryDark", "cssVar": "--pb-primary-dark", "label": "主色加深", "type": "color", "default": "#124489" },
+ { "key": "primaryLight", "cssVar": "--pb-primary-light","label": "主色提亮", "type": "color", "default": "#258cff" },
+ { "key": "accent", "cssVar": "--pb-accent", "label": "活力橙强调", "type": "color", "default": "#ff7b00" },
+ { "key": "secondary", "cssVar": "--pb-secondary", "label": "绿色小标签", "type": "color", "default": "#1c7b46" },
+ { "key": "navBg", "cssVar": "--pb-nav-bg", "label": "主导航底色", "type": "color", "default": "#ffffff" },
+ { "key": "footerBg", "cssVar": "--pb-footer-bg", "label": "页脚底色", "type": "color", "default": "#124489" },
+ { "key": "text", "cssVar": "--pb-text", "label": "正文文字色", "type": "color", "default": "#2f3a47" },
+ { "key": "textLight", "cssVar": "--pb-text-light", "label": "次要文字色", "type": "color", "default": "#708090" },
+ { "key": "bg", "cssVar": "--pb-bg", "label": "页面底色", "type": "color", "default": "#f5f8fc" },
+ { "key": "cardBg", "cssVar": "--pb-card-bg", "label": "卡片底色", "type": "color", "default": "#ffffff" },
+ { "key": "border", "cssVar": "--pb-border", "label": "边框色", "type": "color", "default": "#e2e8f2" },
+ { "key": "headerStyle", "label": "头部样式", "type": "select", "default": "banner",
+ "options": [
+ { "value": "banner", "label": "通栏横幅头图" },
+ { "value": "plain", "label": "深色品牌行+白底吸顶" }
+ ] }
+ ]
+}
diff --git a/src/test/java/com/yunhai/cms/theme/ThemeRegistryTest.java b/src/test/java/com/yunhai/cms/theme/ThemeRegistryTest.java
index 32d3b40..665155a 100644
--- a/src/test/java/com/yunhai/cms/theme/ThemeRegistryTest.java
+++ b/src/test/java/com/yunhai/cms/theme/ThemeRegistryTest.java
@@ -135,6 +135,30 @@ class ThemeRegistryTest {
}
}
+ @Test
+ @DisplayName("高校官网风第二批: poly-blue/agri-forest/jade-normal 注册成功,主色与存量全部互异")
+ void universitySkinsRegisteredWithDistinctPrimary() {
+ String defaultPrimary = registry.get(ThemeRegistry.DEFAULT_THEME).param("primary").getDefaultValue();
+ String scholarPrimary = registry.get("scholar-blue").param("primary").getDefaultValue();
+ java.util.Map seen = new java.util.LinkedHashMap<>();
+ for (String name : new String[] {"poly-blue", "agri-forest", "jade-normal"}) {
+ ThemeInfo info = registry.get(name);
+ assertThat(info).as("%s 皮肤包必须注册(清单+必备模板+截图齐全)", name).isNotNull();
+ assertThat(info.getTitle()).isNotBlank();
+ ThemeParam primary = info.param("primary");
+ assertThat(primary).as("%s 应声明 primary 参数", name).isNotNull();
+ assertThat(primary.getDefaultValue())
+ .as("%s 的 primary 不得与 default 相同", name).isNotEqualTo(defaultPrimary);
+ assertThat(primary.getDefaultValue())
+ .as("%s 的 primary 不得与 scholar-blue 相同(拷贝忘改哨兵)", name)
+ .isNotEqualTo(scholarPrimary);
+ seen.put(name, primary.getDefaultValue());
+ }
+ assertThat(seen.get("poly-blue")).isNotEqualTo(seen.get("agri-forest"));
+ assertThat(seen.get("poly-blue")).isNotEqualTo(seen.get("jade-normal"));
+ assertThat(seen.get("agri-forest")).isNotEqualTo(seen.get("jade-normal"));
+ }
+
@Test
@DisplayName("default 包缺失时 fail-fast(方案 §5.1,启动失败防线)")
void defaultMissingFailsFast() {
diff --git a/src/test/java/com/yunhai/cms/theme/UniversitySkinContractTest.java b/src/test/java/com/yunhai/cms/theme/UniversitySkinContractTest.java
new file mode 100644
index 0000000..d23e940
--- /dev/null
+++ b/src/test/java/com/yunhai/cms/theme/UniversitySkinContractTest.java
@@ -0,0 +1,200 @@
+package com.yunhai.cms.theme;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * 高校官网风皮肤契约·第二批(poly-blue / agri-forest / jade-normal,以 default 为基座派生)。
+ *
+ * 与 AcademicSkinContractTest 同构,钉住同一组渲染不变量(自带九段首页区块、
+ * home.html 按 homeStyle 分发到本包 fragment、中文防塌列、:root 契约变量别名、
+ * 背景带层序、预览图必须是本皮肤自有图)。配色断言按三包定位分档:
+ * poly-blue 主色蓝通道主导(参考浙江理工大学 #0558A5),agri-forest/jade-normal
+ * 主色绿通道主导(参考信阳农林学院 #1C6E19 / 信阳师范大学 #008D3F)——
+ * 粉/紫系已被用户否决(cherry-bloom/violet-iris 事故),此处锁死不回流。
+ */
+@DisplayName("高校官网风皮肤契约·第二批 - 自带首页区块 + 高校官网配色")
+class UniversitySkinContractTest {
+
+ /** 皮肤名:结构类名前缀,两处必须一致(拷贝忘改前缀会让皮肤互相串样式)。 */
+ private static final String[] SKINS = {"poly-blue:pb", "agri-forest:af", "jade-normal:jn"};
+
+ private static String skin(String spec) {
+ return spec.substring(0, spec.indexOf(':'));
+ }
+
+ private static String prefix(String spec) {
+ return spec.substring(spec.indexOf(':') + 1);
+ }
+
+ private static String text(String classpath) {
+ try (InputStream in = UniversitySkinContractTest.class.getResourceAsStream(classpath)) {
+ assertThat(in).as("classpath 资源必须存在:%s", classpath).isNotNull();
+ return new String(readAll(in), StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ private static byte[] readAll(InputStream in) throws IOException {
+ java.io.ByteArrayOutputStream out = new java.io.ByteArrayOutputStream();
+ byte[] buf = new byte[8192];
+ int n;
+ while ((n = in.read(buf)) > 0) {
+ out.write(buf, 0, n);
+ }
+ return out.toByteArray();
+ }
+
+ private static String ruleOf(String css, String selector) {
+ Matcher m = Pattern.compile(Pattern.quote(selector) + "\\s*\\{([^}]*)\\}").matcher(css);
+ assertThat(m.find()).as("main.css 应含选择器 %s 的规则", selector).isTrue();
+ return m.group(1).replaceAll("\\s+", "");
+ }
+
+ /** 抽出所有含 marker 的开始标签,用于检查同一标签上的属性组合。 */
+ private static java.util.List tagsContaining(String html, String marker) {
+ java.util.List tags = new java.util.ArrayList<>();
+ Matcher m = Pattern.compile("<[a-zA-Z][^>]*>").matcher(html);
+ while (m.find()) {
+ if (m.group().contains(marker)) {
+ tags.add(m.group());
+ }
+ }
+ return tags;
+ }
+
+ @Test
+ @DisplayName("派生包自带首页区块 fragment:布局模式下区块由皮肤渲染,不落通用骨架")
+ void skinOwnsHomeBlockFragments() {
+ for (String spec : SKINS) {
+ String html = text("/templates/themes/" + skin(spec) + "/fragments/home-blocks.html");
+ for (String fragment : new String[] {"news_grid", "media_focus", "compact", "image_wall",
+ "card", "ticker", "gallery", "links", "empty"}) {
+ assertThat(html).as("%s 区块 fragment 必须自带", fragment)
+ .contains("th:fragment=\"" + fragment + "(block)\"");
+ }
+ // 空态:th:replace(优先级 100)先于 th:if(300),守卫写在同一标签上等于没写
+ for (String tag : tagsContaining(html, ":: empty(")) {
+ assertThat(tag).as("%s 的空态守卫必须在外层 th:block 上", skin(spec)).doesNotContain("th:if");
+ }
+ assertThat(html).contains("th:block th:if=\"${#lists.isEmpty(block.items)}\"");
+ }
+ }
+
+ @Test
+ @DisplayName("home.html 把布局区块分发到本皮肤 fragment,区块头带右置「更多」")
+ void homeDispatchesToOwnFragments() {
+ for (String spec : SKINS) {
+ String html = text("/templates/themes/" + skin(spec) + "/home.html");
+ assertThat(html).as("须按 layoutBlocks 分支渲染").contains("layoutBlocks != null");
+ for (String style : new String[] {"news_grid", "media_focus", "compact", "image_wall"}) {
+ assertThat(html).as("%s 形态 %s 应走本皮肤 fragment", skin(spec), style)
+ .contains("'/fragments/home-blocks' :: " + style + "(${block})");
+ }
+ assertThat(html).as("区块标题行须有右侧「更多」样式钩子").contains(prefix(spec) + "-more");
+ }
+ }
+
+ @Test
+ @DisplayName("中文行不被压塌:速递条单行可收缩、列表标题超长省略")
+ void rowsMustNotCollapseCjkText() {
+ for (String spec : SKINS) {
+ String css = text("/templates/themes/" + skin(spec) + "/assets/css/main.css");
+ String p = prefix(spec);
+ String list = ruleOf(css, "." + p + "-ticker-list");
+ assertThat(list).as("flex 列表须让出收缩权并锁单行").contains("min-width:0").contains("white-space:nowrap");
+ String item = ruleOf(css, "." + p + "-ticker-item");
+ assertThat(item).as("条目不被压缩且超长省略").contains("flex:none").contains("text-overflow:ellipsis");
+ String title = ruleOf(css, "." + p + "-block-item-title");
+ assertThat(title).contains("min-width:0").contains("overflow:hidden").contains("text-overflow:ellipsis");
+ }
+ }
+
+ @Test
+ @DisplayName("皮肤变量别名到主题契约变量,供 common 兜底骨架继承")
+ void skinAliasesContractVars() {
+ for (String spec : SKINS) {
+ String css = text("/templates/themes/" + skin(spec) + "/assets/css/main.css");
+ String p = prefix(spec);
+ String root = ruleOf(css, ":root");
+ assertThat(root).contains("--primary:var(--" + p + "-primary)")
+ .contains("--text:var(--" + p + "-text)")
+ .contains("--card-bg:var(--" + p + "-card-bg)")
+ .contains("--border:var(--" + p + "-border)");
+ }
+ }
+
+ @Test
+ @DisplayName("新闻背景带画在卡片之下:绝对定位层必须压 z-index,卡片抬起来")
+ void newsBandMustPaintBehindCard() {
+ for (String spec : SKINS) {
+ String css = text("/templates/themes/" + skin(spec) + "/assets/css/main.css");
+ String p = prefix(spec);
+ assertThat(ruleOf(css, "." + p + "-sec-bg")).as("%s 背景带须压到卡片之下", p).contains("z-index:0");
+ assertThat(ruleOf(css, "." + p + "-sec-bg + ." + p + "-block"))
+ .as("%s 卡片须抬到背景带之上,否则新闻带图片盖住正文", p).contains("z-index:1");
+ }
+ }
+
+ @Test
+ @DisplayName("皮肤预览图必须是本皮肤自有图,不得沿用基座 default 的截图")
+ void screenshotMustBeOwnCapture() {
+ byte[] base = bytes("/templates/themes/default/assets/screenshot.png");
+ for (String spec : SKINS) {
+ String path = "/templates/themes/" + skin(spec) + "/assets/screenshot.png";
+ byte[] shot = bytes(path);
+ assertThat(shot).as("%s 的预览图与基座雷同,等于没换肤", skin(spec)).isNotEqualTo(base);
+ assertThat(shot.length).as("%s 预览图不能是空文件", skin(spec)).isGreaterThan(20 * 1024);
+ }
+ }
+
+ private static byte[] bytes(String classpath) {
+ try (InputStream in = UniversitySkinContractTest.class.getResourceAsStream(classpath)) {
+ assertThat(in).as("classpath 资源必须存在:%s", classpath).isNotNull();
+ return readAll(in);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+ @Test
+ @DisplayName("配色必须是高校官网主色:poly-blue 蓝通道主导、agri-forest/jade-normal 绿通道主导,粉紫禁入")
+ void primaryMustBeUniversityHue() throws IOException {
+ for (String spec : SKINS) {
+ JsonNode root = new ObjectMapper()
+ .readTree(text("/templates/themes/" + skin(spec) + "/theme.json"));
+ assertThat(root.path("name").asText()).as("name 必须等于目录名").isEqualTo(skin(spec));
+ String primary = null;
+ for (JsonNode p : root.path("params")) {
+ if ("primary".equals(p.path("key").asText())) {
+ primary = p.path("default").asText();
+ }
+ }
+ assertThat(primary).as("%s theme.json 须声明 primary 颜色参数", skin(spec)).isNotNull();
+ Matcher m = Pattern.compile("#([0-9a-fA-F]{6})").matcher(primary);
+ assertThat(m.matches()).as("primary 需为 6 位 hex,实际 %s", primary).isTrue();
+ int rgb = Integer.parseInt(m.group(1), 16);
+ int r = (rgb >> 16) & 0xFF, g = (rgb >> 8) & 0xFF, b = rgb & 0xFF;
+ double lightness = (Math.max(r, Math.max(g, b)) + Math.min(r, Math.min(g, b))) / 255d / 2d;
+ if ("poly-blue".equals(skin(spec))) {
+ assertThat(b).as("理工蓝主色须蓝通道主导,实际 %s", primary).isGreaterThan(r).isGreaterThan(g);
+ } else {
+ assertThat(g).as("%s 主色须绿通道主导(农林/师范绿),实际 %s", skin(spec), primary)
+ .isGreaterThan(r).isGreaterThan(b);
+ }
+ assertThat(lightness).as("官网主色应为沉稳深色而非粉彩,实际 %s", primary)
+ .isBetween(0.18d, 0.52d);
+ }
+ }
+}