diff --git a/README.md b/README.md
@@ -19,7 +19,7 @@ Vercel, Cloudflare Pages, or a plain directory served over HTTP.
```bash
curl -fsSL https://sqzass.sqzer.com/install.sh | sh # static binary
cargo install --git https://github.com/sqzer-x/sqzass # from source
-paru -S sqzass # Arch, from the AUR
+yay -S sqzass # Arch, from the AUR
```
Every release also carries the tarballs directly, for Linux on x86_64 and ARM64
diff --git a/docs/content/_index.ko.md b/docs/content/_index.ko.md
@@ -11,8 +11,8 @@ hero_title_b = "25밀리초로 쥐어짭니다."
hero_sub = "이름 그대로입니다. 사이트 전체를 한 번에 짜냅니다 — Hugo·Zola·Jekyll·Astro와 같은 머신에서 직접 재고, 측정 방법도 전부 공개해 뒀습니다."
cta_start = "시작하기"
cta_github = "GitHub에서 보기"
-install_alt = "Rust가 있다면 이렇게도 됩니다:"
-install_aur = "Arch라면:"
+install_pick = "설치 방법"
+install_note = "릴리스마다 체크섬이 붙은 타르볼도 함께 나갑니다 — x86_64·ARM64 리눅스, Apple Silicon macOS."
bento_label = "왜 sqzass인가"
@@ -23,6 +23,17 @@ zero_label = "같은 입력을 두 번 빌드했을 때 생기는 바이트 차
foot_benchmark = "벤치마크"
+[[extra.install]]
+label = "curl"
+
+[[extra.install]]
+label = "cargo"
+cmd = "cargo install --git https://github.com/sqzer-x/sqzass"
+
+[[extra.install]]
+label = "AUR"
+cmd = "yay -S sqzass"
+
[[extra.bench]]
label = "1,000페이지, 최소 마크다운"
us_ms = "18"
diff --git a/docs/content/_index.md b/docs/content/_index.md
@@ -11,8 +11,8 @@ hero_title_b = "squeezed into 25 ms."
hero_sub = "The name is the promise: press a whole site out in one go. Measured against Hugo, Zola, Jekyll and Astro on the same machine, with the method published."
cta_start = "Get started"
cta_github = "View on GitHub"
-install_alt = "With Rust instead:"
-install_aur = "On Arch:"
+install_pick = "Install with"
+install_note = "Every release also ships tarballs with checksums — Linux on x86_64 and ARM64, and Apple-silicon macOS."
bento_label = "Why sqzass"
@@ -23,6 +23,18 @@ zero_label = "bytes of difference between two builds of the same input — check
foot_benchmark = "Benchmark"
+[[extra.install]]
+label = "curl"
+# cmd 없음 = 템플릿이 이 사이트의 origin으로 조립한다. 프리뷰 배포에서도 맞는 URL이 나온다.
+
+[[extra.install]]
+label = "cargo"
+cmd = "cargo install --git https://github.com/sqzer-x/sqzass"
+
+[[extra.install]]
+label = "AUR"
+cmd = "yay -S sqzass"
+
[[extra.bench]]
label = "1,000 pages, minimal markdown"
us_ms = "18"
diff --git a/docs/content/start/installation.ko.md b/docs/content/start/installation.ko.md
@@ -35,7 +35,7 @@ AUR에 [`sqzass`](https://aur.archlinux.org/packages/sqzass)가 있습니다.
태그에서 빌드합니다.
```bash
-paru -S sqzass # yay도, 클론해서 makepkg -si도 됩니다
+yay -S sqzass # paru도, 클론해서 makepkg -si도 됩니다
```
`sqzass-bin`은 만들지 않았습니다. Arch에서 Rust 도구를 소스에서 빌드하는 건
diff --git a/docs/content/start/installation.md b/docs/content/start/installation.md
@@ -35,7 +35,7 @@ cargo install --git https://github.com/sqzer-x/sqzass
the release tag:
```bash
-paru -S sqzass # or yay, or makepkg -si on a clone
+yay -S sqzass # or paru, or makepkg -si on a clone
```
There is no `sqzass-bin`. Building a Rust tool from source is normal on Arch,
diff --git a/docs/static/css/landing.css b/docs/static/css/landing.css
@@ -325,19 +325,80 @@ main { display: block; }
}
/* 설치 한 줄 — 페이지에서 제일 중요한 것. CTA 바로 아래에서 눈에 띈다. */
+/* 채널 선택 + 명령. fieldset이라 기본 테두리·여백을 먼저 지운다.
+ align-items: flex-start라서 탭 행도 명령 상자도 제 내용만큼만 넓어진다. */
.install {
- display: inline-flex;
+ display: flex;
+ flex-direction: column;
+ align-items: flex-start;
+ gap: 0.5rem;
+ max-width: 100%;
+ border: 0;
+ padding: 0;
+ margin: 1.6rem 0 0;
+ min-width: 0;
+}
+.pick-tabs { display: flex; flex-wrap: wrap; gap: 0.4rem; }
+.pick-in {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ opacity: 0;
+ pointer-events: none;
+}
+.pick-tab {
+ cursor: pointer;
+ font-family: var(--mono);
+ font-size: 0.82rem;
+ line-height: 1;
+ color: var(--muted);
+ padding: 0.42rem 0.72rem;
+ border: 1px solid var(--line);
+ border-radius: 999px;
+ background: transparent;
+ transition: color 0.15s, border-color 0.15s, background 0.15s;
+}
+.pick-tab:hover { color: var(--ink); border-color: var(--ink-3); }
+.pick-in:checked + .pick-tab {
+ color: var(--accent-ink);
+ border-color: rgba(255, 140, 90, 0.55);
+ background: rgba(255, 120, 70, 0.1);
+}
+/* 라디오가 화면에 없으므로 포커스 링은 라벨이 받는다. 없으면 키보드로 못 쓴다. */
+.pick-in:focus-visible + .pick-tab {
+ outline: 2px solid var(--accent);
+ outline-offset: 2px;
+}
+
+.pick-panel {
+ display: none;
align-items: center;
gap: 0.4rem;
+ min-width: 0;
max-width: 100%;
border: 1px solid rgba(255, 140, 90, 0.45);
border-radius: 13px;
background: var(--bg-hi);
box-shadow: 0 4px 22px rgba(255, 110, 60, 0.16);
padding: 0.72rem 0.55rem 0.72rem 1.05rem;
- margin: 1.6rem 0 0;
}
-.install > code {
+/* 패널만 따로 감싼 건 `nth-child`를 정확히 세기 위해서다. fieldset 바로 아래에
+ 두면 legend와 탭 행까지 형제로 세어 한 칸씩 밀린다 — 실제로 그렇게 밀려서
+ AUR 탭에 cargo 명령이 나왔다.
+
+ 첫 패널이 기본이다. `:has()`를 모르는 브라우저에서도 curl 명령은 그대로
+ 보이고 탭만 안 먹는다 — 이 페이지에서 가장 중요한 내용이 사라지면 안 된다.
+ 채널이 셋인 건 packaging/README.md의 결정이고, 늘리면 여기도 는다. */
+.pick-panels { min-width: 0; max-width: 100%; }
+.pick-panel:first-child { display: flex; }
+.install:has(#inst-2:checked) .pick-panel { display: none; }
+.install:has(#inst-2:checked) .pick-panel:nth-child(2) { display: flex; }
+.install:has(#inst-3:checked) .pick-panel { display: none; }
+.install:has(#inst-3:checked) .pick-panel:nth-child(3) { display: flex; }
+
+.install-note { margin: 0.7rem 0 0; font-size: 0.82rem; color: var(--muted); }
+
+.pick-panel > code {
font-family: var(--mono);
font-size: 0.92rem;
font-weight: 700;
@@ -346,11 +407,18 @@ main { display: block; }
overflow-x: auto;
scrollbar-width: none;
}
-.install-alt { margin: 0.7rem 0 0; font-size: 0.9rem; color: var(--muted); }
-/* 좁은 화면에서는 두 대안이 각자 줄을 갖도록 구분자에서 끊는다. */
-.alt-sep { margin: 0 0.35rem; opacity: 0.55; }
-@media (max-width: 34rem) {
- .alt-sep { display: block; height: 0; margin: 0.35rem 0 0; overflow: hidden; }
+/* 화면에서는 안 보이고 스크린리더에는 읽히는 것. fieldset의 legend가 그렇다 —
+ 눈으로는 버튼 행 자체가 무엇을 고르는지 말해 주지만, 소리로는 아니다. */
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ padding: 0;
+ margin: -1px;
+ overflow: hidden;
+ clip-path: inset(50%);
+ white-space: nowrap;
+ border: 0;
}
.inline { font-family: var(--mono); font-size: 0.85em; color: var(--accent-ink); }
.inst-copy {
diff --git a/docs/templates/landing.html b/docs/templates/landing.html
@@ -80,22 +80,35 @@
<a class="btn btn-primary" href="{{ home }}start/">{{ page.extra.cta_start }}</a>
<a class="btn btn-ghost" href="https://github.com/sqzer-x/sqzass">{{ page.extra.cta_github }}</a>
</p>
- {#- 제일 중요한 것: 설치 한 줄. CTA 바로 아래에 크게 둔다. #}
- <div class="install" data-reveal>
- <code>curl -fsSL {{ site.origin }}{{ site.base_path }}/install.sh | sh</code>
- <button class="inst-copy" type="button" data-copy-text="curl -fsSL {{ site.origin }}{{ site.base_path }}/install.sh | sh"
- aria-label="{{ t("copy") }}" data-copied="{{ t("copied") }}">
- <svg class="i-copy" viewBox="0 0 24 24" width="16" height="16" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>
- <svg class="i-check" viewBox="0 0 24 24" width="16" height="16" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
- </button>
- </div>
- {#- 나머지 두 채널. 큰 블록은 curl 하나로 두고, 여기서 한 줄에 붙인다 —
- 셋을 나란히 크게 놓으면 "무엇을 골라야 하나"가 첫 질문이 된다. #}
- <p class="install-alt" data-reveal>
- {{ page.extra.install_alt }} <code class="inline">cargo install --git https://github.com/sqzer-x/sqzass</code>
- <span class="alt-sep" aria-hidden="true">·</span>
- {{ page.extra.install_aur }} <code class="inline">paru -S sqzass</code>
- </p>
+ {#- 제일 중요한 것: 설치 명령. CTA 바로 아래에 크게 둔다.
+
+ 채널 전환은 radio + CSS만으로 한다. JS 없이도 세 명령이 전부 DOM에 있고
+ 선택이 동작한다 — 이 페이지에서 가장 중요한 내용이 스크립트 로딩에
+ 기대면 안 된다. radio를 쓴 건 접근성 때문이기도 하다: 스크린리더가
+ "curl, 라디오 버튼, 선택됨, 3개 중 1"로 읽는 게 이 UI의 실제 의미다. #}
+ <fieldset class="install" data-reveal>
+ <legend class="sr-only">{{ page.extra.install_pick }}</legend>
+ <div class="pick-tabs">
+ {%- for m in page.extra.install %}
+ <input class="pick-in" type="radio" name="install-channel" id="inst-{{ loop.index }}"{% if loop.first %} checked{% endif %}>
+ <label class="pick-tab" for="inst-{{ loop.index }}">{{ m.label }}</label>
+ {%- endfor %}
+ </div>
+ <div class="pick-panels">
+ {%- for m in page.extra.install %}
+ {%- set cmd = m.cmd if m.cmd else "curl -fsSL " ~ site.origin ~ site.base_path ~ "/install.sh | sh" %}
+ <div class="pick-panel">
+ <code>{{ cmd }}</code>
+ <button class="inst-copy" type="button" data-copy-text="{{ cmd }}"
+ aria-label="{{ t("copy") }}" data-copied="{{ t("copied") }}">
+ <svg class="i-copy" viewBox="0 0 24 24" width="16" height="16" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h10"/></svg>
+ <svg class="i-check" viewBox="0 0 24 24" width="16" height="16" aria-hidden="true" focusable="false" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
+ </button>
+ </div>
+ {%- endfor %}
+ </div>
+ </fieldset>
+ <p class="install-note" data-reveal>{{ page.extra.install_note }}</p>
<div class="lede" data-reveal>
{{ page.content | safe }}
</div>
|