diff --git a/README.md b/README.md index 5206b88..a68dba6 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,6 @@ # GreLin · Typst 文档模板 -GreLin 内部 Typst 模板库,按文档类型分目录维护。 - -## 目录 +GreLin 内部 Typst 模板库,按文档类型分目录维护。目录结构如下: | 文件夹 | 说明 | 入口文件 | |--------|------|----------| @@ -14,21 +12,10 @@ GreLin 内部 Typst 模板库,按文档类型分目录维护。 - [VS Code](https://code.visualstudio.com/) 或 [Cursor](https://cursor.com/) - 扩展:[Tinymist](https://marketplace.visualstudio.com/items?itemName=myriad-dreamin.tinymist)(搜索 `Tinymist` 安装即可,已集成预览与导出,无需单独装 Typst CLI) -> 勿安装已废弃的 `Typst LSP`、`Typst Preview`,会与 Tinymist 冲突。 - ## 快速开始 -1. 用 VS Code / Cursor 打开本仓库 -2. 打开要编辑的入口文件,例如 `resume/cv.typ` -3. **看效果(预览)**:`Ctrl+Shift+P` → 输入 `Typst Preview` → 回车;侧边会实时显示排版效果(快捷键 `Ctrl+K` 然后 `V`) -4. **导出 PDF**:`Ctrl+Shift+P` → 输入 `Typst Export PDF` → 回车;PDF 默认生成在同目录(如 `resume/sample.pdf`) +1. 用 VS Code / Cursor 打开本仓库,打开要编辑的入口文件,例如 `resume/cv.typ` +2. 看效果(预览):`Ctrl+Shift+P` → 输入 `Typst Preview` → 回车;侧边会实时显示排版效果 +3. 导出 PDF:`Ctrl+Shift+P` → 输入 `Typst Export PDF` → 回车;PDF 默认生成在同目录(如 `resume/sample.pdf`) -仓库根目录的 [`typst.toml`](typst.toml) 将项目根设为 GreLin,以便 `resume/` 与 `feasibility/` 共享 [`brand/colors.typ`](brand/colors.typ)。命令行编译示例: - -```bash -typst compile resume/cv.typ resume/sample.pdf --root . -``` - -已填好的示例 PDF 见 [`resume/sample.pdf`](resume/sample.pdf)。 - -不熟悉 Typst?可参考社区维护的 [小蓝书(Typst 中文教程)](https://tutorial.typst.dev/);英文版见 [官方入门教程](https://typst.app/docs/tutorial/)。 +> 不熟悉 Typst?可参考社区维护的 [小蓝书(Typst 中文教程)](https://tutorial.typst.dev/);英文版见 [官方入门教程](https://typst.app/docs/tutorial/)。 diff --git a/resume/README.md b/resume/README.md index 507a63b..8b03b56 100644 --- a/resume/README.md +++ b/resume/README.md @@ -2,40 +2,60 @@ GreLin 双栏中文简历 Typst 模板(HyperLabel 配色),用于融资 BP data room 附录。 -## 快速开始 - -在仓库根目录执行(需共享 `brand/colors.typ`): - -```bash -typst compile resume/cv.typ resume/sample.pdf --root . -typst watch resume/cv.typ --root . -``` - -示例输出:[`sample.pdf`](sample.pdf)(已填内容,供版式参考)。 - -## 定制 - -| 文件 | 说明 | -|------|------| -| [`data/config.typ`](data/config.typ) | 个人信息、教育、能力、技术栈、经历、项目 | -| [`data/theme.typ`](data/theme.typ) | 配色、字号、间距 | -| [`data/layout.typ`](data/layout.typ) | 版式组件(一般无需改动) | - ## 照片 -将证件照放入 `assets/profile.jpeg`,或在 `data/config.typ` 中设置 `author-photo` 路径。 +将证件照放入 `assets/profile.jpeg`,或在 `data/config.typ` 的 `profile` 模块中设置 `photo-path`。 -## 结构 +### 编辑示例(只改 `config.typ`) +```typst +#let profile = ( + name: "姓名", + title: "职位", + summary: "个人简介……", + photo-path: "../assets/profile.jpeg", +) + +#let contact = ( + address: "城市", + phone: "手机号", + email: "邮箱", + website: "https://example.com", + website-label: "example.com", +) + +#let skills = ( + abilities: ( + (name: "全栈开发", level: 0.9), + ), + language: ( + name: "英语", + level: 0.75, + label: "读写", + ), + tags: ("Rust", "Python"), + notes: (), // 可选:侧栏技能补充列表 +) + +#let education = ( + ( + degree: "软件工程 / 硕士", + school: "西北大学", + period: "2022 – 2025", + location: "西安", + notes: "", // 可选:GPA、主修课程等一段说明 + ), +) + +#let awards = () // 可选:主栏获奖经历 + +#let experiences = ( + ( + company: "某某科技", + role: "工程师", + bullets: ("职责……", "动作……", "结果……"), + ), +) ``` -resume/ -├── cv.typ -├── sample.pdf -├── data/ -│ ├── config.typ -│ ├── layout.typ -│ └── theme.typ -└── assets/ - ├── profile.jpeg - └── icons/ -``` + +`bullets` 用字符串元组,不要手写 `-` 列表语法。 diff --git a/resume/cv.typ b/resume/cv.typ index 9aa77af..449485c 100644 --- a/resume/cv.typ +++ b/resume/cv.typ @@ -6,6 +6,7 @@ paper: "a4", margin: page-margin, fill: color-page, + foreground: page-corners-layer(), ) #set text( @@ -18,7 +19,32 @@ #set par(leading: leading-body, spacing: space-none, justify: true) -#page-corners() +#let sidebar-content = [ + #section-title("联系", sidebar: true, above: space-none) + #contact-block() + #sidebar-section-divider() + + #section-title("教育", sidebar: true) + #education-block(show-notes: true) + #sidebar-section-divider() + + #section-title("技能", sidebar: true) + #skills-section-block() +] + +#let main-content = [ + #section-title("工作经历", above: space-none) + #experiences-block() + + #section-title("项目经历") + #projects-block() + + #if awards.len() > 0 [ + #section-title("获奖经历") + #awards-block() + ] +] + #hero-section() #header-divider() @@ -26,24 +52,7 @@ columns: (sidebar-column, stroke-divider-column, main-column), column-gutter: (space-column-gap, space-column-gap), align: (top, top, top), - [ - #section-title("联系", sidebar: true, above: space-none) - #contact-block() - #sidebar-section-divider() - - #section-title("教育", sidebar: true) - #education-block() - #sidebar-section-divider() - - #section-title("技能", sidebar: true) - #skills-section-block() - ], + [#box(width: 100%)[#sidebar-content]], line(length: 100%, stroke: stroke-divider-sidebar), - [ - #section-title("工作经历", above: space-none) - #experiences-block() - - #section-title("项目经历") - #projects-block() - ], + main-content, ) diff --git a/resume/data/config.typ b/resume/data/config.typ index 270dc4f..bd67ae0 100644 --- a/resume/data/config.typ +++ b/resume/data/config.typ @@ -1,32 +1,42 @@ -// ============================================================================= +// ===================================================================== // 个人信息 — 修改此处即可定制简历 -// ============================================================================= +// ===================================================================== #let company-name = "西安高岭绿能科技有限公司" #let meituan-company-name = "北京三快在线科技有限公司" #let company-city = "陕西西安" -#let author-name = "齐梦璠" -#let author-title = "软件研发 | 系统架构" - -#let author-summary = [ - 西北大学软件工程本硕。具备从 0 到 1 构建业务系统的能力:在美团 AI 应用组参与大模型 Agent 类应用的工程落地;现于高岭绿能负责矿石分选系统的软件全链路交付,将算法能力转化为可部署、可运维的工业产品。 -] - -#let author-address = "陕西西安" -#let author-phone = "19829062833" -#let author-email = "19829062833@163.com" -#let author-website = "https://3506897731.github.io/" -#let author-website-label = "3506897731.github.io" - -#let language_profile = ( - name: "英语", - level: 0.75, - label: "读写", +#let profile = ( + name: "齐梦璠", + title: "软件研发 | 系统架构", + summary: "西北大学软件工程本硕。具备从 0 到 1 构建业务系统的能力:在美团 AI 应用组参与大模型 Agent 类应用的工程落地;现于高岭绿能负责矿石分选系统的软件全链路交付,将算法能力转化为可部署、可运维的工业产品。", + photo-path: "../assets/profile.jpeg", ) -// 证件照路径(空字符串表示无照片) -#let author-photo-path = "../assets/profile.jpeg" +#let contact = ( + address: "陕西西安", + phone: "19829062833", + email: "19829062833@163.com", + website: "https://3506897731.github.io/", + website-label: "3506897731.github.io", +) + +#let skills = ( + abilities: ( + (name: "全栈开发", level: 0.9), + (name: "系统架构", level: 0.75), + ), + language: ( + name: "英语", + level: 0.75, + label: "读写", + ), + tags: ( + "Rust", "Python", "Java", "React", "Tauri", "RAG", "Linux", "MySQL", "Redis", + "LLM Agent", + ), + notes: (), +) #let education = ( ( @@ -34,26 +44,17 @@ school: "西北大学", period: "2022 – 2025", location: "西安", + notes: "", ), ( degree: "软件工程 / 学士", school: "西北大学", period: "2018 – 2022", location: "西安", + notes: "", ), ) -#let abilities = ( - (name: "全栈开发", level: 0.9), - (name: "系统架构", level: 0.75), -) - -// 技术栈 pill 标签 -#let tech-tags = ( - "Rust", "Python", "Java", "React", "Tauri", "RAG", "Linux", "MySQL", "Redis", - "LLM Agent", -) - #let experiences = ( ( company: company-name, @@ -61,11 +62,11 @@ location: "西安", start: "2025.06", end: "至今", - description: [ - - 负责矿石分选系统软件研发,覆盖运维工具、运营后台与产线部署联调。 - - 与算法团队协作完成模型服务化接入,设计推理回调、异常降级与运行监控体系。 - - 产线落地 1 条 / 1 客户现场,单线 25 t/h;精矿 A/S 4.0+、尾矿 A/S 1.7-、回收率 30%+。 - ], + bullets: ( + "负责矿石分选系统软件研发,覆盖运维工具、运营后台与产线部署联调。", + "与算法团队协作完成模型服务化接入,设计推理回调、异常降级与运行监控体系。", + "产线落地 1 条 / 1 客户现场,单线 25 t/h;精矿 A/S 4.0+、尾矿 A/S 1.7-、回收率 30%+。", + ), ), ( company: meituan-company-name, @@ -73,11 +74,11 @@ location: "北京", start: "2024.07", end: "2025.06", - description: [ - - 参与大模型 Agent 应用工程化,负责前后端模块开发与 LLM 服务对接。 - - 完成对话编排、工具调用与业务系统集成,独立承担功能从设计到上线交付。 - - 交付 Skill 工具累计覆盖数千名用户、下载量 1 万+;定时任务类能力日均服务约 200 名用户。 - ], + bullets: ( + "参与大模型 Agent 应用工程化,负责前后端模块开发与 LLM 服务对接。", + "完成对话编排、工具调用与业务系统集成,独立承担功能从设计到上线交付。", + "交付 Skill 工具累计覆盖数千名用户、下载量 1 万+;定时任务类能力日均服务约 200 名用户。", + ), ), ) @@ -88,10 +89,10 @@ location: "西安", start: "2025.06", end: "至今", - description: [ - - 面向铝土矿产线的矿石分选系统,实现高光谱采集、模型推理与喷阀执行的闭环控制。 - - 负责产线运维工具与核心软件模块交付;基于 Rust 实现 Ratatui 运维控制台与 ONNX 推理集成,完成「采集 → 推理 → 喷阀」流程联调。 - ], + bullets: ( + "面向铝土矿产线的矿石分选系统,实现高光谱采集、模型推理与喷阀执行的闭环控制。", + "负责产线运维工具与核心软件模块交付;基于 Rust 实现 Ratatui 运维控制台与 ONNX 推理集成,完成「采集 → 推理 → 喷阀」流程联调。", + ), ), ( name: "HyperLabel 高光谱标注工作站", @@ -99,9 +100,11 @@ location: "西安", start: "2025.06", end: "至今", - description: [ - - 高光谱标注桌面工作站,面向矿石分选场景的训练数据生产与样本管理。 - - 负责 Tauri + React 前端,以及项目、样本、标签等业务的 CRUD 后端接口。 - ], + bullets: ( + "高光谱标注桌面工作站,面向矿石分选场景的训练数据生产与样本管理。", + "负责 Tauri + React 前端,以及项目、样本、标签等业务的 CRUD 后端接口。", + ), ), ) + +#let awards = () diff --git a/resume/data/layout.typ b/resume/data/layout.typ index b88fbd6..a144f60 100644 --- a/resume/data/layout.typ +++ b/resume/data/layout.typ @@ -6,8 +6,8 @@ #let icon-mail = image("../assets/icons/mail.svg") #let icon-globe = image("../assets/icons/globe.svg") -#let profile-photo = if author-photo-path != "" { - image(author-photo-path, width: 100%, height: 100%, fit: "cover") +#let profile-photo = if profile.photo-path != "" { + image(profile.photo-path, width: 100%, height: 100%, fit: "cover") } else { none } @@ -29,21 +29,21 @@ } } -/// 左上 / 右下装饰条 -#let page-corners() = { - place( +/// 左上 / 右下装饰条(通过 page foreground 绘制,每页自动出现) +#let page-corners-layer() = box(width: page-paper-width, height: page-paper-height)[ + #place( top + left, - dx: -page-margin.left, - dy: -page-margin.top + corner-bar-inset, + dx: corner-bar-inset-x, + dy: corner-bar-inset-y, block(width: corner-bar-width, height: corner-bar-height, fill: color-skill-bar), ) - place( + #place( bottom + right, - dx: page-margin.right, - dy: page-margin.bottom - corner-bar-inset, + dx: -corner-bar-inset-x, + dy: -corner-bar-inset-y, block(width: corner-bar-width, height: corner-bar-height, fill: color-skill-bar), ) -} +] /// 页眉:姓名 + 职位 + 简介 + 2 寸照片 #let hero-section() = block(width: 100%, below: space-none)[ @@ -52,13 +52,13 @@ column-gutter: space-hero-to-photo, align: (top, top), [ - #text(font: heading-font, size: size-name, weight: "bold", fill: color-ink)[#author-name] + #text(font: heading-font, size: size-name, weight: "bold", fill: color-ink)[#profile.name] #v(space-hero-name-gap) - #text(font: heading-font, size: size-heading, weight: "bold", fill: color-accent-bright)[#author-title] + #text(font: heading-font, size: size-heading, weight: "bold", fill: color-accent-bright)[#profile.title] #v(space-hero-title-gap) #set text(weight: "regular") #set par(leading: leading-summary, spacing: space-none, justify: true) - #text(fill: color-text-light, size: size-body)[#author-summary] + #text(fill: color-text-light, size: size-summary)[#profile.summary] ], [ #align(right)[ @@ -110,29 +110,58 @@ ] #let contact-block() = block(above: space-none)[ - #contact-line(icon-map-pin, author-address) - #contact-line(icon-phone, link("tel:" + author-phone, author-phone)) - #contact-line(icon-mail, link("mailto:" + author-email, author-email)) - #if author-website != "" { - contact-line(icon-globe, link(author-website, author-website-label)) + #contact-line(icon-map-pin, contact.address) + #contact-line(icon-phone, link("tel:" + contact.phone, contact.phone)) + #contact-line(icon-mail, link("mailto:" + contact.email, contact.email)) + #if contact.website != "" { + contact-line(icon-globe, link(contact.website, contact.website-label)) } ] -/// 教育背景条目 -#let edu-entry(degree, school, period, location) = block(above: space-none, below: space-none)[ +/// 教育背景条目(notes 可选,一段普通正文) +#let edu-entry(degree, school, period, location, notes: "") = block(above: space-none, below: space-none)[ #text(fill: color-body, size: size-body)[#degree] #v(space-inline) #text(fill: color-text-light, size: size-secondary)[ #school#if period != "" [ · #period]#if location != "" [ · #location] ] + #if notes != "" [ + #v(space-edu-notes-before) + #set par(leading: leading-edu-notes, spacing: space-none, justify: true) + #text(fill: color-text-light, size: size-secondary)[#notes] + ] ] -#let education-block() = { +#let education-block(show-notes: false) = { for (i, item) in education.enumerate() { if i > 0 { v(space-between-entries) } - edu-entry(item.degree, item.school, item.period, item.location) + edu-entry( + item.degree, + item.school, + item.period, + item.location, + notes: if show-notes { item.at("notes", default: "") } else { "" }, + ) + } +} + +/// 侧栏技能补充列表(skills.notes 为空则不渲染) +#let skill-notes-block() = { + if skills.notes.len() > 0 { + block(above: space-none)[ + #set text(fill: color-text-light, size: size-secondary) + #set par(leading: list-item-leading, spacing: space-none, justify: true) + #set list( + tight: true, + indent: list-indent, + body-indent: list-body-indent, + ) + #for line in skills.notes [ + - #line + ] + ] } } @@ -176,7 +205,7 @@ #let tech-stack-block() = block(width: 100%, above: space-none, below: space-inline)[ #box(width: 100%)[ #set par(spacing: pill-gap, leading: leading-pill-wrap) - #for (i, tag) in tech-tags.enumerate() [ + #for (i, tag) in skills.tags.enumerate() [ #if i > 0 [#h(pill-gap)] #tech-pill(tag) ] @@ -186,7 +215,7 @@ #let skills-section-block() = { sidebar-subtitle("能力", above: space-none) block(below: space-none)[ - #for (i, item) in abilities.enumerate() { + #for (i, item) in skills.abilities.enumerate() { skill-bar( item.name, item.level, @@ -194,14 +223,18 @@ ) } #skill-bar( - language_profile.name, - language_profile.level, - subtitle: language_profile.label, + skills.language.name, + skills.language.level, + subtitle: skills.language.label, above: space-skill-gap, ) ] sidebar-subtitle("技术栈", above: space-subsection-gap) tech-stack-block() + if skills.notes.len() > 0 { + sidebar-subtitle("补充", above: space-subsection-gap) + skill-notes-block() + } } /// 主栏经历 / 项目条目 @@ -225,7 +258,9 @@ indent: list-indent, body-indent: list-body-indent, ) - #entry.description + #for line in entry.bullets [ + - #line + ] ] #let project-entry(entry) = timeline-entry(entry, title-key: "name", subtitle-key: "org") @@ -244,3 +279,30 @@ project-entry(entry) } } + +/// 获奖经历条目(bullets 可留空) +#let award-entry(entry) = block[ + #text(fill: color-body, size: size-body, weight: "bold")[#entry.title] + #v(space-body) + #text(fill: color-text-light, size: size-body)[#entry.meta] + #if entry.bullets.len() > 0 [ + #v(space-body) + #set text(weight: "regular", fill: color-text-light, size: size-body) + #set par(leading: list-item-leading, spacing: space-none, justify: true) + #set list( + tight: true, + indent: list-indent, + body-indent: list-body-indent, + ) + #for line in entry.bullets [ + - #line + ] + ] +] + +#let awards-block() = { + for (i, entry) in awards.enumerate() { + if i > 0 { v(space-between-entries) } + award-entry(entry) + } +} diff --git a/resume/data/theme.typ b/resume/data/theme.typ index 782363a..d75878c 100644 --- a/resume/data/theme.typ +++ b/resume/data/theme.typ @@ -9,17 +9,18 @@ #let heading-font = ("Microsoft YaHei", "Segoe UI") #let body-font = ("Microsoft YaHei UI", "Microsoft YaHei", "Segoe UI") -// ============================================================================= +// ===================================================================== // GreLin Resume · Design Tokens(唯一规范源) // 字号四档:20 · 12 · 10.5 · 9 // 间距三档:6 · 12 · 18(+ 4 micro · 10.5 body 级) -// ============================================================================= +// ===================================================================== // --- 字号 --- #let size-name = 20pt #let size-heading = 12pt #let size-body = 10.5pt #let size-secondary = 9pt +#let size-summary = size-body // --- 行距 --- #let leading-body = 13pt @@ -31,8 +32,10 @@ #let space-none = 0pt #let space-micro = 4pt #let space-inline = 6pt -#let space-body = size-body // 10.5pt:条目内块间距、列表行距 +#let space-body = size-body #let space-title-gap = 12pt +#let space-edu-notes-before = space-title-gap +#let leading-edu-notes = size-secondary #let space-between-entries = 12pt #let space-block = 18pt #let space-hero-to-photo = space-block @@ -40,9 +43,9 @@ #let space-subtitle-gap = space-body #let space-subsection-gap = space-body -#let space-skill-gap = space-body // 能力条 / 英语条之间 +#let space-skill-gap = space-body #let space-hero-name-gap = space-body -#let space-hero-title-gap = space-body +#let space-hero-title-gap = space-block // --- 列表(行内换行与条目间距统一为正文级 10.5pt) --- #let list-item-leading = space-body @@ -71,11 +74,14 @@ #let list-body-indent = 0.4em // --- 布局 --- +#let page-paper-width = 210mm +#let page-paper-height = 297mm #let sidebar-column = 0.85fr #let main-column = 2.15fr #let corner-bar-width = 5mm #let corner-bar-height = 21.6mm -#let corner-bar-inset = 11mm +#let corner-bar-inset-x = 0pt +#let corner-bar-inset-y = 11mm #let page-margin = ( top: 2cm, diff --git a/resume/sample.pdf b/resume/sample.pdf index 06e5a43..c8d21af 100644 --- a/resume/sample.pdf +++ b/resume/sample.pdf @@ -904,23 +904,26 @@ uUL endstream endobj 126 0 obj -<> +<> stream -x]$m]ZuO$ZƱݺ<8il5Ώ4voyqvg)VS#3C  |z}իf蛆jyؤz􊚫 UaRsE~y>4\/>?ۧ|Wuzlcd"XbC -PJ4kȈk7vI1؈$Z ШG`D}鋓ih`mb$CAD,(K/XpZpeCO?Fj.O"~ǿ|rO8)Xo216,5]YN_/l9v.+P(4UA[;u=ֽwFؓ]B{\'{a/!-dmWʴ{v}۽qwڝM) Qt(7BFO?ߏIa& zR2g޽aif6Eyasro8ba /)+X):fMrl~=?E6wQ^R38k.*!Q$?@újK JC I 9EH5͜V;Gr!yɏH>N~{?%-- 缡VߤrlH^q8)ȱy{5vƐZ㝵0"lM>IP=Y7!kՆ&&gad$I(vώ^teo7-z]@Cd^%Ї)wdInP5`9[fUGֆ(TvxݑMK٭|̬A֥pA\56;E -vZϛ3T -u$;GUdOPOm?)sO⿠Wno.s댪ŏ FNL nM+`0HBH i)̪)lPPUo|(BYq$FdUf%de|H7l+`2Pm6ix`x4"#_u:tKwF-~Y$xA(&Է=@^ -&~\\{kܕXHOaF -ݤi i -JV\^g .N`H.ኄ+bĕ#N7WxGmdИG𾱉RijKD >O1Tqذ6 M21D9.Pbo$`H"XT5&p8r8D#T]lİ4pBpƚ F Q "^|#&XW\y¹6b+^ްAa%yIUqna d0ĬIFzh7QCtqk"^U6΄DkA6oHبI;ihw}FI) /%%$\&7)Mc]@ҥ\"EW(Cq-ԳvO!ʒ{_rh\AГ1JoyLeUǂG|KOJr -Ń1QrQ( ]*c!G~2?IE shF RSg#luXB K8u>6 F: ` iaVOHEJ; ߧ|\5(T3\+7ԃ -F~k(Fb82DRdUUoKn0aPhL YYOϑ _ eE|HvF|`)>^gQ|:zS /\*ۂ&#{ #Y'gxX(*&n EV|X--x❶߀df|6H쯆䧥h| XzU+ tx&kEםC,j|԰?r5,(38CtTi6\&r|)7M5զ:'vfҞڔvV6koe沔m^f -+9Fр91G|vkYK:q-%Ub~fY[Gag_wuMh8aux)ĥ)0)TYB%Y-jq=M tU.8KRtLA]˝\,  Ś׿e\NTӝ]XT궫8 ډ17S)5/J~!b:h+"Cg". %H,xnMe2 vj)a=>q[9BhĢ%>'R^`I31 V-7" ˗H2:UREF|Ċ[ؑE{pVJ-$v72EP9B sE5=)K|NpĎ}-%%#YX[s%3Sw։HG `Txu(5lqG_׍DLNF<:r{}j$VXe05iQ(IPc0u`:O|VדB΁EofYӗa!1*GQ+kw?ɛ`dMA;3Ί#=^d*j9ȹGǨ9 J0)kdcZGtG6 0PS}a6pݱٗcyV !_"yuXEj1ALqtILhHxO#gR0ȡb~.:&9b1l("@grl!YaVSٍC*ZFeokBmH(nDV"X֍ A{{0,b_45 [b&4R|9ecfgģ׀Uc YcUx] ir!BZ7Otui1\$BU&}>0v`uvc@M $͖k򇊎(uDa)EjTMk1qA-FnA|G6 `1l=T(ܐ-b'&+l !-/+֐7WTn3^aQ0}\ F={Ma!QCwr^TD[4ŠX~[fTuّ}4>(N6p0$ɽb<-H;+b eڄ `=J.b0|?%m؍rӰ[+ndvx< uUAgc/e=D=\WV'b6?eUEm(h sR#=k Ϲ{"I<a=G`φc#U?c؇hk FI<Lc^k$c/4IvJ\>VAx^~SzVLVQ_~v2%TS2ֳ} O#g"_ׯ|;(,ٱAi QrRIlq1@_l$*=#+"D@\lI 9>CѢI(9"&rl%jn'OPR$@ΉJT"wFcFK/3Y,x)[!<0/B ʽj2"J QBo_ z?)D"e"RKH=vo)JS"=#UźcF+]}GD!s"he[Z-ay+PxKBΉzTun=:!<7DgBd SۮEoM*B!6cZ2φA®^|;D~q údHlqyhŬbf7qVt -lxh<+jz)Fޝy@~>hH~\A}f"Ŵ "љAE^бeR#p>4ІC4bdql4zoN~j?D(!>B3!QޢH3Ǘ Cv&GXthuIٌшbڤR89F_yi8۩.M [6KbtnC-G4h0cO&Hs<.6Ѻ DBta5ܞ97)9K6s Otqɻߒ!_-M|2ʪ:S +x]$m]ZuO$ZƱݺ<8il5Ώ4voyqvg)VS# C  |z}իf蛆jyؤz􊚫 UaRsE~y>4\7CeG_}~Ͼ?4tzLeHjYQϗ^Աҵ겡ۧS#\~^6|"_~.?:kxz2Nm, )Xo216,5]YN_/l9v.q{P6i"+ w;7z{'*ϸL*:^:CZvuۮەim޷{;iRA'7vQTo-"3$?_&0e $ݛvffQF:w'H +{Hf.?(z1H"c$s,Y\sQ "T۝']phHbBHq! $H!9CBFjH.=@#$#ɇӏcD휓ۧ|WC-缡Vߤr3E(1xLAͳGޛ?43%-|苣g-GdUIye$fnG?;zѕضl +u MbuQB}'l}GUI):?)# ;j6_uo&PyuG6~'.ek8FIS3f &Zq,3x uh=oBP),Wq>A=}x-)HtpY'M#JsH%ܼp%\FU2;16AjD BjMNLaVu|Oa􅺾.ʯxG&$15,-Wd[M!y߰9[Dz@-rknmҐazCuYsW]&ѨhK!_ ͍ńH+Aߏ+4cy4 i)HS4u$MvU@IÊ,$<ߥ܉%\0|ePr) +嗀L76Q +0RBmI}'5I|p৘B*aKlXN&db r4] &HE߱ƩjL`q,1%qF"؈ai!ᢵ5A(EA4 +DFL.smVa& J&=b{q$l`TYSnhEvk"^U6΄DkA6oHبI;ihw}FI) /%%$\&7)Qئձ.o| +gmRp._+`ءY\GW8BO(1%k05Um bIF^6,*%)d&FE4Ttۯbe3gH.>>34'u6Υ:u6KutN;Cԙk` +5`/a|l:%t|0ksHEJ; ߧ|\5(T3\+7ԃ +F~k(Fb'.$ɢޖ02`lG9 >@򳲄 #$@ˊ ! R|̉ uj @4^$T\CM0.F;A,C"`"!eixr/Ϩ=o?ƛPkŢxm7,&Y>dG4 !i)?b7H>䧿xSvsEGE|Ufj !;qMSMM;tUiOmJEW_; +L 沔>m=o/f3˕h@Ht|GZZ#^ >C_޵% Ӓ*XXpRuj?,RѰ;'+^M̽3  zFuڪ`y>#R0n,xdɱ7Vpdkɾ7OĨhHѿ;oUnArY=F^VȾ˳%WnjU,&yYQ3$jǩ9 ++٪IQI4:Ȥٌv, wI|sL>B +&9\ CՏ%"AVD5G9& EHL-$:>K{9,êy*qHŚ^+܈\ ByC `E׍(JDeذ4w( Ph1,ASc?5z+fL#ŗS?fvF|L<9y X;(`%0v`uvc@M $͖k򇊎(uDa)EjTMk1qA-FnA|G6 `1l=T(ܐ-b'&+l !-/+֐7WTn3^aQ0}\ F={Ma!QCOH4߂h~ [Xo,78;)Zf"$=T EgeQQ 3LGEaT!fǻ$ Anv`EحLnﺂ'a7l%̷늙ݪd_PW2g,Tq=aNjgAx%äVJ oGH#gñIǪMC[EõV\$Ky FN}r$Xz;c[K}mHD'Ñ3ï˷ׯ|=v,$Qٍ3cY6c>ӘħX;Ai7 b(6HdU"{FdWD8&( 6r|*,TE,QrDnM6L{K$'OPR$@ΉJT"wFcFK/3Y,x)[!<0/B ʽj2"J QBo_ z?)D2o%RGH-ݱ[ҔHψtaXJmW|_5nH/ZVxixy +T!R(vs"?l歳~N ;?zC)Lt&Dq>1xZv*ڔ-H ylǴee k}+];; sdvvuɐ+E ٷTj!8nAM ^Cycݬ̭E60܎Q7t*06x3"XauK 0&J(=4©\k3go=vSLT,&AǬ'q,ziytU_sz٭Rrww ,$uBʗǫ o{+=dquvΉ]DAz ֯vxt8rIL7kͦ;cɴ;ZfqҒhqcĬb!P./vہ蜉Ρ SDQ#@ЛW0y;Y†7oУxgO| +9?}˷u O7l0B6|Ć}Lk2"!2=~#tzsu~*{ :fBq~!otmum746NW[϶w6lոO^ՄP=c"|ꈓ*Ŗ,Ipj%s> +<> endobj 130 0 obj <> stream -Typst 0.15.0zh2026-06-23T14:38:22+08:002026-06-23T14:38:22+08:001application/pdfjKUOrUjtYX9DRppue0Iu0A==jKUOrUjtYX9DRppue0Iu0A==proof1.7 +Typst 0.15.0zh2026-06-23T16:28:44+08:002026-06-23T16:28:44+08:001application/pdfcyD771vaNfjg2k+HwoDFcg==cyD771vaNfjg2k+HwoDFcg==proof1.7 endstream endobj 131 0 obj @@ -4932,13 +4935,13 @@ xref 0000123633 00000 n 0000124345 00000 n 0000143033 00000 n -0000148486 00000 n -0000148893 00000 n -0001010608 00000 n -0001010721 00000 n -0001011794 00000 n +0000148485 00000 n +0000148892 00000 n +0001010607 00000 n +0001010720 00000 n +0001011793 00000 n trailer -<> +<> startxref -1011964 +1011963 %%EOF \ No newline at end of file