Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 36c9b58a8b | |||
| 6d3036fc9c | |||
| d93806d223 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,6 +4,7 @@
|
|||||||
.vscode/
|
.vscode/
|
||||||
docs/
|
docs/
|
||||||
.codex
|
.codex
|
||||||
|
build/
|
||||||
|
|
||||||
# --- Backend (Go) ---
|
# --- Backend (Go) ---
|
||||||
backend/hightube.db
|
backend/hightube.db
|
||||||
|
|||||||
114
scripts/package_linux_appimage.sh
Executable file
114
scripts/package_linux_appimage.sh
Executable file
@@ -0,0 +1,114 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
|
||||||
|
FRONTEND_DIR="${REPO_ROOT}/frontend"
|
||||||
|
DEFAULT_BUNDLE_DIR="${FRONTEND_DIR}/build/linux/x64/release/bundle"
|
||||||
|
|
||||||
|
APP_NAME="hightube"
|
||||||
|
APP_DISPLAY_NAME="Hightube"
|
||||||
|
BUNDLE_DIR="${BUNDLE_DIR:-${DEFAULT_BUNDLE_DIR}}"
|
||||||
|
APPDIR="${APPDIR:-${REPO_ROOT}/build/appimage/${APP_NAME}.AppDir}"
|
||||||
|
OUTPUT="${OUTPUT:-${REPO_ROOT}/hightube-linux_amd64.AppImage}"
|
||||||
|
ICON_SOURCE="${ICON_SOURCE:-${FRONTEND_DIR}/assets/icon/app_icon.png}"
|
||||||
|
APPIMAGETOOL="${APPIMAGETOOL:-appimagetool}"
|
||||||
|
RUN_FLUTTER_BUILD=0
|
||||||
|
|
||||||
|
usage() {
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $(basename "$0") [--build]
|
||||||
|
|
||||||
|
Package the Flutter Linux release bundle into:
|
||||||
|
${OUTPUT}
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--build Run "flutter build linux --release" before packaging.
|
||||||
|
|
||||||
|
Environment overrides:
|
||||||
|
BUNDLE_DIR Flutter Linux release bundle directory.
|
||||||
|
OUTPUT Output AppImage path.
|
||||||
|
APPDIR Temporary AppDir path.
|
||||||
|
ICON_SOURCE PNG icon path.
|
||||||
|
APPIMAGETOOL appimagetool executable path.
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--build)
|
||||||
|
RUN_FLUTTER_BUILD=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
usage
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown argument: $1" >&2
|
||||||
|
usage >&2
|
||||||
|
exit 2
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ "${RUN_FLUTTER_BUILD}" -eq 1 ]]; then
|
||||||
|
(cd "${FRONTEND_DIR}" && flutter build linux --release)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -x "${BUNDLE_DIR}/${APP_NAME}" ]]; then
|
||||||
|
echo "Linux release bundle not found at: ${BUNDLE_DIR}" >&2
|
||||||
|
echo "Run: cd frontend && flutter build linux --release" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -f "${ICON_SOURCE}" ]]; then
|
||||||
|
echo "Icon file not found at: ${ICON_SOURCE}" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v "${APPIMAGETOOL}" >/dev/null 2>&1; then
|
||||||
|
echo "appimagetool not found." >&2
|
||||||
|
echo "Install appimagetool or set APPIMAGETOOL=/path/to/appimagetool" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf "${APPDIR}"
|
||||||
|
mkdir -p \
|
||||||
|
"${APPDIR}/usr/bin" \
|
||||||
|
"${APPDIR}/usr/share/applications" \
|
||||||
|
"${APPDIR}/usr/share/icons/hicolor/512x512/apps"
|
||||||
|
|
||||||
|
cp -a "${BUNDLE_DIR}/." "${APPDIR}/usr/bin/"
|
||||||
|
cp "${ICON_SOURCE}" "${APPDIR}/${APP_NAME}.png"
|
||||||
|
cp "${ICON_SOURCE}" "${APPDIR}/usr/share/icons/hicolor/512x512/apps/${APP_NAME}.png"
|
||||||
|
|
||||||
|
cat > "${APPDIR}/${APP_NAME}.desktop" <<EOF
|
||||||
|
[Desktop Entry]
|
||||||
|
Type=Application
|
||||||
|
Name=${APP_DISPLAY_NAME}
|
||||||
|
Comment=Open source live streaming platform
|
||||||
|
Exec=${APP_NAME}
|
||||||
|
Icon=${APP_NAME}
|
||||||
|
Terminal=false
|
||||||
|
Categories=AudioVideo;Player;
|
||||||
|
EOF
|
||||||
|
|
||||||
|
cp "${APPDIR}/${APP_NAME}.desktop" "${APPDIR}/usr/share/applications/${APP_NAME}.desktop"
|
||||||
|
|
||||||
|
cat > "${APPDIR}/AppRun" <<'EOF'
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
HERE="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
|
cd "${HERE}/usr/bin"
|
||||||
|
exec "./hightube" "$@"
|
||||||
|
EOF
|
||||||
|
|
||||||
|
chmod +x "${APPDIR}/AppRun" "${APPDIR}/usr/bin/${APP_NAME}"
|
||||||
|
rm -f "${OUTPUT}"
|
||||||
|
|
||||||
|
APPIMAGE_EXTRACT_AND_RUN=1 ARCH=x86_64 "${APPIMAGETOOL}" "${APPDIR}" "${OUTPUT}"
|
||||||
|
chmod +x "${OUTPUT}"
|
||||||
|
|
||||||
|
echo "Created AppImage: ${OUTPUT}"
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 8.9 KiB |
File diff suppressed because one or more lines are too long
@@ -1,804 +0,0 @@
|
|||||||
:root {
|
|
||||||
color-scheme: light dark;
|
|
||||||
--primary: #0b57d0;
|
|
||||||
--on-primary: #ffffff;
|
|
||||||
--primary-container: #d7e3ff;
|
|
||||||
--on-primary-container: #001b3f;
|
|
||||||
--secondary: #565f71;
|
|
||||||
--tertiary: #705575;
|
|
||||||
--surface: #fbfcff;
|
|
||||||
--surface-rgb: 251 252 255;
|
|
||||||
--surface-container: #eef3fb;
|
|
||||||
--surface-container-high: #e5ebf5;
|
|
||||||
--outline: #727782;
|
|
||||||
--outline-rgb: 114 119 130;
|
|
||||||
--text: #191c20;
|
|
||||||
--muted: #42474f;
|
|
||||||
--success: #146c2e;
|
|
||||||
--warning: #7a5900;
|
|
||||||
--shadow: 0 24px 60px rgba(11, 87, 208, 0.16);
|
|
||||||
--topbar-bg: rgba(251, 252, 255, 0.68);
|
|
||||||
--topbar-border: rgba(114, 119, 130, 0.18);
|
|
||||||
--topbar-shadow: 0 12px 36px rgba(11, 87, 208, 0.08);
|
|
||||||
--grid-divider: rgba(114, 119, 130, 0.24);
|
|
||||||
--card-border: rgba(114, 119, 130, 0.24);
|
|
||||||
--device-border: rgba(114, 119, 130, 0.32);
|
|
||||||
--status-available-bg: rgba(20, 108, 46, 0.12);
|
|
||||||
--status-planned-bg: rgba(122, 89, 0, 0.12);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Dark theme: forced ---- */
|
|
||||||
[data-theme="dark"] {
|
|
||||||
--primary: #a8c7ff;
|
|
||||||
--on-primary: #001b3f;
|
|
||||||
--primary-container: #003a7a;
|
|
||||||
--on-primary-container: #d7e3ff;
|
|
||||||
--secondary: #bcc7db;
|
|
||||||
--tertiary: #d7bde0;
|
|
||||||
--surface: #111318;
|
|
||||||
--surface-rgb: 17 19 24;
|
|
||||||
--surface-container: #1a1d25;
|
|
||||||
--surface-container-high: #21242d;
|
|
||||||
--outline: #8b909c;
|
|
||||||
--outline-rgb: 139 144 156;
|
|
||||||
--text: #e3e3e8;
|
|
||||||
--muted: #b0b3bd;
|
|
||||||
--success: #81c784;
|
|
||||||
--warning: #ffe08a;
|
|
||||||
--shadow: 0 24px 60px rgba(0, 0, 0, 0.4);
|
|
||||||
--topbar-bg: rgba(17, 19, 24, 0.72);
|
|
||||||
--topbar-border: rgba(139, 144, 156, 0.18);
|
|
||||||
--topbar-shadow: 0 12px 36px rgba(0, 0, 0, 0.28);
|
|
||||||
--grid-divider: rgba(139, 144, 156, 0.2);
|
|
||||||
--card-border: rgba(139, 144, 156, 0.2);
|
|
||||||
--device-border: rgba(139, 144, 156, 0.28);
|
|
||||||
--status-available-bg: rgba(129, 199, 132, 0.15);
|
|
||||||
--status-planned-bg: rgba(255, 224, 138, 0.15);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---- Dark theme: auto (system preference, no manual override) ---- */
|
|
||||||
@media (prefers-color-scheme: dark) {
|
|
||||||
:root:not([data-theme="light"]) {
|
|
||||||
--primary: #a8c7ff;
|
|
||||||
--on-primary: #001b3f;
|
|
||||||
--primary-container: #003a7a;
|
|
||||||
--on-primary-container: #d7e3ff;
|
|
||||||
--secondary: #bcc7db;
|
|
||||||
--tertiary: #d7bde0;
|
|
||||||
--surface: #111318;
|
|
||||||
--surface-rgb: 17 19 24;
|
|
||||||
--surface-container: #1a1d25;
|
|
||||||
--surface-container-high: #21242d;
|
|
||||||
--outline: #8b909c;
|
|
||||||
--outline-rgb: 139 144 156;
|
|
||||||
--text: #e3e3e8;
|
|
||||||
--muted: #b0b3bd;
|
|
||||||
--success: #81c784;
|
|
||||||
--warning: #ffe08a;
|
|
||||||
--shadow: 0 24px 60px rgba(0, 0, 0, 0.4);
|
|
||||||
--topbar-bg: rgba(17, 19, 24, 0.72);
|
|
||||||
--topbar-border: rgba(139, 144, 156, 0.18);
|
|
||||||
--topbar-shadow: 0 12px 36px rgba(0, 0, 0, 0.28);
|
|
||||||
--grid-divider: rgba(139, 144, 156, 0.2);
|
|
||||||
--card-border: rgba(139, 144, 156, 0.2);
|
|
||||||
--device-border: rgba(139, 144, 156, 0.28);
|
|
||||||
--status-available-bg: rgba(129, 199, 132, 0.15);
|
|
||||||
--status-planned-bg: rgba(255, 224, 138, 0.15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
html {
|
|
||||||
scroll-behavior: smooth;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
min-width: 320px;
|
|
||||||
background: var(--surface);
|
|
||||||
color: var(--text);
|
|
||||||
font-family:
|
|
||||||
Inter, Roboto, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
|
|
||||||
sans-serif;
|
|
||||||
line-height: 1.6;
|
|
||||||
transition: background-color 300ms ease, color 300ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
a {
|
|
||||||
color: inherit;
|
|
||||||
}
|
|
||||||
|
|
||||||
.topbar {
|
|
||||||
position: sticky;
|
|
||||||
top: 0;
|
|
||||||
z-index: 10;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 24px;
|
|
||||||
padding: 14px clamp(20px, 5vw, 72px);
|
|
||||||
background: var(--topbar-bg);
|
|
||||||
border-bottom: 1px solid var(--topbar-border);
|
|
||||||
box-shadow: var(--topbar-shadow);
|
|
||||||
-webkit-backdrop-filter: blur(22px) saturate(160%);
|
|
||||||
backdrop-filter: blur(22px) saturate(160%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 10px;
|
|
||||||
color: var(--text);
|
|
||||||
font-weight: 800;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.brand img {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
border-radius: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav a {
|
|
||||||
min-height: 40px;
|
|
||||||
padding: 8px 14px;
|
|
||||||
border-radius: 20px;
|
|
||||||
color: var(--muted);
|
|
||||||
font-size: 0.94rem;
|
|
||||||
font-weight: 650;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav a:hover {
|
|
||||||
background: var(--surface-container);
|
|
||||||
color: var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 立即尝试 CTA button in nav */
|
|
||||||
.nav-cta {
|
|
||||||
background: var(--primary) !important;
|
|
||||||
color: var(--on-primary) !important;
|
|
||||||
margin-left: 8px;
|
|
||||||
font-weight: 800 !important;
|
|
||||||
box-shadow: 0 4px 14px rgba(0, 0, 0, 0.2);
|
|
||||||
transition: transform 160ms ease, box-shadow 160ms ease, background 160ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-cta:hover {
|
|
||||||
filter: brightness(0.88);
|
|
||||||
transform: translateY(-1px);
|
|
||||||
box-shadow: 0 8px 20px rgba(0, 0, 0, 0.26);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hamburger menu button — hidden on desktop */
|
|
||||||
.hamburger {
|
|
||||||
display: none;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 5px;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
padding: 8px;
|
|
||||||
border: none;
|
|
||||||
border-radius: 10px;
|
|
||||||
background: transparent;
|
|
||||||
cursor: pointer;
|
|
||||||
z-index: 20;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger span {
|
|
||||||
display: block;
|
|
||||||
width: 100%;
|
|
||||||
height: 2.5px;
|
|
||||||
border-radius: 2px;
|
|
||||||
background: var(--text);
|
|
||||||
transition: transform 200ms ease, opacity 200ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger[aria-expanded="true"] span:nth-child(1) {
|
|
||||||
transform: translateY(7.5px) rotate(45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger[aria-expanded="true"] span:nth-child(2) {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger[aria-expanded="true"] span:nth-child(3) {
|
|
||||||
transform: translateY(-7.5px) rotate(-45deg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Right-side controls group (theme + hamburger) */
|
|
||||||
.topbar-actions {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 4px;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Theme toggle button */
|
|
||||||
.theme-toggle {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
padding: 0;
|
|
||||||
border: none;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: transparent;
|
|
||||||
color: var(--text);
|
|
||||||
font-size: 1.25rem;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background 200ms ease, transform 200ms ease;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle:hover {
|
|
||||||
background: var(--surface-container);
|
|
||||||
transform: scale(1.08);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle:active {
|
|
||||||
transform: scale(0.94);
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle svg {
|
|
||||||
width: 22px;
|
|
||||||
height: 22px;
|
|
||||||
fill: none;
|
|
||||||
stroke: currentColor;
|
|
||||||
stroke-width: 2;
|
|
||||||
stroke-linecap: round;
|
|
||||||
stroke-linejoin: round;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* hide all icons by default, show based on data-state */
|
|
||||||
.theme-toggle .icon-sun,
|
|
||||||
.theme-toggle .icon-moon,
|
|
||||||
.theme-toggle .icon-auto {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle[data-state="light"] .icon-sun {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle[data-state="dark"] .icon-moon {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.theme-toggle[data-state="auto"] .icon-auto {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: minmax(0, 1.05fr) minmax(320px, 0.95fr);
|
|
||||||
gap: clamp(28px, 6vw, 84px);
|
|
||||||
align-items: center;
|
|
||||||
min-height: calc(100vh - 68px);
|
|
||||||
padding: clamp(48px, 7vw, 96px) clamp(20px, 5vw, 72px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-copy {
|
|
||||||
max-width: 680px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.eyebrow {
|
|
||||||
margin: 0 0 12px;
|
|
||||||
color: var(--primary);
|
|
||||||
font-size: 0.85rem;
|
|
||||||
font-weight: 800;
|
|
||||||
letter-spacing: 0.08em;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1,
|
|
||||||
h2,
|
|
||||||
h3,
|
|
||||||
p {
|
|
||||||
overflow-wrap: anywhere;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
margin: 0;
|
|
||||||
color: var(--text);
|
|
||||||
font-size: clamp(3.5rem, 11vw, 8rem);
|
|
||||||
line-height: 0.9;
|
|
||||||
letter-spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
margin: 0;
|
|
||||||
font-size: clamp(2rem, 4vw, 3.5rem);
|
|
||||||
line-height: 1.05;
|
|
||||||
letter-spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
h3 {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 1.2rem;
|
|
||||||
line-height: 1.2;
|
|
||||||
letter-spacing: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.lead {
|
|
||||||
max-width: 620px;
|
|
||||||
margin: 28px 0 0;
|
|
||||||
color: var(--muted);
|
|
||||||
font-size: clamp(1.1rem, 2vw, 1.35rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: 12px;
|
|
||||||
margin-top: 34px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button,
|
|
||||||
.download-link {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
min-height: 48px;
|
|
||||||
padding: 12px 22px;
|
|
||||||
border-radius: 24px;
|
|
||||||
font-weight: 800;
|
|
||||||
text-decoration: none;
|
|
||||||
transition:
|
|
||||||
transform 160ms ease,
|
|
||||||
box-shadow 160ms ease,
|
|
||||||
background 160ms ease;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button:hover,
|
|
||||||
.download-link:hover {
|
|
||||||
transform: translateY(-1px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.primary {
|
|
||||||
background: var(--primary);
|
|
||||||
color: var(--on-primary);
|
|
||||||
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.18);
|
|
||||||
}
|
|
||||||
|
|
||||||
.secondary {
|
|
||||||
background: var(--primary-container);
|
|
||||||
color: var(--on-primary-container);
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-panel {
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-window {
|
|
||||||
width: min(100%, 560px);
|
|
||||||
overflow: hidden;
|
|
||||||
border: 1px solid var(--device-border);
|
|
||||||
border-radius: 28px;
|
|
||||||
background: var(--surface-container);
|
|
||||||
box-shadow: var(--shadow);
|
|
||||||
}
|
|
||||||
|
|
||||||
.window-bar {
|
|
||||||
display: flex;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 16px 18px;
|
|
||||||
border-bottom: 1px solid var(--card-border);
|
|
||||||
}
|
|
||||||
|
|
||||||
.window-bar span {
|
|
||||||
width: 12px;
|
|
||||||
height: 12px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: var(--outline);
|
|
||||||
}
|
|
||||||
|
|
||||||
.window-bar span:first-child {
|
|
||||||
background: #ba1a1a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.window-bar span:nth-child(2) {
|
|
||||||
background: #a46700;
|
|
||||||
}
|
|
||||||
|
|
||||||
.window-bar span:nth-child(3) {
|
|
||||||
background: #146c2e;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stream-preview {
|
|
||||||
position: relative;
|
|
||||||
display: grid;
|
|
||||||
min-height: 280px;
|
|
||||||
place-items: center;
|
|
||||||
background:
|
|
||||||
linear-gradient(135deg, rgba(11, 87, 208, 0.94), rgba(112, 85, 117, 0.9)),
|
|
||||||
radial-gradient(circle at 30% 30%, #d7e3ff, transparent 32%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.live-badge {
|
|
||||||
position: absolute;
|
|
||||||
top: 18px;
|
|
||||||
left: 18px;
|
|
||||||
padding: 6px 12px;
|
|
||||||
border-radius: 16px;
|
|
||||||
background: #ba1a1a;
|
|
||||||
color: #ffffff;
|
|
||||||
font-size: 0.8rem;
|
|
||||||
font-weight: 900;
|
|
||||||
}
|
|
||||||
|
|
||||||
.play-symbol {
|
|
||||||
width: 86px;
|
|
||||||
height: 86px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: rgba(255, 255, 255, 0.88);
|
|
||||||
clip-path: polygon(28% 18%, 28% 82%, 82% 50%);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(4, 1fr);
|
|
||||||
gap: 1px;
|
|
||||||
background: var(--grid-divider);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-grid div {
|
|
||||||
min-width: 0;
|
|
||||||
padding: 18px 14px;
|
|
||||||
background: var(--surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-grid strong,
|
|
||||||
.stats-grid span {
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-grid strong {
|
|
||||||
color: var(--primary);
|
|
||||||
font-size: 1.02rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-grid span {
|
|
||||||
color: var(--muted);
|
|
||||||
font-size: 0.88rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section {
|
|
||||||
padding: clamp(64px, 8vw, 112px) clamp(20px, 5vw, 72px);
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-heading {
|
|
||||||
max-width: 820px;
|
|
||||||
margin-bottom: 32px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.section-heading p:not(.eyebrow) {
|
|
||||||
max-width: 760px;
|
|
||||||
color: var(--muted);
|
|
||||||
font-size: 1.06rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.architecture-grid,
|
|
||||||
.download-grid {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
||||||
gap: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.architecture-card,
|
|
||||||
.download-card {
|
|
||||||
min-width: 0;
|
|
||||||
padding: 24px;
|
|
||||||
border: 1px solid var(--card-border);
|
|
||||||
border-radius: 24px;
|
|
||||||
background: var(--surface-container);
|
|
||||||
}
|
|
||||||
|
|
||||||
.architecture-card .icon {
|
|
||||||
display: grid;
|
|
||||||
width: 48px;
|
|
||||||
height: 48px;
|
|
||||||
margin-bottom: 20px;
|
|
||||||
place-items: center;
|
|
||||||
border-radius: 16px;
|
|
||||||
background: var(--primary);
|
|
||||||
color: var(--on-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.architecture-card .icon svg {
|
|
||||||
width: 26px;
|
|
||||||
height: 26px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.architecture-card p,
|
|
||||||
.download-card p,
|
|
||||||
.feature-item p,
|
|
||||||
.source-section p {
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-band {
|
|
||||||
background: var(--surface-container);
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-list {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
||||||
gap: 1px;
|
|
||||||
overflow: hidden;
|
|
||||||
border: 1px solid var(--card-border);
|
|
||||||
border-radius: 28px;
|
|
||||||
background: var(--grid-divider);
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-item {
|
|
||||||
min-width: 0;
|
|
||||||
padding: 28px;
|
|
||||||
background: var(--surface);
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-icon {
|
|
||||||
width: 36px;
|
|
||||||
height: 36px;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
color: var(--primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-icon svg {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.download-grid {
|
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
||||||
}
|
|
||||||
|
|
||||||
.download-card {
|
|
||||||
display: flex;
|
|
||||||
min-height: 240px;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.download-icon {
|
|
||||||
width: 32px;
|
|
||||||
height: 32px;
|
|
||||||
margin-bottom: 14px;
|
|
||||||
color: var(--muted);
|
|
||||||
}
|
|
||||||
|
|
||||||
.download-icon svg {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status {
|
|
||||||
margin-bottom: 18px;
|
|
||||||
padding: 5px 10px;
|
|
||||||
border-radius: 14px;
|
|
||||||
background: var(--status-available-bg);
|
|
||||||
color: var(--success);
|
|
||||||
font-size: 0.78rem;
|
|
||||||
font-weight: 850;
|
|
||||||
}
|
|
||||||
|
|
||||||
.status.muted {
|
|
||||||
background: var(--status-planned-bg);
|
|
||||||
color: var(--warning);
|
|
||||||
}
|
|
||||||
|
|
||||||
.download-link {
|
|
||||||
margin-top: auto;
|
|
||||||
background: var(--primary);
|
|
||||||
color: var(--on-primary);
|
|
||||||
}
|
|
||||||
|
|
||||||
.planned {
|
|
||||||
background: var(--surface-container-high);
|
|
||||||
}
|
|
||||||
|
|
||||||
.source-section {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
gap: 24px;
|
|
||||||
background: #001b3f;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.source-section .eyebrow,
|
|
||||||
.source-section p {
|
|
||||||
color: #d7e3ff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.source-section div {
|
|
||||||
max-width: 820px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
display: grid;
|
|
||||||
grid-template-columns: 1fr auto 1fr;
|
|
||||||
align-items: center;
|
|
||||||
gap: 16px;
|
|
||||||
padding: 28px clamp(20px, 5vw, 72px);
|
|
||||||
background: #001533;
|
|
||||||
color: #d7e3ff;
|
|
||||||
font-size: 0.92rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer span:nth-child(2) {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer span:last-child {
|
|
||||||
text-align: right;
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 900px) {
|
|
||||||
.topbar {
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hamburger {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav {
|
|
||||||
display: none;
|
|
||||||
width: 100%;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 2px;
|
|
||||||
padding: 8px 0 4px;
|
|
||||||
border-top: 1px solid var(--topbar-border);
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav.open {
|
|
||||||
display: flex;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav a {
|
|
||||||
width: 100%;
|
|
||||||
padding: 12px 16px;
|
|
||||||
border-radius: 14px;
|
|
||||||
font-size: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-cta {
|
|
||||||
margin-left: 0 !important;
|
|
||||||
margin-top: 6px;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
min-height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.architecture-grid,
|
|
||||||
.download-grid {
|
|
||||||
grid-template-columns: 1fr 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stats-grid {
|
|
||||||
grid-template-columns: repeat(2, 1fr);
|
|
||||||
}
|
|
||||||
|
|
||||||
.source-section {
|
|
||||||
align-items: flex-start;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-width: 640px) {
|
|
||||||
.topbar {
|
|
||||||
padding: 10px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero,
|
|
||||||
.section {
|
|
||||||
padding-right: 16px;
|
|
||||||
padding-left: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero {
|
|
||||||
padding-top: 32px;
|
|
||||||
padding-bottom: 32px;
|
|
||||||
gap: 24px;
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: clamp(2.8rem, 10vw, 4rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
h2 {
|
|
||||||
font-size: clamp(1.6rem, 5vw, 2.4rem);
|
|
||||||
}
|
|
||||||
|
|
||||||
.lead {
|
|
||||||
font-size: 1rem;
|
|
||||||
margin-top: 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hero-panel {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.device-window {
|
|
||||||
width: 100%;
|
|
||||||
border-radius: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.stream-preview {
|
|
||||||
min-height: 180px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.play-symbol {
|
|
||||||
width: 60px;
|
|
||||||
height: 60px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.architecture-grid,
|
|
||||||
.download-grid,
|
|
||||||
.feature-list {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
}
|
|
||||||
|
|
||||||
.architecture-card,
|
|
||||||
.download-card {
|
|
||||||
padding: 20px;
|
|
||||||
border-radius: 18px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.feature-item {
|
|
||||||
padding: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.actions {
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button,
|
|
||||||
.download-link {
|
|
||||||
width: 100%;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav a {
|
|
||||||
min-height: 48px;
|
|
||||||
padding: 14px 16px;
|
|
||||||
font-size: 1.05rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.nav-cta {
|
|
||||||
min-height: 50px;
|
|
||||||
font-size: 1.05rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer {
|
|
||||||
grid-template-columns: 1fr;
|
|
||||||
gap: 8px;
|
|
||||||
padding: 24px 16px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.footer-hide-mobile {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -515,7 +515,11 @@ h3 {
|
|||||||
border-radius: 16px;
|
border-radius: 16px;
|
||||||
background: var(--primary);
|
background: var(--primary);
|
||||||
color: var(--on-primary);
|
color: var(--on-primary);
|
||||||
font-weight: 900;
|
}
|
||||||
|
|
||||||
|
.architecture-card .icon svg {
|
||||||
|
width: 26px;
|
||||||
|
height: 26px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.architecture-card p,
|
.architecture-card p,
|
||||||
@@ -545,6 +549,19 @@ h3 {
|
|||||||
background: var(--surface);
|
background: var(--surface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.feature-icon {
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-icon svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.download-grid {
|
.download-grid {
|
||||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||||
}
|
}
|
||||||
@@ -556,6 +573,19 @@ h3 {
|
|||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.download-icon {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
color: var(--muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.download-icon svg {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.status {
|
.status {
|
||||||
margin-bottom: 18px;
|
margin-bottom: 18px;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
|
|||||||
Reference in New Issue
Block a user