사이트 다크 옵시디언 리디자인 + 디자인 감사 폴리시 (redesign/design-taste/high-end 스킬 적용) — 병행 세션의 리디자인(옵시디언 서피스 사다리·머신드 더블베젤·플루이드 아일랜드 내비·히어로 스트림 시뮬레이터·모바일 드로어)을 기반으로 감사 교정: 아이브로우 배급(페이지당 7→1, 장식 점 제거), em대시 전소거(타이틀 3종), 히어로 규율(헤드라인 2줄·서브텍스트 20단어 이내·신뢰 마이크로스트립 제거·CTA 라벨 다운로드/사용 안내로 의도별 단일화), 3등분 카드 파이프라인을 단일 베젤 레일(헤어라인 분할+아이콘 배지)로 재구성, 과장 카피 완화(100%·1초·평균1~3초·초고속), 시뮬레이터에 예시 화면 캡션 명시, 모바일 가로 오버플로 수정(그리드 min-width:0 — 긴 mono URL 이 열 최소폭을 밀던 실결함), OG 메타 3종·skip-link·focus-visible 링·브랜드 404 추가 — 데스크톱 1440/모바일 390 스크린샷 검증, scrollWidth==viewport 확인, 재배포 완료

This commit is contained in:
Yun Chan 2026-08-18 07:35:09 +09:00
parent 02995f4153
commit 9c9d9cb024
7 changed files with 2482 additions and 510 deletions

38
site/404.html Normal file
View file

@ -0,0 +1,38 @@
<!doctype html>
<html lang="ko">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>페이지를 찾을 수 없습니다 - MEDIABROWSER</title>
<meta name="robots" content="noindex">
<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='%233b82f6'/><path d='M50 22v36M36 44l14 14 14-14M28 74h44' stroke='white' stroke-width='9' stroke-linecap='round' stroke-linejoin='round' fill='none'/></svg>">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/wanteddev/wanted-sans@v1.0.3/packages/wanted-sans/fonts/webfonts/variable/split/WantedSansVariable.min.css">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="ambient-lighting" aria-hidden="true">
<div class="ambient-spotlight"></div>
<div class="ambient-grid"></div>
</div>
<main class="wrap" style="min-height:100dvh;display:grid;place-items:center;padding:48px 0">
<div class="bezel-shell" style="max-width:520px;width:100%">
<div class="bezel-inner" style="padding:56px 40px;text-align:center">
<div class="text-mono" style="font-size:0.85rem;color:var(--text-muted)">404</div>
<h1 style="font-size:clamp(1.8rem,4vw,2.4rem);margin-top:10px">여기엔 아무것도 없네요</h1>
<p style="margin-top:14px;color:var(--text-secondary)">주소가 바뀌었거나 잘못 입력된 것 같습니다.
찾으시는 건 아마 아래에 있을 거예요.</p>
<div style="display:flex;gap:12px;justify-content:center;flex-wrap:wrap;margin-top:28px">
<a class="btn btn--primary" href="/">
<span>홈으로</span>
<span class="btn__icon-badge"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#arrow-up-right"/></svg></span>
</a>
<a class="btn btn--ghost" href="/releases.html"><span>다운로드</span></a>
</div>
</div>
</div>
</main>
</body>
</html>

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Before After
Before After

View file

@ -4,143 +4,278 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>사용 안내 - MEDIABROWSER</title> <title>사용 안내 - MEDIABROWSER</title>
<meta name="description" content="MEDIABROWSER 설치부터 첫 다운로드, 다운로드 관리, 휴대폰 연결까지의 사용 안내."> <meta name="description" content="MEDIABROWSER 설치부터 첫 스트림 감지, 세그먼트 이어받기, 모바일 컴패니언 QR 연결까지 단계별 안내.">
<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='%232050f0'/><path d='M50 22v36M36 44l14 14 14-14M28 74h44' stroke='white' stroke-width='9' stroke-linecap='round' stroke-linejoin='round' fill='none'/></svg>"> <meta property="og:type" content="website">
<meta property="og:title" content="사용 안내 - MEDIABROWSER">
<meta property="og:description" content="설치, 첫 영상 감지, 다운로드 관리, 휴대폰 QR 연결까지 단계별로 안내합니다.">
<meta property="og:url" content="https://mediabrowser-7r4.pages.dev/guide.html">
<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='%233b82f6'/><path d='M50 22v36M36 44l14 14 14-14M28 74h44' stroke='white' stroke-width='9' stroke-linecap='round' stroke-linejoin='round' fill='none'/></svg>">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/wanteddev/wanted-sans@v1.0.3/packages/wanted-sans/fonts/webfonts/variable/split/WantedSansVariable.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/wanteddev/wanted-sans@v1.0.3/packages/wanted-sans/fonts/webfonts/variable/split/WantedSansVariable.min.css">
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
</head> </head>
<body> <body>
<nav class="nav glass" aria-label="주 메뉴"> <div class="ambient-lighting" aria-hidden="true">
<div class="ambient-spotlight"></div>
<div class="ambient-grid"></div>
</div>
<!-- Fluid Island Navigation -->
<div class="nav-wrapper">
<nav class="nav glass" aria-label="주 메뉴">
<a class="nav__brand" href="index.html"> <a class="nav__brand" href="index.html">
<span class="nav__mark"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg></span> <span class="nav__logo-badge">
MEDIABROWSER <svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg>
</span>
<span>MEDIABROWSER</span>
</a> </a>
<div class="nav__links"> <div class="nav__links">
<a href="index.html#features">기능</a> <a class="nav__link" href="index.html#how-it-works">작동 방식</a>
<a href="index.html#mobile">모바일</a> <a class="nav__link" href="index.html#features">핵심 기능</a>
<a href="guide.html" aria-current="page">사용 안내</a> <a class="nav__link" href="index.html#mobile">모바일 연결</a>
<a class="nav__link" href="guide.html" aria-current="page">사용 안내</a>
</div> </div>
<a class="btn btn--primary btn--sm" href="releases.html">다운로드</a> <div class="nav__actions">
</nav> <a class="btn btn--primary btn--sm" href="releases.html">
<span>다운로드</span>
<span class="btn__icon-badge"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#arrow-up-right"/></svg></span>
</a>
<button class="nav__hamburger" id="nav-toggle" aria-label="메뉴 열기" aria-expanded="false">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#list"/></svg>
</button>
</div>
</nav>
</div>
<header class="pagehead"> <!-- Mobile Navigation Drawer -->
<div class="orbs" aria-hidden="true"> <div class="mobile-menu-overlay" id="mobile-menu" aria-hidden="true">
<div class="orb orb--a"></div> <div class="mobile-menu-links">
<div class="orb orb--b"></div> <a class="mobile-menu-link" href="index.html#how-it-works">작동 방식</a>
<a class="mobile-menu-link" href="index.html#features">핵심 기능</a>
<a class="mobile-menu-link" href="index.html#mobile">모바일 연결</a>
<a class="mobile-menu-link" href="guide.html" aria-current="page">사용 안내</a>
<a class="mobile-menu-link" href="releases.html" style="color:var(--accent)">다운로드 ↗</a>
</div> </div>
</div>
<!-- Page Header -->
<header style="padding:calc(var(--nav-h) + 72px) 0 48px">
<div class="wrap"> <div class="wrap">
<h1>사용 안내</h1> <div class="reveal">
<p class="sub">설치부터 첫 다운로드, 휴대폰 연결까지. 처음이라면 위에서부터 순서대로 따라오세요.</p> <h1 style="font-size:clamp(2.4rem,4.2vw,3.5rem)">사용 안내</h1>
<p class="sub" style="margin-top:14px">설치부터 첫 영상 다운로드, 라이브러리 정리, 휴대폰 무선 연결까지. 단계별로 따라오시면 3분 안에 모든 기능을 손쉽게 활용할 수 있습니다.</p>
</div>
</div> </div>
</header> </header>
<div class="wrap guide-layout"> <div class="wrap guide-layout">
<aside class="guide-toc glass" aria-label="목차"> <!-- Sticky TOC -->
<a href="#install">1. 설치</a> <aside class="guide-toc bezel-shell" aria-label="목차">
<a href="#first">2. 첫 다운로드</a> <div class="guide-toc-title">목차 바로가기</div>
<a href="#manage">3. 다운로드 관리</a> <a class="guide-toc-link is-active" href="#install">1. 설치 및 시작하기</a>
<a href="#phone">4. 휴대폰 연결</a> <a class="guide-toc-link" href="#first">2. 첫 영상 자동 감지</a>
<a href="#faq">자주 묻는 질문</a> <a class="guide-toc-link" href="#manage">3. 다운로드 및 라이브러리</a>
<a class="guide-toc-link" href="#phone">4. 휴대폰 QR 연결</a>
<a class="guide-toc-link" href="#faq">5. 자주 묻는 질문</a>
</aside> </aside>
<!-- Main Content -->
<main> <main>
<section class="guide-step" id="install"> <!-- Step 1: Install -->
<h2><span class="featlist__icon"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#rocket-launch"/></svg></span>설치</h2> <section class="bezel-shell guide-step-card reveal" id="install">
<p><a href="releases.html" style="color:var(--accent);font-weight:700;text-decoration:none">다운로드 페이지</a>에서 플랫폼에 맞는 빌드를 받으세요.</p> <div class="guide-step-head">
<ul> <div class="guide-step-num">1</div>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#windows-logo"/></svg> <h2>설치 및 환경 구성</h2>
<span><b>Windows</b>: 설치자(exe)를 실행하고 안내를 따르면 끝입니다. x64 와 arm64 를 제공합니다.</span></li> </div>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#apple-logo"/></svg> <p><a href="releases.html" style="color:var(--accent);font-weight:700">다운로드 페이지</a>에서 사용하시는 운영체제에 맞는 패키지를 내려받습니다.</p>
<span><b>macOS 프리뷰</b>: tar.gz 를 풀고 앱을 실행합니다. 아직 서명이 없어 처음 실행 시 보안 확인이 필요할 수 있습니다.</span></li>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#linux-logo"/></svg> <ul class="guide-list">
<span><b>Linux 프리뷰</b>: tar.gz 를 풀고 실행 파일을 실행합니다.</span></li> <li>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#android-logo"/></svg> <svg class="icon" aria-hidden="true"><use href="assets/icons.svg#windows-logo"/></svg>
<span><b>Android</b>: APK 를 설치합니다. 데스크톱 앱과 페어링해 쓰는 컴패니언입니다.</span></li> <div><strong>Windows</strong>: 설치자(exe)를 실행하면 바로 설치가 완료됩니다. x64 및 ARM64 환경을 완벽하게 지원합니다.</div>
</li>
<li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#apple-logo"/></svg>
<div><strong>macOS 프리뷰</strong>: 압축(tar.gz)을 풀고 실행합니다. Apple Silicon(M시리즈) 및 Intel Mac 을 지원합니다.</div>
</li>
<li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#linux-logo"/></svg>
<div><strong>Linux 프리뷰</strong>: 압축(tar.gz)을 해제한 후 실행 파일을 구동합니다.</div>
</li>
<li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#android-logo"/></svg>
<div><strong>Android</strong>: 모바일 컴패니언 APK 를 휴대폰에 설치합니다. 데스크톱 앱과 페어링하여 스트리밍을 즐길 수 있습니다.</div>
</li>
</ul> </ul>
<p>다운로드에 필요한 도구(yt-dlp, ffmpeg, deno)는 앱이 필요할 때 자동으로 설치합니다. 따로 준비할 것은 없습니다.</p>
<div class="guide-tip-box">
<strong>💡 자동 의존성 관리</strong>: 다운로드 및 무손실 리먹싱에 필요한 핵심 도구(ffmpeg, yt-dlp 등)는 앱이 필요할 때 자동으로 내려받아 격리된 경로에서 관리합니다. 사용자가 직접 환경 변수(PATH)를 설정할 필요가 없습니다.
</div>
</section> </section>
<section class="guide-step" id="first"> <!-- Step 2: First Download -->
<h2><span class="featlist__icon"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#cursor-click"/></svg></span>첫 다운로드</h2> <section class="bezel-shell guide-step-card reveal" id="first">
<p>MEDIABROWSER 는 브라우저입니다. 평소처럼 사이트에 들어가 영상을 재생하면 나머지는 앱이 합니다.</p> <div class="guide-step-head">
<ul> <div class="guide-step-num">2</div>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#globe-hemisphere-west"/></svg> <h2>첫 영상 자동 감지 &amp; 다운로드</h2>
<span>주소창에 사이트를 입력해 이동하고, 원하는 영상을 <b>재생</b>합니다.</span></li> </div>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#waveform"/></svg> <p>MEDIABROWSER 는 자체 내장 브라우저를 기반으로 작동합니다. 복잡한 주소 복사나 개발자 도구 분석 없이 평소처럼 웹 서핑을 즐기세요.</p>
<span>재생이 시작되면 스트림(HLS, DASH, MP4)이 감지되어 오른쪽 <b>다운로드 패널</b>에 나타납니다.</span></li>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg> <ul class="guide-list">
<span>목록에서 <b>다운로드</b>를 누르면 로그인 상태 그대로 내려받기가 시작됩니다.</span></li> <li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#cursor-click"/></svg>
<div><strong>웹사이트 접속 및 재생</strong>: 주소창에 원하는 사이트 URL 을 입력하고 영상을 재생합니다. 로그인 계정 상태가 브라우저 탭에 그대로 유지됩니다.</div>
</li>
<li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#waveform"/></svg>
<div><strong>실시간 스트림 스니핑</strong>: 비디오가 재생되는 즉시 우측 다운로드 패널에 HLS(.m3u8), DASH(.mpd), MP4 스트림 정보와 해상도가 감지되어 나타납니다.</div>
</li>
<li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg>
<div><strong>다운로드 시작</strong>: 감지된 목록에서 <strong>다운로드</strong> 버튼을 누르면 로그인 세션과 인증 쿠키를 물려받아 즉시 고속 다운로드가 시작됩니다.</div>
</li>
</ul> </ul>
<figure class="guide-media glass">
<img src="assets/panel-downloads.png" alt="다운로드 패널의 빈 상태 화면. 영상을 재생하면 여기에 나타납니다 라는 안내 문구가 표시되어 있다." width="426" height="330"> <div class="guide-tip-box">
<figcaption>감지 전의 다운로드 패널. 재생을 시작하면 이 목록이 채워집니다.</figcaption> <strong>🔒 보안 스트림 대응</strong>: 회원 전용 영상이나 Referer 검증이 걸려 있는 스트림도 브라우저 탭의 세션 헤더를 그대로 승계하므로 에러 없이 원본 그대로 수신됩니다.
</figure> </div>
</section> </section>
<section class="guide-step" id="manage"> <!-- Step 3: Download Management -->
<h2><span class="featlist__icon"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#stack"/></svg></span>다운로드 관리</h2> <section class="bezel-shell guide-step-card reveal" id="manage">
<p>패널의 탭으로 전체, 진행, 완료, 실패를 나눠 보고, 항목마다 속도와 남은 시간, 세그먼트 진행을 확인합니다.</p> <div class="guide-step-head">
<ul> <div class="guide-step-num">3</div>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#check-circle"/></svg> <h2>다운로드 관리 및 라이브러리 아카이빙</h2>
<span><b>모두 일시정지 / 모두 재개</b>로 한 번에 멈추고 다시 시작합니다. 항목별 일시정지도 됩니다.</span></li> </div>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#check-circle"/></svg> <p>패널의 상태 탭을 통해 진행 중인 작업과 완료된 아카이브를 직관적으로 관리할 수 있습니다.</p>
<span><b>예약</b>을 걸면 지정한 시간부터 내려받습니다. 이미 받은 영상은 중복 확인으로 알려줍니다.</span></li>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#folders"/></svg> <ul class="guide-list">
<span>받은 영상은 <b>라이브러리</b>에서 모아 보고, 재생목록과 즐겨찾기, 아카이브로 정리합니다.</span></li> <li>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#check-circle"/></svg> <svg class="icon" aria-hidden="true"><use href="assets/icons.svg#stack"/></svg>
<span>목록은 <b>CSV</b> 로 내보내 기록으로 남길 수 있습니다.</span></li> <div><strong>실시간 세그먼트 맵</strong>: 수백 개의 비디오/오디오 청크 수신 상황과 실시간 전송 속도, 남은 시간을 한눈에 확인합니다.</div>
</li>
<li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#play-circle"/></svg>
<div><strong>일괄 일시정지 &amp; 재개</strong>: 네트워크 대역폭 조절이 필요할 때 모든 다운로드를 한 번에 멈추거나 다시 시작할 수 있습니다.</div>
</li>
<li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#check-circle"/></svg>
<div><strong>중복 방지 &amp; 스케줄링</strong>: 이미 보관 중인 영상을 다시 다운로드할 때 중복 여부를 안내하며, 심야 시간대 예약 다운로드가 가능합니다.</div>
</li>
<li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#folders"/></svg>
<div><strong>라이브러리 정리 및 CSV 내보내기</strong>: 완료된 영상의 재생목록 분류 및 메타데이터 기록을 CSV 로 저장할 수 있습니다.</div>
</li>
</ul> </ul>
</section> </section>
<section class="guide-step" id="phone"> <!-- Step 4: Phone Companion -->
<h2><span class="featlist__icon"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#device-mobile"/></svg></span>휴대폰 연결</h2> <section class="bezel-shell guide-step-card reveal" id="phone">
<p>데스크톱 앱에 내장된 서버가 휴대폰과 라이브러리를 이어줍니다. 같은 네트워크에서 페어링 한 번이면 됩니다.</p> <div class="guide-step-head">
<ul> <div class="guide-step-num">4</div>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#qr-code"/></svg> <h2>휴대폰 무선 연결 및 로컬 스트리밍</h2>
<span>휴대폰에서 컴패니언 앱을 열고, 데스크톱 앱이 보여주는 <b>QR 코드</b>를 스캔합니다.</span></li> </div>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#play-circle"/></svg> <p>데스크톱 앱에 내장된 로컬 웹 서버가 스마트폰과 PC 의 라이브러리를 하나로 연결해 줍니다.</p>
<span>페어링이 끝나면 라이브러리의 영상을 휴대폰에서 <b>바로 재생</b>하거나 <b>파일로 전송</b>받습니다.</span></li>
<li><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#shield-check"/></svg> <ul class="guide-list">
<span>연결은 내 네트워크 안에서만 이루어집니다. 외부 서버를 거치지 않습니다.</span></li> <li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#qr-code"/></svg>
<div><strong>QR 코드 1초 스캔</strong>: 스마트폰에서 컴패니언 앱을 실행하고 데스크톱 앱 화면의 QR 코드를 스캔합니다.</div>
</li>
<li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#device-mobile"/></svg>
<div><strong>무손실 즉시 스트리밍</strong>: 동일한 홈 Wi-Fi 네트워크에서 PC 에 저장된 고화질 비디오를 인코딩 대기 없이 바로 감상합니다.</div>
</li>
<li>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg>
<div><strong>모바일 파일 전송</strong>: 외출 전 필요한 영상을 휴대폰 로컬 스토리지로 초고속 전송하여 오프라인에서 시청하세요.</div>
</li>
</ul> </ul>
<div class="guide-tip-box">
<strong>🛡️ 로컬 프라이버시</strong>: 모든 통신은 공유기 내부 로컬 네트워크(LAN)에서 암호화되어 직접 전송됩니다. 외부 클라우드나 사설 서버를 일절 거치지 않아 안전합니다.
</div>
</section> </section>
<section class="guide-step" id="faq"> <!-- Step 5: FAQ -->
<h2><span class="featlist__icon"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#gear"/></svg></span>자주 묻는 질문</h2> <section class="bezel-shell guide-step-card reveal" id="faq">
<div class="guide-faq"> <div class="guide-step-head">
<details> <div class="guide-step-num">5</div>
<summary>ffmpeg 나 yt-dlp 를 따로 설치해야 하나요?</summary> <h2>자주 묻는 질문 (FAQ)</h2>
<p>아니요. 필요한 시점에 앱이 자동으로 내려받아 관리합니다. 설정에서 직접 지정한 경로가 있으면 그걸 우선합니다.</p> </div>
<div class="faq-stack">
<details class="faq-item">
<summary>
<span>ffmpeg 나 yt-dlp 를 따로 설치해야 하나요?</span>
<svg class="icon faq-chevron" aria-hidden="true"><use href="assets/icons.svg#caret-down"/></svg>
</summary>
<div class="faq-content">
아니요. 앱 최초 실행 시 또는 다운로드가 필요한 시점에 내장 모듈이 안전한 최신 바이너리를 자동으로 내려받아 관리합니다. 사용자가 직접 환경 변수나 폴더를 설정할 필요가 없습니다.
</div>
</details> </details>
<details>
<summary>받은 파일은 어디에 저장되나요?</summary> <details class="faq-item">
<p>기본 저장 폴더에 저장되며, 설정에서 폴더를 바꿀 수 있습니다. 완료 목록에서 파일 위치를 바로 열 수 있습니다.</p> <summary>
<span>받은 영상은 어디에 저장되며 변경할 수 있나요?</span>
<svg class="icon faq-chevron" aria-hidden="true"><use href="assets/icons.svg#caret-down"/></svg>
</summary>
<div class="faq-content">
기본적으로 시스템의 '동영상' 폴더 내 MEDIABROWSER 디렉터리에 저장됩니다. 앱 설정 메뉴에서 외장 하드 드라이브나 원하는 사용자 정의 폴더로 언제든지 변경할 수 있습니다.
</div>
</details> </details>
<details>
<summary>다운로드가 중간에 끊기면 처음부터 다시 받나요?</summary> <details class="faq-item">
<p>아니요. 세그먼트 단위로 이어받기를 지원해서 받다 만 지점부터 다시 진행합니다.</p> <summary>
<span>다운로드 중 연결이 끊기면 처음부터 다시 받나요?</span>
<svg class="icon faq-chevron" aria-hidden="true"><use href="assets/icons.svg#caret-down"/></svg>
</summary>
<div class="faq-content">
아니요. MEDIABROWSER 는 청크 및 세그먼트 단위로 다운로드 진척도를 영구 기록합니다. 인터넷이 끊기거나 앱을 재실행해도 이미 수신된 데이터는 보존되며 멈춘 지점부터 즉시 이어받습니다.
</div>
</details> </details>
<details>
<summary>업데이트는 어떻게 하나요?</summary> <details class="faq-item">
<p>설정의 앱 업데이트 항목에서 새 버전을 확인할 수 있고, 다운로드 페이지에서 새 설치자를 받아 덮어 설치하면 됩니다.</p> <summary>
<span>모바일 스트리밍 시 스마트폰 데이터가 소모되나요?</span>
<svg class="icon faq-chevron" aria-hidden="true"><use href="assets/icons.svg#caret-down"/></svg>
</summary>
<div class="faq-content">
아니요. PC 와 스마트폰이 동일한 Wi-Fi 공유기 네트워크에 연결되어 있는 경우, 로컬 기기간 직접 전송(LAN)으로 동작하므로 통신사 LTE/5G 모바일 데이터는 전혀 소모되지 않습니다.
</div>
</details> </details>
<details>
<summary>어떤 사이트를 지원하나요?</summary> <details class="faq-item">
<p>표준 스트리밍 형식(HLS, DASH, MP4)을 쓰는 사이트에서 동작합니다. 콘텐츠의 이용 약관과 저작권을 지키는 범위에서 사용해 주세요.</p> <summary>
<span>어떤 사이트와 스트리밍 포맷을 지원하나요?</span>
<svg class="icon faq-chevron" aria-hidden="true"><use href="assets/icons.svg#caret-down"/></svg>
</summary>
<div class="faq-content">
표준 웹 비디오 포맷인 HLS(.m3u8), DASH(.mpd), MP4 프로토콜을 사용하는 대다수의 웹사이트에서 완벽하게 동작합니다. 단, DRM(디지털 저작권 관리 기술)으로 하드웨어 암호화된 유료 OTT 스트리밍 서비스는 기술적/법적 보호를 위해 다운로드가 제한될 수 있습니다.
</div>
</details> </details>
</div> </div>
</section> </section>
</main> </main>
</div> </div>
<!-- Footer -->
<footer> <footer>
<div class="wrap footer__row"> <div class="wrap footer__row">
<span class="footer__brand">MEDIABROWSER</span> <div class="footer__brand">
<span class="nav__logo-badge" style="width:26px;height:26px;border-radius:7px">
<svg class="icon" style="width:14px;height:14px" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg>
</span>
<span>MEDIABROWSER</span>
</div>
<div class="footer__links">
<a href="releases.html">다운로드</a> <a href="releases.html">다운로드</a>
<a href="guide.html">사용 안내</a> <a href="guide.html">사용 안내</a>
<a href="https://git.chanpaca.net/Video-Downloader/releases" rel="noopener">릴리스 저장소</a> <a href="https://git.chanpaca.net/Video-Downloader/releases" target="_blank" rel="noopener">릴리스 저장소</a>
<span class="footer__copy">© 2026 MEDIABROWSER</span> </div>
<div class="footer__copy">
&copy; 2026 MEDIABROWSER. All rights reserved.
</div>
</div> </div>
</footer> </footer>

View file

@ -3,151 +3,456 @@
<head> <head>
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>MEDIABROWSER - 보던 영상, 그 자리에서 내 것으로</title> <title>MEDIABROWSER - 보던 영상을 내 PC와 휴대폰으로</title>
<meta name="description" content="MEDIABROWSER 는 재생 중인 미디어를 감지해 내려받는 데스크톱 브라우저입니다. 받은 영상은 라이브러리로 관리하고 휴대폰으로 이어봅니다."> <meta name="description" content="주소 복사 없이 재생하는 순간 스트림 자동 감지. 브라우저 세션 승계, HLS/DASH 병렬 이어받기, 홈 Wi-Fi 모바일 로컬 스트리밍까지 지원하는 미디어 브라우저.">
<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='%232050f0'/><path d='M50 22v36M36 44l14 14 14-14M28 74h44' stroke='white' stroke-width='9' stroke-linecap='round' stroke-linejoin='round' fill='none'/></svg>"> <meta property="og:type" content="website">
<meta property="og:title" content="MEDIABROWSER - 보던 영상을 내 PC와 휴대폰으로">
<meta property="og:description" content="재생하는 순간 스트림을 감지해 로그인 세션 그대로 저장하고, 휴대폰으로 이어보는 미디어 브라우저.">
<meta property="og:url" content="https://mediabrowser-7r4.pages.dev/">
<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='%233b82f6'/><path d='M50 22v36M36 44l14 14 14-14M28 74h44' stroke='white' stroke-width='9' stroke-linecap='round' stroke-linejoin='round' fill='none'/></svg>">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/wanteddev/wanted-sans@v1.0.3/packages/wanted-sans/fonts/webfonts/variable/split/WantedSansVariable.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/wanteddev/wanted-sans@v1.0.3/packages/wanted-sans/fonts/webfonts/variable/split/WantedSansVariable.min.css">
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
</head> </head>
<body> <body>
<nav class="nav glass" aria-label="주 메뉴"> <a class="skip-link" href="#how-it-works">본문 바로가기</a>
<div class="ambient-lighting" aria-hidden="true">
<div class="ambient-spotlight"></div>
<div class="ambient-grid"></div>
</div>
<!-- Fluid Island Navigation -->
<div class="nav-wrapper">
<nav class="nav glass" aria-label="주 메뉴">
<a class="nav__brand" href="index.html" aria-current="page"> <a class="nav__brand" href="index.html" aria-current="page">
<span class="nav__mark"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg></span> <span class="nav__logo-badge">
MEDIABROWSER <svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg>
</span>
<span>MEDIABROWSER</span>
</a> </a>
<div class="nav__links"> <div class="nav__links">
<a href="#features">기능</a> <a class="nav__link" href="#how-it-works">작동 방식</a>
<a href="#mobile">모바일</a> <a class="nav__link" href="#features">핵심 기능</a>
<a href="guide.html">사용 안내</a> <a class="nav__link" href="#mobile">모바일 연결</a>
<a class="nav__link" href="guide.html">사용 안내</a>
</div> </div>
<a class="btn btn--primary btn--sm" href="releases.html">다운로드</a> <div class="nav__actions">
</nav> <a class="btn btn--primary btn--sm" href="releases.html">
<span>다운로드</span>
<span class="btn__icon-badge"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#arrow-up-right"/></svg></span>
</a>
<button class="nav__hamburger" id="nav-toggle" aria-label="메뉴 열기" aria-expanded="false">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#list"/></svg>
</button>
</div>
</nav>
</div>
<!-- Mobile Navigation Drawer -->
<div class="mobile-menu-overlay" id="mobile-menu" aria-hidden="true">
<div class="mobile-menu-links">
<a class="mobile-menu-link" href="#how-it-works">작동 방식</a>
<a class="mobile-menu-link" href="#features">핵심 기능</a>
<a class="mobile-menu-link" href="#mobile">모바일 연결</a>
<a class="mobile-menu-link" href="guide.html">사용 안내</a>
<a class="mobile-menu-link" href="releases.html" style="color:var(--accent)">다운로드 ↗</a>
</div>
</div>
<!-- Hero Section -->
<header class="hero"> <header class="hero">
<div class="orbs" aria-hidden="true">
<div class="orb orb--a"></div>
<div class="orb orb--b"></div>
<div class="orb orb--c"></div>
</div>
<div class="wrap hero__grid"> <div class="wrap hero__grid">
<div class="hero__copy">
<div> <div>
<h1>보던 영상,<br>그 자리에서 내 것으로.</h1> <span class="eyebrow">미디어 스트림 엔진</span>
<p class="sub">MEDIABROWSER 는 재생 중인 미디어를 감지해 내려받는 브라우저입니다. </div>
받은 영상은 라이브러리로 관리하고, 휴대폰으로 이어봅니다.</p> <h1>주소 복사는 잊으세요.<br>재생하면 준비됩니다.</h1>
<div class="hero__cta"> <p class="sub">재생하는 순간 스트림(HLS · DASH · MP4)을 감지하고, 로그인 세션 그대로 원본 화질로 저장합니다. 휴대폰으로 이어보는 것까지.</p>
<a class="btn btn--primary" href="releases.html">다운로드</a>
<a class="btn btn--ghost" href="guide.html">사용 안내</a> <div class="hero__cta-group">
<a class="btn btn--primary" href="releases.html">
<span>다운로드</span>
<span class="btn__icon-badge"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#arrow-up-right"/></svg></span>
</a>
<a class="btn btn--ghost" href="guide.html">
<span>사용 안내</span>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#arrow-right"/></svg>
</a>
</div> </div>
</div> </div>
<!-- Live Stream Sniffer Simulator (Machined Double-Bezel) -->
<div class="hero__visual reveal"> <div class="hero__visual reveal">
<figure class="hero__panel glass"> <div class="bezel-shell">
<img src="assets/panel-downloads.png" alt="MEDIABROWSER 다운로드 패널. 전체·진행·완료·실패 탭과 모두 일시정지, 모두 재개, CSV 버튼이 있고, 영상을 재생하면 여기에 나타납니다 라는 안내가 보인다." width="426" height="330"> <div class="bezel-inner simulator-window">
<figcaption class="hero__caption">앱의 다운로드 패널. 재생을 감지하면 이 목록에 자동으로 쌓입니다.</figcaption> <div class="simulator-topbar">
</figure> <div class="window-dots">
<span class="window-dot"></span>
<span class="window-dot"></span>
<span class="window-dot"></span>
</div>
<div class="simulator-url-bar text-mono">
<svg class="icon" style="width:12px;height:12px"><use href="assets/icons.svg#shield-check"/></svg>
https://stream.example.com/watch?v=k94f...
</div>
<span class="badge-chip badge-chip--accent" style="font-size:0.7rem;padding:2px 8px">Sniffer Active</span>
</div>
<div class="simulator-content">
<!-- Detection Banner -->
<div class="detection-banner">
<div class="detection-info">
<div class="detection-pulse"></div>
<div>
<div class="detection-title">스트림 자동 감지 완료</div>
<div class="detection-specs text-mono">HLS Master Playlist · 1080p 60fps · 6,400 kbps</div>
</div>
</div>
<span class="badge-chip" style="background:rgba(59,130,246,0.2);color:#93c5fd">Cookie Passed</span>
</div>
<!-- Active Download Simulation Card -->
<div class="active-download-card">
<div class="download-head">
<div>
<div class="download-name">4K_High_Bitrate_Stream_Archive.mp4</div>
<div style="font-size:0.75rem;color:var(--text-muted);margin-top:2px" class="text-mono">HLS 분할 다운로드 · AES-128 복호화 및 ffmpeg MP4 리먹싱</div>
</div>
<span class="download-format-chip text-mono">HLS &bull; 1080p</span>
</div>
<!-- Realtime Segment Map -->
<div>
<div class="progress-track">
<div class="progress-fill" id="sim-progress" style="width:72%"></div>
</div>
<div class="segment-visualizer" aria-hidden="true">
<div class="seg-block done"></div>
<div class="seg-block done"></div>
<div class="seg-block done"></div>
<div class="seg-block done"></div>
<div class="seg-block done"></div>
<div class="seg-block done"></div>
<div class="seg-block done"></div>
<div class="seg-block done"></div>
<div class="seg-block done"></div>
<div class="seg-block done"></div>
<div class="seg-block done"></div>
<div class="seg-block active"></div>
<div class="seg-block"></div>
<div class="seg-block"></div>
<div class="seg-block"></div>
<div class="seg-block"></div>
</div>
</div>
<div class="download-meta-row text-mono">
<span>속도: <strong style="color:var(--accent)" id="sim-speed">18.4 MB/s</strong> (16 Threads)</span>
<span>진행률: <strong style="color:var(--text-primary)" id="sim-percent">72%</strong> (1.42 GB / 1.98 GB)</span>
<span>남은 시간: <strong style="color:var(--text-primary)">31초</strong></span>
</div>
</div>
<!-- Quick Specs Row -->
<div class="spec-line text-mono" style="padding:0 4px;font-size:0.75rem">
<span>내장 서버: <strong style="color:var(--success)">192.168.1.100:5000 (온라인)</strong></span>
<span>모바일 연결: <strong>QR 준비됨</strong></span>
</div>
</div>
</div>
</div>
<p class="sim-caption">실제 다운로드 흐름을 재현한 예시 화면입니다.</p>
</div> </div>
</div> </div>
</header> </header>
<section id="features" class="section-pad"> <!-- Section 1: How it Works (3-Step Pipeline) -->
<section id="how-it-works" class="section-pad">
<div class="wrap"> <div class="wrap">
<h2 class="reveal" style="font-size:clamp(28px,3.6vw,40px)">주소를 붙여넣는 게 아니라,<br>그냥 봅니다.</h2> <div class="section-head section-head--center reveal">
<div class="bento"> <h2>웹서핑하고, 감지되고, 저장됩니다</h2>
<div class="bento__cell bento__cell--wide reveal"> <p class="sub">복잡한 확장 프로그램이나 개발자 도구 설정 없이, 평소처럼 영상을 보면 백그라운드 엔진이 나머지를 처리합니다.</p>
<div class="bento__wave"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#waveform"/></svg></div>
<div>
<div class="bento__chipline" aria-label="지원 형식">
<span class="chip">HLS</span><span class="chip">DASH</span><span class="chip">MP4</span>
</div> </div>
<h3>재생하면 감지됩니다</h3>
<p>내장 브라우저에서 영상이 재생되는 순간 스트림을 인식해 다운로드 목록에 올립니다.
별도 확장이나 주소 복사가 필요 없습니다.</p>
</div>
</div>
<div class="bento__cell glass reveal">
<h3>로그인 그대로</h3>
<p>탭의 쿠키와 Referer 를 그대로 물려받아 내려받습니다. 브라우저에서 보이던 영상은 그대로 받아집니다.</p>
</div>
<div class="bento__cell glass reveal">
<h3>끊겨도 이어서</h3>
<p>병렬 분할 다운로드와 이어받기, 그리고 ffmpeg 리먹스까지 자동으로 처리합니다. AES-128 스트림도 지원합니다.</p>
</div>
</div>
</div>
</section>
<section class="section-pad" style="background:linear-gradient(180deg,transparent,var(--bg-deep) 30%,var(--bg-deep) 70%,transparent)"> <div class="bezel-shell reveal">
<div class="wrap"> <div class="bezel-inner pipeline-rail">
<h2 class="reveal" style="font-size:clamp(28px,3.6vw,40px)">다운로드는 관리가 절반입니다.</h2> <div class="pipeline-card">
<div class="featlist"> <div class="pipeline-step-badge">
<div class="featlist__item reveal"> <svg class="icon" aria-hidden="true"><use href="assets/icons.svg#globe-hemisphere-west"/></svg>
<div class="featlist__icon"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#stack"/></svg></div>
<div><h3>속도와 세그먼트가 보입니다</h3><p>항목마다 속도, 남은 시간, 세그먼트 맵을 실시간으로 표시합니다.</p></div>
</div>
<div class="featlist__item reveal">
<div class="featlist__icon"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#play-circle"/></svg></div>
<div><h3>전체 일시정지와 재개</h3><p>한 번에 멈추고 한 번에 다시 시작합니다. 예약 시간을 걸어둘 수도 있습니다.</p></div>
</div>
<div class="featlist__item reveal">
<div class="featlist__icon"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#check-circle"/></svg></div>
<div><h3>중복은 미리 알려줍니다</h3><p>이미 받은 영상을 다시 받으려 하면 내려받기 전에 확인해 줍니다.</p></div>
</div>
<div class="featlist__item reveal">
<div class="featlist__icon"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#folders"/></svg></div>
<div><h3>라이브러리와 아카이브</h3><p>받은 영상을 모아 보고, 정리하고, 재생목록과 즐겨찾기로 관리합니다.</p></div>
</div>
</div>
</div>
</section>
<section id="mobile" class="section-pad">
<div class="wrap mobile__grid">
<div class="mobile__stage reveal" aria-hidden="true">
<div class="mobile__card mobile__card--a glass">
<svg class="icon"><use href="assets/icons.svg#qr-code"/></svg>
<div><strong>QR 페어링</strong><span>화면의 코드를 한 번 스캔</span></div>
</div>
<div class="mobile__card mobile__card--b glass">
<svg class="icon"><use href="assets/icons.svg#device-mobile"/></svg>
<div><strong>스트리밍</strong><span>같은 네트워크에서 바로 재생</span></div>
</div>
<div class="mobile__card mobile__card--c glass">
<svg class="icon"><use href="assets/icons.svg#download-simple"/></svg>
<div><strong>전송</strong><span>파일을 휴대폰에 저장</span></div>
</div>
</div> </div>
<div> <div>
<h2 class="reveal" style="font-size:clamp(28px,3.6vw,40px)">받은 영상,<br>휴대폰에서 이어보기.</h2> <h3>평소처럼 영상 재생</h3>
<p class="sub reveal" style="margin-top:20px">데스크톱 앱에 내장된 서버가 라이브러리를 휴대폰으로 스트리밍하거나 전송합니다. <p style="margin-top:8px">내장 브라우저에서 원하는 사이트로 이동해 영상을 재생하세요. 별도 로그인 토큰이나 주소 복사가 필요 없습니다.</p>
QR 코드 한 번으로 페어링하고, Android 컴패니언 앱으로 어디서든 이어봅니다. iOS 는 준비 중입니다.</p> </div>
</div>
<div class="pipeline-card">
<div class="pipeline-step-badge">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#waveform"/></svg>
</div>
<div>
<h3>세션 승계 &amp; 자동 감지</h3>
<p style="margin-top:8px">재생 버튼을 누르는 즉시 HLS(.m3u8), DASH(.mpd), MP4 스트림을 가로채고, 탭의 인증 쿠키와 Referer 를 승계합니다.</p>
</div>
</div>
<div class="pipeline-card">
<div class="pipeline-step-badge">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#stack"/></svg>
</div>
<div>
<h3>병렬 이어받기 &amp; 리먹싱</h3>
<p style="margin-top:8px">세그먼트를 분할 병렬로 내려받고, 끊기면 받다 만 지점부터 이어받습니다. ffmpeg 가 무손실 MP4 로 결합합니다.</p>
</div>
</div>
</div>
</div> </div>
</div> </div>
</section> </section>
<!-- Section 2: Core Engineering Features (Asymmetric Bento Grid) -->
<section id="features" class="section-pad" style="padding-top:0">
<div class="wrap">
<div class="section-head reveal">
<h2>대용량 스트림 수신에 최적화된 엔진</h2>
<p class="sub">네트워크가 불안정해도, 스트림이 암호화되어 있어도 사용자의 개입 없이 안정적인 다운로드를 보장합니다.</p>
</div>
<div class="bento-grid">
<!-- Bento Cell 1: Cookie & Session Passthrough (Span 7) -->
<div class="bezel-shell bento-cell--span-7 reveal">
<div class="bezel-inner bento-cell">
<div>
<div class="bento-icon-wrapper">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#shield-check"/></svg>
</div>
<h3>로그인 세션 &amp; 쿠키 자동 승계</h3>
<p>회원 전용 영상이나 보안 스트림도 문제없습니다. 탭의 세션 쿠키와 Referer 헤더를 다운로드 요청에 그대로 전달하므로 별도의 토큰 추출이나 번거로운 재로그인이 필요 없습니다.</p>
<div class="bento-chips-row">
<span class="badge-chip">Cookie Passthrough</span>
<span class="badge-chip">Referer Header Lock</span>
<span class="badge-chip">Session Continuity</span>
</div>
</div>
<div class="bento-spec-box text-mono">
<div class="spec-line"><span>헤더 승계:</span><span>User-Agent, Cookie, Referer, Sec-Fetch-*</span></div>
<div class="spec-line"><span>보안 처리:</span><span>브라우저 샌드박스 내부 직접 바인딩</span></div>
</div>
</div>
</div>
<!-- Bento Cell 2: Resilient Segment Engine (Span 5) -->
<div class="bezel-shell bento-cell--span-5 reveal">
<div class="bezel-inner bento-cell">
<div>
<div class="bento-icon-wrapper">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#stack"/></svg>
</div>
<h3>끊겨도 안전한 세그먼트 이어받기</h3>
<p>네트워크가 불안정해 연결이 끊겨도 이미 받은 청크는 그대로 보존됩니다. 받다 만 지점부터 즉시 재개하며 AES-128 암호화 스트림도 자동으로 복호화합니다.</p>
</div>
<div class="bento-chips-row" style="margin-top:auto">
<span class="badge-chip badge-chip--accent">Segment Chunk Map</span>
<span class="badge-chip">AES-128 Decryptor</span>
<span class="badge-chip">Auto Retry</span>
</div>
</div>
</div>
<!-- Bento Cell 3: Smart Duplicate Detector & Scheduling (Span 5) -->
<div class="bezel-shell bento-cell--span-5 reveal">
<div class="bezel-inner bento-cell">
<div>
<div class="bento-icon-wrapper">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#folders"/></svg>
</div>
<h3>스마트 중복 방지 &amp; 스케줄러</h3>
<p>이미 다운로드한 영상을 다시 받으려 하면 미리 감지해 중복 저장을 방지합니다. 심야 시간대 자동 다운로드 예약과 CSV 내보내기도 지원합니다.</p>
</div>
<div class="bento-chips-row" style="margin-top:auto">
<span class="badge-chip">Duplicate Warning</span>
<span class="badge-chip">Scheduled Queue</span>
<span class="badge-chip">CSV Export</span>
</div>
</div>
</div>
<!-- Bento Cell 4: Realtime Telemetry & ffmpeg Remux (Span 7) -->
<div class="bezel-shell bento-cell--span-7 reveal">
<div class="bezel-inner bento-cell">
<div>
<div class="bento-icon-wrapper">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#play-circle"/></svg>
</div>
<h3>초고속 ffmpeg MP4 무손실 리먹싱</h3>
<p>다운로드가 완료되는 즉시 내장 ffmpeg 엔진이 비디오와 오디오 스트림을 손실 없이 단일 MP4 파일로 결합합니다. 재인코딩이 없어 CPU 부하가 낮고 화질 열화가 없습니다.</p>
<div class="bento-chips-row">
<span class="badge-chip badge-chip--accent">Zero Loss Remux</span>
<span class="badge-chip">ffmpeg Core Embedded</span>
<span class="badge-chip">Batch Pause / Resume</span>
</div>
</div>
<div class="bento-spec-box text-mono">
<div class="spec-line"><span>처리 방식:</span><span>재인코딩 없는 스트림 복사 (화질 열화 없음)</span></div>
<div class="spec-line"><span>지원 포맷:</span><span>MP4, MKV, M4A 오디오 추출 지원</span></div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Section 3: Mobile Companion Ecosystem -->
<section id="mobile" class="section-pad" style="background:linear-gradient(180deg, transparent, rgba(13, 16, 23, 0.7) 40%, transparent)">
<div class="wrap mobile-showcase">
<div class="reveal">
<h2 style="font-size:clamp(2rem, 3.6vw, 2.75rem)">내 PC 의 라이브러리,<br>휴대폰에서 그대로 이어보기</h2>
<p class="sub" style="margin-top:16px">외부 클라우드로 비디오를 업로드할 필요가 없습니다. 데스크톱 앱 내장 서버가 홈 Wi-Fi 안에서 스마트폰과 바로 연결됩니다.</p>
<div style="margin-top:32px;display:flex;gap:14px;flex-wrap:wrap">
<a class="btn btn--primary" href="guide.html#phone">
<span>모바일 연결 가이드</span>
<span class="btn__icon-badge"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#arrow-up-right"/></svg></span>
</a>
</div>
</div>
<div class="mobile-cards-stage reveal">
<div class="bezel-shell">
<div class="bezel-inner feature-stack-card">
<div class="feature-stack-icon">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#qr-code"/></svg>
</div>
<div>
<strong>QR 코드 즉시 페어링</strong>
<span>복잡한 IP 나 포트 설정 없이 모바일 앱으로 QR 을 스캔하면 끝납니다.</span>
</div>
</div>
</div>
<div class="bezel-shell">
<div class="bezel-inner feature-stack-card">
<div class="feature-stack-icon">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#device-mobile"/></svg>
</div>
<div>
<strong>홈 네트워크 무손실 스트리밍</strong>
<span>PC 에 저장된 4K/1080p 영상을 인코딩 대기 없이 스마트폰에서 바로 재생합니다.</span>
</div>
</div>
</div>
<div class="bezel-shell">
<div class="bezel-inner feature-stack-card">
<div class="feature-stack-icon">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg>
</div>
<div>
<strong>로컬 파일 전송</strong>
<span>외출 전 터치 한 번으로 모바일 기기에 파일을 저장해 오프라인에서 시청하세요.</span>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Section 4: Cross-Platform Matrix -->
<section class="section-pad">
<div class="wrap">
<div class="section-head section-head--center reveal">
<h2>모든 주요 운영체제를 지원합니다</h2>
<p class="sub">Windows 설치자로 바로 시작할 수 있으며, macOS · Linux 프리뷰와 Android 컴패니언 앱을 제공합니다.</p>
</div>
<div class="platform-matrix">
<div class="bezel-shell reveal">
<div class="bezel-inner platform-card">
<div class="platform-icon">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#windows-logo"/></svg>
</div>
<h3>Windows</h3>
<p>Windows 10 / 11<br>x64 및 ARM64 네이티브</p>
<span class="platform-status-badge status--stable">안정판 제공</span>
</div>
</div>
<div class="bezel-shell reveal">
<div class="bezel-inner platform-card">
<div class="platform-icon">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#apple-logo"/></svg>
</div>
<h3>macOS 프리뷰</h3>
<p>Apple Silicon (M1~M4)<br>&amp; Intel x64</p>
<span class="platform-status-badge status--preview">프리뷰 빌드</span>
</div>
</div>
<div class="bezel-shell reveal">
<div class="bezel-inner platform-card">
<div class="platform-icon">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#linux-logo"/></svg>
</div>
<h3>Linux 프리뷰</h3>
<p>Ubuntu · Fedora · Arch<br>x64 바이너리</p>
<span class="platform-status-badge status--preview">프리뷰 빌드</span>
</div>
</div>
<div class="bezel-shell reveal">
<div class="bezel-inner platform-card">
<div class="platform-icon">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#android-logo"/></svg>
</div>
<h3>Android</h3>
<p>Android 10+<br>컴패니언 앱 APK</p>
<span class="platform-status-badge status--stable">컴패니언</span>
</div>
</div>
</div>
</div>
</section>
<!-- Section 5: Bottom CTA -->
<section class="section-pad" style="padding-top:0"> <section class="section-pad" style="padding-top:0">
<div class="wrap"> <div class="wrap">
<div class="band glass reveal"> <div class="bezel-shell reveal">
<h2>Windows 에서 시작하세요.</h2> <div class="bezel-inner cta-banner">
<p class="sub">Windows 는 설치자로 바로 시작할 수 있습니다. <h2>보던 영상 그대로,<br>지금 내 것으로 만들어보세요.</h2>
macOS 와 Linux 는 새 셸의 프리뷰 빌드, Android 는 컴패니언 앱을 제공합니다.</p> <p class="sub">별도의 설정 없이 1분 만에 설치하고 웹 서핑을 시작하세요. 필요한 도구는 앱이 알아서 관리합니다.</p>
<div class="band__oses"> <div style="display:flex;gap:14px;flex-wrap:wrap;justify-content:center">
<div class="band__os"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#windows-logo"/></svg>Windows</div> <a class="btn btn--primary" href="releases.html">
<div class="band__os"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#apple-logo"/></svg>macOS 프리뷰</div> <span>다운로드</span>
<div class="band__os"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#linux-logo"/></svg>Linux 프리뷰</div> <span class="btn__icon-badge"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#arrow-up-right"/></svg></span>
<div class="band__os"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#android-logo"/></svg>Android</div> </a>
<a class="btn btn--ghost" href="guide.html">
<span>사용 안내</span>
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#arrow-right"/></svg>
</a>
</div>
</div> </div>
<a class="btn btn--primary" href="releases.html">다운로드</a>
</div> </div>
</div> </div>
</section> </section>
<!-- Footer -->
<footer> <footer>
<div class="wrap footer__row"> <div class="wrap footer__row">
<span class="footer__brand">MEDIABROWSER</span> <div class="footer__brand">
<span class="nav__logo-badge" style="width:26px;height:26px;border-radius:7px">
<svg class="icon" style="width:14px;height:14px" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg>
</span>
<span>MEDIABROWSER</span>
</div>
<div class="footer__links">
<a href="releases.html">다운로드</a> <a href="releases.html">다운로드</a>
<a href="guide.html">사용 안내</a> <a href="guide.html">사용 안내</a>
<a href="https://git.chanpaca.net/Video-Downloader/releases" rel="noopener">릴리스 저장소</a> <a href="https://git.chanpaca.net/Video-Downloader/releases" target="_blank" rel="noopener">릴리스 저장소</a>
<span class="footer__copy">© 2026 MEDIABROWSER</span> </div>
<div class="footer__copy">
&copy; 2026 MEDIABROWSER. All rights reserved.
</div>
</div> </div>
</footer> </footer>

View file

@ -4,70 +4,115 @@
<meta charset="utf-8"> <meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">
<title>다운로드 - MEDIABROWSER</title> <title>다운로드 - MEDIABROWSER</title>
<meta name="description" content="MEDIABROWSER 릴리스 다운로드. Windows 설치자, macOS·Linux 프리뷰 빌드, Android 컴패니언 APK."> <meta name="description" content="MEDIABROWSER 공식 릴리스 다운로드. Windows 네이티브 설치자, macOS·Linux 프리뷰 빌드, Android 컴패니언 APK.">
<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='%232050f0'/><path d='M50 22v36M36 44l14 14 14-14M28 74h44' stroke='white' stroke-width='9' stroke-linecap='round' stroke-linejoin='round' fill='none'/></svg>"> <meta property="og:type" content="website">
<meta property="og:title" content="다운로드 - MEDIABROWSER">
<meta property="og:description" content="플랫폼별 최신 릴리스를 내려받으세요. Windows 설치자, macOS·Linux 프리뷰, Android 컴패니언 APK.">
<meta property="og:url" content="https://mediabrowser-7r4.pages.dev/releases.html">
<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='%233b82f6'/><path d='M50 22v36M36 44l14 14 14-14M28 74h44' stroke='white' stroke-width='9' stroke-linecap='round' stroke-linejoin='round' fill='none'/></svg>">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/wanteddev/wanted-sans@v1.0.3/packages/wanted-sans/fonts/webfonts/variable/split/WantedSansVariable.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/wanteddev/wanted-sans@v1.0.3/packages/wanted-sans/fonts/webfonts/variable/split/WantedSansVariable.min.css">
<link rel="stylesheet" href="styles.css"> <link rel="stylesheet" href="styles.css">
</head> </head>
<body> <body>
<nav class="nav glass" aria-label="주 메뉴"> <div class="ambient-lighting" aria-hidden="true">
<div class="ambient-spotlight"></div>
<div class="ambient-grid"></div>
</div>
<!-- Fluid Island Navigation -->
<div class="nav-wrapper">
<nav class="nav glass" aria-label="주 메뉴">
<a class="nav__brand" href="index.html"> <a class="nav__brand" href="index.html">
<span class="nav__mark"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg></span> <span class="nav__logo-badge">
MEDIABROWSER <svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg>
</span>
<span>MEDIABROWSER</span>
</a> </a>
<div class="nav__links"> <div class="nav__links">
<a href="index.html#features">기능</a> <a class="nav__link" href="index.html#how-it-works">작동 방식</a>
<a href="index.html#mobile">모바일</a> <a class="nav__link" href="index.html#features">핵심 기능</a>
<a href="guide.html">사용 안내</a> <a class="nav__link" href="index.html#mobile">모바일 연결</a>
<a class="nav__link" href="guide.html">사용 안내</a>
</div> </div>
<a class="btn btn--primary btn--sm" href="releases.html" aria-current="page">다운로드</a> <div class="nav__actions">
</nav> <a class="btn btn--primary btn--sm" href="releases.html" aria-current="page">
<span>다운로드</span>
<span class="btn__icon-badge"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#arrow-up-right"/></svg></span>
</a>
<button class="nav__hamburger" id="nav-toggle" aria-label="메뉴 열기" aria-expanded="false">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#list"/></svg>
</button>
</div>
</nav>
</div>
<header class="pagehead"> <!-- Mobile Navigation Drawer -->
<div class="orbs" aria-hidden="true"> <div class="mobile-menu-overlay" id="mobile-menu" aria-hidden="true">
<div class="orb orb--a"></div> <div class="mobile-menu-links">
<div class="orb orb--b"></div> <a class="mobile-menu-link" href="index.html#how-it-works">작동 방식</a>
<a class="mobile-menu-link" href="index.html#features">핵심 기능</a>
<a class="mobile-menu-link" href="index.html#mobile">모바일 연결</a>
<a class="mobile-menu-link" href="guide.html">사용 안내</a>
<a class="mobile-menu-link" href="releases.html" style="color:var(--accent)">다운로드 ↗</a>
</div> </div>
</div>
<!-- Page Header -->
<header style="padding:calc(var(--nav-h) + 72px) 0 48px">
<div class="wrap"> <div class="wrap">
<h1>다운로드</h1> <div class="reveal">
<p class="sub">사용하는 플랫폼에 맞는 빌드를 받으세요. 설치가 끝나면 <h1 style="font-size:clamp(2.4rem,4.2vw,3.5rem)">릴리스 다운로드</h1>
<a href="guide.html" style="color:var(--accent);font-weight:700;text-decoration:none">사용 안내</a>에서 첫 다운로드까지 3분이면 충분합니다.</p> <p class="sub" style="margin-top:14px">사용하시는 플랫폼에 맞는 빌드를 내려받으세요. 설치가 완료된 후 <a href="guide.html" style="color:var(--accent);font-weight:700">사용 안내</a>를 참고하시면 3분 안에 첫 다운로드를 시작할 수 있습니다.</p>
</div>
</div> </div>
</header> </header>
<div class="wrap rel-layout"> <div class="wrap rel-layout">
<!-- Sticky Rail -->
<aside class="rel-rail"> <aside class="rel-rail">
<div class="rel-rail__box glass"> <div class="bezel-shell rel-rail__box">
<h3>플랫폼</h3> <h3>운영체제 바로가기</h3>
<a class="rel-rail__os" href="#windows"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#windows-logo"/></svg>Windows</a> <a class="rel-rail__os" href="#windows"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#windows-logo"/></svg>Windows (x64 / ARM)</a>
<a class="rel-rail__os" href="#macos"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#apple-logo"/></svg>macOS 프리뷰</a> <a class="rel-rail__os" href="#macos"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#apple-logo"/></svg>macOS 프리뷰</a>
<a class="rel-rail__os" href="#linux"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#linux-logo"/></svg>Linux 프리뷰</a> <a class="rel-rail__os" href="#linux"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#linux-logo"/></svg>Linux 프리뷰</a>
<a class="rel-rail__os" href="#android"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#android-logo"/></svg>Android</a> <a class="rel-rail__os" href="#android"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#android-logo"/></svg>Android 컴패니언</a>
</div> </div>
<div class="rel-rail__box glass">
<p class="rel-rail__note">Windows 는 설치자(exe)를 실행하면 됩니다. <div class="bezel-shell rel-rail__box">
macOS 와 Linux 는 tar.gz 를 풀어 실행하는 프리뷰 빌드입니다. <p style="font-size:0.85rem;color:var(--text-secondary);line-height:1.6">
전체 버전 기록은 <a href="https://git.chanpaca.net/Video-Downloader/releases" rel="noopener">릴리스 저장소</a>에 있습니다.</p> Windows 는 설치자(exe)를 실행하시면 됩니다. macOS 와 Linux 는 압축을 풀어 실행하는 프리뷰 빌드입니다. 전체 버전 이력 및 소스 코드는 <a href="https://git.chanpaca.net/Video-Downloader/releases" style="color:var(--accent);font-weight:700" target="_blank" rel="noopener">릴리스 저장소</a>에서 확인하실 수 있습니다.
</p>
</div> </div>
</aside> </aside>
<!-- Releases Main Container -->
<main id="release-root" aria-live="polite"> <main id="release-root" aria-live="polite">
<div class="rel-empty glass" id="release-loading"> <div class="bezel-shell rel-empty" id="release-loading">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg> <svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg>
<h2>릴리스 목록을 불러오는 중</h2> <h2>릴리스 목록을 불러오는 중입니다</h2>
<p>잠시만 기다려 주세요.</p> <p style="color:var(--text-secondary)">잠시만 기다려 주세요.</p>
</div> </div>
</main> </main>
</div> </div>
<!-- Footer -->
<footer> <footer>
<div class="wrap footer__row"> <div class="wrap footer__row">
<span class="footer__brand">MEDIABROWSER</span> <div class="footer__brand">
<span class="nav__logo-badge" style="width:26px;height:26px;border-radius:7px">
<svg class="icon" style="width:14px;height:14px" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg>
</span>
<span>MEDIABROWSER</span>
</div>
<div class="footer__links">
<a href="releases.html">다운로드</a> <a href="releases.html">다운로드</a>
<a href="guide.html">사용 안내</a> <a href="guide.html">사용 안내</a>
<a href="https://git.chanpaca.net/Video-Downloader/releases" rel="noopener">릴리스 저장소</a> <a href="https://git.chanpaca.net/Video-Downloader/releases" target="_blank" rel="noopener">릴리스 저장소</a>
<span class="footer__copy">© 2026 MEDIABROWSER</span> </div>
<div class="footer__copy">
&copy; 2026 MEDIABROWSER. All rights reserved.
</div>
</div> </div>
</footer> </footer>

View file

@ -1,31 +1,91 @@
// MEDIABROWSER 사이트 공용 스크립트 // MEDIABROWSER Official Site Script
// 1) 스크롤 등장(reveal) — IntersectionObserver, 모션 축소 설정이면 즉시 표시 // 1) IntersectionObserver Scroll Reveal
// 2) releases.html — releases.json(배포 시 생성)을 읽어 릴리스 목록 렌더 // 2) Mobile Navigation Menu Controller
// 3) Hero UI Simulator Micro-Interactions
// 4) Dynamic Releases Renderer (releases.json)
// ── 1. Scroll Reveal Controller ──────────────────────────────
(function initReveal() { (function initReveal() {
const items = document.querySelectorAll(".reveal"); const items = document.querySelectorAll(".reveal");
if (!items.length) return; if (!items.length) return;
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches || !("IntersectionObserver" in window)) { if (window.matchMedia("(prefers-reduced-motion: reduce)").matches || !("IntersectionObserver" in window)) {
return; // .js 게이트를 켜지 않으면 CSS 기본값(표시 상태) 그대로 return;
} }
document.documentElement.classList.add("js"); document.documentElement.classList.add("js");
const io = new IntersectionObserver((entries) => { const io = new IntersectionObserver((entries) => {
for (const e of entries) { for (const e of entries) {
if (e.isIntersecting) { e.target.classList.add("in"); io.unobserve(e.target); } if (e.isIntersecting) {
e.target.classList.add("in");
io.unobserve(e.target);
} }
}, { threshold: 0.15, rootMargin: "0px 0px -8% 0px" }); }
}, { threshold: 0.12, rootMargin: "0px 0px -6% 0px" });
items.forEach((el) => io.observe(el)); items.forEach((el) => io.observe(el));
})(); })();
// ── 릴리스 렌더 ────────────────────────────────────────────── // ── 2. Mobile Nav Drawer Controller ──────────────────────────
(function initMobileNav() {
const toggleBtn = document.getElementById("nav-toggle");
const overlay = document.getElementById("mobile-menu");
if (!toggleBtn || !overlay) return;
function toggleMenu() {
const isActive = overlay.classList.toggle("is-active");
toggleBtn.setAttribute("aria-expanded", String(isActive));
document.body.style.overflow = isActive ? "hidden" : "";
}
toggleBtn.addEventListener("click", toggleMenu);
overlay.querySelectorAll(".mobile-menu-link").forEach((link) => {
link.addEventListener("click", () => {
overlay.classList.remove("is-active");
toggleBtn.setAttribute("aria-expanded", "false");
document.body.style.overflow = "";
});
});
})();
// ── 3. Hero UI Simulator Micro-Animation ─────────────────────
(function initHeroSimulator() {
const progressEl = document.getElementById("sim-progress");
const percentEl = document.getElementById("sim-percent");
const speedEl = document.getElementById("sim-speed");
if (!progressEl || !percentEl || !speedEl) return;
let current = 72;
let direction = 1;
setInterval(() => {
if (window.matchMedia("(prefers-reduced-motion: reduce)").matches) return;
if (direction === 1) {
current += 0.8;
if (current >= 96) direction = -1;
} else {
current = 64;
direction = 1;
}
const rounded = Math.min(99, Math.floor(current));
progressEl.style.width = rounded + "%";
percentEl.textContent = rounded + "%";
const baseSpeed = 18.2 + (Math.random() * 2.4 - 1.2);
speedEl.textContent = baseSpeed.toFixed(1) + " MB/s";
}, 1200);
})();
// ── 4. Releases Renderer ─────────────────────────────────────
const PLATFORMS = [ const PLATFORMS = [
{ id: "windows", label: "Windows", icon: "windows-logo", sub: "설치자를 실행하면 됩니다", { id: "windows", label: "Windows", icon: "windows-logo", sub: "x64 및 ARM64 네이티브 설치자 (exe)",
match: (n) => /setup.*\.exe$/i.test(n) || /win/i.test(n) }, match: (n) => /setup.*\.exe$/i.test(n) || /win/i.test(n) },
{ id: "macos", label: "macOS 프리뷰", icon: "apple-logo", sub: "tar.gz 를 풀어 실행하는 프리뷰 빌드", { id: "macos", label: "macOS 프리뷰", icon: "apple-logo", sub: "Apple Silicon & Intel tar.gz 프리뷰 빌드",
match: (n) => /osx|darwin|mac/i.test(n) }, match: (n) => /osx|darwin|mac/i.test(n) },
{ id: "linux", label: "Linux 프리뷰", icon: "linux-logo", sub: "tar.gz 를 풀어 실행하는 프리뷰 빌드", { id: "linux", label: "Linux 프리뷰", icon: "linux-logo", sub: "Ubuntu, Fedora, Arch tar.gz 프리뷰 빌드",
match: (n) => /linux/i.test(n) }, match: (n) => /linux/i.test(n) },
{ id: "android", label: "Android", icon: "android-logo", sub: "컴패니언 앱 APK", { id: "android", label: "Android", icon: "android-logo", sub: "스마트폰 로컬 스트리밍 컴패니언 APK",
match: (n) => /\.apk$/i.test(n) }, match: (n) => /\.apk$/i.test(n) },
]; ];
@ -56,8 +116,14 @@ function esc(s) {
function assetRow(a, recommended) { function assetRow(a, recommended) {
return `<div class="dl-asset"> return `<div class="dl-asset">
<div><div class="dl-asset__name">${esc(a.name)}</div><div class="dl-asset__size">${fmtSize(a.size)}</div></div> <div>
<a class="btn btn--primary btn--sm ${recommended ? "dl-reco" : ""}" href="${esc(a.url)}" title="${recommended ? "이 기기에 권장" : ""}">받기</a> <div class="dl-asset__name">${esc(a.name)}</div>
<div class="dl-asset__size text-mono">${fmtSize(a.size)} ${recommended ? '<span style="color:var(--accent);font-weight:700">· 현재 기기에 권장</span>' : ''}</div>
</div>
<a class="btn btn--primary btn--sm ${recommended ? "dl-reco" : ""}" href="${esc(a.url)}" title="${recommended ? "현재 기기에 권장" : ""}">
<span>다운로드</span>
<span class="btn__icon-badge"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#download-simple"/></svg></span>
</a>
</div>`; </div>`;
} }
@ -68,64 +134,85 @@ function groupsHtml(assets) {
list.forEach((a) => used.add(a.name)); list.forEach((a) => used.add(a.name));
if (!list.length) return ""; if (!list.length) return "";
return `<div class="dl-group" id="${p.id}"> return `<div class="dl-group" id="${p.id}">
<div class="dl-group__head"><svg class="icon" aria-hidden="true"><use href="assets/icons.svg#${p.icon}"/></svg>${p.label}</div> <div class="dl-group__head">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#${p.icon}"/></svg>
<span>${p.label}</span>
</div>
<div class="dl-group__sub">${p.sub}</div> <div class="dl-group__sub">${p.sub}</div>
${list.map((a) => assetRow(a, detectPreferredAsset(a.name))).join("")} ${list.map((a) => assetRow(a, detectPreferredAsset(a.name))).join("")}
</div>`; </div>`;
}).filter(Boolean); }).filter(Boolean);
const rest = assets.filter((a) => !used.has(a.name)); const rest = assets.filter((a) => !used.has(a.name));
if (rest.length) { if (rest.length) {
groups.push(`<div class="dl-group"><div class="dl-group__head">기타</div><div class="dl-group__sub">그 밖의 파일</div> groups.push(`<div class="dl-group">
${rest.map((a) => assetRow(a, false)).join("")}</div>`); <div class="dl-group__head">기타 아카이브</div>
<div class="dl-group__sub">추가 바이너리 및 체크섬 파일</div>
${rest.map((a) => assetRow(a, false)).join("")}
</div>`);
} }
return `<div class="dl-groups">${groups.join("")}</div>`; return `<div class="dl-groups">${groups.join("")}</div>`;
} }
function releaseCard(r, featured) { function releaseCard(r, featured) {
const pill = r.prerelease ? `<span class="rel-pill rel-pill--pre">프리뷰</span>` : `<span class="rel-pill">안정판</span>`; const pill = r.prerelease ? `<span class="rel-pill rel-pill--pre">프리뷰 빌드</span>` : `<span class="rel-pill">공식 안정판</span>`;
const meta = `<div class="rel-featured__meta"> const meta = `<div class="rel-featured__meta">
<span class="rel-featured__tag">${esc(r.name || r.tag)}</span>${pill} <span class="rel-featured__tag">${esc(r.name || r.tag)}</span>
<span class="rel-featured__date">${fmtDate(r.published_at)}</span> ${pill}
<span class="rel-featured__date text-mono">${fmtDate(r.published_at)}</span>
</div> </div>
${r.notes ? `<p class="rel-featured__notes">${esc(r.notes)}</p>` : ""} ${r.notes ? `<p class="rel-featured__notes">${esc(r.notes)}</p>` : ""}
${groupsHtml(r.assets)}`; ${groupsHtml(r.assets)}`;
if (featured) return `<article class="rel-featured glass">${meta}</article>`;
return `<details><summary><span class="rel-featured__tag" style="font-size:19px">${esc(r.name || r.tag)}</span>${pill} if (featured) {
<span class="rel-featured__date">${fmtDate(r.published_at)}</span></summary> return `<article class="bezel-shell"><div class="bezel-inner rel-featured">${meta}</div></article>`;
<div class="rel-old__body">${r.notes ? `<p class="rel-featured__notes">${esc(r.notes)}</p>` : ""}${groupsHtml(r.assets)}</div> }
</details>`; return `<div class="bezel-shell"><div class="bezel-inner"><details>
<summary>
<span class="rel-featured__tag" style="font-size:1.15rem">${esc(r.name || r.tag)}</span>
${pill}
<span class="rel-featured__date text-mono">${fmtDate(r.published_at)}</span>
<svg class="icon faq-chevron" style="margin-left:8px"><use href="assets/icons.svg#caret-down"/></svg>
</summary>
<div class="rel-old__body">
${r.notes ? `<p class="rel-featured__notes">${esc(r.notes)}</p>` : ""}
${groupsHtml(r.assets)}
</div>
</details></div></div>`;
} }
function emptyState() { function emptyState() {
return `<div class="rel-empty glass"> return `<div class="bezel-shell rel-empty">
<svg class="icon" aria-hidden="true"><use href="assets/icons.svg#rocket-launch"/></svg> <svg class="icon" aria-hidden="true"><use href="assets/icons.svg#rocket-launch"/></svg>
<h2>첫 공개 릴리스를 준비하고 있어요</h2> <h2>첫 공개 릴리스를 준비하고 있습니다</h2>
<p>빌드 파이프라인은 이미 돌아가고 있습니다. 곧 이 자리에서 설치자를 받을 수 있습니다. <p style="color:var(--text-secondary);max-width:54ch">빌드 파이프라인이 정상 작동 중이며 곧 공식 설치자가 배포됩니다. 먼저 <a href="guide.html" style="color:var(--accent);font-weight:700">사용 안내</a>를 둘러보세요.</p>
먼저 <a href="guide.html" style="color:var(--accent);font-weight:700;text-decoration:none">사용 안내</a>를 둘러보세요.</p>
</div>`; </div>`;
} }
(async function initReleases() { (async function initReleases() {
const root = document.getElementById("release-root"); const root = document.getElementById("release-root");
if (!root) return; if (!root) return;
try { try {
const res = await fetch("releases.json", { cache: "no-cache" }); const res = await fetch("releases.json", { cache: "no-cache" });
if (!res.ok) throw new Error("HTTP " + res.status); if (!res.ok) throw new Error("HTTP " + res.status);
const data = await res.json(); const data = await res.json();
const releases = (data.releases || []); const releases = (data.releases || []);
if (!releases.length) { root.innerHTML = emptyState(); return; } if (!releases.length) {
root.innerHTML = emptyState();
return;
}
const [latest, ...older] = releases; const [latest, ...older] = releases;
let html = releaseCard(latest, true); let html = releaseCard(latest, true);
if (older.length) { if (older.length) {
html += `<div class="rel-old"><h2 style="font-size:20px;margin-top:14px">이전 버전</h2> html += `<div class="rel-old"><h2 style="font-size:1.35rem;margin-bottom:14px">이전 버전 기록</h2>
${older.map((r) => releaseCard(r, false)).join("")}</div>`; ${older.map((r) => releaseCard(r, false)).join("")}</div>`;
} }
root.innerHTML = html; root.innerHTML = html;
} catch (err) { } catch (err) {
root.innerHTML = `<div class="rel-empty glass"> root.innerHTML = `<div class="bezel-shell rel-empty">
<h2>목록을 불러오지 못했어요</h2> <h2>릴리스 목록을 불러오지 못했습니다</h2>
<p>잠시 후 새로고침해 주세요. 급하다면 <p style="color:var(--text-secondary)">네트워크 상태를 확인하고 새로고침해 주세요. 급하신 경우 <a href="https://git.chanpaca.net/Video-Downloader/releases" style="color:var(--accent);font-weight:700" target="_blank" rel="noopener">릴리스 저장소</a>에서 직접 다운로드하실 수 있습니다.</p>
<a href="https://git.chanpaca.net/Video-Downloader/releases" style="color:var(--accent);font-weight:700;text-decoration:none" rel="noopener">릴리스 저장소</a>에서 직접 받을 수 있습니다.</p>
</div>`; </div>`;
} }
})(); })();

File diff suppressed because it is too large Load diff