feat: add trusted mirror update source
Version checks and downloads previously depended on GitHub Release. About & Updates now offers GitHub or a validated mirror source, keeps the selector beneath the startup-check switch, and disables it when startup checks are off. The website resolves platform downloads from a bounded OSS release index with a GitHub fallback. Tagged releases publish and verify immutable OSS assets through OIDC before switching the latest-version index; deployment requires the configured Alibaba Cloud environment variables and role. Release note: “关于与更新”新增 GitHub 与镜像节点选择,启动检查、手动检查和下载页使用同一可信来源;官网下载也可按系统、架构和安装包类型直接选择。
This commit is contained in:
+8
-6
@@ -39,25 +39,27 @@ node sites/scripts/validate.mjs
|
||||
node --check sites/app.js
|
||||
```
|
||||
|
||||
校验脚本会检查必需文件、页内链接、本地资源、关键产品文案、主题与响应式规则,以及下载入口是否始终指向官方最新 Release。
|
||||
校验脚本会检查必需文件、页内链接、本地资源、关键产品文案、主题与响应式
|
||||
规则,以及下载选择器是否从受信任的正式发布索引加载并保留 GitHub
|
||||
Release 回退入口。
|
||||
|
||||
## 下载入口
|
||||
|
||||
官网正文不展示具体版本号,三个系统下载按钮直接指向 GitHub 最新正式
|
||||
官网正文不写死版本号,页面启动后读取最新正式发布索引。
|
||||
Windows、macOS 和 Linux 下载卡片分别提供处理器架构与安装包类型选择器,
|
||||
选择后直接下载经过发布校验的不可变版本对象。发布索引请求失败、
|
||||
格式无效或返回非受信任的官方下载地址时,按钮继续指向 GitHub 最新正式
|
||||
Release:
|
||||
|
||||
```text
|
||||
https://github.com/mesalogo/goodbuddy/releases/latest
|
||||
```
|
||||
|
||||
新版本发布后 GitHub 会自动更新该地址的目标,官网无需同步修改版本号
|
||||
或安装资产名称。用户在 Release 页面按系统与架构选择文件并核对
|
||||
SHA-256 清单。
|
||||
|
||||
## 文件
|
||||
|
||||
- `index.html`:页面结构与简体中文内容
|
||||
- `styles.css`:语义令牌、浅深主题、焦点与响应式布局
|
||||
- `app.js`:主题、移动导航和当前章节
|
||||
- `assets/goodbuddy-light.png`、`assets/goodbuddy-dark.png`:由 `npm run icons` 与桌面应用同步生成的官方品牌图标
|
||||
- `assets/linux-plain.svg`:Devicon v2.17.0 提供的黑白 Linux 图标,许可见 `assets/devicon-LICENSE`
|
||||
- `scripts/validate.mjs`:无依赖静态检查
|
||||
|
||||
+132
@@ -12,6 +12,137 @@
|
||||
const systemTheme = window.matchMedia("(prefers-color-scheme: dark)");
|
||||
const finePointer = window.matchMedia("(hover: hover) and (pointer: fine)");
|
||||
const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
||||
const releaseManifestUrl =
|
||||
"https://goodbuddy.oss-cn-hangzhou.aliyuncs.com/releases/latest.json";
|
||||
const releaseFallbackUrl =
|
||||
"https://github.com/mesalogo/goodbuddy/releases/latest";
|
||||
const releaseStatus = document.querySelector("[data-release-status]");
|
||||
const downloadCards = [
|
||||
...document.querySelectorAll("[data-download-card]"),
|
||||
];
|
||||
const platformNames = {
|
||||
windows: "Windows",
|
||||
macos: "macOS",
|
||||
linux: "Linux",
|
||||
};
|
||||
const formatNames = {
|
||||
nsis: "安装版",
|
||||
portable: "便携版",
|
||||
dmg: "DMG",
|
||||
zip: "ZIP",
|
||||
AppImage: "AppImage",
|
||||
deb: "DEB",
|
||||
};
|
||||
|
||||
const formatFileSize = (bytes) => {
|
||||
const megabytes = bytes / (1024 * 1024);
|
||||
return `${megabytes >= 100 ? megabytes.toFixed(0) : megabytes.toFixed(1)} MB`;
|
||||
};
|
||||
|
||||
const isTrustedReleaseUrl = (value) => {
|
||||
try {
|
||||
const url = new URL(value);
|
||||
return (
|
||||
url.protocol === "https:" &&
|
||||
url.hostname === "goodbuddy.oss-cn-hangzhou.aliyuncs.com" &&
|
||||
url.pathname.startsWith("/releases/")
|
||||
);
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const configureDownloads = (release) => {
|
||||
if (
|
||||
release?.formatVersion !== 1 ||
|
||||
release?.productName !== "GoodBuddy" ||
|
||||
typeof release?.version !== "string" ||
|
||||
!release?.targets
|
||||
) {
|
||||
throw new Error("发布索引格式无效");
|
||||
}
|
||||
|
||||
const updateCard = (card) => {
|
||||
const platform = card.dataset.downloadCard;
|
||||
const archSelect = card.querySelector("[data-download-arch]");
|
||||
const formatSelect = card.querySelector("[data-download-format]");
|
||||
const link = card.closest(".download-card")?.querySelector("[data-release-link]");
|
||||
const meta = card.closest(".download-card")?.querySelector("[data-download-meta]");
|
||||
if (
|
||||
!platform ||
|
||||
!(archSelect instanceof HTMLSelectElement) ||
|
||||
!(formatSelect instanceof HTMLSelectElement) ||
|
||||
!(link instanceof HTMLAnchorElement) ||
|
||||
!(meta instanceof HTMLElement)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const target = release.targets[`${platform}-${archSelect.value}`];
|
||||
const file = target?.files?.[formatSelect.value];
|
||||
if (
|
||||
!file ||
|
||||
typeof file.name !== "string" ||
|
||||
!Number.isSafeInteger(file.size) ||
|
||||
file.size < 1 ||
|
||||
!isTrustedReleaseUrl(file.url)
|
||||
) {
|
||||
link.href = releaseFallbackUrl;
|
||||
link.textContent =
|
||||
`前往 GitHub 下载 ${platformNames[platform] ?? platform} →`;
|
||||
meta.textContent = "当前选项暂不可用,请在 GitHub Release 中选择文件。";
|
||||
return;
|
||||
}
|
||||
|
||||
link.href = file.url;
|
||||
const platformName = platformNames[platform] ?? platform;
|
||||
const archName =
|
||||
platform === "macos" && archSelect.value === "arm64"
|
||||
? "Apple 芯片"
|
||||
: archSelect.value === "arm64"
|
||||
? "ARM64"
|
||||
: "x64";
|
||||
const formatName = formatNames[formatSelect.value] ?? formatSelect.value;
|
||||
link.textContent = `下载 ${platformName} ${archName} ${formatName} →`;
|
||||
meta.textContent =
|
||||
`GoodBuddy ${release.version} · ${formatFileSize(file.size)} · ` +
|
||||
`${archSelect.options[archSelect.selectedIndex]?.text ?? archSelect.value}`;
|
||||
};
|
||||
|
||||
for (const card of downloadCards) {
|
||||
const selects = card.querySelectorAll("select");
|
||||
for (const select of selects) {
|
||||
select.addEventListener("change", () => updateCard(card));
|
||||
}
|
||||
updateCard(card);
|
||||
}
|
||||
|
||||
if (releaseStatus instanceof HTMLElement) {
|
||||
releaseStatus.textContent =
|
||||
`官方下载源已就绪:GoodBuddy ${release.version}。` +
|
||||
"请选择处理器和安装包类型。";
|
||||
releaseStatus.classList.add("is-ready");
|
||||
}
|
||||
};
|
||||
|
||||
const loadRelease = async () => {
|
||||
try {
|
||||
const response = await fetch(releaseManifestUrl, {
|
||||
cache: "no-store",
|
||||
credentials: "omit",
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error(`发布索引请求失败:${response.status}`);
|
||||
}
|
||||
configureDownloads(await response.json());
|
||||
} catch {
|
||||
if (releaseStatus instanceof HTMLElement) {
|
||||
releaseStatus.textContent =
|
||||
"官方下载源暂不可用,下载按钮已切换到 GitHub Release。";
|
||||
releaseStatus.classList.add("is-fallback");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const getSavedTheme = () => {
|
||||
try {
|
||||
@@ -51,6 +182,7 @@
|
||||
|
||||
applyTheme(getSavedTheme() ?? (systemTheme.matches ? "dark" : "light"));
|
||||
setHeaderState();
|
||||
void loadRelease();
|
||||
|
||||
themeToggle?.addEventListener("click", () => {
|
||||
applyTheme(root.dataset.theme === "dark" ? "light" : "dark", true);
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 konpa
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><path fill-rule="evenodd" clip-rule="evenodd" d="M113.823 104.595c-1.795-1.478-3.629-2.921-5.308-4.525-1.87-1.785-3.045-3.944-2.789-6.678.147-1.573-.216-2.926-2.113-3.452.446-1.154.864-1.928 1.033-2.753.188-.92.178-1.887.204-2.834.264-9.96-3.334-18.691-8.663-26.835-2.454-3.748-5.017-7.429-7.633-11.066-4.092-5.688-5.559-12.078-5.633-18.981a47.564 47.564 0 00-1.081-9.475C80.527 11.956 77.291 7.233 71.422 4.7c-4.497-1.942-9.152-2.327-13.901-1.084-6.901 1.805-11.074 6.934-10.996 14.088.074 6.885.417 13.779.922 20.648.288 3.893-.312 7.252-2.895 10.34-2.484 2.969-4.706 6.172-6.858 9.397-1.229 1.844-2.317 3.853-3.077 5.931-2.07 5.663-3.973 11.373-7.276 16.5-1.224 1.9-1.363 4.026-.494 6.199.225.563.363 1.429.089 1.882-2.354 3.907-5.011 7.345-10.066 8.095-3.976.591-4.172 1.314-4.051 5.413.1 3.337.061 6.705-.28 10.021-.363 3.555.008 4.521 3.442 5.373 7.924 1.968 15.913 3.647 23.492 6.854 3.227 1.365 6.465.891 9.064-1.763 2.713-2.771 6.141-3.855 9.844-3.859 6.285-.005 12.572.298 18.86.369 1.702.02 2.679.653 3.364 2.199.84 1.893 2.26 3.284 4.445 3.526 4.193.462 8.013-.16 11.19-3.359 3.918-3.948 8.436-7.066 13.615-9.227 1.482-.619 2.878-1.592 4.103-2.648 2.231-1.922 2.113-3.146-.135-5zM62.426 24.12c.758-2.601 2.537-4.289 5.243-4.801 2.276-.43 4.203.688 5.639 3.246 1.546 2.758 2.054 5.64.734 8.658-1.083 2.474-1.591 2.707-4.123 1.868-.474-.157-.937-.343-1.777-.652.708-.594 1.154-1.035 1.664-1.382 1.134-.772 1.452-1.858 1.346-3.148-.139-1.694-1.471-3.194-2.837-3.175-1.225.017-2.262 1.167-2.4 2.915-.086 1.089.095 2.199.173 3.589-3.446-1.023-4.711-3.525-3.662-7.118zm-12.75-2.251c1.274-1.928 3.197-2.314 5.101-1.024 2.029 1.376 3.547 5.256 2.763 7.576-.285.844-1.127 1.5-1.716 2.241l-.604-.374c-.23-1.253-.276-2.585-.757-3.733-.304-.728-1.257-1.184-1.919-1.762-.622.739-1.693 1.443-1.757 2.228-.088 1.084.477 2.28.969 3.331.311.661 1.001 1.145 1.713 1.916l-1.922 1.51c-3.018-2.7-3.915-8.82-1.871-11.909zM87.34 86.075c-.203 2.604-.5 2.713-3.118 3.098-1.859.272-2.359.756-2.453 2.964a101.744 101.744 0 00-.012 7.753c.061 1.77-.537 3.158-1.755 4.393-6.764 6.856-14.845 10.105-24.512 8.926-4.17-.509-6.896-3.047-9.097-6.639.98-.363 1.705-.607 2.412-.894 3.122-1.27 3.706-3.955 1.213-6.277-1.884-1.757-3.986-3.283-6.007-4.892-1.954-1.555-3.934-3.078-5.891-4.629-1.668-1.323-2.305-3.028-2.345-5.188-.094-5.182.972-10.03 3.138-14.747 1.932-4.209 3.429-8.617 5.239-12.885.935-2.202 1.906-4.455 3.278-6.388 1.319-1.854 2.134-3.669 1.988-5.94-.084-1.276-.016-2.562-.016-3.843l.707-.352c1.141.985 2.302 1.949 3.423 2.959 4.045 3.646 7.892 3.813 12.319.67 1.888-1.341 3.93-2.47 5.927-3.652.497-.294 1.092-.423 1.934-.738 2.151 5.066 4.262 10.033 6.375 15 1.072 2.524 1.932 5.167 3.264 7.547 2.671 4.775 4.092 9.813 4.07 15.272-.012 2.83.137 5.67-.081 8.482z"/></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
+66
-9
@@ -229,14 +229,33 @@
|
||||
<path d="m3 5 8-1v8H3V5Zm10-1.3L21 3v9h-8V3.7ZM3 14h8v8l-8-1v-7Zm10 0h8v9l-8-1v-8Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div><h3>Windows</h3><p>x64 / arm64 · NSIS / 便携版</p></div>
|
||||
<div><h3>Windows</h3><p>x64 / arm64 · 安装版 / 便携版</p></div>
|
||||
<div class="download-options" data-download-card="windows">
|
||||
<label>
|
||||
<span>处理器</span>
|
||||
<select data-download-arch aria-label="Windows 处理器架构">
|
||||
<option value="x64">x64(Intel / AMD)</option>
|
||||
<option value="arm64">ARM64</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>类型</span>
|
||||
<select data-download-format aria-label="Windows 安装包类型">
|
||||
<option value="nsis">安装版(推荐)</option>
|
||||
<option value="portable">便携版 ZIP</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<a
|
||||
class="button button--download"
|
||||
href="https://github.com/mesalogo/goodbuddy/releases/latest"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
data-release-link
|
||||
>下载 Windows 版<span class="sr-only">(在新窗口打开)</span></a>
|
||||
>下载 Windows 版 →<span class="sr-only">(在新窗口打开)</span></a>
|
||||
<p class="download-meta" data-download-meta aria-live="polite">
|
||||
正在获取最新版本,暂时可前往 GitHub 下载。
|
||||
</p>
|
||||
</article>
|
||||
<article class="download-card">
|
||||
<div class="platform-icon">
|
||||
@@ -244,32 +263,70 @@
|
||||
<path d="M16.8 12.7c0-2.7 2.2-4 2.3-4.1A5 5 0 0 0 15.2 6c-1.7-.2-3.2 1-4.1 1-.9 0-2.2-1-3.6-1-1.8 0-3.5 1.1-4.5 2.7-2 3.5-.5 8.7 1.4 11.5.9 1.4 2 2.8 3.5 2.7 1.4 0 1.9-.9 3.7-.9 1.7 0 2.2.9 3.7.9s2.5-1.4 3.4-2.7a10 10 0 0 0 1.6-3.3 4.6 4.6 0 0 1-3.5-4.2ZM14.1 4.3A4.7 4.7 0 0 0 15.2 1a4.8 4.8 0 0 0-3.1 1.6A4.4 4.4 0 0 0 11 5.8c1.2.1 2.3-.5 3.1-1.5Z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div><h3>macOS</h3><p>x64 / arm64 · DMG / ZIP</p></div>
|
||||
<div><h3>macOS</h3><p>Apple 芯片 / Intel · DMG / ZIP</p></div>
|
||||
<div class="download-options" data-download-card="macos">
|
||||
<label>
|
||||
<span>处理器</span>
|
||||
<select data-download-arch aria-label="macOS 处理器架构">
|
||||
<option value="arm64">Apple 芯片(推荐)</option>
|
||||
<option value="x64">Intel</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>类型</span>
|
||||
<select data-download-format aria-label="macOS 安装包类型">
|
||||
<option value="dmg">DMG(推荐)</option>
|
||||
<option value="zip">ZIP</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<a
|
||||
class="button button--download"
|
||||
href="https://github.com/mesalogo/goodbuddy/releases/latest"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
data-release-link
|
||||
>下载 macOS 版<span class="sr-only">(在新窗口打开)</span></a>
|
||||
>下载 macOS 版 →<span class="sr-only">(在新窗口打开)</span></a>
|
||||
<p class="download-meta" data-download-meta aria-live="polite">
|
||||
正在获取最新版本,暂时可前往 GitHub 下载。
|
||||
</p>
|
||||
</article>
|
||||
<article class="download-card">
|
||||
<div class="platform-icon">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true">
|
||||
<path d="M12 3c-3 0-4.7 2.5-4.5 5.4-1.3 1.4-2 3.4-2 5.6 0 3.9 2.9 7 6.5 7s6.5-3.1 6.5-7c0-2.2-.7-4.2-2-5.6C16.7 5.5 15 3 12 3Z" />
|
||||
<path d="M9.3 10.2h.1M14.6 10.2h.1M9.5 15c1.6 1.2 3.4 1.2 5 0M7 19l-2 2M17 19l2 2" />
|
||||
</svg>
|
||||
<img src="./assets/linux-plain.svg" alt="" />
|
||||
</div>
|
||||
<div><h3>Linux</h3><p>x64 / arm64 · AppImage / DEB</p></div>
|
||||
<div class="download-options" data-download-card="linux">
|
||||
<label>
|
||||
<span>处理器</span>
|
||||
<select data-download-arch aria-label="Linux 处理器架构">
|
||||
<option value="x64">x64(Intel / AMD)</option>
|
||||
<option value="arm64">ARM64</option>
|
||||
</select>
|
||||
</label>
|
||||
<label>
|
||||
<span>类型</span>
|
||||
<select data-download-format aria-label="Linux 安装包类型">
|
||||
<option value="AppImage">AppImage(推荐)</option>
|
||||
<option value="deb">DEB</option>
|
||||
</select>
|
||||
</label>
|
||||
</div>
|
||||
<a
|
||||
class="button button--download"
|
||||
href="https://github.com/mesalogo/goodbuddy/releases/latest"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
data-release-link
|
||||
>下载 Linux 版<span class="sr-only">(在新窗口打开)</span></a>
|
||||
>下载 Linux 版 →<span class="sr-only">(在新窗口打开)</span></a>
|
||||
<p class="download-meta" data-download-meta aria-live="polite">
|
||||
正在获取最新版本,暂时可前往 GitHub 下载。
|
||||
</p>
|
||||
</article>
|
||||
</div>
|
||||
<div class="download-release-status" data-release-status role="status">
|
||||
正在连接官方下载源…
|
||||
</div>
|
||||
|
||||
<aside class="domestic-support" aria-labelledby="domestic-support-title">
|
||||
<div>
|
||||
|
||||
@@ -11,6 +11,8 @@ const requiredFiles = [
|
||||
"app.js",
|
||||
"assets/goodbuddy-light.png",
|
||||
"assets/goodbuddy-dark.png",
|
||||
"assets/linux-plain.svg",
|
||||
"assets/devicon-LICENSE",
|
||||
"README.md",
|
||||
];
|
||||
|
||||
@@ -132,6 +134,31 @@ for (const link of releaseLinks) {
|
||||
report(/target="_blank"/.test(link), `下载入口必须在新窗口打开:${link}`);
|
||||
report(/rel="[^"]*noreferrer[^"]*"/.test(link), `下载入口缺少 noreferrer:${link}`);
|
||||
}
|
||||
report(
|
||||
(html.match(/data-download-card="(?:windows|macos|linux)"/g) ?? []).length === 3,
|
||||
"下载区必须包含 Windows、macOS 和 Linux 选择器",
|
||||
);
|
||||
report(
|
||||
(html.match(/data-download-arch/g) ?? []).length === 3,
|
||||
"每个平台必须提供处理器架构选择器",
|
||||
);
|
||||
report(
|
||||
(html.match(/data-download-format/g) ?? []).length === 3,
|
||||
"每个平台必须提供安装包类型选择器",
|
||||
);
|
||||
report(/data-release-status/.test(html), "下载区缺少发布源状态");
|
||||
report(
|
||||
appJs.includes(
|
||||
"https://goodbuddy.oss-cn-hangzhou.aliyuncs.com/releases/latest.json",
|
||||
),
|
||||
"官网必须从 GoodBuddy OSS 加载最新发布索引",
|
||||
);
|
||||
report(
|
||||
appJs.includes("https://github.com/mesalogo/goodbuddy/releases/latest"),
|
||||
"官网必须保留 GitHub Release 回退地址",
|
||||
);
|
||||
report(/credentials:\s*"omit"/.test(appJs), "OSS 发布索引请求不得携带凭据");
|
||||
report(/isTrustedReleaseUrl/.test(appJs), "OSS 下载链接缺少来源校验");
|
||||
|
||||
const ids = [...html.matchAll(/\sid="([^"]+)"/g)].map((match) => match[1]);
|
||||
const duplicateIds = ids.filter((id, index) => ids.indexOf(id) !== index);
|
||||
@@ -173,7 +200,7 @@ for (const link of externalBlankLinks) {
|
||||
|
||||
report(
|
||||
!/<a\b[^>]*href="[^"]+\.(?:exe|dmg|zip|AppImage|deb)(?:[?#][^"]*)?"/i.test(html),
|
||||
"具体安装资产链接应由 Release 页面统一提供",
|
||||
"具体安装资产链接应由 OSS 发布索引动态提供",
|
||||
);
|
||||
report(
|
||||
!/(?:react|vue|angular|bootstrap|tailwind)(?:\.min)?\.(?:js|css)/i.test(html),
|
||||
|
||||
+96
-8
@@ -1258,6 +1258,39 @@ p {
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.download-options {
|
||||
display: grid;
|
||||
grid-column: 1 / -1;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
gap: var(--space-3);
|
||||
}
|
||||
|
||||
.download-options label {
|
||||
display: grid;
|
||||
gap: var(--space-2);
|
||||
color: var(--text-muted);
|
||||
font-size: var(--font-caption);
|
||||
font-weight: 680;
|
||||
}
|
||||
|
||||
.download-options select {
|
||||
width: 100%;
|
||||
min-height: 40px;
|
||||
padding: 0 var(--space-3);
|
||||
border: 1px solid var(--border-control);
|
||||
border-radius: var(--radius-control);
|
||||
background: var(--surface-subtle);
|
||||
color: var(--text-primary);
|
||||
font: inherit;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
|
||||
.download-options select:focus-visible {
|
||||
border-color: var(--accent);
|
||||
outline: 2px solid color-mix(in srgb, var(--accent) 28%, transparent);
|
||||
outline-offset: 2px;
|
||||
}
|
||||
|
||||
.platform-icon {
|
||||
display: grid;
|
||||
width: 48px;
|
||||
@@ -1278,14 +1311,66 @@ p {
|
||||
stroke-width: 1.3;
|
||||
}
|
||||
|
||||
.download-card:nth-child(3) .platform-icon svg {
|
||||
fill: none;
|
||||
.platform-icon img {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .platform-icon img {
|
||||
filter: invert(1);
|
||||
}
|
||||
|
||||
.button--download {
|
||||
grid-column: 1 / -1;
|
||||
width: 100%;
|
||||
width: fit-content;
|
||||
min-height: 40px;
|
||||
justify-content: flex-start;
|
||||
justify-self: start;
|
||||
padding: var(--space-2) 0;
|
||||
margin-top: var(--space-2);
|
||||
border: 0;
|
||||
background: transparent;
|
||||
color: var(--accent);
|
||||
overflow-wrap: anywhere;
|
||||
text-align: left;
|
||||
text-decoration: underline;
|
||||
text-decoration-color: transparent;
|
||||
text-underline-offset: 4px;
|
||||
}
|
||||
|
||||
.button--download:not(.is-disabled):hover {
|
||||
color: var(--accent-hover);
|
||||
text-decoration-color: currentColor;
|
||||
transform: translateX(2px);
|
||||
}
|
||||
|
||||
.download-meta {
|
||||
grid-column: 1 / -1;
|
||||
min-height: 18px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.download-release-status {
|
||||
padding: var(--space-3) var(--space-4);
|
||||
margin-top: var(--space-4);
|
||||
border: 1px solid var(--border-default);
|
||||
border-radius: var(--radius-control);
|
||||
background: var(--surface-subtle);
|
||||
color: var(--text-secondary);
|
||||
font-size: 0.75rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.download-release-status.is-ready {
|
||||
border-color: color-mix(in srgb, var(--success) 34%, var(--border-default));
|
||||
background: var(--success-subtle);
|
||||
color: var(--success);
|
||||
}
|
||||
|
||||
.download-release-status.is-fallback {
|
||||
border-color: color-mix(in srgb, var(--warning) 34%, var(--border-default));
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.domestic-support {
|
||||
@@ -1601,7 +1686,7 @@ p {
|
||||
}
|
||||
|
||||
.download-card {
|
||||
grid-template-columns: auto 1fr auto;
|
||||
grid-template-columns: auto 1fr;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
@@ -1610,9 +1695,8 @@ p {
|
||||
}
|
||||
|
||||
.button--download {
|
||||
grid-column: auto;
|
||||
width: auto;
|
||||
margin-top: 0;
|
||||
grid-column: 1 / -1;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.assistant-grid {
|
||||
@@ -1802,9 +1886,13 @@ p {
|
||||
grid-template-columns: auto 1fr;
|
||||
}
|
||||
|
||||
.download-options {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.button--download {
|
||||
grid-column: 1 / -1;
|
||||
width: 100%;
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.domestic-support {
|
||||
|
||||
Reference in New Issue
Block a user