2 Commits

Author SHA1 Message Date
gylove1994
63b98f42b4 feat(calendar, souvenir): update food map image source and add coming soon modal
- Updated the food map image source based on locale in CalendarPage.astro.
- Introduced a "coming soon" modal in SouvenirPage.astro with relevant translations and styling.
- Updated the CTA URL in translations.json for both English and Chinese versions.
2026-05-20 06:25:37 +08:00
gylove1994
4f9099abb6 feat(site): migrate from Starlight docs to custom Astro website
- Remove Starlight and MDX docs content
- Add multilingual routing under [lang]/
- Add Home, Calendar, Souvenir, and CMS Guide pages
- Move static assets to public/images
- Add i18n config and translations
- Add client scripts for badge tilt, parallax, and nixflake animation
- Update astro config and dependencies

Signed-off-by: gylove1994 <gylove1994@acgsteps.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-19 17:05:41 +08:00
59 changed files with 5148 additions and 1974 deletions

View File

@@ -1,49 +1,13 @@
// @ts-check
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import mdx from '@astrojs/mdx';
import starlightUITweaks from 'starlight-ui-tweaks';
// https://astro.build/config
export default defineConfig({
site: 'https://meetup.nixos-cn.org',
integrations: [
starlight({
title: 'Nix CN',
defaultLocale: 'root',
logo: {
light: './src/assets/nix-cn.svg',
dark: './src/assets/nix-cn-dark.svg',
replacesTitle: true,
},
locales: {
root: {
label: '简体中文',
lang: 'zh-CN',
},
en: {
label: 'English',
},
},
social: [
{
icon: 'seti:git',
label: 'Source',
href: 'https://github.com/NixOS-CN/nixcn-web',
},
],
sidebar: ['meetup-2-guide', 'souvenir-customization', 'volunteers', 'code-of-conduct', 'calendar'],
plugins: [
starlightUITweaks({
navbarLinks: [{ label: 'Nix CN 社区 ↗', href: 'https://nixos-cn.org/' }],
locales: {
en: {
navbarLinks: [{ label: 'Nix CN Community ↗', href: 'https://nixos-cn.org/' }],
},
},
}),
],
}),
mdx(),
],
server: {
host: true,
},
redirects: {
'/': '/zh-CN/',
},
});

View File

@@ -7,14 +7,16 @@
"start": "astro dev",
"build": "astro build",
"preview": "astro preview",
"astro": "astro"
"astro": "astro",
"check": "astro check",
"typecheck": "astro check",
"lint:fix": "prettier --write ."
},
"dependencies": {
"@astrojs/mdx": "^4.3.12",
"@astrojs/starlight": "^0.37.0",
"@astrojs/check": "^0.9.9",
"astro": "^5.6.1",
"sharp": "^0.34.2",
"starlight-ui-tweaks": "^0.1.0"
"typescript": "^6.0.3"
},
"devDependencies": {
"prettier": "^3.7.4",

1601
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

4
pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,4 @@
onlyBuiltDependencies:
- esbuild
- sharp
- workerd

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 491 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 274 KiB

View File

@@ -0,0 +1,489 @@
<svg width="520" height="450" viewBox="0 0 520 450" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.6" clip-path="url(#clip0_178_5)">
<g filter="url(#filter0_dddiii_178_5)">
<path d="M275.063 79.1703L302.836 127.278H59.7998L87.573 79.1703H143.119L115.346 31.0623L129.241 7H157.014L198.682 79.1703H275.063Z" fill="#64AEE0" fill-opacity="0.8" shape-rendering="crispEdges"/>
</g>
<g filter="url(#filter1_iii_178_5)">
<path d="M268.8 86L289.8 121H72.2998L93.2998 86H155.3L124.8 32.5L134.8 16H151.8L192.8 86H268.8Z" fill="url(#paint0_linear_178_5)"/>
</g>
<path d="M151.37 16.75L192.152 86.3789L192.37 86.75H268.375L288.475 120.25H73.625L93.7246 86.75H156.591L155.951 85.6289L125.669 32.5117L135.223 16.75H151.37Z" stroke="url(#paint1_linear_178_5)" stroke-opacity="0.8" stroke-width="1.5"/>
<g filter="url(#filter2_dddiii_178_5)">
<path d="M391.094 169.508L363.318 217.614L241.8 7.13911L297.349 7.1374L325.122 55.2419L352.898 7.13567L380.684 7.13786L394.571 31.1901L352.904 103.361L391.094 169.508Z" fill="#D5ECF9"/>
</g>
<g filter="url(#filter3_iii_178_5)">
<path d="M382.048 167.499L362.237 203.186L253.487 14.8253L294.298 15.5118L325.298 69.2054L356.38 16.0417L375.67 16.4519L384.17 31.1743L344.048 101.681L382.048 167.499Z" fill="url(#paint2_linear_178_5)"/>
</g>
<path d="M383.305 31.1772L343.396 101.31L343.184 101.684L381.186 167.506L362.224 201.663L254.799 15.598L293.861 16.2547L325.294 70.6985L325.945 69.584L356.805 16.8002L375.232 17.1931L383.305 31.1772Z" stroke="url(#paint3_linear_178_5)" stroke-opacity="0.6" stroke-width="1.5"/>
<g filter="url(#filter4_dddiii_178_5)">
<path d="M369.906 313.645L314.356 313.643L435.874 103.168L463.65 151.274L435.877 199.379L491.427 199.381L505.318 223.445L491.431 247.497L408.096 247.498L369.906 313.645Z" fill="#64AEE0" fill-opacity="0.8" shape-rendering="crispEdges"/>
</g>
<g filter="url(#filter5_iii_178_5)">
<path d="M367.122 304.807L326.311 305.493L435.061 117.133L454.872 152.819L423.872 206.513L485.455 206.849L494.744 223.759L486.244 238.482L405.122 238.989L367.122 304.807Z" fill="url(#paint4_linear_178_5)"/>
</g>
<path d="M485.809 237.734L405.118 238.238L404.688 238.242L366.685 304.064L327.624 304.72L435.048 118.655L454.01 152.812L422.577 207.256L423.868 207.262L485.01 207.596L493.883 223.75L485.809 237.734Z" stroke="url(#paint5_linear_178_5)" stroke-opacity="0.8" stroke-width="1.5"/>
<g filter="url(#filter6_dddiii_178_5)">
<path d="M233.655 368.962L205.882 320.854L448.918 320.854L421.145 368.962L365.598 368.962L393.371 417.07L379.477 441.133L351.703 441.133L310.035 368.962L233.655 368.962Z" fill="#D5ECF9"/>
</g>
<g filter="url(#filter7_iii_178_5)">
<path d="M239.918 362.133L218.918 327.133L436.418 327.133L415.418 362.133L353.418 362.133L383.918 415.633L373.918 432.133L356.918 432.133L315.918 362.133L239.918 362.133Z" fill="url(#paint6_linear_178_5)"/>
</g>
<path d="M357.347 431.383L316.565 361.754L316.347 361.383L240.343 361.383L220.243 327.883L435.093 327.883L414.993 361.383L352.127 361.383L352.766 362.504L383.049 415.621L373.495 431.383L357.347 431.383Z" stroke="url(#paint7_linear_178_5)" stroke-opacity="0.6" stroke-width="1.5"/>
<g filter="url(#filter8_dddiii_178_5)">
<path d="M119.472 276.862L147.248 228.756L268.766 439.231L213.217 439.233L185.444 391.128L157.668 439.235L129.882 439.232L115.995 415.18L157.662 343.009L119.472 276.862Z" fill="#64AEE0" fill-opacity="0.8" shape-rendering="crispEdges"/>
</g>
<g filter="url(#filter9_iii_178_5)">
<path d="M128.518 278.871L148.329 243.184L257.079 431.545L216.268 430.858L185.268 377.165L154.186 430.329L134.896 429.918L126.396 415.196L166.518 344.689L128.518 278.871Z" fill="url(#paint8_linear_178_5)"/>
</g>
<path d="M127.261 415.193L167.17 345.06L167.383 344.686L129.38 278.864L148.342 244.707L255.767 430.772L216.705 430.116L185.272 375.672L184.621 376.786L153.761 429.57L135.335 429.177L127.261 415.193Z" stroke="url(#paint9_linear_178_5)" stroke-opacity="0.8" stroke-width="1.5"/>
<g filter="url(#filter10_dddiii_178_5)">
<path d="M139.692 131.207L195.241 131.209L73.7228 341.684L45.9467 293.578L73.7199 245.473L18.1706 245.472L4.27945 221.407L18.166 197.355L101.501 197.354L139.692 131.207Z" fill="#D5ECF9"/>
</g>
<g filter="url(#filter11_iii_178_5)">
<path d="M142.475 140.046L183.286 139.359L74.5357 327.72L54.7248 292.033L85.7248 238.339L24.1425 238.003L14.853 221.093L23.353 206.371L104.475 205.864L142.475 140.046Z" fill="url(#paint10_linear_178_5)"/>
</g>
<path d="M23.7877 207.118L104.479 206.614L104.909 206.611L142.912 140.788L181.974 140.132L74.5488 326.197L55.5867 292.04L87.0198 237.596L85.7291 237.59L24.5872 237.256L15.714 221.102L23.7877 207.118Z" stroke="url(#paint11_linear_178_5)" stroke-opacity="0.6" stroke-width="1.5"/>
</g>
<defs>
<filter id="filter0_dddiii_178_5" x="49.7998" y="1" width="271.036" height="141.278" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.78001 0 0 0 0 0.879966 0 0 0 0 0.943096 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_5" result="effect2_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.722437 0 0 0 0 0.844379 0 0 0 0 0.932091 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_5" result="effect3_dropShadow_178_5"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_5" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.379415 0 0 0 0 0.641102 0 0 0 0 0.815561 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_5" result="effect5_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_5" result="effect6_innerShadow_178_5"/>
</filter>
<filter id="filter1_iii_178_5" x="69.2998" y="16" width="222.5" height="111" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.416157 0 0 0 0 0.679176 0 0 0 0 0.863751 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_5" result="effect2_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_5" result="effect3_innerShadow_178_5"/>
</filter>
<filter id="filter2_dddiii_178_5" x="231.8" y="1.13568" width="180.771" height="231.479" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.78001 0 0 0 0 0.879966 0 0 0 0 0.943096 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_5" result="effect2_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.851409 0 0 0 0 0.909227 0 0 0 0 0.950815 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_5" result="effect3_dropShadow_178_5"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_5" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.837358 0 0 0 0 0.881424 0 0 0 0 0.904616 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_5" result="effect5_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_5" result="effect6_innerShadow_178_5"/>
</filter>
<filter id="filter3_iii_178_5" x="250.487" y="14.8253" width="135.683" height="194.361" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.769899 0 0 0 0 0.871498 0 0 0 0 0.942796 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_5" result="effect2_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_5" result="effect3_innerShadow_178_5"/>
</filter>
<filter id="filter4_dddiii_178_5" x="304.356" y="97.1682" width="218.961" height="231.477" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.78001 0 0 0 0 0.879966 0 0 0 0 0.943096 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_5" result="effect2_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.722437 0 0 0 0 0.844379 0 0 0 0 0.932091 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_5" result="effect3_dropShadow_178_5"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_5" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.379415 0 0 0 0 0.641102 0 0 0 0 0.815561 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_5" result="effect5_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_5" result="effect6_innerShadow_178_5"/>
</filter>
<filter id="filter5_iii_178_5" x="323.312" y="117.133" width="173.433" height="194.361" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.416157 0 0 0 0 0.679176 0 0 0 0 0.863751 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_5" result="effect2_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_5" result="effect3_innerShadow_178_5"/>
</filter>
<filter id="filter6_dddiii_178_5" x="195.882" y="314.854" width="271.036" height="141.278" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.78001 0 0 0 0 0.879966 0 0 0 0 0.943096 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_5" result="effect2_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.851409 0 0 0 0 0.909227 0 0 0 0 0.950815 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_5" result="effect3_dropShadow_178_5"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_5" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.837358 0 0 0 0 0.881424 0 0 0 0 0.904616 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_5" result="effect5_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_5" result="effect6_innerShadow_178_5"/>
</filter>
<filter id="filter7_iii_178_5" x="215.918" y="327.133" width="222.5" height="111" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.769899 0 0 0 0 0.871498 0 0 0 0 0.942796 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_5" result="effect2_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_5" result="effect3_innerShadow_178_5"/>
</filter>
<filter id="filter8_dddiii_178_5" x="105.995" y="222.756" width="180.771" height="231.479" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.78001 0 0 0 0 0.879966 0 0 0 0 0.943096 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_5" result="effect2_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.722437 0 0 0 0 0.844379 0 0 0 0 0.932091 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_5" result="effect3_dropShadow_178_5"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_5" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.379415 0 0 0 0 0.641102 0 0 0 0 0.815561 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_5" result="effect5_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_5" result="effect6_innerShadow_178_5"/>
</filter>
<filter id="filter9_iii_178_5" x="123.396" y="243.184" width="135.683" height="194.361" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.416157 0 0 0 0 0.679176 0 0 0 0 0.863751 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_5" result="effect2_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_5" result="effect3_innerShadow_178_5"/>
</filter>
<filter id="filter10_dddiii_178_5" x="-5.72046" y="125.207" width="218.961" height="231.477" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.78001 0 0 0 0 0.879966 0 0 0 0 0.943096 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_5" result="effect2_dropShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.851409 0 0 0 0 0.909227 0 0 0 0 0.950815 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_5" result="effect3_dropShadow_178_5"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_5" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.837358 0 0 0 0 0.881424 0 0 0 0 0.904616 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_5" result="effect5_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_5" result="effect6_innerShadow_178_5"/>
</filter>
<filter id="filter11_iii_178_5" x="11.853" y="139.359" width="173.433" height="194.361" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.769899 0 0 0 0 0.871498 0 0 0 0 0.942796 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_5" result="effect2_innerShadow_178_5"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_5" result="effect3_innerShadow_178_5"/>
</filter>
<linearGradient id="paint0_linear_178_5" x1="134.3" y1="31.5" x2="255.3" y2="121" gradientUnits="userSpaceOnUse">
<stop stop-color="#7FBBE3"/>
<stop offset="0.490385" stop-color="#9AD1FA"/>
<stop offset="1" stop-color="#7FBBE3"/>
</linearGradient>
<linearGradient id="paint1_linear_178_5" x1="133.3" y1="16" x2="327.8" y2="135" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#67A7D3"/>
<stop offset="0.3125" stop-color="#80AFCD"/>
<stop offset="0.591346" stop-color="#8EC1E4"/>
<stop offset="1" stop-color="#92CDED"/>
</linearGradient>
<linearGradient id="paint2_linear_178_5" x1="361.996" y1="23.7689" x2="344.987" y2="173.308" gradientUnits="userSpaceOnUse">
<stop stop-color="#DCEFF9"/>
<stop offset="0.490385" stop-color="#E2F2FB"/>
<stop offset="1" stop-color="#DCEFF9"/>
</linearGradient>
<linearGradient id="paint3_linear_178_5" x1="374.92" y1="15.1529" x2="369.113" y2="243.095" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#C0E3FC"/>
<stop offset="0.3125" stop-color="#D2ECFD"/>
<stop offset="0.591346" stop-color="#BBDBF0"/>
<stop offset="1" stop-color="#B4E0F8"/>
</linearGradient>
<linearGradient id="paint4_linear_178_5" x1="481.571" y1="215.576" x2="343.561" y2="275.615" gradientUnits="userSpaceOnUse">
<stop stop-color="#7FBBE3"/>
<stop offset="0.490385" stop-color="#9AD1FA"/>
<stop offset="1" stop-color="#7FBBE3"/>
</linearGradient>
<linearGradient id="paint5_linear_178_5" x1="495.494" y1="222.46" x2="295.187" y2="331.402" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#67A7D3"/>
<stop offset="0.3125" stop-color="#80AFCD"/>
<stop offset="0.591346" stop-color="#8EC1E4"/>
<stop offset="1" stop-color="#92CDED"/>
</linearGradient>
<linearGradient id="paint6_linear_178_5" x1="374.418" y1="416.633" x2="253.418" y2="327.133" gradientUnits="userSpaceOnUse">
<stop stop-color="#DCEFF9"/>
<stop offset="0.490385" stop-color="#E2F2FB"/>
<stop offset="1" stop-color="#DCEFF9"/>
</linearGradient>
<linearGradient id="paint7_linear_178_5" x1="375.418" y1="432.133" x2="180.918" y2="313.133" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#C0E3FC"/>
<stop offset="0.3125" stop-color="#D2ECFD"/>
<stop offset="0.591346" stop-color="#BBDBF0"/>
<stop offset="1" stop-color="#B4E0F8"/>
</linearGradient>
<linearGradient id="paint8_linear_178_5" x1="148.57" y1="422.601" x2="165.579" y2="273.062" gradientUnits="userSpaceOnUse">
<stop stop-color="#7FBBE3"/>
<stop offset="0.490385" stop-color="#9AD1FA"/>
<stop offset="1" stop-color="#7FBBE3"/>
</linearGradient>
<linearGradient id="paint9_linear_178_5" x1="135.646" y1="431.217" x2="141.454" y2="203.275" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#67A7D3"/>
<stop offset="0.3125" stop-color="#80AFCD"/>
<stop offset="0.591346" stop-color="#8EC1E4"/>
<stop offset="1" stop-color="#92CDED"/>
</linearGradient>
<linearGradient id="paint10_linear_178_5" x1="28.0264" y1="229.276" x2="166.036" y2="169.237" gradientUnits="userSpaceOnUse">
<stop stop-color="#DCEFF9"/>
<stop offset="0.490385" stop-color="#E2F2FB"/>
<stop offset="1" stop-color="#DCEFF9"/>
</linearGradient>
<linearGradient id="paint11_linear_178_5" x1="14.103" y1="222.392" x2="214.41" y2="113.45" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#C0E3FC"/>
<stop offset="0.3125" stop-color="#D2ECFD"/>
<stop offset="0.591346" stop-color="#BBDBF0"/>
<stop offset="1" stop-color="#B4E0F8"/>
</linearGradient>
<clipPath id="clip0_178_5">
<rect width="520" height="450" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

@@ -1,12 +1,14 @@
<svg width="7582" height="2107" viewBox="0 0 7582 2107" fill="none" xmlns="http://www.w3.org/2000/svg">
<svg width="7194" height="2107" viewBox="0 0 7194 2107" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M560 1302.5L688 1080.8L1248 2050.75H992L864 1829.05L736 2050.75H608L544 1939.9L736 1607.34L560 1302.5Z" fill="url(#paint0_linear_1_55)"/>
<path d="M656 637.395L912 637.395L352 1607.34L224 1385.64L352 1163.94L96 1163.94L32 1053.09L96 942.236L480 942.236L656 637.395Z" fill="url(#paint1_linear_1_55)"/>
<path d="M1280 387.979L1408 609.682L288 609.682L416 387.979L672 387.979L544 166.277L608 55.4255L736 55.4255L928 387.979L1280 387.979Z" fill="url(#paint2_linear_1_55)"/>
<path d="M1808 803.672L1680 1025.37L1120 55.4255L1376 55.4255L1504 277.128L1632 55.4255H1760L1824 166.277L1632 498.831L1808 803.672Z" fill="url(#paint3_linear_1_55)"/>
<path d="M1712 1468.78L1456 1468.78L2016 498.831L2144 720.533L2016 942.236L2272 942.236L2336 1053.09L2272 1163.94L1888 1163.94L1712 1468.78Z" fill="url(#paint4_linear_1_55)"/>
<path d="M1088 1718.19L960 1496.49L2080 1496.49L1952 1718.19L1696 1718.19L1824 1939.9L1760 2050.75L1632 2050.75L1440 1718.19L1088 1718.19Z" fill="url(#paint5_linear_1_55)"/>
<g transform="translate(-388 0)">
<path d="M7427.29 420H7582V1700H7434.48L6689.71 684.649V1700H6535V420H6682.52L7427.29 1435.35V420Z" fill="black"/>
<path d="M5992.34 1720.1C5647.41 1720.1 5411.68 1517.33 5411.68 1073.67C5411.68 633.466 5692.48 389.103 6044.34 389.103C6189.94 389.103 6306.08 418.565 6399.68 472.29L6354.61 588.406C6271.41 548.546 6170.88 527.749 6044.34 527.749C5772.21 527.749 5581.54 706.255 5581.54 1061.54C5581.54 1439.35 5784.34 1581.46 6016.61 1581.46C6151.81 1581.46 6241.94 1550.26 6333.81 1487.87L6391.01 1602.25C6278.34 1678.51 6157.01 1720.1 5992.34 1720.1Z" fill="black"/>
</g>
<path d="M3587.52 387.194H3742.52V1718.19H3594.52L2850.52 663.194V1718.19H2695.52V387.194H2843.52L3587.52 1443.19" fill="black"/>
<path d="M4062.3 574.194V429.194C4022.3 418.194 3944.3 418.194 3904.3 429.194V574.194C3944.3 585.194 4022.3 585.194 4062.3 574.194ZM4062.3 1718.19V783.194L3904.3 765.194V1718.19" fill="black"/>
<path d="M5024.13 783.194L4687.13 1238.19L5022.13 1718.19H4829.13L4599.13 1348.19L4371.13 1718.19H4188.13L4522.13 1251.19L4204.13 783.194H4398.13L4606.13 1144.19L4833.13 783.194" fill="black"/>

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View File

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 180 KiB

View File

@@ -0,0 +1,489 @@
<svg width="520" height="450" viewBox="0 0 520 450" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_178_4)">
<g filter="url(#filter0_dddiii_178_4)">
<path d="M275.063 79.1703L302.836 127.278H59.7998L87.573 79.1703H143.119L115.346 31.0623L129.241 7H157.014L198.682 79.1703H275.063Z" fill="#64AEE0" fill-opacity="0.8" shape-rendering="crispEdges"/>
</g>
<g filter="url(#filter1_iii_178_4)">
<path d="M268.8 86L289.8 121H72.2998L93.2998 86H155.3L124.8 32.5L134.8 16H151.8L192.8 86H268.8Z" fill="url(#paint0_linear_178_4)"/>
</g>
<path d="M151.37 16.75L192.152 86.3789L192.37 86.75H268.375L288.475 120.25H73.625L93.7246 86.75H156.591L155.951 85.6289L125.669 32.5117L135.223 16.75H151.37Z" stroke="url(#paint1_linear_178_4)" stroke-opacity="0.8" stroke-width="1.5"/>
<g filter="url(#filter2_dddiii_178_4)">
<path d="M391.094 169.508L363.318 217.614L241.8 7.13911L297.349 7.1374L325.122 55.2419L352.898 7.13567L380.684 7.13786L394.571 31.1901L352.904 103.361L391.094 169.508Z" fill="#D5ECF9"/>
</g>
<g filter="url(#filter3_iii_178_4)">
<path d="M382.048 167.499L362.237 203.186L253.487 14.8253L294.298 15.5118L325.298 69.2054L356.38 16.0417L375.67 16.4519L384.17 31.1743L344.048 101.681L382.048 167.499Z" fill="url(#paint2_linear_178_4)"/>
</g>
<path d="M383.305 31.1772L343.396 101.31L343.184 101.684L381.186 167.506L362.224 201.663L254.799 15.598L293.861 16.2547L325.294 70.6985L325.945 69.584L356.805 16.8002L375.232 17.1931L383.305 31.1772Z" stroke="url(#paint3_linear_178_4)" stroke-opacity="0.6" stroke-width="1.5"/>
<g filter="url(#filter4_dddiii_178_4)">
<path d="M369.906 313.645L314.356 313.643L435.874 103.168L463.65 151.274L435.877 199.379L491.427 199.381L505.318 223.445L491.431 247.497L408.096 247.498L369.906 313.645Z" fill="#64AEE0" fill-opacity="0.8" shape-rendering="crispEdges"/>
</g>
<g filter="url(#filter5_iii_178_4)">
<path d="M367.122 304.807L326.311 305.493L435.061 117.133L454.872 152.819L423.872 206.513L485.455 206.849L494.744 223.759L486.244 238.482L405.122 238.989L367.122 304.807Z" fill="url(#paint4_linear_178_4)"/>
</g>
<path d="M485.809 237.734L405.118 238.238L404.688 238.242L366.685 304.064L327.624 304.72L435.048 118.655L454.01 152.812L422.577 207.256L423.868 207.262L485.01 207.596L493.883 223.75L485.809 237.734Z" stroke="url(#paint5_linear_178_4)" stroke-opacity="0.8" stroke-width="1.5"/>
<g filter="url(#filter6_dddiii_178_4)">
<path d="M233.655 368.962L205.882 320.854L448.918 320.854L421.145 368.962L365.598 368.962L393.371 417.07L379.477 441.133L351.703 441.133L310.035 368.962L233.655 368.962Z" fill="#D5ECF9"/>
</g>
<g filter="url(#filter7_iii_178_4)">
<path d="M239.918 362.133L218.918 327.133L436.418 327.133L415.418 362.133L353.418 362.133L383.918 415.633L373.918 432.133L356.918 432.133L315.918 362.133L239.918 362.133Z" fill="url(#paint6_linear_178_4)"/>
</g>
<path d="M357.347 431.383L316.565 361.754L316.347 361.383L240.343 361.383L220.243 327.883L435.093 327.883L414.993 361.383L352.127 361.383L352.766 362.504L383.049 415.621L373.495 431.383L357.347 431.383Z" stroke="url(#paint7_linear_178_4)" stroke-opacity="0.6" stroke-width="1.5"/>
<g filter="url(#filter8_dddiii_178_4)">
<path d="M119.472 276.862L147.248 228.756L268.766 439.231L213.217 439.233L185.444 391.128L157.668 439.235L129.882 439.232L115.995 415.18L157.662 343.009L119.472 276.862Z" fill="#64AEE0" fill-opacity="0.8" shape-rendering="crispEdges"/>
</g>
<g filter="url(#filter9_iii_178_4)">
<path d="M128.518 278.871L148.329 243.184L257.079 431.545L216.268 430.858L185.268 377.165L154.186 430.329L134.896 429.918L126.396 415.196L166.518 344.689L128.518 278.871Z" fill="url(#paint8_linear_178_4)"/>
</g>
<path d="M127.261 415.193L167.17 345.06L167.383 344.686L129.38 278.864L148.342 244.707L255.767 430.772L216.705 430.116L185.272 375.672L184.621 376.786L153.761 429.57L135.335 429.177L127.261 415.193Z" stroke="url(#paint9_linear_178_4)" stroke-opacity="0.8" stroke-width="1.5"/>
<g filter="url(#filter10_dddiii_178_4)">
<path d="M139.692 131.207L195.241 131.209L73.7228 341.684L45.9467 293.578L73.7199 245.473L18.1706 245.472L4.27945 221.407L18.166 197.355L101.501 197.354L139.692 131.207Z" fill="#D5ECF9"/>
</g>
<g filter="url(#filter11_iii_178_4)">
<path d="M142.475 140.046L183.286 139.359L74.5357 327.72L54.7248 292.033L85.7248 238.34L24.1425 238.003L14.853 221.093L23.353 206.371L104.475 205.864L142.475 140.046Z" fill="url(#paint10_linear_178_4)"/>
</g>
<path d="M23.7877 207.118L104.479 206.614L104.909 206.611L142.912 140.789L181.974 140.132L74.5488 326.197L55.5867 292.04L87.0198 237.596L85.7291 237.59L24.5872 237.256L15.714 221.102L23.7877 207.118Z" stroke="url(#paint11_linear_178_4)" stroke-opacity="0.6" stroke-width="1.5"/>
</g>
<defs>
<filter id="filter0_dddiii_178_4" x="49.7998" y="1" width="271.036" height="141.278" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.30 0 0 0 0 0.62 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_4" result="effect2_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.25 0 0 0 0 0.58 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_4" result="effect3_dropShadow_178_4"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_4" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.379415 0 0 0 0 0.641102 0 0 0 0 0.815561 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_4" result="effect5_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_4" result="effect6_innerShadow_178_4"/>
</filter>
<filter id="filter1_iii_178_4" x="69.2998" y="16" width="222.5" height="111" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.416157 0 0 0 0 0.679176 0 0 0 0 0.863751 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_4" result="effect2_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_4" result="effect3_innerShadow_178_4"/>
</filter>
<filter id="filter2_dddiii_178_4" x="231.8" y="1.13562" width="180.771" height="231.479" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.30 0 0 0 0 0.62 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_4" result="effect2_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.32 0 0 0 0 0.62 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_4" result="effect3_dropShadow_178_4"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_4" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.837358 0 0 0 0 0.881424 0 0 0 0 0.904616 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_4" result="effect5_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_4" result="effect6_innerShadow_178_4"/>
</filter>
<filter id="filter3_iii_178_4" x="250.487" y="14.8253" width="135.683" height="194.36" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.769899 0 0 0 0 0.871498 0 0 0 0 0.942796 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_4" result="effect2_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_4" result="effect3_innerShadow_178_4"/>
</filter>
<filter id="filter4_dddiii_178_4" x="304.356" y="97.1681" width="218.961" height="231.477" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.30 0 0 0 0 0.62 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_4" result="effect2_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.25 0 0 0 0 0.58 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_4" result="effect3_dropShadow_178_4"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_4" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.379415 0 0 0 0 0.641102 0 0 0 0 0.815561 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_4" result="effect5_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_4" result="effect6_innerShadow_178_4"/>
</filter>
<filter id="filter5_iii_178_4" x="323.312" y="117.133" width="173.433" height="194.361" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.416157 0 0 0 0 0.679176 0 0 0 0 0.863751 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_4" result="effect2_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_4" result="effect3_innerShadow_178_4"/>
</filter>
<filter id="filter6_dddiii_178_4" x="195.882" y="314.854" width="271.036" height="141.278" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.30 0 0 0 0 0.62 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_4" result="effect2_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.32 0 0 0 0 0.62 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_4" result="effect3_dropShadow_178_4"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_4" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.837358 0 0 0 0 0.881424 0 0 0 0 0.904616 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_4" result="effect5_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_4" result="effect6_innerShadow_178_4"/>
</filter>
<filter id="filter7_iii_178_4" x="215.918" y="327.133" width="222.5" height="111" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.769899 0 0 0 0 0.871498 0 0 0 0 0.942796 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_4" result="effect2_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_4" result="effect3_innerShadow_178_4"/>
</filter>
<filter id="filter8_dddiii_178_4" x="105.995" y="222.756" width="180.771" height="231.479" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.30 0 0 0 0 0.62 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_4" result="effect2_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.25 0 0 0 0 0.58 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_4" result="effect3_dropShadow_178_4"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_4" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.379415 0 0 0 0 0.641102 0 0 0 0 0.815561 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_4" result="effect5_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_4" result="effect6_innerShadow_178_4"/>
</filter>
<filter id="filter9_iii_178_4" x="123.396" y="243.184" width="135.683" height="194.36" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.416157 0 0 0 0 0.679176 0 0 0 0 0.863751 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_4" result="effect2_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_4" result="effect3_innerShadow_178_4"/>
</filter>
<filter id="filter10_dddiii_178_4" x="-5.72046" y="125.207" width="218.961" height="231.477" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="5"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.30 0 0 0 0 0.62 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="2"/>
<feGaussianBlur stdDeviation="1"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_dropShadow_178_4" result="effect2_dropShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="8" dy="4"/>
<feGaussianBlur stdDeviation="5"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.32 0 0 0 0 0.62 0 0 0 0 0.88 0 0 0 1 0"/>
<feBlend mode="normal" in2="effect2_dropShadow_178_4" result="effect3_dropShadow_178_4"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect3_dropShadow_178_4" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.837358 0 0 0 0 0.881424 0 0 0 0 0.904616 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect4_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-2" dy="-3"/>
<feGaussianBlur stdDeviation="3"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.46 0"/>
<feBlend mode="normal" in2="effect4_innerShadow_178_4" result="effect5_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-4" dy="4"/>
<feGaussianBlur stdDeviation="2"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect5_innerShadow_178_4" result="effect6_innerShadow_178_4"/>
</filter>
<filter id="filter11_iii_178_4" x="11.853" y="139.359" width="173.433" height="194.36" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="6"/>
<feGaussianBlur stdDeviation="4.6"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 0.769899 0 0 0 0 0.871498 0 0 0 0 0.942796 0 0 0 1 0"/>
<feBlend mode="normal" in2="shape" result="effect1_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="2" dy="3"/>
<feGaussianBlur stdDeviation="2.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.3 0"/>
<feBlend mode="normal" in2="effect1_innerShadow_178_4" result="effect2_innerShadow_178_4"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dx="-3" dy="2"/>
<feGaussianBlur stdDeviation="1.5"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 0.25 0"/>
<feBlend mode="normal" in2="effect2_innerShadow_178_4" result="effect3_innerShadow_178_4"/>
</filter>
<linearGradient id="paint0_linear_178_4" x1="134.3" y1="31.5" x2="255.3" y2="121" gradientUnits="userSpaceOnUse">
<stop stop-color="#7FBBE3"/>
<stop offset="0.490385" stop-color="#9AD1FA"/>
<stop offset="1" stop-color="#7FBBE3"/>
</linearGradient>
<linearGradient id="paint1_linear_178_4" x1="133.3" y1="16" x2="327.8" y2="135" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#67A7D3"/>
<stop offset="0.3125" stop-color="#80AFCD"/>
<stop offset="0.591346" stop-color="#8EC1E4"/>
<stop offset="1" stop-color="#92CDED"/>
</linearGradient>
<linearGradient id="paint2_linear_178_4" x1="361.996" y1="23.7689" x2="344.987" y2="173.308" gradientUnits="userSpaceOnUse">
<stop stop-color="#DCEFF9"/>
<stop offset="0.490385" stop-color="#E2F2FB"/>
<stop offset="1" stop-color="#DCEFF9"/>
</linearGradient>
<linearGradient id="paint3_linear_178_4" x1="374.92" y1="15.1529" x2="369.113" y2="243.095" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#C0E3FC"/>
<stop offset="0.3125" stop-color="#D2ECFD"/>
<stop offset="0.591346" stop-color="#BBDBF0"/>
<stop offset="1" stop-color="#B4E0F8"/>
</linearGradient>
<linearGradient id="paint4_linear_178_4" x1="481.571" y1="215.576" x2="343.561" y2="275.615" gradientUnits="userSpaceOnUse">
<stop stop-color="#7FBBE3"/>
<stop offset="0.490385" stop-color="#9AD1FA"/>
<stop offset="1" stop-color="#7FBBE3"/>
</linearGradient>
<linearGradient id="paint5_linear_178_4" x1="495.494" y1="222.46" x2="295.187" y2="331.402" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#67A7D3"/>
<stop offset="0.3125" stop-color="#80AFCD"/>
<stop offset="0.591346" stop-color="#8EC1E4"/>
<stop offset="1" stop-color="#92CDED"/>
</linearGradient>
<linearGradient id="paint6_linear_178_4" x1="374.418" y1="416.633" x2="253.418" y2="327.133" gradientUnits="userSpaceOnUse">
<stop stop-color="#DCEFF9"/>
<stop offset="0.490385" stop-color="#E2F2FB"/>
<stop offset="1" stop-color="#DCEFF9"/>
</linearGradient>
<linearGradient id="paint7_linear_178_4" x1="375.418" y1="432.133" x2="180.918" y2="313.133" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#C0E3FC"/>
<stop offset="0.3125" stop-color="#D2ECFD"/>
<stop offset="0.591346" stop-color="#BBDBF0"/>
<stop offset="1" stop-color="#B4E0F8"/>
</linearGradient>
<linearGradient id="paint8_linear_178_4" x1="148.57" y1="422.601" x2="165.579" y2="273.062" gradientUnits="userSpaceOnUse">
<stop stop-color="#7FBBE3"/>
<stop offset="0.490385" stop-color="#9AD1FA"/>
<stop offset="1" stop-color="#7FBBE3"/>
</linearGradient>
<linearGradient id="paint9_linear_178_4" x1="135.646" y1="431.217" x2="141.454" y2="203.275" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#67A7D3"/>
<stop offset="0.3125" stop-color="#80AFCD"/>
<stop offset="0.591346" stop-color="#8EC1E4"/>
<stop offset="1" stop-color="#92CDED"/>
</linearGradient>
<linearGradient id="paint10_linear_178_4" x1="28.0264" y1="229.276" x2="166.036" y2="169.237" gradientUnits="userSpaceOnUse">
<stop stop-color="#DCEFF9"/>
<stop offset="0.490385" stop-color="#E2F2FB"/>
<stop offset="1" stop-color="#DCEFF9"/>
</linearGradient>
<linearGradient id="paint11_linear_178_4" x1="14.103" y1="222.392" x2="214.41" y2="113.45" gradientUnits="userSpaceOnUse">
<stop offset="0.0288462" stop-color="#C0E3FC"/>
<stop offset="0.3125" stop-color="#D2ECFD"/>
<stop offset="0.591346" stop-color="#BBDBF0"/>
<stop offset="1" stop-color="#B4E0F8"/>
</linearGradient>
<clipPath id="clip0_178_4">
<rect width="520" height="450" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 33 KiB

View File

@@ -0,0 +1,17 @@
<svg width="71" height="22" viewBox="0 0 71 22" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_f_46_47)">
<path d="M4.17478 13.0171C3.96503 13.1967 3.94061 13.5124 4.12023 13.7221C4.29984 13.9319 4.61548 13.9563 4.82522 13.7767L4.5 13.3969L4.17478 13.0171ZM36 15.8969L35.6263 15.5647V15.5647L36 15.8969ZM34 8.39689L33.8167 7.93168L34 8.39689ZM67 8.39689L63.2583 4L61.3213 9.43889L67 8.39689ZM4.5 13.3969L4.82522 13.7767C7.36375 11.6028 11.0681 10.0844 15.1111 9.18709C19.1469 8.29134 23.474 8.0247 27.2182 8.31973C30.9885 8.61683 34.072 9.47617 35.7003 10.7502C36.4998 11.3758 36.9001 12.0612 36.9279 12.7954C36.9563 13.5427 36.6042 14.4645 35.6263 15.5647L36 15.8969L36.3737 16.2291C37.4424 15.0268 37.9691 13.8627 37.9272 12.7575C37.8848 11.6392 37.266 10.7056 36.3165 9.96261C34.4466 8.49948 31.1122 7.62347 27.2967 7.32282C23.455 7.02011 19.0284 7.29332 14.8945 8.21084C10.7677 9.12677 6.88625 10.6951 4.17478 13.0171L4.5 13.3969ZM36 15.8969L35.6263 15.5647C34.7452 16.5559 33.6404 16.8548 32.6069 16.7055C31.556 16.5538 30.5797 15.9372 30.0085 15.0928C29.4472 14.263 29.2791 13.2223 29.8049 12.1531C30.3416 11.0616 31.6402 9.86391 34.1833 8.86209L34 8.39689L33.8167 7.93168C31.1523 8.98129 29.5972 10.3094 28.9075 11.7118C28.2069 13.1366 28.4397 14.5583 29.1802 15.6531C29.9109 16.7333 31.1374 17.5037 32.4639 17.6953C33.8077 17.8893 35.2548 17.4879 36.3737 16.2291L36 15.8969ZM34 8.39689L34.1833 8.86209C42.965 5.40262 54.045 4.96785 62.626 7.36867L62.7607 6.88716L62.8954 6.40566C54.108 3.94706 42.8045 4.39106 33.8167 7.93168L34 8.39689Z" fill="#7EBAE4"/>
</g>
<path d="M4.17478 10.0171C3.96503 10.1967 3.94061 10.5124 4.12023 10.7221C4.29984 10.9319 4.61548 10.9563 4.82522 10.7767L4.5 10.3969L4.17478 10.0171ZM36 12.8969L35.6263 12.5647V12.5647L36 12.8969ZM34 5.39689L33.8167 4.93168L34 5.39689ZM67 5.39689L63.2583 1L61.3213 6.43889L67 5.39689ZM4.5 10.3969L4.82522 10.7767C7.36375 8.60277 11.0681 7.08443 15.1111 6.18709C19.1469 5.29134 23.474 5.0247 27.2182 5.31973C30.9885 5.61683 34.072 6.47617 35.7003 7.75018C36.4998 8.37579 36.9001 9.06117 36.9279 9.79537C36.9563 10.5427 36.6042 11.4645 35.6263 12.5647L36 12.8969L36.3737 13.2291C37.4424 12.0268 37.9691 10.8627 37.9272 9.7575C37.8848 8.63921 37.266 7.70558 36.3165 6.96261C34.4466 5.49948 31.1122 4.62347 27.2967 4.32282C23.455 4.02011 19.0284 4.29332 14.8945 5.21084C10.7677 6.12677 6.88625 7.69511 4.17478 10.0171L4.5 10.3969ZM36 12.8969L35.6263 12.5647C34.7452 13.5559 33.6404 13.8548 32.6069 13.7055C31.556 13.5538 30.5797 12.9372 30.0085 12.0928C29.4472 11.263 29.2791 10.2223 29.8049 9.1531C30.3416 8.06156 31.6402 6.86391 34.1833 5.86209L34 5.39689L33.8167 4.93168C31.1523 5.98129 29.5972 7.30935 28.9075 8.71183C28.2069 10.1366 28.4397 11.5583 29.1802 12.6531C29.9109 13.7333 31.1374 14.5037 32.4639 14.6953C33.8077 14.8893 35.2548 14.4879 36.3737 13.2291L36 12.8969ZM34 5.39689L34.1833 5.86209C42.965 2.40262 54.045 1.96785 62.626 4.36867L62.7607 3.88716L62.8954 3.40566C54.108 0.94706 42.8045 1.39106 33.8167 4.93168L34 5.39689Z" fill="url(#paint0_linear_46_47)"/>
<defs>
<filter id="filter0_f_46_47" x="0" y="0" width="71" height="21.7416" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="2" result="effect1_foregroundBlur_46_47"/>
</filter>
<linearGradient id="paint0_linear_46_47" x1="4.5" y1="8.29995" x2="67" y2="8.29995" gradientUnits="userSpaceOnUse">
<stop stop-color="#5277C3"/>
<stop offset="1" stop-color="#7EBAE4"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 434 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@@ -1,27 +0,0 @@
---
import { Image } from 'astro:assets';
import NormalBadgeTemplate from '@assets/badges/normal.webp';
import RainbowBadgeTemplate from '@assets/badges/rainbow.webp';
import TransBadgeTemplate from '@assets/badges/trans.webp';
---
<div class='badge-row'>
<Image class='badge' src={NormalBadgeTemplate} alt='NormalBadgeTemplate' />
<Image class='badge' src={RainbowBadgeTemplate} alt='RainbowBadgeTemplate' />
<Image class='badge' src={TransBadgeTemplate} alt='TransBadgeTemplate' />
</div>
<style>
.badge-row {
display: flex;
gap: 1.5rem;
align-items: flex-start;
}
.badge {
margin-top: 0;
min-width: 0;
width: clamp(180px, 24vw, 240px);
height: auto;
}
</style>

View File

@@ -0,0 +1,580 @@
---
import Navbar from './Navbar.astro';
import BaseLayout from '../layouts/BaseLayout.astro';
import { type Locale, getTranslations } from '../i18n/config';
interface Props {
locale: Locale;
}
const { locale } = Astro.props;
const t = getTranslations(locale);
const tp = t.calendar;
const foodMapSrc =
locale === 'en' ? '/images/calendar/food-map-en.png' : '/images/calendar/food-map.png';
---
<BaseLayout title={tp.meta.title} description={tp.meta.description} lang={tp.meta.htmlLang}>
<Navbar locale={locale} activePage='calendar' />
<!-- ======= Page Heading ======= -->
<section class='page-heading'>
<h1 class='heading-title'>{tp.heading.title}</h1>
<p class='heading-sub'>{tp.heading.sub}</p>
</section>
<!-- ======= Guide Card ======= -->
<section class='guide-card'>
<div class='guide-inner'>
<!-- 装饰竖线(分隔左右两栏,绝对定位贯穿全高) -->
<span class='deco-line deco-v' aria-hidden='true'></span>
<div class='guide-grid'>
<!-- ============ 左栏 ============ -->
<div class='col col-left'>
<!-- 活动议程要点 -->
<div class='block agenda-points'>
<p class='point-lead'>
<span class='emoji'>{tp.agenda.leadEmoji}</span>
<span class='point-text'><Fragment set:html={tp.agenda.leadHtml} /></span>
</p>
<ul class='bullet-list'>
{
tp.agenda.bullets.map((html) => (
<li>
<Fragment set:html={html} />
</li>
))
}
</ul>
</div>
<!-- 装饰横线in-flow 居于两块之间gap 自动给上下等距)-->
<span class='deco-line deco-h' aria-hidden='true'></span>
<!-- 会议安排 -->
<div class='block schedule-block'>
<p class='section-title'>
<span class='emoji'>{tp.schedule.emoji}</span>
<span>{tp.schedule.title}</span>
</p>
<div class='info-card'>
<div class='info-row'>
<span class='info-label'>{tp.schedule.timeLabel}</span>
<span class='info-value'>{tp.schedule.timeValue}</span>
</div>
<div class='info-row info-row-stack'>
<span class='info-label'>{tp.schedule.flowLabel}</span>
<ul class='timeline-list'>
{
tp.schedule.flow.map((item) => (
<li>
<Fragment set:html={item} />
</li>
))
}
</ul>
</div>
</div>
</div>
</div>
<!-- ============ 右栏 ============ -->
<div class='col col-right'>
<div class='block food-block' id='food-block'>
<p class='section-title'>
<span class='emoji'>{tp.food.emoji}</span>
<span>{tp.food.title}</span>
</p>
<figure class='food-map'>
<img
src={foodMapSrc}
alt={tp.food.mapAlt}
class='food-map-img'
loading='lazy'
decoding='async'
/>
</figure>
</div>
</div>
</div>
</div>
</section>
</BaseLayout>
<style>
:global(.page) {
padding: 0 16px 16px;
--hero-ease: cubic-bezier(0.22, 1, 0.36, 1);
}
@media (max-width: 639px) {
:global(.page) {
padding: 0 8px 8px;
}
}
@keyframes heroFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes heroFadeUp {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes heroFadeDown {
from {
opacity: 0;
transform: translateY(-12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes decoFadeIn {
from {
opacity: 0;
}
to {
opacity: 0.65;
}
}
:global(.navbar) {
animation: heroFadeDown 0.45s var(--hero-ease) both;
}
/* ===== 页面标题区 ===== */
.page-heading {
padding: 48px 16px 24px;
text-align: center;
flex-shrink: 0;
}
.heading-title {
font-size: clamp(2.25rem, 5vw, 4rem);
font-weight: 600;
letter-spacing: -0.05em;
color: #030f20;
margin: 0 0 16px;
line-height: 1.1;
text-shadow: 0 4px 12px rgba(3, 15, 32, 0.06);
animation: heroFadeUp 0.55s var(--hero-ease) both;
animation-delay: 0.1s;
}
.heading-sub {
font-size: 16px;
color: #030f20;
letter-spacing: -0.05em;
margin: 0;
line-height: 1.4;
animation: heroFadeUp 0.5s var(--hero-ease) both;
animation-delay: 0.18s;
}
/* ===== 主卡片:双层圆角描边 ===== */
.guide-card {
position: relative;
margin: 16px 0 0;
border-radius: 24px;
border: 2px solid rgba(155, 206, 241, 0.8);
background: transparent;
padding: 10px;
overflow: hidden;
animation: heroFadeIn 0.5s var(--hero-ease) both;
animation-delay: 0.22s;
}
.guide-inner {
position: relative;
border-radius: 16px;
border: 2px solid rgba(155, 206, 241, 0.8);
background: rgba(249, 251, 255, 0.85);
backdrop-filter: blur(4px);
-webkit-backdrop-filter: blur(4px);
padding: 40px clamp(20px, 4vw, 56px);
min-height: 600px;
overflow: hidden;
}
/* === 装饰:用 nix-tile-100.svg 堆出来的横/竖分隔线 === */
.deco-line {
pointer-events: none;
opacity: 0.65;
background-image: url('/images/shared/nix-tile-100.svg');
background-position: center;
animation: decoFadeIn 0.6s var(--hero-ease) both;
animation-delay: 0.36s;
}
/* 横线:作为 .col-left 的 flex 成员位于两块之间,
依赖 .col { gap } 自动获得上下等距的呼吸距离 */
.deco-h {
position: relative;
display: block;
height: 24px;
background-size: 24px 24px;
background-repeat: repeat-x;
/* 左端:负 margin 反向延伸,让横线贴到卡片内描边(恢复原始 left:3px 的视觉位置) */
margin-left: calc(3px - clamp(20px, 4vw, 56px));
/* 右端:延伸到竖线 .deco-v 的左缘以补齐栏间 grid gap */
margin-right: calc(12px - clamp(24px, 4vw, 56px) / 2);
}
/* 竖线:仍保持绝对定位,贯穿整张卡片的高度 */
.deco-v {
position: absolute;
left: calc(50% - 12px);
top: 0;
width: 24px;
height: 100%;
background-size: 24px 24px;
background-repeat: repeat-y;
}
/* ===== 两栏网格 ===== */
.guide-grid {
position: relative;
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
gap: clamp(24px, 4vw, 56px);
z-index: 1;
}
.col {
display: flex;
flex-direction: column;
gap: 36px;
min-width: 0;
}
.block {
display: flex;
flex-direction: column;
gap: 16px;
}
/* 左栏「活动议程要点」整体限宽到 480与下方 .info-card / 右栏 .food-block 三者同宽。
这样 .bullet-list li 底部的浅蓝 underline 右缘也会停在 info-card 的右缘上,
不再伸进中间分割线那条「走廊」里 */
.agenda-points {
max-width: 480px;
animation: heroFadeUp 0.55s var(--hero-ease) both;
animation-delay: 0.32s;
}
.emoji {
font-size: 20px;
line-height: 1;
display: inline-block;
margin-right: 12px;
vertical-align: middle;
}
.point-lead,
.section-title {
font-size: 20px;
font-weight: 500;
letter-spacing: -0.05em;
color: #030f20;
margin: 0;
line-height: 1.4;
display: flex;
align-items: center;
}
.point-lead .emoji {
margin-right: 8px;
}
:global(.accent) {
color: #5277c3;
font-weight: 500;
}
.bullet-list {
list-style: none;
margin: 0;
padding: 0 0 0 12px;
display: flex;
flex-direction: column;
gap: 12px;
}
.bullet-list li {
position: relative;
/* 左侧 22 用于让位 ::before 的圆点;右侧同样补 22 以保持文案 + 下划线视觉居中,
尤其是在移动端 li 宽度较大时,左右不对称会让整段看上去偏右 */
padding: 0 22px 4px 22px;
font-size: 20px;
line-height: 1.6;
color: #33466d;
letter-spacing: -0.05em;
font-weight: 500;
background: linear-gradient(rgba(126, 186, 228, 0.31), rgba(126, 186, 228, 0.31)) no-repeat;
background-position: 22px 100%;
background-size: calc(100% - 44px) 8px;
}
.bullet-list li::before {
content: '';
position: absolute;
left: 4px;
top: 0.7em;
width: 6px;
height: 6px;
border-radius: 50%;
background: #33466d;
}
.bullet-list li :global(strong) {
font-size: 24px;
font-weight: 600;
color: #33466d;
margin: 0 2px;
}
.info-card {
background: #fff;
border: 1px solid #5277c3;
border-radius: 24px;
padding: 24px 28px;
display: flex;
flex-direction: column;
gap: 26px;
box-shadow: 0 6px 22px rgba(82, 119, 195, 0.08);
max-width: 480px;
}
.schedule-block {
animation: heroFadeUp 0.55s var(--hero-ease) both;
animation-delay: 0.4s;
}
.info-row {
display: flex;
align-items: flex-start;
gap: 12px;
flex-wrap: wrap;
}
.info-row-stack {
align-items: flex-start;
}
.info-label {
font-size: 16px;
color: #030f20;
letter-spacing: -0.05em;
line-height: 1.6;
flex-shrink: 0;
padding-top: 4px;
}
.info-value {
font-size: 20px;
font-weight: 500;
color: #030f20;
letter-spacing: -0.05em;
line-height: 1.4;
}
.timeline-list {
margin: 0;
padding-left: 22px;
list-style: disc;
display: flex;
flex-direction: column;
gap: 8px;
}
.timeline-list li {
font-size: 20px;
font-weight: 500;
color: #030f20;
letter-spacing: -0.05em;
line-height: 1.4;
}
.timeline-list li::marker {
color: #030f20;
font-size: 1em;
}
/* 锚点跳转时给目标区块一点呼吸距离 */
#food-block {
scroll-margin-top: 24px;
}
.food-block {
gap: 20px;
/* 与左栏 .info-card 镜像max-width 480 + 整体靠 col-right 右缘对齐,
这样「分割线 → food-map 左缘」的距离 = 「info-card 右缘 → 分割线」的距离 */
align-self: flex-end;
width: 100%;
max-width: 480px;
animation: heroFadeUp 0.55s var(--hero-ease) both;
animation-delay: 0.48s;
}
.food-map {
margin: 0;
border-radius: 24px;
overflow: hidden;
border: 1px solid #5277c3;
background: #f6fafc;
box-shadow: 0 8px 28px rgba(82, 119, 195, 0.1);
}
.food-map-img {
display: block;
width: 100%;
height: auto;
object-fit: cover;
}
@media (max-width: 1023px) {
.page-heading {
padding: 32px 16px 20px;
}
.guide-inner {
padding: 32px 32px;
min-height: 0;
}
.guide-grid {
grid-template-columns: 1fr;
gap: 40px;
}
.deco-h,
.deco-v {
display: none;
}
.info-card {
max-width: none;
}
.agenda-points {
max-width: none;
}
.food-block {
align-self: auto;
max-width: none;
width: auto;
}
}
@media (max-width: 639px) {
.page {
padding: 0 8px 8px;
}
.page-heading {
padding: 24px 8px 16px;
}
.heading-title {
margin-bottom: 12px;
}
.heading-sub {
font-size: 14px;
padding: 0 8px;
}
.guide-card {
border-radius: 16px;
padding: 6px;
}
.guide-inner {
border-radius: 10px;
padding: 24px 18px;
}
.col {
gap: 28px;
}
.point-lead,
.section-title {
font-size: 17px;
}
.bullet-list li {
font-size: 16px;
background-size: calc(100% - 44px) 6px;
}
.bullet-list li :global(strong) {
font-size: 19px;
}
.info-card {
padding: 20px 18px;
gap: 20px;
border-radius: 18px;
}
.info-label {
font-size: 14px;
}
.info-value {
font-size: 16px;
}
.timeline-list li {
font-size: 16px;
}
.info-row {
flex-direction: column;
gap: 4px;
}
.food-map {
border-radius: 16px;
}
}
@media (prefers-reduced-motion: reduce) {
:global(.navbar),
.heading-title,
.heading-sub,
.guide-card,
.deco-line,
.agenda-points,
.schedule-block,
.food-block {
animation: none !important;
opacity: 1 !important;
transform: none !important;
}
.deco-line {
opacity: 0.65 !important;
}
}
</style>

View File

@@ -0,0 +1,434 @@
---
import Navbar from './Navbar.astro';
import BaseLayout from '../layouts/BaseLayout.astro';
import { type Locale, getTranslations } from '../i18n/config';
interface Props {
locale: Locale;
}
const { locale } = Astro.props;
const t = getTranslations(locale);
const tp = t.cmsGuide;
---
<BaseLayout title={tp.meta.title} description={tp.meta.description} lang={tp.meta.htmlLang}>
<Navbar locale={locale} activePage='cmsGuide' />
<!-- ======= Hero BannerFigma Desktop - 4 切图) ======= -->
<section class='hero-banner' aria-labelledby='cms-title'>
<div class='hero-bg' aria-hidden='true'>
<img class='hero-bg-img' src='/images/cms-guide/hero-bg.png' alt='' />
</div>
<div class='hero-content'>
<h1 class='hero-title' id='cms-title'>{tp.hero.title}</h1>
{tp.hero.subs.map((s) => <p class='hero-sub'>{s}</p>)}
</div>
</section>
<!-- ======= Guide content ======= -->
<main class='guide-main'>
{
tp.steps.map((step, i) => (
<article class='step' id={step.id} style={`--step-delay: ${0.56 + i * 0.06}s`}>
<h2 class='step-title'>
<span class='step-num'>{step.num}</span>
<span class='step-divider'></span>
<span class='step-name'>{step.name}</span>
</h2>
{'bodyHtml' in step && step.bodyHtml !== undefined && (
<p class='step-body'>
<Fragment set:html={step.bodyHtml} />
</p>
)}
{'bodyHtmls' in step &&
step.bodyHtmls !== undefined &&
step.bodyHtmls.map((html) => (
<p class='step-body'>
<Fragment set:html={html} />
</p>
))}
{'list' in step && step.list !== undefined && (
<ul class='step-list'>
{step.list.map((item) => (
<li>{item}</li>
))}
</ul>
)}
{'afterListHtml' in step && step.afterListHtml !== undefined && (
<p class='step-body'>
<Fragment set:html={step.afterListHtml} />
</p>
)}
{step.tip?.text && (
<div class='tip tip--inline'>
<p>
<span class='tip-bell' aria-hidden='true'>
{tp.tipBell}
</span>
<span class='tip-label'>{tp.tipLabel}</span>
{step.tip.text}
</p>
</div>
)}
</article>
))
}
</main>
<!-- ======= 底部同心圆装饰Figma 切图) ======= -->
<div class='bottom-circles' aria-hidden='true'>
<img src='/images/cms-guide/bottom-circles.png' alt='' />
</div>
</BaseLayout>
<style>
:global(.page) {
position: relative;
overflow: hidden;
--hero-ease: cubic-bezier(0.22, 1, 0.36, 1);
}
@keyframes heroFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes heroFadeUp {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes heroFadeDown {
from {
opacity: 0;
transform: translateY(-12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
:global(.navbar) {
animation: heroFadeDown 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
}
/* ===== Hero Banner ===== */
.hero-banner {
position: relative;
padding: 38px 24px 48px;
text-align: center;
isolation: isolate;
overflow: hidden;
min-height: 215px;
}
.hero-bg {
position: absolute;
inset: 0;
z-index: 0;
pointer-events: none;
overflow: hidden;
}
.hero-bg-img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center top;
display: block;
animation: heroFadeIn 0.6s var(--hero-ease) both;
}
.hero-content {
position: relative;
z-index: 1;
max-width: 720px;
margin: 0 auto;
}
.hero-title {
font-size: clamp(2.5rem, 5.5vw, 4.5rem);
font-weight: 600;
color: #030f20;
margin: 0 0 20px;
letter-spacing: -0.05em;
line-height: 1.1;
text-shadow: 0 4px 14px rgba(3, 15, 32, 0.08);
animation: heroFadeUp 0.45s var(--hero-ease) both;
animation-delay: 0.1s;
}
.hero-sub {
font-size: clamp(0.875rem, 1vw, 1rem);
color: #1a2332;
margin: 0;
line-height: 1.7;
letter-spacing: -0.02em;
animation: heroFadeUp 0.45s var(--hero-ease) both;
}
.hero-sub:nth-of-type(1) {
animation-delay: 0.4s;
}
.hero-sub:nth-of-type(2) {
animation-delay: 0.48s;
}
.hero-sub:nth-of-type(3) {
animation-delay: 0.56s;
}
.hero-sub + .hero-sub {
margin-top: 2px;
}
/* ===== Guide content ===== */
.guide-main {
position: relative;
z-index: 2;
width: 100%;
max-width: 1120px;
margin: 0 auto;
padding: 24px 40px 120px;
display: flex;
flex-direction: column;
gap: 40px;
}
.step {
display: flex;
flex-direction: column;
gap: 16px;
animation: heroFadeUp 0.45s var(--hero-ease) both;
animation-delay: var(--step-delay, 0.56s);
}
.step-title {
display: flex;
align-items: baseline;
gap: 0;
margin: 0;
font-weight: 600;
line-height: 1.2;
letter-spacing: -0.04em;
color: #030f20;
}
.step-num {
font-size: clamp(1.75rem, 2.4vw, 2.25rem);
font-weight: 700;
color: #030f20;
font-feature-settings: 'tnum';
margin-right: 8px;
}
.step-divider {
font-size: clamp(1.5rem, 2vw, 1.875rem);
color: #a7b8d0;
margin: 0 6px 0 0;
font-weight: 400;
}
.step-name {
font-size: clamp(1.5rem, 2vw, 1.875rem);
color: #030f20;
font-weight: 600;
}
.step-body {
font-size: 15px;
line-height: 1.8;
color: #1a2332;
margin: 0;
letter-spacing: -0.01em;
}
.step-list {
margin: 0;
padding-left: 24px;
font-size: 15px;
line-height: 1.9;
color: #1a2332;
}
.step-list li {
padding-left: 4px;
}
.step-list li::marker {
color: #5277c3;
}
/* "前两周" 高亮red 胶囊)—— 通过 set:html 注入,需要 :global */
:global(.hl-warn) {
display: inline-block;
padding: 0 8px;
margin: 0 2px;
color: #d94f4f;
font-weight: 600;
border: 1px solid rgba(217, 79, 79, 0.45);
border-radius: 8px;
background: rgba(217, 79, 79, 0.06);
}
/* 提示框(🔔) */
.tip {
font-size: 14px;
line-height: 1.7;
color: #c66a2a;
background: rgba(245, 166, 35, 0.06);
border-left: 3px solid rgba(245, 166, 35, 0.5);
border-radius: 0 8px 8px 0;
padding: 12px 16px;
margin-top: 4px;
}
.tip p {
margin: 0;
}
.tip p + p {
margin-top: 4px;
}
.tip-head {
font-weight: 600;
}
.tip-bell {
display: inline-block;
margin-right: 4px;
}
.tip--inline {
padding: 8px 14px;
}
.tip-label {
font-weight: 600;
margin-right: 2px;
}
/* ===== 底部同心圆装饰 ===== */
.bottom-circles {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: min(710px, 100%);
pointer-events: none;
z-index: 0;
animation: heroFadeIn 0.8s cubic-bezier(0.22, 1, 0.36, 1) both;
animation-delay: 0.92s;
}
.bottom-circles img {
display: block;
width: 100%;
height: auto;
}
@media (max-width: 1023px) {
.hero-banner {
padding: 32px 20px 40px;
}
.guide-main {
padding: 16px 28px 100px;
gap: 36px;
}
.bottom-circles {
width: min(560px, 100%);
}
}
@media (max-width: 639px) {
.hero-banner {
padding: 24px 16px 32px;
}
.hero-title {
margin-bottom: 12px;
}
.hero-sub {
font-size: 13px;
line-height: 1.65;
}
.guide-main {
padding: 8px 18px 80px;
gap: 32px;
}
.step {
gap: 12px;
}
.step-num {
font-size: 28px;
}
.step-divider,
.step-name {
font-size: 22px;
}
.step-body {
font-size: 14px;
line-height: 1.75;
}
.step-list {
font-size: 14px;
}
.tip {
font-size: 13px;
padding: 10px 12px;
}
.bottom-circles {
width: min(380px, 100%);
}
}
@media (prefers-reduced-motion: reduce) {
:global(.navbar),
.hero-bg-img,
.hero-title,
.hero-sub,
.step {
animation: none !important;
opacity: 1 !important;
transform: none !important;
}
.bottom-circles {
animation: none !important;
opacity: 1 !important;
transform: translateX(-50%) !important;
}
}
</style>

View File

@@ -0,0 +1,576 @@
---
import Navbar from './Navbar.astro';
import BaseLayout from '../layouts/BaseLayout.astro';
import { type Locale, getTranslations, getPageUrl } from '../i18n/config';
interface Props {
locale: Locale;
}
const { locale } = Astro.props;
const t = getTranslations(locale);
const tp = t.home;
const url = (p: Parameters<typeof getPageUrl>[1]) => getPageUrl(locale, p);
---
<BaseLayout title={tp.meta.title} description={tp.meta.description} lang={tp.meta.htmlLang}>
<Navbar locale={locale} activePage='home' />
<!-- ======= Hero Card ======= -->
<div class='hero-card'>
<!-- Layer 0: dot-grid texture (bottom-most) -->
<div class='bg-texture' aria-hidden='true'></div>
<!-- Layer 1a: concentric circles (top-left) -->
<div class='bg-circles' aria-hidden='true'>
<div class='circle c1'></div>
<div class='circle c2'></div>
<div class='circle c3'></div>
</div>
<!-- Layer 1b: interactive NixOS snowflake — background decoration anchored to bottom-right -->
<div class='hero-decoration' aria-hidden='true'>
<canvas id='nixflake'></canvas>
</div>
<!-- Layer 2: foreground content (text floats above all background layers) -->
<div class='hero-content'>
<div class='hero-text'>
<p class='conference-title'>
{tp.hero.conferenceTitle}
<span class='year'>{tp.hero.year}</span>
</p>
<h1 class:list={['headline', { 'headline--split-mobile': locale === 'en' }]}>
{tp.hero.headlineBefore}<span class='nix-highlight'>{tp.hero.headlineBadge}</span><span
class='headline-tail'
set:html={tp.hero.headlineAfter}
/>
</h1>
<p class='lead'>{tp.hero.lead}</p>
<div class='cta-group'>
<a class='btn btn-primary' href={url('cmsGuide')}>{tp.hero.ctaPrimary}</a>
<a class='btn btn-outline' href={url('cmsGuide')}>{tp.hero.ctaSecondary}</a>
</div>
</div>
</div>
</div>
</BaseLayout>
<!-- ======= Interactive NixOS snowflake canvas + background parallax ======= -->
<script>
import { initNixflakeAnimation } from '../scripts/nixflake-animation';
import { initBadgeTilt } from '../scripts/badge-tilt';
import { initBgParallax } from '../scripts/bg-parallax';
initNixflakeAnimation();
initBadgeTilt();
initBgParallax();
</script>
<style>
:global(.page) {
padding: 0 16px 16px;
}
@media (max-width: 639px) {
:global(.page) {
padding: 0 8px 8px;
}
}
@keyframes heroFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes heroFadeInTo70 {
from {
opacity: 0;
}
to {
opacity: 0.7;
}
}
@keyframes heroFadeUp {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes heroFadeDown {
from {
opacity: 0;
transform: translateY(-12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
:global(.navbar) {
animation: heroFadeDown 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
}
.hero-card {
--hero-ease: cubic-bezier(0.22, 1, 0.36, 1);
flex: 1;
position: relative;
display: flex;
flex-direction: column;
border-radius: 24px;
border: 2px solid rgba(155, 206, 241, 0.8);
background: #f9fbff;
overflow: hidden;
min-height: 640px;
animation: heroFadeIn 0.5s var(--hero-ease) both;
}
.bg-circles {
position: absolute;
inset: 0;
z-index: 1;
pointer-events: none;
will-change: transform;
}
.circle {
position: absolute;
border-radius: 50%;
border: 1.5px solid rgba(126, 186, 228, 0.28);
top: 0;
left: 0;
box-shadow:
0 2px 8px rgba(126, 186, 228, 0.12),
0 10px 28px rgba(126, 186, 228, 0.2);
animation: heroFadeIn 0.8s var(--hero-ease) both;
}
.c1 {
width: 502px;
height: 502px;
transform: translate(-269px, -241px);
animation-delay: 0.1s;
}
.c2 {
width: 459px;
height: 459px;
transform: translate(-248px, -220px);
animation-delay: 0.16s;
}
.c3 {
width: 408px;
height: 408px;
transform: translate(-222px, -199px);
animation-delay: 0.22s;
}
.bg-texture {
position: absolute;
inset: 0;
z-index: 0;
background-image:
radial-gradient(ellipse 80% 70% at 60% 48%, transparent 15%, rgba(249, 251, 255, 0.85) 85%),
radial-gradient(circle, rgba(126, 186, 228, 0.28) 2.5px, transparent 2.5px);
background-size:
auto,
20px 20px;
pointer-events: none;
will-change: transform;
animation: heroFadeIn 0.7s var(--hero-ease) both;
animation-delay: 0.06s;
}
.hero-content {
flex: 1;
position: relative;
z-index: 3;
display: flex;
align-items: center;
min-height: 640px;
padding: 48px 80px;
}
.hero-text {
width: 100%;
max-width: 640px;
will-change: transform;
}
.conference-title {
font-size: clamp(1.5rem, 3.33vw, 3rem);
font-weight: 600;
letter-spacing: -0.05em;
color: #030f20;
margin: 0 0 16px;
line-height: 1.2;
text-shadow: 0 4px 12px rgba(3, 15, 32, 0.1);
animation: heroFadeUp 0.55s var(--hero-ease) both;
animation-delay: 0.12s;
}
.year {
color: #7ebae4;
}
.headline {
font-size: clamp(2rem, 4.44vw, 4rem);
font-weight: 600;
letter-spacing: -0.05em;
color: #5277c3;
margin: 0 0 28px;
line-height: 1.15;
text-shadow: 0 6px 18px rgba(82, 119, 195, 0.18);
perspective: 800px;
perspective-origin: 50% 50%;
animation: heroFadeUp 0.6s var(--hero-ease) both;
animation-delay: 0.22s;
}
.nix-highlight {
position: relative;
display: inline-block;
padding: 2px 14px;
line-height: inherit;
border-radius: 100px;
background: linear-gradient(
135deg,
rgba(196, 226, 247, 0.65) 0%,
rgba(126, 186, 228, 0.42) 48%,
rgba(82, 140, 200, 0.34) 100%
);
box-shadow:
inset 0 1px 0 rgba(255, 255, 255, 0.7),
inset 0 -1px 2px rgba(82, 119, 195, 0.2),
0 6px 14px rgba(82, 119, 195, 0.22),
0 14px 30px rgba(82, 119, 195, 0.14);
transform-style: preserve-3d;
will-change: transform;
transform: translateZ(0);
transition: box-shadow 0.3s ease;
--gloss-x: 30%;
--gloss-y: 25%;
}
.nix-highlight::before {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
background: radial-gradient(
circle at var(--gloss-x) var(--gloss-y),
rgba(255, 255, 255, 0.55) 0%,
rgba(255, 255, 255, 0.18) 28%,
rgba(255, 255, 255, 0) 60%
);
mix-blend-mode: screen;
pointer-events: none;
transform: translateZ(1px);
}
.nix-highlight::after {
content: '';
position: absolute;
inset: 0;
border-radius: inherit;
border: 1px solid rgba(255, 255, 255, 0.45);
pointer-events: none;
transform: translateZ(1px);
}
/* 英文桌面:徽章与后半句间距(移动端由 block 换行,不需前导空格) */
.headline--split-mobile .nix-highlight {
margin-inline-end: 0.22em;
}
.lead {
font-size: clamp(1rem, 1.39vw, 1.25rem);
color: #1a2332;
margin: 0 0 40px;
line-height: 1.65;
letter-spacing: -0.02em;
max-width: 480px;
animation: heroFadeUp 0.55s var(--hero-ease) both;
animation-delay: 0.32s;
}
.cta-group {
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.btn {
display: inline-flex;
align-items: center;
padding: 12px 20px;
border-radius: 24px;
font-size: 16px;
font-weight: 500;
letter-spacing: -0.05em;
text-decoration: none;
transition:
background 0.2s,
border-color 0.2s,
transform 0.15s,
box-shadow 0.2s;
white-space: nowrap;
cursor: pointer;
font-family: inherit;
animation: heroFadeUp 0.5s var(--hero-ease) both;
}
.cta-group .btn:nth-child(1) {
animation-delay: 0.42s;
}
.cta-group .btn:nth-child(2) {
animation-delay: 0.5s;
}
.btn-primary {
background: #5277c3;
color: #fff;
border: 1.5px solid #5277c3;
}
.btn-primary:hover {
background: #4269b8;
border-color: #4269b8;
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(82, 119, 195, 0.35);
}
.btn-outline {
background: rgba(249, 251, 255, 0.45);
color: #5277c3;
border: 1.5px solid #5277c3;
backdrop-filter: blur(10px) saturate(1.4);
-webkit-backdrop-filter: blur(10px) saturate(1.4);
}
.btn-outline:hover {
background: rgba(82, 119, 195, 0.12);
transform: translateY(-2px);
box-shadow: 0 4px 16px rgba(82, 119, 195, 0.15);
}
.hero-decoration {
position: absolute;
right: -80px;
bottom: -120px;
z-index: 2;
pointer-events: none;
line-height: 0;
animation: heroFadeIn 0.9s var(--hero-ease) both;
animation-delay: 0.18s;
}
.hero-decoration canvas {
display: block;
max-width: none;
pointer-events: none;
}
@media (max-width: 1023px) {
.hero-content {
padding: 40px 40px 48px;
min-height: 520px;
}
.hero-text {
max-width: 100%;
}
.hero-decoration {
right: -120px;
bottom: -140px;
transform: scale(0.7);
transform-origin: bottom right;
}
.c1 {
width: 300px;
height: 300px;
transform: translate(-160px, -144px);
}
.c2 {
width: 275px;
height: 275px;
transform: translate(-148px, -132px);
}
.c3 {
width: 244px;
height: 244px;
transform: translate(-133px, -119px);
}
}
@media (max-width: 639px) {
.headline :global(.headline-break) {
display: none;
}
.headline {
line-height: 1.35;
}
/* 英文:徽章后整段换行,第二行与第一行左缘对齐 */
.headline--split-mobile .nix-highlight {
margin-inline-end: 0;
}
.headline--split-mobile .headline-tail {
display: block;
margin: 0;
padding: 0;
}
.hero-card {
border-radius: 16px;
min-height: auto;
}
.hero-content {
padding: 32px 24px 44px;
min-height: 560px;
}
.lead {
margin-bottom: 32px;
}
.hero-decoration {
display: block;
right: -90px;
bottom: -100px;
transform: scale(0.7);
transform-origin: bottom right;
animation-name: heroFadeInTo70;
}
.cta-group {
flex-direction: column;
align-items: flex-start;
gap: 10px;
}
.btn {
width: 100%;
justify-content: center;
}
.c1 {
width: 220px;
height: 220px;
transform: translate(-120px, -108px);
}
.c2 {
width: 200px;
height: 200px;
transform: translate(-108px, -96px);
}
.c3 {
width: 178px;
height: 178px;
transform: translate(-96px, -86px);
}
}
@media (max-width: 639px) and (max-height: 683px) {
.hero-decoration {
display: none;
}
}
@media (prefers-reduced-motion: reduce) {
:global(.navbar),
.hero-card,
.bg-texture,
.circle,
.hero-decoration,
.conference-title,
.headline,
.lead,
.btn {
animation: none !important;
opacity: 1 !important;
}
.hero-decoration,
.bg-circles,
.bg-texture,
.hero-text,
.nix-highlight {
will-change: auto;
transition: none !important;
}
.conference-title,
.headline,
.lead,
.btn,
:global(.navbar) {
transform: none !important;
}
.nix-highlight {
transform: none !important;
}
}
@media (prefers-reduced-motion: reduce) and (max-width: 639px) {
.hero-decoration {
opacity: 0.7 !important;
}
}
/* 移动端:设计稿静态徽章(浅蓝胶囊 + 叠字阴影) */
@media (max-width: 639px) {
.headline {
perspective: none;
}
.nix-highlight {
position: relative;
display: inline-block;
padding: 0 9px 2px;
margin-inline: 0;
border-radius: 999px;
background: rgba(197, 219, 245, 0.78);
color: #5277c3;
font-size: 1.22em;
line-height: 1.05;
vertical-align: baseline;
box-shadow: none;
/* 单层文字 + 右下偏移浅色影,避免 ::before 叠在主字上方 */
text-shadow: 3px 4px 0 #9eb8e8;
transform: none !important;
transform-style: flat;
will-change: auto;
transition: none;
}
.nix-highlight::before,
.nix-highlight::after {
display: none;
}
}
</style>

318
src/components/Navbar.astro Normal file
View File

@@ -0,0 +1,318 @@
---
import { type Locale, type PageSlug, getTranslations, getPageUrl, LOCALES } from '../i18n/config';
type Page = PageSlug;
interface Props {
locale: Locale;
activePage: Page;
}
const { locale, activePage } = Astro.props;
const t = getTranslations(locale);
const otherLocale = LOCALES.find((l) => l !== locale) ?? LOCALES[0];
const url = (l: Locale, p: Page) => getPageUrl(l, p);
const switchHref = url(otherLocale, activePage);
---
<header class='navbar'>
<a href={url(locale, 'home')} class='navbar-logo' aria-label={t.nav.ariaLogoHome}>
<img src='/images/shared/nix-cn.svg' alt='NixCN' width='110' height='31' class='logo-img' />
</a>
<nav class='navbar-links' aria-label={t.nav.ariaMain}>
<a
href={url(locale, 'home')}
class:list={['nav-link', activePage === 'home' && 'active']}
aria-current={activePage === 'home' ? 'page' : undefined}
>
{t.nav.home}
</a>
<a
href={url(locale, 'calendar')}
class:list={['nav-link', activePage === 'calendar' && 'active']}
aria-current={activePage === 'calendar' ? 'page' : undefined}
>
{t.nav.calendar}
</a>
<a
href={url(locale, 'cmsGuide')}
class:list={['nav-link', activePage === 'cmsGuide' && 'active']}
aria-current={activePage === 'cmsGuide' ? 'page' : undefined}
>
{t.nav.cmsGuide}
</a>
<a
href={url(locale, 'souvenir')}
class:list={['nav-link', activePage === 'souvenir' && 'active']}
aria-current={activePage === 'souvenir' ? 'page' : undefined}
>
{t.nav.souvenir}
</a>
</nav>
<div class='navbar-social'>
<a
href='https://t.me/nixos_cn'
target='_blank'
rel='noopener noreferrer'
aria-label={t.nav.ariaTelegram}
class='social-link'
>
<svg viewBox='0 0 24 24' fill='currentColor' width='22' height='22' aria-hidden='true'>
<path
d='M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.894 8.221-1.97 9.28c-.145.658-.537.818-1.084.508l-3-2.21-1.447 1.394c-.16.16-.295.295-.605.295l.213-3.053 5.56-5.023c.242-.213-.054-.333-.373-.12l-6.871 4.326-2.962-.924c-.643-.204-.657-.643.136-.953l11.57-4.461c.537-.194 1.006.131.833.941z'
>
</path>
</svg>
</a>
<a
href='https://matrix.to/#/#nixos-cn:matrix.org'
target='_blank'
rel='noopener noreferrer'
aria-label={t.nav.ariaMatrix}
class='social-link'
>
<svg viewBox='0 0 24 24' fill='currentColor' width='22' height='22' aria-hidden='true'>
<path
d='M.632.55v22.9H2.28V24H0V0h2.28v.55zm7.043 7.26v1.157h.033c.309-.443.683-.784 1.117-1.024.433-.245.936-.365 1.5-.365.54 0 1.033.107 1.481.32.448.214.785.582 1.02 1.108.254-.374.6-.706 1.034-.993.434-.287.95-.43 1.546-.43.453 0 .872.056 1.26.167.388.11.716.286.993.53.276.243.489.564.646.96.157.395.232.863.232 1.408v5.786h-2.35v-4.928c0-.27-.012-.53-.04-.785-.027-.255-.09-.48-.19-.678-.102-.197-.258-.355-.462-.48-.203-.124-.475-.185-.81-.185-.337 0-.607.068-.816.205-.21.136-.373.318-.49.54-.12.222-.197.47-.24.745-.04.274-.062.555-.062.843v4.723h-2.35v-4.835c0-.243-.008-.486-.025-.73-.017-.243-.067-.467-.15-.668-.086-.202-.225-.366-.42-.49-.196-.125-.476-.187-.838-.187-.12 0-.265.024-.433.073-.17.048-.337.135-.5.262-.164.127-.302.304-.412.534-.11.228-.167.523-.167.884v5.157H5.41V7.81zm15.693 15.64V.55H21.72V0H24v24h-2.28v-.55z'
>
</path>
</svg>
</a>
<span class='social-divider' aria-hidden='true'></span>
<a href={switchHref} aria-label={t.nav.ariaLangSwitch} class='social-link'>
<svg
viewBox='0 0 24 24'
fill='none'
stroke='currentColor'
stroke-width='1.5'
width='22'
height='22'
aria-hidden='true'
>
<circle cx='12' cy='12' r='9.5'></circle>
<path
d='M12 2.5a14.5 14.5 0 0 1 3.5 9.5 14.5 14.5 0 0 1-3.5 9.5M12 2.5a14.5 14.5 0 0 0-3.5 9.5 14.5 14.5 0 0 0 3.5 9.5M2.5 12h19'
>
</path>
</svg>
</a>
</div>
<details class='mobile-menu'>
<summary class='hamburger' aria-label={t.nav.ariaMenu}>
<span></span>
<span></span>
<span></span>
</summary>
<nav class='mobile-nav' aria-label={t.nav.ariaMobile}>
<a href={url(locale, 'home')} aria-current={activePage === 'home' ? 'page' : undefined}>{t.nav.home}</a>
<a href={url(locale, 'calendar')} aria-current={activePage === 'calendar' ? 'page' : undefined}>
{t.nav.calendar}
</a>
<a href={url(locale, 'cmsGuide')} aria-current={activePage === 'cmsGuide' ? 'page' : undefined}>
{t.nav.cmsGuide}
</a>
<a href={url(locale, 'souvenir')} aria-current={activePage === 'souvenir' ? 'page' : undefined}>
{t.nav.souvenir}
</a>
<hr class='mobile-nav-divider' />
<a href='https://t.me/nixos_cn' target='_blank' rel='noopener noreferrer'>Telegram</a>
<a href='https://matrix.to/#/#nixos-cn:matrix.org' target='_blank' rel='noopener noreferrer'>Matrix</a>
<a href={switchHref}>{t.nav.ariaLangSwitch}</a>
</nav>
</details>
</header>
<style>
.navbar {
display: flex;
align-items: center;
padding: 0 20px;
height: 56px;
flex-shrink: 0;
position: relative;
z-index: 20;
}
.navbar-logo {
display: flex;
align-items: center;
flex-shrink: 0;
text-decoration: none;
}
.logo-img {
height: 31px;
width: auto;
display: block;
}
.navbar-links {
display: flex;
align-items: center;
gap: 32px;
position: absolute;
left: 50%;
transform: translateX(-50%);
}
.nav-link {
font-size: 14px;
font-weight: 500;
color: #a7b8d0;
text-decoration: none;
letter-spacing: -0.05em;
white-space: nowrap;
transition: color 0.2s;
position: relative;
padding-bottom: 2px;
}
.nav-link:hover {
color: #5277c3;
}
.nav-link.active {
color: #5277c3;
}
.nav-link.active::after {
content: '';
position: absolute;
bottom: -18px;
left: 50%;
transform: translateX(-50%);
width: 71px;
height: 22px;
background: url('/images/shared/tab-line.svg') center / contain no-repeat;
pointer-events: none;
}
.navbar-social {
display: flex;
align-items: center;
gap: 16px;
margin-left: auto;
}
.social-link {
color: #a7b8d0;
display: flex;
align-items: center;
text-decoration: none;
transition: color 0.2s;
}
.social-link:hover {
color: #5277c3;
}
.social-divider {
display: block;
width: 1px;
height: 20px;
background: #a7b8d0;
opacity: 0.4;
}
.mobile-menu {
display: none;
margin-left: 8px;
}
.hamburger {
display: flex;
flex-direction: column;
gap: 5px;
padding: 8px 4px;
cursor: pointer;
list-style: none;
}
.hamburger::marker,
.hamburger::-webkit-details-marker {
display: none;
}
.hamburger span {
display: block;
width: 22px;
height: 2px;
background: #5277c3;
border-radius: 2px;
transition: all 0.2s;
}
.mobile-nav {
position: fixed;
top: 56px;
left: 8px;
right: 8px;
background: rgba(249, 251, 255, 0.97);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(155, 206, 241, 0.5);
border-radius: 16px;
padding: 16px 20px;
display: flex;
flex-direction: column;
gap: 4px;
z-index: 100;
box-shadow: 0 8px 32px rgba(82, 119, 195, 0.12);
}
.mobile-nav a {
font-size: 15px;
font-weight: 500;
color: #5277c3;
text-decoration: none;
padding: 10px 0;
border-bottom: 1px solid rgba(155, 206, 241, 0.3);
transition: opacity 0.15s;
}
.mobile-nav a:last-child {
border-bottom: none;
}
.mobile-nav a:hover {
opacity: 0.7;
}
.mobile-nav a[aria-current='page'] {
font-weight: 700;
}
.mobile-nav-divider {
border: none;
border-top: 1px solid rgba(155, 206, 241, 0.4);
margin: 4px 0;
}
@media (max-width: 1023px) {
.navbar-links {
display: none;
}
.mobile-menu {
display: block;
}
.navbar-social {
margin-left: auto;
}
}
@media (max-width: 639px) {
.navbar {
padding: 0 16px;
}
.navbar-social {
display: none;
}
}
</style>

View File

@@ -0,0 +1,637 @@
---
import Navbar from './Navbar.astro';
import BaseLayout from '../layouts/BaseLayout.astro';
import { type Locale, getTranslations } from '../i18n/config';
interface Props {
locale: Locale;
}
const { locale } = Astro.props;
const t = getTranslations(locale);
const tp = t.souvenir;
const ts = tp.comingSoon;
---
<BaseLayout title={tp.meta.title} description={tp.meta.description} lang={tp.meta.htmlLang}>
<Navbar locale={locale} activePage='souvenir' />
<!-- ======= Hero Banner ======= -->
<section class='hero-banner' aria-labelledby='souvenir-title'>
<div class='hero-bg' aria-hidden='true'>
<img class='hero-bg-img' src='/images/souvenir/hero-bg.png' alt='' />
</div>
<div class='hero-content'>
<h1 class='hero-title' id='souvenir-title'>{tp.hero.title}</h1>
<p class='hero-sub'>{tp.hero.sub}</p>
</div>
</section>
<!-- ======= Feature Card ======= -->
<main class='souvenir-main'>
<section class='feature-card' aria-labelledby='feature-title'>
<div class='card-bg-texture' aria-hidden='true'>
<img class='card-texture-img' src='/images/souvenir/card-texture.png' alt='' />
</div>
<div class='card-snowflake' aria-hidden='true'>
<img src='/images/souvenir/card-snowflake.png' alt='' width='327' height='325' />
</div>
<div class='card-content'>
<h2 class='card-title' id='feature-title'>{tp.card.title}</h2>
<p class='card-body'>{tp.card.body}</p>
<button type='button' class='cta-btn' id='souvenir-cta-btn' aria-haspopup='dialog'>
{tp.card.cta}
<img class='cta-arrow' src='/images/souvenir/cta-arrow.png' alt='' width='35' height='35' />
</button>
</div>
</section>
</main>
<!-- ======= 等待开放弹窗 ======= -->
<div class='coming-soon-overlay' id='coming-soon-overlay' hidden aria-hidden='true'>
<button
type='button'
class='coming-soon-backdrop'
id='coming-soon-backdrop'
tabindex='-1'
aria-label={ts.ariaClose}></button>
<div
class='coming-soon-dialog'
role='dialog'
aria-modal='true'
aria-labelledby='coming-soon-title'
id='coming-soon-dialog'
>
<div class='coming-soon-icon' aria-hidden='true'>
<svg width='48' height='48' viewBox='0 0 48 48' fill='none' xmlns='http://www.w3.org/2000/svg'>
<circle cx='24' cy='24' r='22' stroke='currentColor' stroke-width='2' opacity='0.25'></circle>
<path
d='M24 14v12l8 4'
stroke='currentColor'
stroke-width='2.5'
stroke-linecap='round'
stroke-linejoin='round'></path>
</svg>
</div>
<h3 class='coming-soon-title' id='coming-soon-title'>{ts.title}</h3>
<p class='coming-soon-body'>{ts.body}</p>
<button type='button' class='coming-soon-close' id='coming-soon-close'>
{ts.close}
</button>
</div>
</div>
<!-- ======= 底部同心圆装饰Figma 切图) ======= -->
<div class='bottom-circles' aria-hidden='true'>
<img src='/images/souvenir/bottom-circles.png' alt='' />
</div>
</BaseLayout>
<style>
:global(.page) {
position: relative;
overflow: hidden;
}
@keyframes heroFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes heroFadeUp {
from {
opacity: 0;
transform: translateY(16px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
@keyframes heroFadeDown {
from {
opacity: 0;
transform: translateY(-12px);
}
to {
opacity: 1;
transform: translateY(0);
}
}
:global(.navbar) {
animation: heroFadeDown 0.45s cubic-bezier(0.22, 1, 0.36, 1) both;
}
/* ===== Hero Banner ===== */
.hero-banner {
--hero-ease: cubic-bezier(0.22, 1, 0.36, 1);
position: relative;
padding: 38px 24px 48px;
text-align: center;
isolation: isolate;
overflow: hidden;
min-height: 215px;
}
.hero-bg {
position: absolute;
inset: 0;
z-index: 0;
pointer-events: none;
overflow: hidden;
}
.hero-bg-img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
object-fit: cover;
object-position: center top;
display: block;
animation: heroFadeIn 0.6s var(--hero-ease) both;
}
.hero-content {
position: relative;
z-index: 1;
max-width: 720px;
margin: 0 auto;
}
.hero-title {
font-size: clamp(2.5rem, 5.5vw, 4.5rem);
font-weight: 600;
color: #030f20;
margin: 0 0 16px;
letter-spacing: -0.05em;
line-height: 1.1;
text-shadow: 0 4px 14px rgba(3, 15, 32, 0.08);
animation: heroFadeUp 0.55s var(--hero-ease) both;
animation-delay: 0.1s;
}
.hero-sub {
font-size: clamp(0.875rem, 1vw, 1rem);
color: #1a2332;
margin: 0;
line-height: 1.7;
letter-spacing: -0.02em;
max-width: 640px;
margin-inline: auto;
animation: heroFadeUp 0.5s var(--hero-ease) both;
animation-delay: 0.18s;
}
/* ===== Feature Card ===== */
.souvenir-main {
position: relative;
z-index: 2;
width: 100%;
max-width: 1152px;
margin: 0 auto;
padding: 16px 40px 120px;
}
.feature-card {
position: relative;
min-height: 400px;
border-radius: 24px;
border: 2px solid rgba(155, 206, 241, 0.8);
background: #f9fbff;
overflow: hidden;
display: flex;
align-items: stretch;
animation: heroFadeIn 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
animation-delay: 0.22s;
}
.card-bg-texture {
position: absolute;
inset: 0;
z-index: 0;
pointer-events: none;
overflow: hidden;
}
.card-texture-img {
position: absolute;
/* Figma 198:294 — 底纹在卡片内偏移 */
left: -15%;
top: -35%;
width: 130%;
height: auto;
min-height: 100%;
object-fit: cover;
object-position: center;
display: block;
}
.card-snowflake {
position: absolute;
/* Figma 202:325 — x=737 y=155 within 1120×400 card */
right: 56px;
top: 155px;
z-index: 1;
pointer-events: none;
animation: heroFadeIn 0.7s cubic-bezier(0.22, 1, 0.36, 1) both;
animation-delay: 0.36s;
}
.card-snowflake img {
display: block;
width: 327px;
height: auto;
}
.card-content {
position: relative;
z-index: 2;
display: flex;
flex-direction: column;
justify-content: center;
gap: 24px;
padding: 60px 48px;
max-width: 720px;
}
.card-title {
font-size: clamp(1.5rem, 2.2vw, 2rem);
font-weight: 600;
color: #030f20;
margin: 0;
letter-spacing: -0.04em;
line-height: 1.25;
animation: heroFadeUp 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
animation-delay: 0.32s;
}
.card-body {
font-size: 15px;
line-height: 1.8;
color: #1a2332;
margin: 0;
letter-spacing: -0.01em;
max-width: 560px;
animation: heroFadeUp 0.55s cubic-bezier(0.22, 1, 0.36, 1) both;
animation-delay: 0.4s;
}
.cta-btn {
display: inline-flex;
align-items: center;
gap: 10px;
align-self: flex-start;
padding: 18px 32px;
border: none;
border-radius: 36px;
background: #5277c3;
color: #ffffff;
font-size: 16px;
font-weight: 500;
font-family: inherit;
letter-spacing: -0.05em;
cursor: pointer;
transition:
background 0.2s,
transform 0.15s,
box-shadow 0.2s;
white-space: nowrap;
animation: heroFadeUp 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
animation-delay: 0.48s;
}
.cta-btn:hover {
background: #4269b8;
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(82, 119, 195, 0.35);
}
.cta-btn:focus-visible {
outline: 2px solid #5277c3;
outline-offset: 3px;
}
/* ===== Coming Soon Modal ===== */
@keyframes modalOverlayIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes modalDialogIn {
from {
opacity: 0;
transform: translateY(12px) scale(0.98);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.coming-soon-overlay {
--modal-ease: cubic-bezier(0.22, 1, 0.36, 1);
position: fixed;
inset: 0;
z-index: 1000;
display: grid;
place-items: center;
padding: 24px;
}
.coming-soon-overlay[hidden] {
display: none;
}
.coming-soon-overlay.is-open {
animation: modalOverlayIn 0.28s var(--modal-ease) both;
}
.coming-soon-backdrop {
position: absolute;
inset: 0;
border: none;
padding: 0;
margin: 0;
background: rgba(3, 15, 32, 0.45);
backdrop-filter: blur(4px);
cursor: pointer;
}
.coming-soon-dialog {
position: relative;
z-index: 1;
width: min(100%, 420px);
padding: 36px 32px 28px;
border-radius: 24px;
border: 2px solid rgba(155, 206, 241, 0.8);
background: #f9fbff;
box-shadow:
0 24px 48px rgba(3, 15, 32, 0.14),
0 0 0 1px rgba(255, 255, 255, 0.6) inset;
text-align: center;
animation: modalDialogIn 0.35s var(--modal-ease) both;
animation-delay: 0.04s;
}
.coming-soon-icon {
display: flex;
justify-content: center;
margin-bottom: 16px;
color: #5277c3;
}
.coming-soon-title {
margin: 0 0 12px;
font-size: clamp(1.25rem, 2.5vw, 1.5rem);
font-weight: 600;
color: #030f20;
letter-spacing: -0.04em;
line-height: 1.3;
}
.coming-soon-body {
margin: 0 0 28px;
font-size: 15px;
line-height: 1.75;
color: #1a2332;
letter-spacing: -0.01em;
}
.coming-soon-close {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 140px;
padding: 14px 28px;
border: none;
border-radius: 36px;
background: #5277c3;
color: #ffffff;
font-size: 15px;
font-weight: 500;
font-family: inherit;
letter-spacing: -0.03em;
cursor: pointer;
transition:
background 0.2s,
transform 0.15s,
box-shadow 0.2s;
}
.coming-soon-close:hover {
background: #4269b8;
transform: translateY(-1px);
box-shadow: 0 6px 20px rgba(82, 119, 195, 0.35);
}
.coming-soon-close:focus-visible {
outline: 2px solid #5277c3;
outline-offset: 3px;
}
.cta-arrow {
display: block;
width: 35px;
height: 35px;
flex-shrink: 0;
}
/* ===== 底部同心圆装饰 ===== */
.bottom-circles {
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: min(710px, 100%);
pointer-events: none;
z-index: 0;
animation: heroFadeIn 0.8s cubic-bezier(0.22, 1, 0.36, 1) both;
animation-delay: 0.4s;
}
.bottom-circles img {
display: block;
width: 100%;
height: auto;
}
@media (max-width: 1023px) {
.hero-banner {
padding: 32px 20px 40px;
}
.souvenir-main {
padding: 12px 28px 100px;
}
.feature-card {
min-height: 360px;
}
.card-content {
padding: 48px 36px;
}
.card-snowflake {
right: 24px;
top: auto;
bottom: 16px;
}
.card-snowflake img {
width: min(260px, 32vw);
}
.bottom-circles {
width: min(560px, 100%);
}
}
@media (max-width: 639px) {
.hero-banner {
padding: 24px 16px 32px;
}
.hero-title {
margin-bottom: 12px;
}
.hero-sub {
font-size: 13px;
line-height: 1.65;
}
.souvenir-main {
padding: 8px 18px 80px;
}
.feature-card {
min-height: auto;
}
.card-content {
padding: 32px 24px 40px;
gap: 20px;
}
.card-title {
font-size: 22px;
}
.card-body {
font-size: 14px;
line-height: 1.75;
}
.card-snowflake {
right: -12px;
bottom: -8px;
top: auto;
}
.card-snowflake img {
width: 180px;
}
.cta-btn {
width: 100%;
justify-content: center;
padding: 16px 24px;
}
.cta-arrow {
width: 28px;
height: 28px;
}
.bottom-circles {
width: min(380px, 100%);
}
}
@media (prefers-reduced-motion: reduce) {
:global(.navbar),
.hero-bg-img,
.hero-title,
.hero-sub,
.feature-card,
.card-snowflake,
.card-title,
.card-body,
.cta-btn {
animation: none !important;
opacity: 1 !important;
transform: none !important;
}
.bottom-circles {
animation: none !important;
opacity: 1 !important;
transform: translateX(-50%) !important;
}
.coming-soon-overlay.is-open,
.coming-soon-dialog {
animation: none !important;
}
}
</style>
<script>
function initComingSoonModal() {
const overlay = document.getElementById('coming-soon-overlay');
const openBtn = document.getElementById('souvenir-cta-btn');
const closeBtn = document.getElementById('coming-soon-close');
const backdrop = document.getElementById('coming-soon-backdrop');
if (!overlay || !openBtn || !closeBtn || !backdrop || overlay.dataset.init === 'true') {
return;
}
overlay.dataset.init = 'true';
let lastFocused: HTMLElement | null = null;
const openModal = () => {
lastFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
overlay.hidden = false;
overlay.setAttribute('aria-hidden', 'false');
overlay.classList.add('is-open');
document.body.style.overflow = 'hidden';
closeBtn.focus();
};
const closeModal = () => {
overlay.classList.remove('is-open');
overlay.hidden = true;
overlay.setAttribute('aria-hidden', 'true');
document.body.style.overflow = '';
lastFocused?.focus();
lastFocused = null;
};
openBtn.addEventListener('click', openModal);
closeBtn.addEventListener('click', closeModal);
backdrop.addEventListener('click', closeModal);
document.addEventListener('keydown', (event) => {
if (event.key === 'Escape' && !overlay.hidden) {
closeModal();
}
});
}
initComingSoonModal();
document.addEventListener('astro:page-load', initComingSoonModal);
</script>

View File

@@ -1,7 +0,0 @@
import { defineCollection } from 'astro:content';
import { docsLoader } from '@astrojs/starlight/loaders';
import { docsSchema } from '@astrojs/starlight/schema';
export const collections = {
docs: defineCollection({ loader: docsLoader(), schema: docsSchema() }),
};

View File

@@ -1,437 +0,0 @@
Attribution-NonCommercial-ShareAlike 4.0 International
=======================================================================
Creative Commons Corporation ("Creative Commons") is not a law firm and
does not provide legal services or legal advice. Distribution of
Creative Commons public licenses does not create a lawyer-client or
other relationship. Creative Commons makes its licenses and related
information available on an "as-is" basis. Creative Commons gives no
warranties regarding its licenses, any material licensed under their
terms and conditions, or any related information. Creative Commons
disclaims all liability for damages resulting from their use to the
fullest extent possible.
Using Creative Commons Public Licenses
Creative Commons public licenses provide a standard set of terms and
conditions that creators and other rights holders may use to share
original works of authorship and other material subject to copyright
and certain other rights specified in the public license below. The
following considerations are for informational purposes only, are not
exhaustive, and do not form part of our licenses.
Considerations for licensors: Our public licenses are
intended for use by those authorized to give the public
permission to use material in ways otherwise restricted by
copyright and certain other rights. Our licenses are
irrevocable. Licensors should read and understand the terms
and conditions of the license they choose before applying it.
Licensors should also secure all rights necessary before
applying our licenses so that the public can reuse the
material as expected. Licensors should clearly mark any
material not subject to the license. This includes other CC-
licensed material, or material used under an exception or
limitation to copyright. More considerations for licensors:
wiki.creativecommons.org/Considerations_for_licensors
Considerations for the public: By using one of our public
licenses, a licensor grants the public permission to use the
licensed material under specified terms and conditions. If
the licensor's permission is not necessary for any reason--for
example, because of any applicable exception or limitation to
copyright--then that use is not regulated by the license. Our
licenses grant only permissions under copyright and certain
other rights that a licensor has authority to grant. Use of
the licensed material may still be restricted for other
reasons, including because others have copyright or other
rights in the material. A licensor may make special requests,
such as asking that all changes be marked or described.
Although not required by our licenses, you are encouraged to
respect those requests where reasonable. More considerations
for the public:
wiki.creativecommons.org/Considerations_for_licensees
=======================================================================
Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International
Public License
By exercising the Licensed Rights (defined below), You accept and agree
to be bound by the terms and conditions of this Creative Commons
Attribution-NonCommercial-ShareAlike 4.0 International Public License
("Public License"). To the extent this Public License may be
interpreted as a contract, You are granted the Licensed Rights in
consideration of Your acceptance of these terms and conditions, and the
Licensor grants You such rights in consideration of benefits the
Licensor receives from making the Licensed Material available under
these terms and conditions.
Section 1 -- Definitions.
a. Adapted Material means material subject to Copyright and Similar
Rights that is derived from or based upon the Licensed Material
and in which the Licensed Material is translated, altered,
arranged, transformed, or otherwise modified in a manner requiring
permission under the Copyright and Similar Rights held by the
Licensor. For purposes of this Public License, where the Licensed
Material is a musical work, performance, or sound recording,
Adapted Material is always produced where the Licensed Material is
synched in timed relation with a moving image.
b. Adapter's License means the license You apply to Your Copyright
and Similar Rights in Your contributions to Adapted Material in
accordance with the terms and conditions of this Public License.
c. BY-NC-SA Compatible License means a license listed at
creativecommons.org/compatiblelicenses, approved by Creative
Commons as essentially the equivalent of this Public License.
d. Copyright and Similar Rights means copyright and/or similar rights
closely related to copyright including, without limitation,
performance, broadcast, sound recording, and Sui Generis Database
Rights, without regard to how the rights are labeled or
categorized. For purposes of this Public License, the rights
specified in Section 2(b)(1)-(2) are not Copyright and Similar
Rights.
e. Effective Technological Measures means those measures that, in the
absence of proper authority, may not be circumvented under laws
fulfilling obligations under Article 11 of the WIPO Copyright
Treaty adopted on December 20, 1996, and/or similar international
agreements.
f. Exceptions and Limitations means fair use, fair dealing, and/or
any other exception or limitation to Copyright and Similar Rights
that applies to Your use of the Licensed Material.
g. License Elements means the license attributes listed in the name
of a Creative Commons Public License. The License Elements of this
Public License are Attribution, NonCommercial, and ShareAlike.
h. Licensed Material means the artistic or literary work, database,
or other material to which the Licensor applied this Public
License.
i. Licensed Rights means the rights granted to You subject to the
terms and conditions of this Public License, which are limited to
all Copyright and Similar Rights that apply to Your use of the
Licensed Material and that the Licensor has authority to license.
j. Licensor means the individual(s) or entity(ies) granting rights
under this Public License.
k. NonCommercial means not primarily intended for or directed towards
commercial advantage or monetary compensation. For purposes of
this Public License, the exchange of the Licensed Material for
other material subject to Copyright and Similar Rights by digital
file-sharing or similar means is NonCommercial provided there is
no payment of monetary compensation in connection with the
exchange.
l. Share means to provide material to the public by any means or
process that requires permission under the Licensed Rights, such
as reproduction, public display, public performance, distribution,
dissemination, communication, or importation, and to make material
available to the public including in ways that members of the
public may access the material from a place and at a time
individually chosen by them.
m. Sui Generis Database Rights means rights other than copyright
resulting from Directive 96/9/EC of the European Parliament and of
the Council of 11 March 1996 on the legal protection of databases,
as amended and/or succeeded, as well as other essentially
equivalent rights anywhere in the world.
n. You means the individual or entity exercising the Licensed Rights
under this Public License. Your has a corresponding meaning.
Section 2 -- Scope.
a. License grant.
1. Subject to the terms and conditions of this Public License,
the Licensor hereby grants You a worldwide, royalty-free,
non-sublicensable, non-exclusive, irrevocable license to
exercise the Licensed Rights in the Licensed Material to:
a. reproduce and Share the Licensed Material, in whole or
in part, for NonCommercial purposes only; and
b. produce, reproduce, and Share Adapted Material for
NonCommercial purposes only.
2. Exceptions and Limitations. For the avoidance of doubt, where
Exceptions and Limitations apply to Your use, this Public
License does not apply, and You do not need to comply with
its terms and conditions.
3. Term. The term of this Public License is specified in Section
6(a).
4. Media and formats; technical modifications allowed. The
Licensor authorizes You to exercise the Licensed Rights in
all media and formats whether now known or hereafter created,
and to make technical modifications necessary to do so. The
Licensor waives and/or agrees not to assert any right or
authority to forbid You from making technical modifications
necessary to exercise the Licensed Rights, including
technical modifications necessary to circumvent Effective
Technological Measures. For purposes of this Public License,
simply making modifications authorized by this Section 2(a)
(4) never produces Adapted Material.
5. Downstream recipients.
a. Offer from the Licensor -- Licensed Material. Every
recipient of the Licensed Material automatically
receives an offer from the Licensor to exercise the
Licensed Rights under the terms and conditions of this
Public License.
b. Additional offer from the Licensor -- Adapted Material.
Every recipient of Adapted Material from You
automatically receives an offer from the Licensor to
exercise the Licensed Rights in the Adapted Material
under the conditions of the Adapter's License You apply.
c. No downstream restrictions. You may not offer or impose
any additional or different terms or conditions on, or
apply any Effective Technological Measures to, the
Licensed Material if doing so restricts exercise of the
Licensed Rights by any recipient of the Licensed
Material.
6. No endorsement. Nothing in this Public License constitutes or
may be construed as permission to assert or imply that You
are, or that Your use of the Licensed Material is, connected
with, or sponsored, endorsed, or granted official status by,
the Licensor or others designated to receive attribution as
provided in Section 3(a)(1)(A)(i).
b. Other rights.
1. Moral rights, such as the right of integrity, are not
licensed under this Public License, nor are publicity,
privacy, and/or other similar personality rights; however, to
the extent possible, the Licensor waives and/or agrees not to
assert any such rights held by the Licensor to the limited
extent necessary to allow You to exercise the Licensed
Rights, but not otherwise.
2. Patent and trademark rights are not licensed under this
Public License.
3. To the extent possible, the Licensor waives any right to
collect royalties from You for the exercise of the Licensed
Rights, whether directly or through a collecting society
under any voluntary or waivable statutory or compulsory
licensing scheme. In all other cases the Licensor expressly
reserves any right to collect such royalties, including when
the Licensed Material is used other than for NonCommercial
purposes.
Section 3 -- License Conditions.
Your exercise of the Licensed Rights is expressly made subject to the
following conditions.
a. Attribution.
1. If You Share the Licensed Material (including in modified
form), You must:
a. retain the following if it is supplied by the Licensor
with the Licensed Material:
i. identification of the creator(s) of the Licensed
Material and any others designated to receive
attribution, in any reasonable manner requested by
the Licensor (including by pseudonym if
designated);
ii. a copyright notice;
iii. a notice that refers to this Public License;
iv. a notice that refers to the disclaimer of
warranties;
v. a URI or hyperlink to the Licensed Material to the
extent reasonably practicable;
b. indicate if You modified the Licensed Material and
retain an indication of any previous modifications; and
c. indicate the Licensed Material is licensed under this
Public License, and include the text of, or the URI or
hyperlink to, this Public License.
2. You may satisfy the conditions in Section 3(a)(1) in any
reasonable manner based on the medium, means, and context in
which You Share the Licensed Material. For example, it may be
reasonable to satisfy the conditions by providing a URI or
hyperlink to a resource that includes the required
information.
3. If requested by the Licensor, You must remove any of the
information required by Section 3(a)(1)(A) to the extent
reasonably practicable.
b. ShareAlike.
In addition to the conditions in Section 3(a), if You Share
Adapted Material You produce, the following conditions also apply.
1. The Adapter's License You apply must be a Creative Commons
license with the same License Elements, this version or
later, or a BY-NC-SA Compatible License.
2. You must include the text of, or the URI or hyperlink to, the
Adapter's License You apply. You may satisfy this condition
in any reasonable manner based on the medium, means, and
context in which You Share Adapted Material.
3. You may not offer or impose any additional or different terms
or conditions on, or apply any Effective Technological
Measures to, Adapted Material that restrict exercise of the
rights granted under the Adapter's License You apply.
Section 4 -- Sui Generis Database Rights.
Where the Licensed Rights include Sui Generis Database Rights that
apply to Your use of the Licensed Material:
a. for the avoidance of doubt, Section 2(a)(1) grants You the right
to extract, reuse, reproduce, and Share all or a substantial
portion of the contents of the database for NonCommercial purposes
only;
b. if You include all or a substantial portion of the database
contents in a database in which You have Sui Generis Database
Rights, then the database in which You have Sui Generis Database
Rights (but not its individual contents) is Adapted Material,
including for purposes of Section 3(b); and
c. You must comply with the conditions in Section 3(a) if You Share
all or a substantial portion of the contents of the database.
For the avoidance of doubt, this Section 4 supplements and does not
replace Your obligations under this Public License where the Licensed
Rights include other Copyright and Similar Rights.
Section 5 -- Disclaimer of Warranties and Limitation of Liability.
a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE
EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS
AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF
ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS,
IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION,
WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS,
ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT
KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT
ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU.
b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE
TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION,
NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT,
INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES,
COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR
USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN
ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR
DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR
IN PART, THIS LIMITATION MAY NOT APPLY TO YOU.
c. The disclaimer of warranties and limitation of liability provided
above shall be interpreted in a manner that, to the extent
possible, most closely approximates an absolute disclaimer and
waiver of all liability.
Section 6 -- Term and Termination.
a. This Public License applies for the term of the Copyright and
Similar Rights licensed here. However, if You fail to comply with
this Public License, then Your rights under this Public License
terminate automatically.
b. Where Your right to use the Licensed Material has terminated under
Section 6(a), it reinstates:
1. automatically as of the date the violation is cured, provided
it is cured within 30 days of Your discovery of the
violation; or
2. upon express reinstatement by the Licensor.
For the avoidance of doubt, this Section 6(b) does not affect any
right the Licensor may have to seek remedies for Your violations
of this Public License.
c. For the avoidance of doubt, the Licensor may also offer the
Licensed Material under separate terms or conditions or stop
distributing the Licensed Material at any time; however, doing so
will not terminate this Public License.
d. Sections 1, 5, 6, 7, and 8 survive termination of this Public
License.
Section 7 -- Other Terms and Conditions.
a. The Licensor shall not be bound by any additional or different
terms or conditions communicated by You unless expressly agreed.
b. Any arrangements, understandings, or agreements regarding the
Licensed Material not stated herein are separate from and
independent of the terms and conditions of this Public License.
Section 8 -- Interpretation.
a. For the avoidance of doubt, this Public License does not, and
shall not be interpreted to, reduce, limit, restrict, or impose
conditions on any use of the Licensed Material that could lawfully
be made without permission under this Public License.
b. To the extent possible, if any provision of this Public License is
deemed unenforceable, it shall be automatically reformed to the
minimum extent necessary to make it enforceable. If the provision
cannot be reformed, it shall be severed from this Public License
without affecting the enforceability of the remaining terms and
conditions.
c. No term or condition of this Public License will be waived and no
failure to comply consented to unless expressly agreed to by the
Licensor.
d. Nothing in this Public License constitutes or may be interpreted
as a limitation upon, or waiver of, any privileges and immunities
that apply to the Licensor or You, including from the legal
processes of any jurisdiction or authority.
=======================================================================
Creative Commons is not a party to its public
licenses. Notwithstanding, Creative Commons may elect to apply one of
its public licenses to material it publishes and in those instances
will be considered the “Licensor.” The text of the Creative Commons
public licenses is dedicated to the public domain under the CC0 Public
Domain Dedication. Except for the limited purpose of indicating that
material is shared under a Creative Commons public license or as
otherwise permitted by the Creative Commons policies published at
creativecommons.org/policies, Creative Commons does not authorize the
use of the trademark "Creative Commons" or any other trademark or logo
of Creative Commons without its prior written consent including,
without limitation, in connection with any unauthorized modifications
to any of its public licenses or any other arrangements,
understandings, or agreements concerning use of licensed material. For
the avoidance of doubt, this paragraph does not form part of the
public licenses.
Creative Commons may be contacted at creativecommons.org.

View File

@@ -1,18 +0,0 @@
---
title: '议程日历'
description: '议程日历'
sidebar:
label: '议程日历'
---
点击右上角“月”按钮,选择“日程”视图,以获得最佳的查看体验。
<iframe
class='calendar'
src='https://calendar.google.com/calendar/embed?src=5a48432d43f3ef6bdba99eb12fc804bbff13942ca4102f55bae32c440db5ef56%40group.calendar.google.com&ctz=Asia%2FShanghai'
style='border: 0;height:600px'
width='800'
height='600'
frameborder='0'
scrolling='no'
></iframe>

View File

@@ -1,52 +0,0 @@
---
title: '参会行为准则'
description: '本行为准则用于说明我们对所有 Nix CN Meetup #2 参与者的基本期待。我们希望每一位参与者都能在活动中感到被尊重、被接纳,并拥有安全、友好的交流体验。'
sidebar:
label: '参会行为准则'
---
# Nix CN Meetup #2 - 行为准则
本行为准则用于说明我们对所有 Nix CN Meetup #2 参与者的基本期待。我们希望每一位参与者都能在活动中感到被尊重、被接纳,并拥有安全、友好的交流体验。
## 尊重与友善
- 请尽量以开放、少偏见的态度与他人相处。每个人的背景、经历和表达方式都可能不同。
- 与他人互动时,请保持体贴与尊重,关注他人的需求和界限。这包括尊重个人空间、认真倾听对方发言,以及避免打断或压迫他人。
- 默认使用性别中立、不过度假设的称呼方式。当你清楚了解对方偏好的称呼或代词时再使用;如果不确定,可以礼貌地询问。请尊重只使用姓名、或不使用任何代词的选择,并支持他人正确使用其偏好的称呼方式。
## 自我照顾
- 请为自己的身心状态负责,并优先照顾好自己的感受与需求。如果你在任何对话或场合中感到不适,你随时可以选择退出、离开或寻求帮助,这完全是被尊重的选择。
## 开放沟通与相互支持
- 如果你不确定自己的言行是否合适,欢迎主动询问。界限和是否构成冒犯,应以当事人的感受为准。
- 面对分歧或不同观点时,请保持开放和好奇,尝试理解对方的立场,并愿意倾听,而不是急于否定或争论。
- 如果有人向你寻求支持,或你注意到可能存在不适或风险的情况,请在尊重当事人意愿的前提下提供帮助。如有需要,也可以及时联系活动工作人员。
- 你不需要独自承担。当你不确定该如何处理某种情况时,随时可以向活动工作人员寻求建议或协助。
## 承担责任与持续学习
- 每个人都有可能犯错。当你意识到自己的言行给他人带来不适时,请真诚道歉,并愿意倾听反馈。我们鼓励把反馈视为彼此学习、共同成长的机会。
## 尊重活动环境
- 请尊重活动场地及其相关规定,共同维护整洁、舒适的公共空间。
## 举报与求助
如果你亲身经历或目睹了违反本行为准则的行为,或因任何原因需要帮助:
- 请联系活动组织者或指定的支持人员。
- 我们会对所有反馈和举报进行谨慎、保密的处理。活动组织者有权并有责任根据情况采取适当的应对措施。
## 改编说明
本行为准则参考并改编自 NixCon 2025 行为准则及 bUm 行为准则。

View File

@@ -1,18 +0,0 @@
---
title: 'Agenda Calendar'
description: 'Agenda Calendar'
sidebar:
label: 'Agenda Calendar'
---
Click "Month" button, select "Agenda" view, to get the best viewing experience.
<iframe
class='calendar'
src='https://calendar.google.com/calendar/embed?src=5a48432d43f3ef6bdba99eb12fc804bbff13942ca4102f55bae32c440db5ef56%40group.calendar.google.com&ctz=Asia%2FShanghai'
style='border: 0;height:600px'
width='800'
height='600'
frameborder='0'
scrolling='no'
></iframe>

View File

@@ -1,52 +0,0 @@
---
title: 'Code Of Conduct'
description: 'This Code of Conduct outlines our expectations for all participants at Nix CN Meetup #2. We are committed to providing a respectful and inclusive experience for everyone.'
sidebar:
label: 'Code Of Conduct'
---
# Nix CN Meetup #2 - Code of Conduct
This Code of Conduct outlines our expectations for all participants at Nix CN Meetup #2. We are committed to providing a respectful and inclusive experience for everyone.
## Respectful Interaction
- Encounter everyone with as little bias as possible.
- Act considerately and respectfully towards others, their needs, and boundaries. This includes respecting personal space, listening attentively, and refraining from interrupting.
- Use gender-neutral ways of addressing people by default. Only use pronouns when you know which pronouns (if any) an individual prefers. Ask respectfully how others wish to be addressed. Respect preferences for names only or no pronouns. Support others in using correct pronouns.
## Personal Responsibility
- Take responsibility for your own wellbeing and look after your needs. You can leave any conversation or situation at any time if you feel uncomfortable.
## Openness & Support
- If you are unsure if your behaviour is acceptable, ask. Boundaries and discrimination are defined by those who experience them.
- Approach conflicts or differences of opinion with openness, curiosity, and a willingness to listen.
- If someone asks for your support or if you notice something concerning, offer support if appropriate, but respect their wishes. Alert event staff if necessary.
- You are not alone. Ask for help or advice from event staff when you don't know what to do.
## Accountability & Learning
- Apologize when you make mistakes and be open to criticism and feedback. View feedback as an opportunity to learn.
## Respect for the Environment
- Respect the event venue and any specific rules it may have. Help keep shared spaces tidy.
## Reporting & Assistance
If you experience or witness behavior that violates this Code of Conduct, or if you need assistance for any reason:
- Please contact event organizers or designated support staff.
- All reports will be treated with discretion. Event organizers are empowered to take appropriate actions in response to violations.
## Adaptation
This Code of Conduct is adapted from the NixCon 2025 Code of Conduct and the bUm Code of Conduct.

View File

@@ -1,16 +0,0 @@
---
title: 'Nix CN'
description: Explore a reproducible future with the Nix CN community
template: splash
hero:
tagline: Explore a reproducible future with the Nix CN community
image:
file: ../../../assets/nix-flake-logo.svg
actions:
- text: 'Meetup #2 Attendee Guide'
link: /en/meetup-2-guide
icon: right-arrow
- text: Join event group
link: /en/meetup-2-guide#event-groups
variant: minimal
---

View File

@@ -1,60 +0,0 @@
---
title: 'Nix CN Meetup #2 Guide'
description: 'Nix CN Meetup #2 is the second Nix-themed meetup in China. We aim to bring together Nix enthusiasts, developers, and practitioners to share usage experiences, best practices, and real-world applications of Nix.'
sidebar:
label: 'Meetup #2 Guide'
---
import { LinkButton } from '@astrojs/starlight/components';
Nix CN Meetup #2 is the second Nix-themed gathering in China. We aim to bring together Nix enthusiasts, developers, and practitioners to share their experiences, best practices, and use cases of Nix in various scenarios.
## Event Information
- Date (UTC+8): 2025/12/27 (Sat.) ~ 2025/12/28 (Sun.)
- Checkin Time (UTC+8): 9:30 - 10:00
- Venue: Tongji Jingdu Office Building, No. 25 Yixian Road, Yangpu District, Shanghai Wait for event staff
- Live: [youtube:@nixcn-meetup](https://youtube.com/@nixcn-meetup)
<LinkButton href='https://v.wjx.cn/vm/m9YRDuN.aspx' icon='external' iconPlacement='end'>
Register (Chinese)
</LinkButton>
<LinkButton href='https://www.wjx.top/vm/Qi3eqxV.aspx' icon='external' variant='secondary' iconPlacement='end'>
Propose a talk (Chinese)
</LinkButton>
<LinkButton href='/en/souvenir-customization/' icon='external' variant='secondary' iconPlacement='end'>
Request Souvenir Customization
</LinkButton>
## Event Groups
<LinkButton href='https://t.me/nixcnmeetup' icon='telegram' variant='secondary' iconPlacement='start'>
Telegram event group
</LinkButton>
<LinkButton
href='https://matrix.to/#/#nix-cn-meetup:rebmit.moe'
icon='matrix'
variant='secondary'
iconPlacement='start'
>
Matrix event group
</LinkButton>
## Transportation
### Arriving in Shanghai
Shanghai is accessible by air or by rail. The city has two major airports — **Shanghai Pudong International Airport (PVG)** and **Shanghai Hongqiao International Airport (SHA)** — and several railway stations, including **Shanghai Hongqiao Station**, **Shanghai Station**, **Shanghai South Station**, and **Shanghai Songjiang Station**.
Arriving via Jinshan North Rail Station or Nanxiang North Rail Station is possible but strongly discouraged because they are exceptionally far from the venue. Please pay attention to the distinctions when purchasing tickets.
Due to the considerable distance from all aforementioned transport hubs to the venue, please take careful note of the **first and last service times** of public transportation (metro, bus, etc.) and allow ample time for transfers.
### Getting to the Venue
- From Hongqiao Railway Station / Hongqiao Airport: Take Metro Line 2 to Zhongshan Park Station, transfer to Metro Line 3 to Dabaishu Station, then walk to the venue.
- From Pudong Airport: Take Metro Line 2 or Maglev to Longyang Road Station, transfer to Metro Line 18 to Fudan University Station, then walk to the venue.
- From Shanghai Railway Station / Shanghai South Railway Station: Take Metro Line 3 to Dabaishu Station, then walk to the venue.
- From Shanghai Songjiang Station: Take Metro Line 9 to Yishan Road Station, transfer to Metro Line 3 to Dabaishu Station, then walk to the venue.

View File

@@ -1,47 +0,0 @@
---
title: 'Souvenir Customization'
description: 'Souvenir Customization'
sidebar:
label: 'Souvenir Customization'
---
import { Image } from 'astro:assets';
import { LinkButton } from '@astrojs/starlight/components';
import BadgeTemplates from '@components/BadgeTemplates.astro';
import Nameplate from '@assets/nameplate.webp';
# Attendee Badge Customization
We offer three attendee badge templates:
<BadgeTemplates />
For all attendees, the first template style (Nix color scheme) will be used by default.
The `#name` and `#type` fields on the badge will be determined by the information you provide during registration and your attendance role (Attendee / Volunteer / Speaker).
To select a different template or make other customizations, file a request here:
<LinkButton href='https://forms.cloud.microsoft/r/bJMeW1iu4C' icon='external' variant='secondary' iconPlacement='end'>
Fill a Souvenir Customization Request form (Chinese)
</LinkButton>
※ The following customizations are currently supported.
Please fill them out in the "Attendee Badge Customization" section of the Souvenir Customization Request Form.
- color of the the text at bottom
- Please provide the specific location of the text to be modified and the color HEX code (e.g., `#5277C3`).
- the snowflake logo in the bottom right Corner
- Please use [this file](https://meetup-files.nixos.org.cn/nixos-template.svg) as the basis for your customization.
- Please **do** keep the aspect ratio of the original file.
- After modification, please export a **PNG file with transparent background**, maintaining the original aspect ratio, and send the file to [nixcn-meetup@sne.moe](mailto:nixcn-meetup@sne.moe) using the email address provided in the Souvenir Customization Request form.
# Name Plate Customization
<Image src={Nameplate} alt='Nameplate' />
※ The souvenir name plate only supports customization of the subtitle.
Please fill this out in the Name Plate Customization section of the Souvenir Customization Request form mentioned above.
- The souvenir name plate is made from cut metal.
- The subtitle should be less than 20 half-width characters wide in English (full-width characters such as CJK characters each count as 2 half-width characters).

View File

@@ -1,30 +0,0 @@
---
title: 'Volunteer Staffing'
description: 'Volunteer Staffing'
sidebar:
label: 'Volunteer Staffing'
---
import { LinkButton } from '@astrojs/starlight/components';
We are recruiting volunteers for Nix CN Meetup #2!
<LinkButton href='https://forms.cloud.microsoft/r/MPL7NmaqXd' icon='external' variant='secondary' iconPlacement='end'>
Fill out the Volunteer Application Form (Chinese)
</LinkButton>
Open roles are as follows:
- On-site Support (3 people)
- Handle check-in and souvenir distribution
- Provide guidance and answer general inquiries
- Pass the microphone for audience questions
- Online Streaming Support (2 people)
- Monitor livestream status
- Answer general online inquiries
- Refreshment Pickup (~5 people)
- Heavy lifting involved.
- Venue Setup (2 people)
- Please arrive at the venue 3 days before the event starts.
- Flexible (≤10 people)
- Tasks assigned based on real-time needs.

View File

@@ -1,16 +0,0 @@
---
title: 'Nix CN'
description: 与 Nix 中文社群一起探索可复现的未来
template: splash
hero:
tagline: 与 Nix 中文社群一起探索可复现的未来
image:
file: ../../assets/nix-flake-logo.svg
actions:
- text: 'Meetup #2 参会指南'
link: /meetup-2-guide
icon: right-arrow
- text: 加入活动群组
link: /meetup-2-guide#%E6%B4%BB%E5%8A%A8%E7%BE%A4%E7%BB%84
variant: minimal
---

View File

@@ -1,63 +0,0 @@
---
title: 'Nix CN Meetup #2 参会指南'
description: 'Nix CN Meetup #2 是国内第二次以 Nix 为主题的聚会。我们希望汇聚国内 Nix 爱好者、开发者和实践者,共同分享 Nix 的使用经验、最佳实践以及在不同场景下的应用案例。'
sidebar:
label: 'Meetup #2 参会指南'
---
import { LinkButton } from '@astrojs/starlight/components';
Nix CN Meetup #2 是国内第二次以 Nix 为主题的聚会。我们希望汇聚国内 Nix 爱好者、开发者和实践者,共同分享 Nix 的使用经验、最佳实践以及在不同场景下的应用案例。
## 会议信息
- 日期UTC+82025/12/27 (Sat.) ~ 2025/12/28 (Sun.)
- 签到时间UTC+8 9:30 - 10:00
- 线下会议地点上海市杨浦区逸仙路25号同济·晶度写字楼于大堂前台等待活动工作人员引导
- 线上直播地址:[youtube:@nixcn-meetup](https://youtube.com/@nixcn-meetup)
<LinkButton href='https://v.wjx.cn/vm/m9YRDuN.aspx' icon='external' iconPlacement='end'>
填写报名表
</LinkButton>
<LinkButton href='https://www.wjx.top/vm/Qi3eqxV.aspx' icon='external' variant='secondary' iconPlacement='end'>
填写议程收集表
</LinkButton>
<LinkButton href='/souvenir-customization/' icon='external' variant='secondary' iconPlacement='end'>
纪念品定制说明
</LinkButton>
## 活动群组
<LinkButton href='https://t.me/nixcnmeetup' icon='telegram' variant='secondary' iconPlacement='start'>
Telegram 活动群组
</LinkButton>
<LinkButton
href='https://matrix.to/#/#nix-cn-meetup:rebmit.moe'
icon='matrix'
variant='secondary'
iconPlacement='start'
>
Matrix 活动群组
</LinkButton>
## 交通信息
### 抵达上海
可通过航空、铁路抵达上海。上海有 **浦东国际机场**、**虹桥国际机场** 两大机场和 **上海虹桥站**、**上海站**、**上海南站**、**上海松江站** 等火车站。
不建议通过金山北站、南翔北站抵达上海,因为它们位于上海郊区,距离市中心和会议地点太远;购票时请注意不要买错。
从各大交通枢纽到达会场的路程均较远,请留意地铁、公交等公共交通的**首末班车时间**以免错过末班车,并预留充足的换乘时间。
### 前往会场
- 虹桥火车站/虹桥机场乘坐地铁2号线至中山公园站
换乘地铁3号线至大柏树站步行到达会场。
- 浦东机场乘坐地铁2号线/磁浮快线至龙阳路站,
换乘地铁18号线至复旦大学站步行到达会场。
- 上海火车站/上海南站乘坐地铁3号线至大柏树站步行到达会场。
- 上海松江站乘坐地铁9号线至宜山路站
换乘地铁3号线至大柏树站步行到达会场。

View File

@@ -1,45 +0,0 @@
---
title: '纪念品定制说明'
description: '纪念品定制说明'
sidebar:
label: '纪念品定制说明'
---
import { Image } from 'astro:assets';
import { LinkButton } from '@astrojs/starlight/components';
import BadgeTemplates from '@components/BadgeTemplates.astro';
import Nameplate from '@assets/nameplate.webp';
# 参会证定制
我们提供三种预设的参会证模板:
<BadgeTemplates />
对于所有参会者默认会使用第一种模板样式Nix 配色)制作参会证。
参会证上的 `#name` 和 `#type` 字段,将由您在报名时填写的信息和您的与会身份(参会者/志愿者/讲者)决定。
如果需要选择模板或有其他定制需求,您可以在这里提交申请:
<LinkButton href='https://forms.cloud.microsoft/r/bJMeW1iu4C' icon='external' variant='secondary' iconPlacement='end'>
填写纪念品定制需求表
</LinkButton>
※ 目前支持以下内容的定制。请在「纪念品定制需求表」的「参会证定制」分区中进行填写。
- 下方文字颜色定制
- 请提供具体需要修改的文字位置和颜色HEX码`#5277C3`)。
- 右下角雪花标志定制
- 请使用[此文件](https://meetup-files.nixos.org.cn/nixos-template.svg)作为定制基础进行修改。
- 请勿修改原文件的比例。
- 修改后,请维持原比例导出**透明底 PNG 文件**,并使用「纪念品定制需求表」中填写的邮件地址,发送文件到 [nixcn-meetup@sne.moe](mailto:nixcn-meetup@sne.moe)。
# 铭牌定制
<Image src={Nameplate} alt='Nameplate' />
※ 纪念品铭牌仅支持定制副标题。请在上述「纪念品定制需求表」的「铭牌定制」分区中一并填写。
- 纪念品铭牌为金属切削制成。
- 副标题字数应小于 20 个英文字符宽度(中文字符宽度计为 2

View File

@@ -1,30 +0,0 @@
---
title: '志愿者人员安排'
description: '志愿者人员安排'
sidebar:
label: '志愿者人员安排'
---
import { LinkButton } from '@astrojs/starlight/components';
我们正在为 Nix CN Meetup #2 招募志愿者!
<LinkButton href='https://forms.cloud.microsoft/r/MPL7NmaqXd' icon='external' variant='secondary' iconPlacement='end'>
填写志愿者报名表
</LinkButton>
开放岗位如下:
- 场务3人
- 处理签到和纪念品分发
- 提供指引答疑
- 在提问环节传递话筒等
- 直播维护2人
- 监控直播状态
- 回答线上提问
- 茶歇取货5人
- 请确保体力充足。
- 场地准备2人
- 请在活动开始前3天到达会场。
- 自由岗位≤10人
- 灵活处理场中其他事务

27
src/i18n/config.ts Normal file
View File

@@ -0,0 +1,27 @@
import translations from './translations.json';
export const LOCALES = ['zh-CN', 'en'] as const;
export type Locale = (typeof LOCALES)[number];
export const defaultLocale: Locale = 'zh-CN';
export function getLocalePaths() {
return LOCALES.map((lang) => ({ params: { lang } }));
}
export function getTranslations(locale: Locale) {
return translations[locale];
}
export const PAGE_SLUGS = {
home: '',
calendar: 'calendar',
cmsGuide: 'cms-guide',
souvenir: 'souvenir',
} as const;
export type PageSlug = keyof typeof PAGE_SLUGS;
export function getPageUrl(locale: Locale, page: PageSlug): string {
const slug = PAGE_SLUGS[page];
return slug ? `/${locale}/${slug}` : `/${locale}/`;
}

334
src/i18n/translations.json Normal file
View File

@@ -0,0 +1,334 @@
{
"zh-CN": {
"nav": {
"home": "HOME",
"calendar": "活动指南",
"cmsGuide": "CMS 系统指引",
"souvenir": "纪念品信息",
"ariaLogoHome": "NixCN 首页",
"ariaMain": "主导航",
"ariaMobile": "移动导航",
"ariaMenu": "打开导航菜单",
"ariaTelegram": "Telegram 群组",
"ariaMatrix": "Matrix 频道",
"ariaLangSwitch": "切换语言 / Switch Language"
},
"home": {
"meta": {
"htmlLang": "zh-CN",
"title": "NixCN Conference 2605",
"description": "NixCN Conference 2605 — 一次面向中文社区的 Nix / NixOS 线下聚会,让真实的实践、问题与探索,在现场被看见。"
},
"hero": {
"conferenceTitle": "NixCN Conference",
"year": "2605",
"headlineBefore": "让你的\u00a0",
"headlineBadge": "Nix",
"headlineAfter": "\u00a0实践被看见",
"lead": "欢迎回来相聚。这是又一次面向中文社区的 Nix / NixOS 线下聚会——更丰富,也更好玩。我们希望把正在使用 Nix、研究 Nix或刚刚开始了解 Nix 的人聚在一起。让真实的实践、问题与探索,在现场被看见。",
"ctaPrimary": "报名参会\u00a0→",
"ctaSecondary": "CMS 系统指引\u00a0👈"
}
},
"calendar": {
"meta": {
"htmlLang": "zh-CN",
"title": "活动指南 · NixCN Conference 2605",
"description": "NixCN Conference 2605 活动指南 — 议程安排、会议时间、周边美食地图,让你的参会体验更具体。"
},
"heading": {
"title": "活动指南",
"sub": "如果你对 Nix 有一点好奇,这里可能会给你一个更具体的答案。"
},
"agenda": {
"leadEmoji": "🌟",
"leadHtml": "本次活动以&nbsp;<span class='accent'>议题分享Talk Session</span>&nbsp;为主。",
"bullets": [
"每个议题分享约 <strong>30</strong> 分钟",
"每场议题结束后设有约 <strong>10</strong> 分钟交流 / 提问环节",
"下午约 <strong>15:00</strong> 设置茶歇时间"
]
},
"schedule": {
"emoji": "📅",
"title": "会议安排",
"timeLabel": "会议时间:",
"timeValue": "2026/06/13 (Sat.) ~ 2026/06/14 (Sun.)",
"flowLabel": "当天流程:",
"flow": [
"签到时间08:30 09:30",
"议题分享09:30 开始",
"午休时间12:00 14:00",
"下午议题14:00 18:00",
"活动结束18:30 前"
]
},
"food": {
"emoji": "🍜",
"title": "美食指引",
"mapAlt": "NixCN Conference 2605 会场周边美食地图,标注了 2-13 分钟步行距离内的推荐餐厅"
}
},
"cmsGuide": {
"meta": {
"htmlLang": "zh-CN",
"title": "CMS 系统指引 · NixCN Conference 2605",
"description": "NixCN Conference 2605 CMS 系统指引 — 邮箱登录、查看活动、身份认证、提交议程、议程审核、入场签到的完整使用流程。"
},
"hero": {
"title": "CMS 系统指引",
"subs": [
"通过报名系统,你可以完成活动报名、身份认证、议程提交,以及后续入场签到等操作。",
"首次使用无需提前注册,使用邮箱登录后,系统会自动创建账号。"
]
},
"tipBell": "🔔",
"tipLabel": "提示:",
"steps": [
{
"id": "step-01",
"num": "01",
"name": "使用邮箱登录",
"bodyHtml": "进入报名系统后,输入任意可正常接收邮件的邮箱,即可获取登录链接。<br />首次登录时,系统会自动为你创建账号。你只需要根据提示设置用户名和昵称,即可进入系统。",
"tip": {
"kind": "inline",
"text": "请尽量使用常用邮箱登录哦。后续活动报名、身份认证、议程提交和会务通知,都将与该邮箱关联。"
}
},
{
"id": "step-02",
"num": "02",
"name": "查看近期活动",
"bodyHtml": "登录后,你可以在「活动列表」中查看当前开放的会议活动。<br />选择对应活动后,可以进入活动详情页,查看会议时间、地点、活动说明、报名状态与相关操作入口。<br />你可以在这里完成:",
"list": ["加入活动", "查看活动详情", "提交议程", "查看已加入的活动"]
},
{
"id": "step-03",
"num": "03",
"name": "加入活动并完成身份认证",
"bodyHtmls": [
"点击「加入活动」后,系统会提示你完成身份认证。",
"身份认证用于确认参会者身份,保障现场入场、签到和会务管理的准确性。认证信息仅用于本次活动身份核验,我们会妥善保护你的个人信息安全,你填写的身份信息会在 30 天内销毁。",
"你可以选择以下方式完成认证:"
],
"list": ["身份证认证", "护照认证"],
"afterListHtml": "完成认证后,即可继续参与活动相关操作。",
"tip": {
"kind": "inline",
"text": "需要填写个人有效证件的真实信息哦。"
}
},
{
"id": "step-04",
"num": "04",
"name": "提交议程",
"bodyHtml": "加入活动后,你可以在活动页面提交议程。<br />提交时需要填写议程名称、简要描述和预计分享时长等信息。请尽量清晰说明你的分享主题、内容方向和希望讨论的问题,方便主办方进行审核与安排。"
},
{
"id": "step-05",
"num": "05",
"name": "议程审核与排期",
"bodyHtmls": [
"提交后的议程将由主办方统一审核。<br />我们会根据主题相关性、内容完整度、分享价值和会议整体安排进行筛选。通过审核的议程将进入排期流程。",
"最终议程预计将在会议开始前两周进行公示。<br />请以后续官网或活动页面发布的信息为准。"
]
},
{
"id": "step-06",
"num": "06",
"name": "入场码和签到码",
"bodyHtml": "活动开始后,系统将为已加入活动的参会者生成入场码和签到码。<br />入场码和签到码是你现场参会的重要凭证。到达会场后,请根据工作人员指引,在对应环节出示使用。"
}
]
},
"souvenir": {
"meta": {
"htmlLang": "zh-CN",
"title": "纪念品信息 · NixCN Conference 2605",
"description": "NixCN Conference 2605 纪念品信息 — DIY 个性化参会证,提前解锁活动限定纪念品定制服务。"
},
"hero": {
"title": "纪念品信息",
"sub": "打造你的专属参会名片!你可以在此 DIY 个性化参会证,并提前解锁更多活动限定纪念品信息。"
},
"card": {
"title": "NixCN Conference 2605 打造你的专属参会证 ✨",
"body": "提供纪念品的个性化设定服务。点击下方按钮跳转至外部定制通道,录入你的专属身份参数以生成定制化参会证。",
"cta": "开启专属定制",
"ctaUrl": "https://forms.office.com/Pages/DesignPageV2.aspx?subpage=design&FormId=DQSIkWdsW0yxEjajBLZtrQAAAAAAAAAAAAZ__u0jrMtUODNTWUpJSEs0STZZWThNTTJVUlNHN01OQy4u&Token=f0e798fadec04532bf2ef8b474a4d7b2"
},
"comingSoon": {
"title": "定制通道暂未开放",
"body": "纪念品个性化定制功能正在准备中,敬请期待。通道开放后,点击下方按钮即可跳转至外部表单完成定制。",
"close": "知道了",
"ariaClose": "关闭弹窗"
}
}
},
"en": {
"nav": {
"home": "HOME",
"calendar": "Event Guide",
"cmsGuide": "CMS Guide",
"souvenir": "Souvenirs",
"ariaLogoHome": "NixCN Home",
"ariaMain": "Primary navigation",
"ariaMobile": "Mobile navigation",
"ariaMenu": "Open navigation menu",
"ariaTelegram": "Telegram group",
"ariaMatrix": "Matrix channel",
"ariaLangSwitch": "Switch Language / 切换语言"
},
"home": {
"meta": {
"htmlLang": "en",
"title": "NixCN Conference 2605",
"description": "NixCN Conference 2605 — an in-person Nix / NixOS gathering for the Chinese community, where real-world practice, questions and exploration get to be seen onstage."
},
"hero": {
"conferenceTitle": "NixCN Conference",
"year": "2605",
"headlineBefore": "Let your\u00a0",
"headlineBadge": "Nix",
"headlineAfter": "practice <br class=\"headline-break\" />be seen",
"lead": "Welcome back to the table. This is another in-person Nix / NixOS meetup for the Chinese community — richer, and more fun. We want to bring together people who are already using Nix, studying Nix, or just starting to learn about Nix. Let real practice, questions and exploration be seen onstage.",
"ctaPrimary": "Sign up\u00a0→",
"ctaSecondary": "CMS Guide\u00a0👈"
}
},
"calendar": {
"meta": {
"htmlLang": "en",
"title": "Event Guide · NixCN Conference 2605",
"description": "NixCN Conference 2605 Event Guide — agenda, schedule, and a nearby food map to make your conference experience more concrete."
},
"heading": {
"title": "Event Guide",
"sub": "If you are a little curious about Nix, this page may give you a more concrete answer."
},
"agenda": {
"leadEmoji": "🌟",
"leadHtml": "This event centers on&nbsp;<span class='accent'>Talk Sessions</span>.",
"bullets": [
"Each talk runs for about <strong>30</strong> minutes",
"Every talk is followed by about <strong>10</strong> minutes of discussion / Q&amp;A",
"A tea break is scheduled around <strong>15:00</strong> in the afternoon"
]
},
"schedule": {
"emoji": "📅",
"title": "Conference schedule",
"timeLabel": "Conference dates:",
"timeValue": "2026/06/13 (Sat.) ~ 2026/06/14 (Sun.)",
"flowLabel": "Daily flow:",
"flow": [
"Check-in: 08:30 09:30",
"Talks start: 09:30",
"Lunch break: 12:00 14:00",
"Afternoon talks: 14:00 18:00",
"Wrap up before: 18:30"
]
},
"food": {
"emoji": "🍜",
"title": "Food guide",
"mapAlt": "NixCN Conference 2605 nearby food map, with recommended restaurants within a 213 minute walk from the venue"
}
},
"cmsGuide": {
"meta": {
"htmlLang": "en",
"title": "CMS Guide · NixCN Conference 2605",
"description": "NixCN Conference 2605 CMS Guide — the full flow for email login, browsing events, identity verification, talk submission, talk review and on-site check-in."
},
"hero": {
"title": "CMS Guide",
"subs": [
"Through the registration system you can sign up for events, complete identity verification, submit talks, and check in on-site.",
"First-time users do not need to register in advance. Log in with your email and the system will create your account automatically."
]
},
"tipBell": "🔔",
"tipLabel": "Tip:",
"steps": [
{
"id": "step-01",
"num": "01",
"name": "Log in with your email",
"bodyHtml": "Once you open the registration system, enter any email address that can receive mail and you will get a login link.<br />On first login the system creates an account for you automatically. Just follow the prompts to set a username and display name, and you are in.",
"tip": {
"kind": "inline",
"text": "Please use an email address you check often. Future event sign-ups, identity verification, talk submissions and event notifications will all be tied to this address."
}
},
{
"id": "step-02",
"num": "02",
"name": "Browse upcoming events",
"bodyHtml": "Once logged in, you can browse currently open events on the Events page.<br />Select an event to open its detail page, where you can see the date, venue, description, registration status and the action entries you need.<br />Here you can:",
"list": ["Join the event", "View event details", "Submit a talk", "View events you have joined"]
},
{
"id": "step-03",
"num": "03",
"name": "Join an event and complete identity verification",
"bodyHtmls": [
"Once you click Join, the system will prompt you to complete identity verification.",
"Identity verification is used to confirm attendee identity and to ensure accurate on-site entry, check-in and event management. The information is used only for verifying your identity for this event. We take care to protect your personal information, and the identity data you submit will be destroyed within 30 days.",
"You can verify your identity using either of the following:"
],
"list": ["National ID card verification", "Passport verification"],
"afterListHtml": "Once verified, you can continue with the rest of the event actions.",
"tip": {
"kind": "inline",
"text": "Please fill in real information from a valid personal ID document."
}
},
{
"id": "step-04",
"num": "04",
"name": "Submit a talk",
"bodyHtml": "Once you have joined an event, you can submit a talk from the event page.<br />When submitting, fill in the talk title, a short description, and the expected length. Please describe your topic, the direction of the content, and the questions you want to discuss as clearly as you can — it helps the organizers review and schedule the program."
},
{
"id": "step-05",
"num": "05",
"name": "Talk review and scheduling",
"bodyHtmls": [
"Submitted talks are reviewed by the organizers as a whole.<br />We curate the program based on topic relevance, content completeness, sharing value and the overall conference plan. Accepted talks then move into the scheduling phase.",
"The final program is expected to be announced two weeks before the conference.<br />Please refer to the latest information on the website or event page closer to the date."
]
},
{
"id": "step-06",
"num": "06",
"name": "Entry code and check-in code",
"bodyHtml": "Once the event starts, the system will generate an entry code and a check-in code for every attendee who has joined.<br />These codes are your essential credentials on-site. Once you arrive at the venue, please present them at the matching step under staff guidance."
}
]
},
"souvenir": {
"meta": {
"htmlLang": "en",
"title": "Souvenirs · NixCN Conference 2605",
"description": "NixCN Conference 2605 Souvenirs — DIY your personalized conference badge and unlock event-limited souvenir customization."
},
"hero": {
"title": "Souvenirs",
"sub": "Create your exclusive conference name card! DIY your personalized badge here and unlock more event-limited souvenir information in advance."
},
"card": {
"title": "NixCN Conference 2605 — Create Your Exclusive Badge ✨",
"body": "We offer personalized souvenir settings. Click the button below to open the external customization channel and enter your identity details to generate a customized conference badge.",
"cta": "Start Customization",
"ctaUrl": "https://forms.office.com/Pages/DesignPageV2.aspx?subpage=design&FormId=DQSIkWdsW0yxEjajBLZtrQAAAAAAAAAAAAZ__u0jrMtUODNTWUpJSEs0STZZWThNTTJVUlNHN01OQy4u&Token=f0e798fadec04532bf2ef8b474a4d7b2"
},
"comingSoon": {
"title": "Customization Not Open Yet",
"body": "Personalized souvenir customization is still being prepared. Please check back later — once live, the button below will take you to the external form.",
"close": "Got it",
"ariaClose": "Close dialog"
}
}
}
}

View File

@@ -0,0 +1,59 @@
---
interface Props {
title: string;
description?: string;
lang: string;
}
const { title, description, lang } = Astro.props;
---
<!doctype html>
<html lang={lang}>
<head>
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1' />
{description && <meta name='description' content={description} />}
<link rel='icon' type='image/svg+xml' href='/favicon.svg' />
<title>{title}</title>
</head>
<body>
<div class='page'>
<slot />
</div>
</body>
</html>
<style is:global>
*,
*::before,
*::after {
box-sizing: border-box;
}
html,
body {
margin: 0;
padding: 0;
min-height: 100%;
}
body {
font-family:
'PingFang SC',
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
sans-serif;
background: #ffffff;
color: #030f20;
-webkit-font-smoothing: antialiased;
}
.page {
min-height: 100dvh;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -0,0 +1,10 @@
---
import CalendarPage from '../../components/CalendarPage.astro';
import { getLocalePaths, type Locale } from '../../i18n/config';
export const getStaticPaths = getLocalePaths;
const { lang } = Astro.params as { lang: Locale };
---
<CalendarPage locale={lang} />

View File

@@ -0,0 +1,10 @@
---
import CmsGuidePage from '../../components/CmsGuidePage.astro';
import { getLocalePaths, type Locale } from '../../i18n/config';
export const getStaticPaths = getLocalePaths;
const { lang } = Astro.params as { lang: Locale };
---
<CmsGuidePage locale={lang} />

View File

@@ -0,0 +1,10 @@
---
import HomePage from '../../components/HomePage.astro';
import { getLocalePaths, type Locale } from '../../i18n/config';
export const getStaticPaths = getLocalePaths;
const { lang } = Astro.params as { lang: Locale };
---
<HomePage locale={lang} />

View File

@@ -0,0 +1,10 @@
---
import SouvenirPage from '../../components/SouvenirPage.astro';
import { getLocalePaths, type Locale } from '../../i18n/config';
export const getStaticPaths = getLocalePaths;
const { lang } = Astro.params as { lang: Locale };
---
<SouvenirPage locale={lang} />

View File

@@ -1,3 +0,0 @@
<script lang='ts'>
location.href = 'https://nix.org.cn';
</script>

101
src/scripts/badge-tilt.ts Normal file
View File

@@ -0,0 +1,101 @@
// Nix badge: 3D tilt + 光泽追踪(仅鼠标 / 触控笔等精确指针)
//
// 效果:徽章的"正面法线"始终指向指针 —— 指针在徽章右上方时,
// 徽章右上角往前凸rotateY 正、rotateX 负),整体像被指针"吸引"
// 而面向它转动。同时一个软高光斑跟着指针在徽章表面上滑动,
// 进一步强化 3D 玻璃药丸的观感。
//
// 仅响应鼠标:触屏滑动也会触发 pointermove会让徽章跟着滚走。
// 不用 pointer:coarse 整段禁用,避免触屏笔记本在桌面宽度下丢失鼠标 3D 效果。
export function initBadgeTilt() {
const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
const nixBadge = document.querySelector('.nix-highlight') as HTMLElement | null;
if (!nixBadge || prefersReducedMotion) return;
const MAX_ROT_Y = 18;
const MAX_ROT_X = 14;
const LIFT_BASE = 6;
const LIFT_AMP = 10;
const RANGE = 360;
const SMOOTH = 0.14;
const REST_GX = 0.3;
const REST_GY = 0.25;
let tgtX = 0;
let tgtY = 0;
let curX = 0;
let curY = 0;
let tgtGX = REST_GX;
let tgtGY = REST_GY;
let curGX = REST_GX;
let curGY = REST_GY;
let rafBadge = 0;
const clamp = (v: number, lo: number, hi: number) => (v < lo ? lo : v > hi ? hi : v);
function scheduleTick() {
if (!rafBadge) rafBadge = requestAnimationFrame(tickBadge);
}
function onMove(e: PointerEvent) {
if (e.pointerType !== 'mouse') return;
const rect = nixBadge!.getBoundingClientRect();
const cxB = rect.left + rect.width / 2;
const cyB = rect.top + rect.height / 2;
const dx = e.clientX - cxB;
const dy = e.clientY - cyB;
tgtX = clamp(dx / RANGE, -1, 1);
tgtY = clamp(dy / RANGE, -1, 1);
const localX = (e.clientX - rect.left) / rect.width;
const localY = (e.clientY - rect.top) / rect.height;
tgtGX = clamp(localX, -0.2, 1.2);
tgtGY = clamp(localY, -0.2, 1.2);
scheduleTick();
}
function onPointerEnd(e: PointerEvent) {
if (e.pointerType === 'touch' || e.pointerType === 'pen') {
tgtX = 0;
tgtY = 0;
tgtGX = REST_GX;
tgtGY = REST_GY;
scheduleTick();
}
}
function tickBadge() {
curX += (tgtX - curX) * SMOOTH;
curY += (tgtY - curY) * SMOOTH;
curGX += (tgtGX - curGX) * SMOOTH;
curGY += (tgtGY - curGY) * SMOOTH;
const rotY = curX * MAX_ROT_Y;
const rotX = -curY * MAX_ROT_X;
const lift = LIFT_BASE + (Math.abs(curX) + Math.abs(curY)) * LIFT_AMP;
nixBadge!.style.transform = `rotateY(${rotY.toFixed(2)}deg) rotateX(${rotX.toFixed(
2,
)}deg) translateZ(${lift.toFixed(2)}px)`;
nixBadge!.style.setProperty('--gloss-x', `${(curGX * 100).toFixed(1)}%`);
nixBadge!.style.setProperty('--gloss-y', `${(curGY * 100).toFixed(1)}%`);
if (
Math.abs(tgtX - curX) > 0.0008 ||
Math.abs(tgtY - curY) > 0.0008 ||
Math.abs(tgtGX - curGX) > 0.001 ||
Math.abs(tgtGY - curGY) > 0.001
) {
rafBadge = requestAnimationFrame(tickBadge);
} else {
rafBadge = 0;
}
}
document.addEventListener('pointermove', onMove, { passive: true });
document.addEventListener('pointerup', onPointerEnd, { passive: true });
document.addEventListener('pointercancel', onPointerEnd, { passive: true });
}

View File

@@ -0,0 +1,36 @@
export function initBgParallax() {
const isCoarse = window.matchMedia('(pointer: coarse)').matches;
if (isCoarse) return;
const circles = document.querySelector('.bg-circles') as HTMLElement | null;
const texture = document.querySelector('.bg-texture') as HTMLElement | null;
const textBlock = document.querySelector('.hero-text') as HTMLElement | null;
if (!circles || !texture || !textBlock) return;
let rafBg = 0;
let tx = 0,
ty = 0;
let cx = 0,
cy = 0;
document.addEventListener('mousemove', (e: MouseEvent) => {
tx = (e.clientX / window.innerWidth - 0.5) * 2;
ty = (e.clientY / window.innerHeight - 0.5) * 2;
cancelAnimationFrame(rafBg);
rafBg = requestAnimationFrame(tickBg);
});
function tickBg() {
cx += (tx - cx) * 0.07;
cy += (ty - cy) * 0.07;
circles!.style.transform = `translate(${cx * -20}px, ${cy * -14}px)`;
texture!.style.transform = `translate(${cx * -10}px, ${cy * -7}px)`;
textBlock!.style.transform = `translate(${cx * 6}px, ${cy * 3}px)`;
if (Math.abs(tx - cx) > 0.0005 || Math.abs(ty - cy) > 0.0005) {
rafBg = requestAnimationFrame(tickBg);
}
}
}

View File

@@ -0,0 +1,396 @@
export function initNixflakeAnimation() {
// ─── Canvas: NixOS snowflake — single SVG tile, drawn 78 times ──
//
// Strategy: each of the 78 tiles renders the SAME mini-snowflake SVG
// at its home position. Spring physics repels tiles from the cursor
// and springs them back. Per Figma source (node 23:289 etc.) all 78
// tiles use the same image at the same orientation — the arms only
// look angled because the tile positions are arranged along 6 lines
// at 60° intervals. No per-tile rotation needed.
//
// Coordinate derivation:
// Raw relX/relY come from tile.absoluteTransform logoFrame.x (684)
// Desktop-2 page-abs position: x=1319, y=36
// Logo frame within Desktop-2: x=684, y=139 → size 863×856 px
//
// tile position IN logo frame:
// x_wl = relX 1319 (since: absX = 1319 + 684 + x_wl, relX = absX 684)
// y_wl = relY + 36 (since: absY = 36 + 139 + y_wl, relY = absY 139)
//
// Canvas logical size: 700×700 px → fills the right column + overflows right
// Canvas scale vs Figma: CS = 700/863 ≈ 0.811
//
const canvas = document.getElementById('nixflake') as HTMLCanvasElement | null;
if (!canvas) return;
const DPR = Math.min(window.devicePixelRatio || 1, 2);
const W = 700;
const H = 700;
canvas.width = W * DPR;
canvas.height = H * DPR;
canvas.style.width = W + 'px';
canvas.style.height = H + 'px';
const ctx = canvas.getContext('2d')!;
ctx.scale(DPR, DPR);
// Figma logo frame dimensions
const LFW = 863;
// Scale factor: canvas px per Figma unit
const CS = W / LFW; // ≈ 0.811
// Tile pitch in Figma units (from Figma rect dimensions). Used to
// anchor RAW coordinates; tile rendering itself is square below.
const TW_F = 39.7;
const TH_F = 36.5;
// Tile dest size on canvas — SQUARE so the hexagonally-symmetric
// mini-snowflake has equal margin on all sides (no horizontal
// squash that made arms look uneven). Use the larger of the two
// Figma dimensions so the glyph keeps its natural size.
const DS = TW_F * CS; // ≈ 32.2 px (square edge)
// SVG viewBox is now 530×530 (was 530×456). The snowflake glyph
// occupies the central 530×455 band → 2.3px transparent padding
// top + bottom when drawn at DS×DS. Shift hy up by half the
// height increase so the snowflake's visual center stays at the
// exact same canvas position as before.
const HY_SHIFT = (DS - TH_F * CS) / 2; // ≈ 1.3 px
// Nix flake = Star of David (hexagram): two overlapping equilateral
// triangles. Each triangle contributes 3 bars (= triangle edges),
// and the 6 bars are shifted SHIFT units along their triangle's CCW
// edge direction. This shift is what creates the characteristic
// 6-pointed star — bars from the two triangles cross at the 6
// outer star tips, giving the design its 6-fold rotational symmetry.
//
// Each bar is 9 main tiles (along its edge) plus a 4-tile branch
// extending outward from the bar midpoint, rotated 60° (Figma
// matrix [cos60, -sin60; sin60, cos60]) from the bar direction.
//
// Geometry derived from the Figma source — bar center spacing,
// shift, and branch direction all match the original to within
// sub-pixel tolerance. We regenerate (instead of using the raw
// Figma coords) only to even out 2% variance between horizontal
// sides (PITCH ≈ 38.96) and diagonal sides (PITCH ≈ 39.6), and to
// make SHIFT identical across all 6 bars (Figma source varied 92100).
// Hexagram center in RAW coord space, chosen so the snowflake
// visually centers at (W/2, H/2) on canvas. Derived from the
// inverse of the (rx, ry) → (hx, hy) transform below:
// STAR_C_X = (W/2) / CS + 1319 = 350/0.8112 + 1319 ≈ 1750.5
// STAR_C_Y = (H/2 + HY_SHIFT) / CS 36 ≈ 396.9
const STAR_C_X = 1750.5;
const STAR_C_Y = 396.9;
const STAR_R = 388.8; // triangle circumradius (vertex distance from center)
const STAR_PITCH = 39; // main-bar tile-to-tile spacing
const STAR_BRANCH_PITCH = 41; // branch tile-to-tile spacing
// Bar offset along its triangle's CCW edge direction.
//
// For the 6 outer star tips (branch outermost tiles) to land on a
// proper AXIS-ALIGNED regular hexagon (flat-top, horizontal top/
// bottom edges), this offset must equal R·√3/6. Derivation: pick
// the leftmost tip (UP-1 bar's branch end). Its y component
// relative to center is R/4 SHIFT·√3/2. Setting that to 0
// (tip exactly on the horizontal axis) gives SHIFT = R/(2√3) =
// R·√3/6. The other 5 tips then fall at 60° intervals around
// a circle of radius R·√3/3 + 4·BRANCH_PITCH, by symmetry.
//
// (The Figma source used SHIFT ≈ 96, which gives a hex rotated
// ~2° off-axis. We use the exact value to make the outer hex
// perfectly axis-aligned.)
const STAR_SHIFT = (STAR_R * Math.sqrt(3)) / 6; // ≈ 112.24
// 6 edges, identified by their two endpoint vertex angles (math y-up).
// Upward triangle CCW: v90 → v210 → v330 → v90.
// Downward triangle CCW: v30 → v150 → v270 → v30.
const STAR_EDGES: { v_from_deg: number; v_to_deg: number }[] = [
{ v_from_deg: 90, v_to_deg: 210 }, // UP-1
{ v_from_deg: 210, v_to_deg: 330 }, // UP-2 (horizontal, bottom of upward triangle)
{ v_from_deg: 330, v_to_deg: 90 }, // UP-3
{ v_from_deg: 30, v_to_deg: 150 }, // DN-1 (horizontal, top of downward triangle)
{ v_from_deg: 150, v_to_deg: 270 }, // DN-2
{ v_from_deg: 270, v_to_deg: 30 }, // DN-3
];
const COS60 = 0.5;
const SIN60 = Math.sqrt(3) / 2;
const RAW: { tiles: [number, number][]; isLight: boolean }[] = STAR_EDGES.map(
({ v_from_deg, v_to_deg }, edgeIdx) => {
const a1 = (v_from_deg * Math.PI) / 180;
const a2 = (v_to_deg * Math.PI) / 180;
// Triangle vertices (math y-up → Figma y-down: flip y).
const vfx = STAR_C_X + STAR_R * Math.cos(a1);
const vfy = STAR_C_Y - STAR_R * Math.sin(a1);
const vtx = STAR_C_X + STAR_R * Math.cos(a2);
const vty = STAR_C_Y - STAR_R * Math.sin(a2);
// Edge midpoint and CCW direction along the edge.
const Mx = (vfx + vtx) / 2;
const My = (vfy + vty) / 2;
const ex = vtx - vfx;
const ey = vty - vfy;
const elen = Math.sqrt(ex * ex + ey * ey);
const dx = ex / elen;
const dy = ey / elen;
// Bar midpoint = edge midpoint shifted SHIFT units along d.
const bcx = Mx + STAR_SHIFT * dx;
const bcy = My + STAR_SHIFT * dy;
// Branch direction = bar dir rotated 60° in Figma (matrix
// [cos60, -sin60; sin60, cos60]). Verified to match the Figma
// source's branch directions across all 6 bars.
const bdx = dx * COS60 - dy * SIN60;
const bdy = dx * SIN60 + dy * COS60;
const tiles: [number, number][] = [];
// 9 main bar tiles, centered on bar midpoint, j=0..8 along d.
for (let j = 0; j < 9; j++) {
const cx = bcx + (j - 4) * STAR_PITCH * dx;
const cy = bcy + (j - 4) * STAR_PITCH * dy;
tiles.push([cx - TW_F / 2, cy - TH_F / 2]);
}
// 4 branch tiles extending out from bar midpoint.
for (let k = 1; k <= 4; k++) {
const cx = bcx + k * STAR_BRANCH_PITCH * bdx;
const cy = bcy + k * STAR_BRANCH_PITCH * bdy;
tiles.push([cx - TW_F / 2, cy - TH_F / 2]);
}
// Each bar gets ONE color (dark or light) — uniform across its
// 9 main + 4 branch tiles. The split matches the canonical
// Nix flake logo (public/images/shared/nix-flake-logo.svg), whose 6
// lambdas alternate around flat-top hex positions:
// DARK at math 0° / 120° / 240°
// LIGHT at math 60° / 180° / 300°
// Our bar midpoints (after STAR_SHIFT) land exactly on those
// 6 hex positions, with a clean triangle correspondence:
// indices 02 (UP-*, upward triangle) → hit 60° / 180° / 300° → LIGHT
// indices 35 (DN-*, downward triangle) → hit 0° / 120° / 240° → DARK
// We can't use a bar-midpoint-Y vs center-Y test because
// UP-1 (180°) and DN-3 (0°) both sit exactly on the
// horizontal axis — a Y comparison misclassifies them.
const isLight = edgeIdx < 3;
return { tiles, isLight };
},
);
interface Tile {
hx: number;
hy: number;
ox: number;
oy: number;
vx: number;
vy: number;
isLight: boolean;
}
const tiles: Tile[] = [];
for (const { tiles: groupTiles, isLight } of RAW) {
for (const [rx, ry] of groupTiles) {
const x_wl = rx - 1319;
const y_wl = ry + 36;
tiles.push({
hx: x_wl * CS,
hy: y_wl * CS - HY_SHIFT,
ox: 0,
oy: 0,
vx: 0,
vy: 0,
isLight,
});
}
}
// Single clean mini-snowflake SVG, pre-rasterized ONCE to an
// offscreen bitmap. The SVG contains multi-layer drop-shadow +
// inner-shadow + Gaussian-blur filter chains; drawing it directly
// 78× per frame forces the browser to re-run the entire filter
// pipeline on every drawImage call → tanks performance.
// Pre-rasterizing collapses each per-frame tile draw to a cheap
// bitmap copy.
const img = new Image();
img.src = '/images/shared/nix-tile-100.svg';
// Offscreen bitmap dimensioning targets a "soft fog"
// shadow rather than a sharp cast shadow:
// - Larger BMP → SVG's stdDev=5 Gaussian blur survives
// more downscale → shadow spreads SOFTER over a
// WIDER area (looks blurrier).
// - Lower globalAlpha → each pixel of that wider
// spread is more transparent → looks LIGHTER.
// The two compensate so total shadow "ink" stays modest
// but the shadow's visual radius grows.
//
// Letterbox keeps the SVG's 1.156:1 hexagram aspect.
const SVG_W = 520;
const SVG_H = 450;
const SVG_RATIO = SVG_W / SVG_H;
// SCALE 5.5 → BMP ≈ 355 px → SVG downscale ~1.46×
// stdDev=5 blurs render at ~3.4 px (vs ~2.5 at SCALE=4)
// — softer, broader penumbra without the SVG-native
// overweight you get at full SVG resolution.
const TILE_BMP_SCALE = 5.5;
const BMP_SIZE = Math.ceil(DS * DPR * TILE_BMP_SCALE);
const SVG_DRAW_W = BMP_SIZE;
const SVG_DRAW_H = BMP_SIZE / SVG_RATIO;
const SVG_DRAW_Y = (BMP_SIZE - SVG_DRAW_H) / 2;
const bmpDark = document.createElement('canvas');
bmpDark.width = BMP_SIZE;
bmpDark.height = BMP_SIZE;
const bmpLight = document.createElement('canvas');
bmpLight.width = BMP_SIZE;
bmpLight.height = BMP_SIZE;
// Shadow strategy: instead of a uniform CSS drop-shadow
// (single tint, fully alpha-driven) we cast a SOFT BLURRED
// COPY of the SVG itself. Because the bitmap retains the
// SVG's per-path color, deep-blue arms (#64AEE0 at
// fill-opacity 0.8) naturally cast a stronger, deeper
// shadow than the pale arms (#D5ECF9) — matches the
// physical intuition "opaque blocks light, translucent
// lets it through" without having to hack fill-opacity.
//
// Padding: ctx.filter='blur(r)' spreads pixels by ~3r
// beyond the source bounds; we pad the shadow bitmap so
// the halo isn't clipped at tile edges.
const SHADOW_BLUR_BMP = 28;
const SHADOW_PAD_BMP = SHADOW_BLUR_BMP * 4;
const bmpShadow = document.createElement('canvas');
bmpShadow.width = BMP_SIZE + SHADOW_PAD_BMP * 2;
bmpShadow.height = BMP_SIZE + SHADOW_PAD_BMP * 2;
let bmpReady = false;
function buildBitmaps() {
const dctx = bmpDark.getContext('2d')!;
const lctx = bmpLight.getContext('2d')!;
const sctx = bmpShadow.getContext('2d')!;
dctx.clearRect(0, 0, BMP_SIZE, BMP_SIZE);
lctx.clearRect(0, 0, BMP_SIZE, BMP_SIZE);
sctx.clearRect(0, 0, bmpShadow.width, bmpShadow.height);
// Foreground bitmaps — small main-arm tint difference
// only. The shadow story is told by bmpShadow below,
// not by globalAlpha here.
dctx.globalAlpha = 0.85;
dctx.drawImage(img, 0, SVG_DRAW_Y, SVG_DRAW_W, SVG_DRAW_H);
lctx.globalAlpha = 0.62;
lctx.drawImage(img, 0, SVG_DRAW_Y, SVG_DRAW_W, SVG_DRAW_H);
// Shadow bitmap: same SVG, drawn ONCE with a
// gaussian blur via ctx.filter and reduced alpha,
// shifted into the bitmap by SHADOW_PAD_BMP so the
// halo has room to bleed in every direction.
sctx.filter = `blur(${SHADOW_BLUR_BMP}px)`;
sctx.globalAlpha = 0.6;
sctx.drawImage(img, SHADOW_PAD_BMP, SHADOW_PAD_BMP + SVG_DRAW_Y, SVG_DRAW_W, SVG_DRAW_H);
sctx.filter = 'none';
bmpReady = true;
}
// Shadow offset on the main canvas (right-down). Sized
// relative to the tile so the offset scales with DS.
const SHADOW_OFF_X = DS * 0.32;
const SHADOW_OFF_Y = DS * 0.44;
// SHADOW_PAD_BMP in canvas px (bmpShadow's BMP_SIZE region
// covers DS canvas px, so pad converts at the same ratio).
const SHADOW_PAD_PX = (SHADOW_PAD_BMP / BMP_SIZE) * DS;
const SHADOW_DRAW_SIZE = DS + SHADOW_PAD_PX * 2;
const SPRING = 0.09;
const DAMPING = 0.72;
const REPEL_R = 90;
const REPEL_F = 6000;
let mxC = -9999;
let myC = -9999;
function syncPointer(clientX: number, clientY: number) {
const rect = canvas!.getBoundingClientRect();
mxC = (clientX - rect.left) * (W / rect.width);
myC = (clientY - rect.top) * (H / rect.height);
}
document.addEventListener('mousemove', (e: MouseEvent) => {
syncPointer(e.clientX, e.clientY);
});
canvas.addEventListener('mouseleave', () => {
mxC = -9999;
});
// Touch 输入(手机 / 平板)。全局 passive 监听,绝不
// preventDefault —— 否则会破坏页面纵向滚动。手指抬起 /
// 取消时把指针拉到极远处,让 spring 自然把雪花拉回原位。
const onTouch = (e: TouchEvent) => {
const t = e.touches[0];
if (t) syncPointer(t.clientX, t.clientY);
};
const releaseTouch = () => {
mxC = -9999;
};
document.addEventListener('touchstart', onTouch, { passive: true });
document.addEventListener('touchmove', onTouch, { passive: true });
document.addEventListener('touchend', releaseTouch, { passive: true });
document.addEventListener('touchcancel', releaseTouch, { passive: true });
let rafId = 0;
function tick() {
ctx.clearRect(0, 0, W, H);
// Pass 1: physics update (spring + cursor repulsion).
for (const tile of tiles) {
tile.vx += -tile.ox * SPRING;
tile.vy += -tile.oy * SPRING;
if (mxC > -100) {
const tcx = tile.hx + DS / 2 + tile.ox;
const tcy = tile.hy + DS / 2 + tile.oy;
const dx = tcx - mxC;
const dy = tcy - myC;
const d2 = dx * dx + dy * dy;
if (d2 < REPEL_R * REPEL_R && d2 > 0.25) {
const d = Math.sqrt(d2);
const f = REPEL_F / d2;
tile.vx += (dx / d) * f;
tile.vy += (dy / d) * f;
}
}
tile.vx *= DAMPING;
tile.vy *= DAMPING;
tile.ox += tile.vx;
tile.oy += tile.vy;
}
if (bmpReady) {
// Pass 2: paint ALL shadows first, right-down
// offset. Doing this before any foreground means
// a tile's shadow can correctly slide under its
// right-down neighbor's body instead of being
// overpainted by that neighbor's own shadow.
for (const tile of tiles) {
ctx.drawImage(
bmpShadow,
tile.hx + tile.ox + SHADOW_OFF_X - SHADOW_PAD_PX,
tile.hy + tile.oy + SHADOW_OFF_Y - SHADOW_PAD_PX,
SHADOW_DRAW_SIZE,
SHADOW_DRAW_SIZE,
);
}
// Pass 3: paint all sharp foregrounds on top.
for (const tile of tiles) {
ctx.drawImage(tile.isLight ? bmpLight : bmpDark, tile.hx + tile.ox, tile.hy + tile.oy, DS, DS);
}
}
rafId = requestAnimationFrame(tick);
}
img.onload = () => {
buildBitmaps();
cancelAnimationFrame(rafId);
tick();
};
if (img.complete && img.naturalWidth > 0) {
buildBitmaps();
tick();
} else {
tick();
}
}

View File

@@ -3,7 +3,6 @@
"include": [".astro/types.d.ts", "**/*"],
"compilerOptions": {
"paths": {
"@assets/*": ["./src/assets/*"],
"@components/*": ["./src/components/*"]
}
},