������� �� Avalonia 2.0 (�����-���������, ����������, �������� ��������) #1

Merged
Exest merged 18 commits from feature/avalonia-ui into master 2026-08-11 09:41:09 +03:00
10 changed files with 292 additions and 10 deletions
Showing only changes of commit 028c588d2a - Show all commits

5
.gitignore vendored
View File

@ -25,3 +25,8 @@ packages/
installer/output/
dist/
# Кросс-платформенные публикации и артефакты сборки
publish/
build/
installer/output/

View File

@ -3,7 +3,7 @@
#define MyAppName "Электронная Фармация"
#define MyAppBrand "ЭльФиСА"
#define MyAppVersion "1.0.20"
#define MyAppVersion "2.0.0"
#define MyAppPublisher "PharmData"
#define MyAppURL "https://cdn.24pharmdata.ru"
#define MyAppSupportURL "https://24pharmdata.ru"
@ -89,12 +89,10 @@ russian.BrandLine=ЭльФиСА — удобный заказ лекарств
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
; Основной выпуск Release (без отладочных PDB и XML-документации)
Source: "..\src\ElectronicPharmacy\bin\Release\*.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\ElectronicPharmacy\bin\Release\*.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\ElectronicPharmacy\bin\Release\*.config"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\src\ElectronicPharmacy\bin\Release\x86\*"; DestDir: "{app}\x86"; Flags: ignoreversion recursesubdirs createallsubdirs skipifsourcedoesntexist
Source: "..\src\ElectronicPharmacy\bin\Release\x64\*"; DestDir: "{app}\x64"; Flags: ignoreversion recursesubdirs createallsubdirs skipifsourcedoesntexist
; Avalonia self-contained выпуск (весь рантайм .NET внутри — без зависимостей у клиента).
; Сборка кладётся в ..\publish\win-x64 скриптом build-installer.ps1, exe уже переименован
; в «Электронная Фармация.exe» (совместимо с авто-обновлением старых клиентов).
Source: "..\publish\win-x64\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "assets\elfisa.ico"; DestDir: "{app}"; DestName: "elfisa.ico"; Flags: ignoreversion
[Icons]

Binary file not shown.

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 201 KiB

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 9.6 KiB

View File

@ -15,12 +15,23 @@ if (-not $iscc) {
throw "Inno Setup 6 (ISCC.exe) не найден. Установите: winget install JRSoftware.InnoSetup"
}
$pub = "publish\win-x64"
if (-not $SkipBuild) {
Write-Host "Сборка Release..." -ForegroundColor Cyan
dotnet build "src\ElectronicPharmacy\ElectronicPharmacy.csproj" -c Release
if ($LASTEXITCODE -ne 0) { throw "Сборка приложения завершилась с ошибкой" }
Write-Host "Публикация Avalonia (win-x64, self-contained)..." -ForegroundColor Cyan
if (Test-Path $pub) { Remove-Item $pub -Recurse -Force }
dotnet publish "src\Elfisa.Avalonia\Elfisa.Avalonia.csproj" -c Release -r win-x64 `
--self-contained true -p:PublishSingleFile=false -p:DebugType=none -o $pub
if ($LASTEXITCODE -ne 0) { throw "Публикация приложения завершилась с ошибкой" }
}
# Имя exe, совместимое с авто-обновлением старых WinForms-клиентов
# (батч-апдейтер перезапускает файл по имени «Электронная Фармация.exe»).
# apphost находит свой .dll независимо от имени exe, поэтому переименование безопасно.
$srcExe = Join-Path $pub "Elfisa.Avalonia.exe"
$dstExe = Join-Path $pub "Электронная Фармация.exe"
if (Test-Path $srcExe) { Move-Item $srcExe $dstExe -Force }
elseif (-not (Test-Path $dstExe)) { throw "Не найден собранный exe в $pub" }
Write-Host "Сборка установщика..." -ForegroundColor Cyan
& $iscc "installer\ElfisaPharmacy.iss"
if ($LASTEXITCODE -ne 0) { throw "Inno Setup завершился с ошибкой" }

View File

@ -5,6 +5,13 @@
<Nullable>enable</Nullable>
<ApplicationManifest>app.manifest</ApplicationManifest>
<AvaloniaUseCompiledBindingsByDefault>true</AvaloniaUseCompiledBindingsByDefault>
<Version>2.0.0</Version>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<FileVersion>2.0.0.0</FileVersion>
<Product>ЭльФиСА — Электронная Фармация</Product>
<Company>PharmData</Company>
<!-- Кросс-платформенная публикация задаётся флагами CLI (RID + self-contained). -->
<SatelliteResourceLanguages>ru;en</SatelliteResourceLanguages>
</PropertyGroup>
<ItemGroup>

261
web/download/index.html Normal file
View File

@ -0,0 +1,261 @@
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Скачать ЭльФиСА — Электронная Фармация</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='24' fill='%230F766E'/><rect x='42' y='20' width='16' height='60' rx='5' fill='%23fff'/><rect x='20' y='42' width='60' height='16' rx='5' fill='%23fff'/></svg>">
<style>
:root{
--bg:#eef3f2; --bg2:#f7faf9; --panel:#ffffff; --panel-2:#f2f6f5;
--ink:#0c1a17; --ink-soft:#38504a; --muted:#6b827c;
--line:#dbe6e3; --line-soft:#e7efed;
--brand:#0f766e; --brand-2:#14b8a6; --brand-ink:#0b5750; --brand-soft:#d8ebe8;
--shadow:0 1px 2px rgba(12,26,23,.05), 0 12px 34px -12px rgba(12,26,23,.16);
--shadow-lift:0 2px 6px rgba(12,26,23,.08), 0 30px 60px -20px rgba(15,118,110,.32);
--radius:18px;
}
@media (prefers-color-scheme:dark){
:root{
--bg:#0a1512; --bg2:#0c1a16; --panel:#10201c; --panel-2:#152825;
--ink:#eaf4f1; --ink-soft:#b6cbc5; --muted:#7f9791;
--line:#20342f; --line-soft:#1a2c28;
--brand:#2dd4bf; --brand-2:#5eead4; --brand-ink:#99f6e4; --brand-soft:#12312c;
--shadow:0 1px 2px rgba(0,0,0,.4), 0 18px 44px -16px rgba(0,0,0,.6);
--shadow-lift:0 2px 8px rgba(0,0,0,.5), 0 36px 70px -24px rgba(0,0,0,.7);
}
}
:root[data-theme="light"]{
--bg:#eef3f2; --bg2:#f7faf9; --panel:#ffffff; --panel-2:#f2f6f5;
--ink:#0c1a17; --ink-soft:#38504a; --muted:#6b827c;
--line:#dbe6e3; --line-soft:#e7efed;
--brand:#0f766e; --brand-2:#14b8a6; --brand-ink:#0b5750; --brand-soft:#d8ebe8;
--shadow:0 1px 2px rgba(12,26,23,.05), 0 12px 34px -12px rgba(12,26,23,.16);
--shadow-lift:0 2px 6px rgba(12,26,23,.08), 0 30px 60px -20px rgba(15,118,110,.32);
}
:root[data-theme="dark"]{
--bg:#0a1512; --bg2:#0c1a16; --panel:#10201c; --panel-2:#152825;
--ink:#eaf4f1; --ink-soft:#b6cbc5; --muted:#7f9791;
--line:#20342f; --line-soft:#1a2c28;
--brand:#2dd4bf; --brand-2:#5eead4; --brand-ink:#99f6e4; --brand-soft:#12312c;
--shadow:0 1px 2px rgba(0,0,0,.4), 0 18px 44px -16px rgba(0,0,0,.6);
--shadow-lift:0 2px 8px rgba(0,0,0,.5), 0 36px 70px -24px rgba(0,0,0,.7);
}
*{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
margin:0; color:var(--ink); background:var(--bg);
font-family:"Segoe UI Variable Text","Segoe UI",-apple-system,BlinkMacSystemFont,"Inter",system-ui,Roboto,Arial,sans-serif;
line-height:1.55; -webkit-font-smoothing:antialiased; text-rendering:optimizeLegibility;
background-image:
radial-gradient(1100px 600px at 82% -8%, color-mix(in srgb, var(--brand) 20%, transparent), transparent 60%),
radial-gradient(900px 500px at 6% 4%, color-mix(in srgb, var(--brand-2) 12%, transparent), transparent 55%);
background-attachment:fixed;
}
.wrap{max-width:1060px; margin:0 auto; padding:0 22px}
/* ---- header ---- */
header{padding:22px 0 6px}
.bar{display:flex; align-items:center; justify-content:space-between; gap:16px}
.brand{display:flex; align-items:center; gap:12px; text-decoration:none; color:inherit}
.logo{width:40px; height:40px; border-radius:12px; background:linear-gradient(150deg,var(--brand),var(--brand-2));
display:grid; place-items:center; box-shadow:0 6px 18px -6px color-mix(in srgb,var(--brand) 60%, transparent); flex:0 0 auto}
.logo svg{width:22px; height:22px}
.brand b{font-size:17px; font-weight:700; letter-spacing:.2px; display:block; line-height:1.1}
.brand span{font-size:12px; color:var(--muted)}
.top-link{color:var(--ink-soft); text-decoration:none; font-size:13.5px; font-weight:600;
padding:9px 15px; border:1px solid var(--line); border-radius:11px; background:var(--panel); transition:.16s}
.top-link:hover{border-color:var(--brand); color:var(--brand)}
/* ---- hero ---- */
.hero{padding:52px 0 30px; text-align:center; max-width:760px; margin:0 auto}
.eyebrow{display:inline-flex; align-items:center; gap:8px; font-size:12px; font-weight:700;
letter-spacing:.10em; text-transform:uppercase; color:var(--brand-ink);
background:var(--brand-soft); border:1px solid color-mix(in srgb,var(--brand) 28%, transparent);
padding:6px 13px; border-radius:999px}
.dot{width:7px; height:7px; border-radius:50%; background:var(--brand-2); box-shadow:0 0 0 3px color-mix(in srgb,var(--brand-2) 30%, transparent)}
h1{font-size:clamp(32px,5.2vw,52px); line-height:1.05; letter-spacing:-.02em; margin:20px 0 14px; text-wrap:balance; font-weight:800}
h1 .accent{background:linear-gradient(120deg,var(--brand),var(--brand-2)); -webkit-background-clip:text; background-clip:text; color:transparent}
.lead{font-size:clamp(16px,2.1vw,19px); color:var(--ink-soft); margin:0 auto; max-width:56ch}
.cta{margin-top:30px; display:flex; flex-direction:column; align-items:center; gap:12px}
.btn-primary{display:inline-flex; align-items:center; gap:12px; text-decoration:none;
background:linear-gradient(135deg,var(--brand),var(--brand-2)); color:#fff; font-weight:700; font-size:16.5px;
padding:16px 28px; border-radius:14px; box-shadow:var(--shadow-lift); transition:transform .14s, box-shadow .14s; border:0}
.btn-primary:hover{transform:translateY(-2px)}
.btn-primary:active{transform:translateY(0)}
.btn-primary svg{width:22px; height:22px; fill:currentColor}
.cta-meta{font-size:13.5px; color:var(--muted)}
.cta-meta a{color:var(--brand); text-decoration:none; font-weight:600}
.cta-meta a:hover{text-decoration:underline}
/* ---- os cards ---- */
.os{padding:20px 0 8px}
.os-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:16px}
@media (max-width:760px){ .os-grid{grid-template-columns:1fr} }
.card{position:relative; background:var(--panel); border:1px solid var(--line); border-radius:var(--radius);
padding:22px 20px; box-shadow:var(--shadow); display:flex; flex-direction:column; gap:2px; transition:.18s}
.card:hover{transform:translateY(-3px); box-shadow:var(--shadow-lift)}
.card.you{border-color:color-mix(in srgb,var(--brand) 55%, transparent);
box-shadow:0 0 0 1px color-mix(in srgb,var(--brand) 45%, transparent), var(--shadow-lift)}
.youbadge{position:absolute; top:14px; right:14px; font-size:11px; font-weight:700; letter-spacing:.04em;
text-transform:uppercase; color:#fff; background:linear-gradient(135deg,var(--brand),var(--brand-2));
padding:4px 10px; border-radius:999px; display:none}
.card.you .youbadge{display:inline-block}
.os-ico{width:46px; height:46px; border-radius:12px; background:var(--panel-2); border:1px solid var(--line-soft);
display:grid; place-items:center; margin-bottom:14px}
.os-ico svg{width:26px; height:26px; fill:var(--ink)}
.card h3{margin:0; font-size:19px; font-weight:700}
.os-sub{color:var(--muted); font-size:13px; margin:2px 0 0}
.specs{margin:16px 0 18px; display:flex; flex-direction:column; gap:7px; font-size:13.5px}
.spec{display:flex; justify-content:space-between; gap:10px; color:var(--ink-soft)}
.spec b{font-weight:600; color:var(--ink); font-variant-numeric:tabular-nums}
.dl{margin-top:auto; display:inline-flex; align-items:center; justify-content:center; gap:9px; text-decoration:none;
font-weight:650; font-size:14.5px; padding:12px 16px; border-radius:12px; transition:.16s;
background:var(--brand-soft); color:var(--brand-ink); border:1px solid color-mix(in srgb,var(--brand) 26%, transparent)}
.dl:hover{background:var(--brand); color:#fff}
.dl svg{width:17px; height:17px; fill:currentColor}
/* ---- features ---- */
.feats{padding:30px 0 8px; display:grid; grid-template-columns:repeat(3,1fr); gap:14px}
@media (max-width:760px){ .feats{grid-template-columns:1fr} }
.feat{display:flex; gap:12px; align-items:flex-start; padding:16px; border-radius:14px;
background:color-mix(in srgb,var(--panel) 60%, transparent); border:1px solid var(--line-soft)}
.feat .fi{flex:0 0 auto; width:36px; height:36px; border-radius:10px; background:var(--brand-soft);
display:grid; place-items:center; color:var(--brand-ink)}
.feat .fi svg{width:19px; height:19px; fill:currentColor}
.feat h4{margin:2px 0 3px; font-size:14.5px}
.feat p{margin:0; font-size:13px; color:var(--muted); line-height:1.45}
/* ---- footer ---- */
footer{margin-top:34px; border-top:1px solid var(--line); padding:22px 0 40px;
display:flex; flex-wrap:wrap; gap:12px 22px; align-items:center; justify-content:space-between; color:var(--muted); font-size:13px}
footer a{color:var(--ink-soft); text-decoration:none; font-weight:600}
footer a:hover{color:var(--brand)}
.foot-links{display:flex; gap:20px; flex-wrap:wrap}
@media (prefers-reduced-motion:reduce){ *{transition:none!important} .btn-primary:hover,.card:hover{transform:none} }
</style>
</head>
<body>
<div class="wrap">
<header>
<div class="bar">
<a class="brand" href="https://24pharmdata.ru">
<span class="logo"><svg viewBox="0 0 100 100"><rect x="42" y="18" width="16" height="64" rx="5" fill="#fff"/><rect x="18" y="42" width="64" height="16" rx="5" fill="#fff"/></svg></span>
<span><b>ЭльФиСА</b><span>Электронная Фармация</span></span>
</a>
</div>
</header>
<section class="hero">
<h1>Заказ лекарств для аптеки — <span class="accent">на вашем компьютере</span></h1>
<p class="lead">Прайс-листы поставщиков, сборка и отправка заказов, накладные и отчёты. Одно приложение для Windows, macOS и Linux.</p>
<div class="cta">
<a class="btn-primary" id="heroBtn" href="ElfisaPharmacy-Setup.exe" download>
<svg id="heroIco" viewBox="0 0 24 24"><path d="M3 5.5 10.5 4.4v7.1H3zM10.5 12.5v7.1L3 18.5v-6zM11.6 4.2 21 3v8.5h-9.4zM21 12.5V21l-9.4-1.3v-7.2z"/></svg>
<span id="heroLbl">Скачать для Windows</span>
</a>
<div class="cta-meta"><span id="heroMeta">Windows 10/11 · 64-бит · ~90 МБ</span> · <a href="#os">другие системы ↓</a></div>
</div>
</section>
<section class="os" id="os">
<div class="os-grid">
<div class="card" data-os="windows">
<span class="youbadge">Ваша система</span>
<div class="os-ico"><svg viewBox="0 0 24 24"><path d="M3 5.5 10.5 4.4v7.1H3zM10.5 12.5v7.1L3 18.5v-6zM11.6 4.2 21 3v8.5h-9.4zM21 12.5V21l-9.4-1.3v-7.2z"/></svg></div>
<h3>Windows</h3>
<p class="os-sub">Установщик · рекомендуется</p>
<div class="specs">
<div class="spec"><span>Формат</span><b>.exe установщик</b></div>
<div class="spec"><span>Система</span><b>Windows 10 / 11</b></div>
<div class="spec"><span>Разрядность</span><b>64-бит</b></div>
<div class="spec"><span>Размер</span><b>~90 МБ</b></div>
</div>
<a class="dl" href="ElfisaPharmacy-Setup.exe" download>
<svg viewBox="0 0 24 24"><path d="M12 3v10m0 0 4-4m-4 4-4-4M4 17v2a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-2" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
Скачать установщик
</a>
</div>
<div class="card" data-os="mac">
<span class="youbadge">Ваша система</span>
<div class="os-ico"><svg viewBox="0 0 24 24"><path d="M16.4 12.7c0-2.3 1.9-3.4 2-3.5-1.1-1.6-2.8-1.8-3.4-1.8-1.4-.1-2.8.9-3.5.9-.7 0-1.8-.8-3-.8-1.5 0-3 .9-3.8 2.3-1.6 2.8-.4 7 1.2 9.3.8 1.1 1.7 2.4 2.9 2.3 1.2 0 1.6-.7 3-.7s1.8.7 3 .7c1.2 0 2-1.1 2.8-2.2.5-.8.9-1.6 1.2-2.5-.1 0-2.1-.9-2.1-3.2zM14.2 5.9c.6-.8 1-1.8.9-2.9-.9 0-2 .6-2.6 1.4-.6.7-1.1 1.7-.9 2.7 1 .1 2-.5 2.6-1.2z"/></svg></div>
<h3>macOS</h3>
<p class="os-sub">Образ диска · Apple Silicon и Intel</p>
<div class="specs">
<div class="spec"><span>Формат</span><b>.dmg образ</b></div>
<div class="spec"><span>Система</span><b>macOS 12+</b></div>
<div class="spec"><span>Процессор</span><b>Apple / Intel</b></div>
<div class="spec"><span>Размер</span><b>~95 МБ</b></div>
</div>
<a class="dl" href="Elfisa-macOS.dmg" download>
<svg viewBox="0 0 24 24"><path d="M12 3v10m0 0 4-4m-4 4-4-4M4 17v2a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-2" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
Скачать образ .dmg
</a>
</div>
<div class="card" data-os="linux">
<span class="youbadge">Ваша система</span>
<div class="os-ico"><svg viewBox="0 0 24 24"><path d="M12 2c-1.9 0-3 1.7-3 3.6 0 1 .1 1.9-.4 2.8-.5.9-1.6 1.7-2.3 3.2-.6 1.3-.9 2.4-1.6 3.1-.5.5-1 .8-1 1.4 0 .5.4.7 1 .9.8.3 1.3.4 1.6 1 .3.6.3 1.3 1.1 1.6.7.3 1.7 0 2.5-.2.8-.2 1.5-.2 2.3 0 .8.2 1.8.5 2.5.2.8-.3.8-1 1.1-1.6.3-.6.8-.7 1.6-1 .6-.2 1-.4 1-.9 0-.6-.5-.9-1-1.4-.7-.7-1-1.8-1.6-3.1-.7-1.5-1.8-2.3-2.3-3.2-.5-.9-.4-1.8-.4-2.8C15 3.7 13.9 2 12 2zm-1.4 3.9c.3 0 .6.4.6.9s-.3.9-.6.9-.6-.4-.6-.9.3-.9.6-.9zm2.8 0c.3 0 .6.4.6.9s-.3.9-.6.9-.6-.4-.6-.9.3-.9.6-.9zM12 8.4c.9 0 2 .5 2 1 0 .3-.4.4-.8.6-.4.3-.9.7-1.2.7-.3 0-.8-.4-1.2-.7-.4-.2-.8-.3-.8-.6 0-.5 1.1-1 2-1z"/></svg></div>
<h3>Linux</h3>
<p class="os-sub">AppImage · запуск без установки</p>
<div class="specs">
<div class="spec"><span>Формат</span><b>.AppImage</b></div>
<div class="spec"><span>Система</span><b>glibc 2.31+</b></div>
<div class="spec"><span>Разрядность</span><b>x86-64</b></div>
<div class="spec"><span>Размер</span><b>~95 МБ</b></div>
</div>
<a class="dl" href="Elfisa-Linux-x86_64.AppImage" download>
<svg viewBox="0 0 24 24"><path d="M12 3v10m0 0 4-4m-4 4-4-4M4 17v2a1 1 0 0 0 1 1h14a1 1 0 0 0 1-1v-2" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>
Скачать AppImage
</a>
</div>
</div>
<div class="feats">
<div class="feat"><span class="fi"><svg viewBox="0 0 24 24"><path d="M4 6h16M4 12h16M4 18h10" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></span>
<div><h4>Прайс-листы поставщиков</h4><p>Поиск по названию, дозировке и предложениям — заказ собирается в пару кликов.</p></div></div>
<div class="feat"><span class="fi"><svg viewBox="0 0 24 24"><path d="m3 12 4 4L21 4M3 20h12" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg></span>
<div><h4>Заказы и накладные</h4><p>Отправка заказов поставщикам, приём накладных и выгрузка в нужном формате.</p></div></div>
<div class="feat"><span class="fi"><svg viewBox="0 0 24 24"><path d="M4 19V5m4 14V9m4 10V4m4 15v-7m4 7V8" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"/></svg></span>
<div><h4>Отчёты и ИИ</h4><p>Сводки по закупкам и отчёты по вашему запросу на понятном языке.</p></div></div>
</div>
</section>
<footer>
<div>© PharmData · ЭльФиСА</div>
</footer>
</div>
<script>
(function(){
var files = { windows:"ElfisaPharmacy-Setup.exe", mac:"Elfisa-macOS.dmg", linux:"Elfisa-Linux-x86_64.AppImage" };
var labels = { windows:"Скачать для Windows", mac:"Скачать для macOS", linux:"Скачать для Linux" };
var metas = { windows:"Windows 10/11 · 64-бит · ~90 МБ", mac:"macOS 12+ · Apple/Intel · ~95 МБ", linux:"x86-64 · glibc 2.31+ · ~95 МБ" };
function detect(){
var ua = navigator.userAgent || "";
var plat = ((navigator.userAgentData && navigator.userAgentData.platform) || navigator.platform || "").toLowerCase();
if (plat.indexOf("win")>-1 || /Windows/i.test(ua)) return "windows";
if (plat.indexOf("mac")>-1 || (/Mac/i.test(ua) && !/iPhone|iPad/i.test(ua))) return "mac";
if (plat.indexOf("linux")>-1 || /Linux|X11|Ubuntu|Fedora/i.test(ua)) return "linux";
return "windows";
}
var os = detect();
var hero = document.getElementById("heroBtn");
if (hero){ hero.setAttribute("href", files[os]); }
var lbl = document.getElementById("heroLbl"); if(lbl) lbl.textContent = labels[os];
var meta = document.getElementById("heroMeta"); if(meta) meta.textContent = metas[os];
var card = document.querySelector('.card[data-os="'+os+'"]');
if (card){ card.classList.add("you"); }
})();
</script>
</body>
</html>