fix: align website branding and spacing
The website used redrawn brand marks, generated icons retained opaque white edges, and adjacent download and Runtime sections accumulated excessive vertical space. It now uses synchronized official theme icons with transparent antialiased edges and a consistent responsive section rhythm. Release note: 官网与应用图标现统一使用官方 GoodBuddy 标识,并优化下载区与 Agent Runtime 区之间的页面间距。
@@ -66,6 +66,19 @@ npm run build
|
||||
|
||||
中间构建输出位于 `out`。该目录为生成内容,应修改源文件后重新构建,不要直接编辑。
|
||||
|
||||
## 图标生成
|
||||
|
||||
应用图标源文件位于 `icons`。修改源图或图标处理逻辑后运行:
|
||||
|
||||
```bash
|
||||
npm run icons
|
||||
```
|
||||
|
||||
脚本会精确裁出亮色和深色圆角卡片,清理圆角外侧背景并使用适合主题的
|
||||
边缘颜色生成透明抗锯齿,避免缩放后出现白边。它会统一更新 `build` 中的
|
||||
PNG / ICO、Renderer 图标,以及官网使用的亮色和深色品牌图标。任务栏和
|
||||
托盘图标保持透明背景。
|
||||
|
||||
## 平台打包
|
||||
|
||||
### 当前平台默认包
|
||||
|
||||
@@ -17,6 +17,25 @@ const darkSourcePath = join(
|
||||
'ChatGPT_qPkaIrLGsm.png'
|
||||
)
|
||||
const rendererAssetRoot = join(root, 'src', 'renderer', 'src', 'assets')
|
||||
const websiteAssetRoot = join(root, 'sites', 'assets')
|
||||
|
||||
const lightTile = {
|
||||
left: 40,
|
||||
top: 32,
|
||||
right: 704,
|
||||
bottom: 696,
|
||||
radius: 126,
|
||||
edgeColor: [255, 255, 255]
|
||||
}
|
||||
|
||||
const darkTile = {
|
||||
left: 20,
|
||||
top: 16,
|
||||
right: 684,
|
||||
bottom: 680,
|
||||
radius: 126,
|
||||
edgeColor: [15, 21, 31]
|
||||
}
|
||||
|
||||
function cropSquare(source, size) {
|
||||
const output = new PNG({ width: size, height: size })
|
||||
@@ -24,6 +43,102 @@ function cropSquare(source, size) {
|
||||
return output
|
||||
}
|
||||
|
||||
function scaleTile(tile, sourceSize, targetSize) {
|
||||
const scale = targetSize / sourceSize
|
||||
return {
|
||||
left: tile.left * scale,
|
||||
top: tile.top * scale,
|
||||
right: tile.right * scale,
|
||||
bottom: tile.bottom * scale,
|
||||
radius: tile.radius * scale,
|
||||
edgeColor: tile.edgeColor
|
||||
}
|
||||
}
|
||||
|
||||
function cropTile(source, tile) {
|
||||
const width = Math.round(tile.right - tile.left)
|
||||
const height = Math.round(tile.bottom - tile.top)
|
||||
if (width !== height || width <= 0) {
|
||||
throw new Error('图标卡片裁剪区域必须是有效正方形')
|
||||
}
|
||||
const output = new PNG({ width, height })
|
||||
PNG.bitblt(
|
||||
source,
|
||||
output,
|
||||
Math.round(tile.left),
|
||||
Math.round(tile.top),
|
||||
width,
|
||||
height,
|
||||
0,
|
||||
0
|
||||
)
|
||||
return {
|
||||
image: output,
|
||||
tile: {
|
||||
left: 0,
|
||||
top: 0,
|
||||
right: width,
|
||||
bottom: height,
|
||||
radius: tile.radius,
|
||||
edgeColor: tile.edgeColor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function roundedRectangleDistance(x, y, tile) {
|
||||
const centerX = (tile.left + tile.right) / 2
|
||||
const centerY = (tile.top + tile.bottom) / 2
|
||||
const halfWidth = (tile.right - tile.left) / 2
|
||||
const halfHeight = (tile.bottom - tile.top) / 2
|
||||
const offsetX = Math.abs(x - centerX) - (halfWidth - tile.radius)
|
||||
const offsetY = Math.abs(y - centerY) - (halfHeight - tile.radius)
|
||||
return (
|
||||
Math.hypot(Math.max(offsetX, 0), Math.max(offsetY, 0)) +
|
||||
Math.min(Math.max(offsetX, offsetY), 0) -
|
||||
tile.radius
|
||||
)
|
||||
}
|
||||
|
||||
function applyRoundedTransparency(image, tile) {
|
||||
for (let y = 0; y < image.height; y += 1) {
|
||||
for (let x = 0; x < image.width; x += 1) {
|
||||
const offset = pixelOffset(image, x, y)
|
||||
const distance = roundedRectangleDistance(x + 0.5, y + 0.5, tile)
|
||||
const coverage = Math.min(Math.max(0.5 - distance, 0), 1)
|
||||
if (coverage >= 1) {
|
||||
if (distance > -2 && image.data[offset + 3] < 255) {
|
||||
image.data[offset] = tile.edgeColor[0]
|
||||
image.data[offset + 1] = tile.edgeColor[1]
|
||||
image.data[offset + 2] = tile.edgeColor[2]
|
||||
}
|
||||
continue
|
||||
}
|
||||
image.data[offset] = tile.edgeColor[0]
|
||||
image.data[offset + 1] = tile.edgeColor[1]
|
||||
image.data[offset + 2] = tile.edgeColor[2]
|
||||
image.data[offset + 3] = Math.round(
|
||||
image.data[offset + 3] * coverage
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createRoundedIcon(source, tile, size) {
|
||||
const cropped = cropTile(source, tile)
|
||||
applyRoundedTransparency(cropped.image, cropped.tile)
|
||||
const output = resize(
|
||||
cropped.image,
|
||||
size,
|
||||
size,
|
||||
'bicubicInterpolation'
|
||||
)
|
||||
applyRoundedTransparency(
|
||||
output,
|
||||
scaleTile(cropped.tile, cropped.image.width, size)
|
||||
)
|
||||
return output
|
||||
}
|
||||
|
||||
function pixelOffset(image, x, y) {
|
||||
return (y * image.width + x) * 4
|
||||
}
|
||||
@@ -119,6 +234,51 @@ function assertTaskbarIcon(image) {
|
||||
}
|
||||
}
|
||||
|
||||
function assertTransparentCorners(image, label) {
|
||||
const corners = [
|
||||
pixelOffset(image, 0, 0),
|
||||
pixelOffset(image, image.width - 1, 0),
|
||||
pixelOffset(image, 0, image.height - 1),
|
||||
pixelOffset(image, image.width - 1, image.height - 1)
|
||||
]
|
||||
if (corners.some((offset) => image.data[offset + 3] !== 0)) {
|
||||
throw new Error(`${label} 的圆角外侧必须透明`)
|
||||
}
|
||||
}
|
||||
|
||||
function assertDarkEdgeHasNoWhiteFringe(image) {
|
||||
const edgeWidth = Math.max(4, Math.round(image.width * 0.08))
|
||||
for (let y = 0; y < image.height; y += 1) {
|
||||
for (let x = 0; x < image.width; x += 1) {
|
||||
if (
|
||||
x >= edgeWidth &&
|
||||
x < image.width - edgeWidth &&
|
||||
y >= edgeWidth &&
|
||||
y < image.height - edgeWidth
|
||||
) {
|
||||
continue
|
||||
}
|
||||
const offset = pixelOffset(image, x, y)
|
||||
const alpha = image.data[offset + 3]
|
||||
if (
|
||||
alpha > 0 &&
|
||||
alpha < 255 &&
|
||||
Math.max(
|
||||
image.data[offset],
|
||||
image.data[offset + 1],
|
||||
image.data[offset + 2]
|
||||
) > 96
|
||||
) {
|
||||
throw new Error(
|
||||
`暗色图标的透明边缘仍包含白色像素:${x},${y} ` +
|
||||
`rgba(${image.data[offset]},${image.data[offset + 1]},` +
|
||||
`${image.data[offset + 2]},${alpha})`
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function repairDarkCursor(dark, light) {
|
||||
for (let y = 570; y <= 606; y += 1) {
|
||||
const backgroundOffset = pixelOffset(dark, 640, y)
|
||||
@@ -197,22 +357,31 @@ async function main() {
|
||||
repairDarkCursor(darkSquare, lightSquare)
|
||||
assertCursorRemoved(lightSquare, darkSquare)
|
||||
|
||||
const light = resize(lightSquare, 512, 512, 'bicubicInterpolation')
|
||||
const dark = resize(darkSquare, 512, 512, 'bicubicInterpolation')
|
||||
const taskbar = createTaskbarIcon(lightSquare)
|
||||
const light = createRoundedIcon(lightSquare, lightTile, 512)
|
||||
const dark = createRoundedIcon(darkSquare, darkTile, 512)
|
||||
const rendererLight = createRoundedIcon(lightSquare, lightTile, 128)
|
||||
const rendererDark = createRoundedIcon(darkSquare, darkTile, 128)
|
||||
assertTaskbarIcon(taskbar)
|
||||
assertTransparentCorners(light, '亮色图标')
|
||||
assertTransparentCorners(dark, '暗色图标')
|
||||
assertTransparentCorners(rendererLight, '亮色界面图标')
|
||||
assertTransparentCorners(rendererDark, '暗色界面图标')
|
||||
assertTransparentCorners(taskbar, '任务栏图标')
|
||||
assertDarkEdgeHasNoWhiteFringe(dark)
|
||||
assertDarkEdgeHasNoWhiteFringe(rendererDark)
|
||||
const tray = resize(taskbar, 32, 32, 'bicubicInterpolation')
|
||||
assertTransparentCorners(tray, '托盘图标')
|
||||
const lightPng = PNG.sync.write(light)
|
||||
const darkPng = PNG.sync.write(dark)
|
||||
const taskbarPng = PNG.sync.write(taskbar)
|
||||
const trayPng = PNG.sync.write(tray)
|
||||
const rendererLightPng = PNG.sync.write(
|
||||
resize(light, 128, 128, 'bicubicInterpolation')
|
||||
)
|
||||
const rendererDarkPng = PNG.sync.write(
|
||||
resize(dark, 128, 128, 'bicubicInterpolation')
|
||||
)
|
||||
await mkdir(rendererAssetRoot, { recursive: true })
|
||||
const rendererLightPng = PNG.sync.write(rendererLight)
|
||||
const rendererDarkPng = PNG.sync.write(rendererDark)
|
||||
await Promise.all([
|
||||
mkdir(rendererAssetRoot, { recursive: true }),
|
||||
mkdir(websiteAssetRoot, { recursive: true })
|
||||
])
|
||||
|
||||
const outputs = [
|
||||
[join(root, 'build', 'icon-light.png'), lightPng],
|
||||
@@ -221,7 +390,9 @@ async function main() {
|
||||
[join(root, 'build', 'icon-taskbar.png'), taskbarPng],
|
||||
[join(root, 'build', 'icon-tray.png'), trayPng],
|
||||
[join(rendererAssetRoot, 'goodbuddy-light.png'), rendererLightPng],
|
||||
[join(rendererAssetRoot, 'goodbuddy-dark.png'), rendererDarkPng]
|
||||
[join(rendererAssetRoot, 'goodbuddy-dark.png'), rendererDarkPng],
|
||||
[join(websiteAssetRoot, 'goodbuddy-light.png'), rendererLightPng],
|
||||
[join(websiteAssetRoot, 'goodbuddy-dark.png'), rendererDarkPng]
|
||||
]
|
||||
await Promise.all(outputs.map(([path, contents]) => writeFile(path, contents)))
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 279 KiB After Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 302 KiB After Width: | Height: | Size: 284 KiB |
|
Before Width: | Height: | Size: 279 KiB After Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 294 KiB After Width: | Height: | Size: 287 KiB |
|
Before Width: | Height: | Size: 279 KiB After Width: | Height: | Size: 279 KiB |
|
Before Width: | Height: | Size: 294 KiB After Width: | Height: | Size: 287 KiB |
@@ -59,5 +59,5 @@ SHA-256 清单。
|
||||
- `index.html`:页面结构与简体中文内容
|
||||
- `styles.css`:语义令牌、浅深主题、焦点与响应式布局
|
||||
- `app.js`:主题、移动导航和当前章节
|
||||
- `assets/favicon.svg`:站点图标
|
||||
- `assets/goodbuddy-light.png`、`assets/goodbuddy-dark.png`:由 `npm run icons` 与桌面应用同步生成的官方品牌图标
|
||||
- `scripts/validate.mjs`:无依赖静态检查
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
|
||||
<defs>
|
||||
<linearGradient id="g" x1="8" y1="8" x2="56" y2="56" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#0877e8"/>
|
||||
<stop offset="1" stop-color="#08b89b"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect width="64" height="64" rx="16" fill="#fff"/>
|
||||
<path d="M9 34a14 14 0 1 1 28 0v12H23A14 14 0 0 1 9 34Z" fill="none" stroke="url(#g)" stroke-width="7" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M27 34a14 14 0 1 1 28 0 14 14 0 0 1-28 0Z" fill="none" stroke="url(#g)" stroke-width="7"/>
|
||||
<path d="M32 20v-7M41 17l5-5M23 17l-5-5" fill="none" stroke="url(#g)" stroke-width="4" stroke-linecap="round"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 702 B |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 18 KiB |
@@ -10,7 +10,18 @@
|
||||
<link rel="canonical" href="https://mesalogo.github.io/goodbuddy/" />
|
||||
<meta name="theme-color" content="#f6f8fb" />
|
||||
<title>GoodBuddy|桌面助手与 AI 编程工具台</title>
|
||||
<link rel="icon" href="./assets/favicon.svg" type="image/svg+xml" />
|
||||
<link
|
||||
rel="icon"
|
||||
href="./assets/goodbuddy-light.png"
|
||||
type="image/png"
|
||||
media="(prefers-color-scheme: light)"
|
||||
/>
|
||||
<link
|
||||
rel="icon"
|
||||
href="./assets/goodbuddy-dark.png"
|
||||
type="image/png"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
/>
|
||||
<link rel="stylesheet" href="./styles.css" />
|
||||
<script>
|
||||
(() => {
|
||||
@@ -35,11 +46,10 @@
|
||||
<header class="site-header" data-site-header>
|
||||
<div class="header-inner">
|
||||
<a class="brand" href="#home" aria-label="GoodBuddy 首页">
|
||||
<svg class="brand-mark" viewBox="0 0 40 40" aria-hidden="true">
|
||||
<path d="M6 21a9 9 0 1 1 18 0v8H15a9 9 0 0 1-9-8Z" />
|
||||
<path d="M16 21a9 9 0 1 1 18 0 9 9 0 0 1-18 0Z" />
|
||||
<path d="M20 13V8M25 10l3-3M15 10l-3-3" />
|
||||
</svg>
|
||||
<span class="brand-icon" aria-hidden="true">
|
||||
<img class="brand-icon__image brand-icon__image--light" src="./assets/goodbuddy-light.png" alt="" />
|
||||
<img class="brand-icon__image brand-icon__image--dark" src="./assets/goodbuddy-dark.png" alt="" />
|
||||
</span>
|
||||
<span>GoodBuddy</span>
|
||||
</a>
|
||||
|
||||
@@ -136,10 +146,10 @@
|
||||
<div class="app-layout">
|
||||
<aside class="app-sidebar" aria-hidden="true">
|
||||
<div class="mini-brand">
|
||||
<svg viewBox="0 0 40 40">
|
||||
<path d="M6 21a9 9 0 1 1 18 0v8H15a9 9 0 0 1-9-8Z" />
|
||||
<path d="M16 21a9 9 0 1 1 18 0 9 9 0 0 1-18 0Z" />
|
||||
</svg>
|
||||
<span class="brand-icon" aria-hidden="true">
|
||||
<img class="brand-icon__image brand-icon__image--light" src="./assets/goodbuddy-light.png" alt="" />
|
||||
<img class="brand-icon__image brand-icon__image--dark" src="./assets/goodbuddy-dark.png" alt="" />
|
||||
</span>
|
||||
</div>
|
||||
<div class="side-item is-active"><span></span>对话</div>
|
||||
<div class="side-item"><span></span>知识库</div>
|
||||
@@ -161,7 +171,12 @@
|
||||
<div class="message message--user">修复构建问题,并验证三个桌面系统。</div>
|
||||
<div class="message message--assistant">
|
||||
<div class="assistant-label">
|
||||
<span class="assistant-avatar">G</span>
|
||||
<span class="assistant-avatar" aria-hidden="true">
|
||||
<span class="brand-icon">
|
||||
<img class="brand-icon__image brand-icon__image--light" src="./assets/goodbuddy-light.png" alt="" />
|
||||
<img class="brand-icon__image brand-icon__image--dark" src="./assets/goodbuddy-dark.png" alt="" />
|
||||
</span>
|
||||
</span>
|
||||
<strong>GoodBuddy</strong>
|
||||
</div>
|
||||
<p>已通过 Agent Runtime 载入项目、Skills 和受控工具。</p>
|
||||
@@ -373,10 +388,10 @@
|
||||
<div class="section-inner assistant-grid">
|
||||
<div class="assistant-intro">
|
||||
<div class="assistant-mark" aria-hidden="true">
|
||||
<svg viewBox="0 0 48 48">
|
||||
<path d="M9 25a11 11 0 1 1 22 0v10H20A11 11 0 0 1 9 25Z" />
|
||||
<path d="M21 25a11 11 0 1 1 22 0 11 11 0 0 1-22 0Z" />
|
||||
</svg>
|
||||
<span class="brand-icon">
|
||||
<img class="brand-icon__image brand-icon__image--light" src="./assets/goodbuddy-light.png" alt="" />
|
||||
<img class="brand-icon__image brand-icon__image--dark" src="./assets/goodbuddy-dark.png" alt="" />
|
||||
</span>
|
||||
</div>
|
||||
<p class="kicker">桌面助手</p>
|
||||
<h2 id="assistant-title">对话、知识、笔记与任务,都在桌面上</h2>
|
||||
@@ -418,11 +433,10 @@
|
||||
<footer class="site-footer">
|
||||
<div class="section-inner footer-inner">
|
||||
<a class="brand brand--footer" href="#home" aria-label="返回 GoodBuddy 首页">
|
||||
<svg class="brand-mark" viewBox="0 0 40 40" aria-hidden="true">
|
||||
<path d="M6 21a9 9 0 1 1 18 0v8H15a9 9 0 0 1-9-8Z" />
|
||||
<path d="M16 21a9 9 0 1 1 18 0 9 9 0 0 1-18 0Z" />
|
||||
<path d="M20 13V8M25 10l3-3M15 10l-3-3" />
|
||||
</svg>
|
||||
<span class="brand-icon" aria-hidden="true">
|
||||
<img class="brand-icon__image brand-icon__image--light" src="./assets/goodbuddy-light.png" alt="" />
|
||||
<img class="brand-icon__image brand-icon__image--dark" src="./assets/goodbuddy-dark.png" alt="" />
|
||||
</span>
|
||||
<span>GoodBuddy</span>
|
||||
</a>
|
||||
<p>桌面助手|AI 编程工具台</p>
|
||||
|
||||
@@ -9,7 +9,8 @@ const requiredFiles = [
|
||||
"index.html",
|
||||
"styles.css",
|
||||
"app.js",
|
||||
"assets/favicon.svg",
|
||||
"assets/goodbuddy-light.png",
|
||||
"assets/goodbuddy-dark.png",
|
||||
"README.md",
|
||||
];
|
||||
|
||||
@@ -67,6 +68,15 @@ report(/class="skip-link"\s+href="#main-content"/.test(html), "缺少跳到主
|
||||
report(/<main\s+id="main-content">/.test(html), "缺少 main-content 主区域");
|
||||
report(/aria-label="主导航"/.test(html), "主导航缺少可访问名称");
|
||||
report(/data-theme-toggle/.test(html), "缺少主题切换控件");
|
||||
report(
|
||||
(html.match(/src="\.\/assets\/goodbuddy-light\.png"/g) ?? []).length >= 5,
|
||||
"品牌位置必须使用官方亮色图标",
|
||||
);
|
||||
report(
|
||||
(html.match(/src="\.\/assets\/goodbuddy-dark\.png"/g) ?? []).length >= 5,
|
||||
"品牌位置必须使用官方深色图标",
|
||||
);
|
||||
report(!/class="brand-mark"/.test(html), "官网不得使用自绘品牌标志");
|
||||
report(/data-tilt-stage/.test(html), "首屏产品界面缺少倾斜交互区域");
|
||||
report(/data-tilt-card/.test(html), "首屏产品界面缺少倾斜卡片");
|
||||
report(/prefers-reduced-motion:\s*reduce/.test(css), "缺少减少动态效果规则");
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
--space-12: 48px;
|
||||
--space-16: 64px;
|
||||
--space-20: 80px;
|
||||
--section-space: 96px;
|
||||
--font-caption: 0.625rem;
|
||||
--font-body: 0.875rem;
|
||||
--font-section-title: 1rem;
|
||||
@@ -212,7 +213,7 @@ p {
|
||||
}
|
||||
|
||||
.section {
|
||||
padding-block: 112px;
|
||||
padding-block: var(--section-space);
|
||||
}
|
||||
|
||||
.section-inner,
|
||||
@@ -262,23 +263,32 @@ p {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.brand-mark {
|
||||
.brand-icon {
|
||||
position: relative;
|
||||
display: inline-grid;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
overflow: visible;
|
||||
fill: none;
|
||||
stroke: var(--accent);
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-width: 3;
|
||||
flex: 0 0 auto;
|
||||
place-items: center;
|
||||
}
|
||||
|
||||
.brand-mark path:nth-child(2) {
|
||||
stroke: var(--accent-mint);
|
||||
.brand-icon__image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
grid-area: 1 / 1;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.brand-mark path:last-child {
|
||||
stroke-width: 2.5;
|
||||
.brand-icon__image--dark {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .brand-icon__image--light {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .brand-icon__image--dark {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.site-navigation {
|
||||
@@ -737,21 +747,11 @@ p {
|
||||
height: 30px;
|
||||
margin: 0 0 var(--space-3) 6px;
|
||||
place-items: center;
|
||||
border-radius: var(--radius-control);
|
||||
background: var(--accent-subtle);
|
||||
}
|
||||
|
||||
.mini-brand svg {
|
||||
width: 22px;
|
||||
fill: none;
|
||||
stroke: var(--accent);
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-width: 3;
|
||||
}
|
||||
|
||||
.mini-brand path:last-child {
|
||||
stroke: var(--accent-mint);
|
||||
.mini-brand .brand-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.side-item {
|
||||
@@ -852,11 +852,11 @@ p {
|
||||
width: 23px;
|
||||
height: 23px;
|
||||
place-items: center;
|
||||
border-radius: 7px;
|
||||
background: linear-gradient(135deg, var(--accent), var(--accent-mint));
|
||||
color: var(--text-on-accent);
|
||||
font-size: 9px;
|
||||
font-weight: 800;
|
||||
}
|
||||
|
||||
.assistant-avatar .brand-icon {
|
||||
width: 23px;
|
||||
height: 23px;
|
||||
}
|
||||
|
||||
.message--assistant p {
|
||||
@@ -1225,7 +1225,11 @@ p {
|
||||
}
|
||||
|
||||
.download-section {
|
||||
padding-top: var(--space-20);
|
||||
padding-top: var(--section-space);
|
||||
}
|
||||
|
||||
.download-section + .features-section {
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.download-grid {
|
||||
@@ -1361,24 +1365,14 @@ p {
|
||||
}
|
||||
|
||||
.assistant-mark {
|
||||
display: grid;
|
||||
width: 76px;
|
||||
height: 76px;
|
||||
margin-bottom: var(--space-8);
|
||||
place-items: center;
|
||||
border: 1px solid color-mix(in srgb, var(--accent-cyan) 40%, transparent);
|
||||
border-radius: 20px;
|
||||
background: color-mix(in srgb, var(--accent-cyan) 10%, transparent);
|
||||
color: var(--accent-cyan);
|
||||
}
|
||||
|
||||
.assistant-mark svg {
|
||||
width: 42px;
|
||||
fill: none;
|
||||
stroke: currentColor;
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-width: 2;
|
||||
.assistant-mark .brand-icon {
|
||||
width: 76px;
|
||||
height: 76px;
|
||||
}
|
||||
|
||||
.text-link {
|
||||
@@ -1442,7 +1436,7 @@ p {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.brand--footer .brand-mark {
|
||||
.brand--footer .brand-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
@@ -1503,8 +1497,8 @@ p {
|
||||
}
|
||||
|
||||
@media (max-width: 959px) {
|
||||
.section {
|
||||
padding-block: 88px;
|
||||
:root {
|
||||
--section-space: var(--space-20);
|
||||
}
|
||||
|
||||
.header-inner {
|
||||
@@ -1632,6 +1626,10 @@ p {
|
||||
}
|
||||
|
||||
@media (max-width: 719px) {
|
||||
:root {
|
||||
--section-space: var(--space-16);
|
||||
}
|
||||
|
||||
html {
|
||||
scroll-padding-top: 72px;
|
||||
}
|
||||
@@ -1641,10 +1639,6 @@ p {
|
||||
width: calc(100% - 32px);
|
||||
}
|
||||
|
||||
.section {
|
||||
padding-block: var(--space-16);
|
||||
}
|
||||
|
||||
.header-inner {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
min-height: 64px;
|
||||
@@ -1654,7 +1648,7 @@ p {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.brand-mark {
|
||||
.brand-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
@@ -1830,6 +1824,11 @@ p {
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.assistant-mark .brand-icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.assistant-list article {
|
||||
grid-template-columns: 32px 1fr;
|
||||
gap: var(--space-3);
|
||||
|
||||
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 18 KiB |