feat(site): redesign promotion experience

This commit is contained in:
Yun Chan 2026-08-30 17:52:54 +09:00
parent 6930906583
commit 13dd160c16
39 changed files with 5764 additions and 5738 deletions

View file

@ -0,0 +1,501 @@
---
import CopyCommand from "./CopyCommand.astro";
import HeroSystemGraphic from "./HeroSystemGraphic.astro";
import OutputSpecimens from "./OutputSpecimens.astro";
import type { LandingContent } from "../i18n/landing";
interface Props {
c: LandingContent;
lang: "ko" | "en";
}
const { c, lang } = Astro.props;
const repoUrl = "https://git.chanpaca.net/yunchan/designpaca";
const docsUrl = `${repoUrl}#readme`;
const showcasePath = lang === "ko" ? "/showcase/" : "/en/showcase/";
const copyLabel = c.hero.primaryCta;
const copiedLabel = lang === "ko" ? "복사했어요" : "Copied";
---
<section class="landing-hero grain" aria-labelledby="hero-title">
<div class="hero-grid shell">
<div class="hero-copy">
<h1 id="hero-title">
{c.hero.h1.split("\n").map((line) => <span>{line}</span>)}
</h1>
<p class="hero-lead">{c.hero.lead}</p>
<div class="hero-actions">
<CopyCommand
command={c.hero.command}
copyLabel={copyLabel}
copiedLabel={copiedLabel}
/>
<a class="btn btn-text" href="#outputs">
{c.hero.secondaryCta}
<svg viewBox="0 0 16 16" width="15" height="15" aria-hidden="true">
<path d="M3 5.5 8 10l5-4.5" />
</svg>
</a>
</div>
</div>
<div class="hero-visual">
<HeroSystemGraphic lang={lang} />
</div>
</div>
</section>
<section id="outputs" class="output-section">
<div class="section-head shell">
<h2>{c.outputs.h2}</h2>
<div>
<p>{c.outputs.lead}</p>
<a class="section-link" href={showcasePath}>
{c.outputs.archiveCta}
<svg viewBox="0 0 16 16" width="15" height="15" aria-hidden="true">
<path d="M3 8h10M9 4l4 4-4 4" />
</svg>
</a>
</div>
</div>
<div class="output-surface shell">
<OutputSpecimens lang={lang} />
</div>
</section>
<section id="process" class="process-section grain">
<div class="process-grid shell">
<header class="process-head">
<h2>{c.process.h2}</h2>
<p>{c.process.lead}</p>
</header>
<ol class="stage-list">
{c.process.stages.map((stage) => (
<li>
<span class="stage-index nums">{stage.step}</span>
<h3>{stage.name}</h3>
<p>{stage.result}</p>
</li>
))}
</ol>
</div>
</section>
<section id="proof" class="proof-section">
<div class="section-head shell">
<h2>{c.proof.h2}</h2>
<p>{c.proof.lead}</p>
</div>
<dl class="proof-facts shell">
{c.proof.facts.map((fact) => (
<div>
<dt>
<span class="proof-value nums">{fact.value}</span>
<span>{fact.label}</span>
</dt>
<dd>{fact.description}</dd>
</div>
))}
</dl>
<details class="audit-details shell">
<summary>
<span>{c.proof.details.summary}</span>
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
<path d="M3 5.5 8 10l5-4.5" />
</svg>
</summary>
<ol>
{c.proof.details.items.map((item) => <li>{item}</li>)}
</ol>
</details>
</section>
<section id="install" class="install-section">
<div class="install-grid shell">
<div>
<h2>{c.install.h2}</h2>
<p class="install-lead">{c.install.lead}</p>
</div>
<div class="install-action">
<CopyCommand
command={c.install.command}
copyLabel={copyLabel}
copiedLabel={copiedLabel}
/>
<ul>
{c.install.support.map((item) => (
<li>
<svg viewBox="0 0 16 16" width="16" height="16" aria-hidden="true">
<path d="m3 8 3 3 7-7" />
</svg>
<span>{item}</span>
</li>
))}
</ul>
<div class="install-links">
<a href={docsUrl}>{c.install.docsLabel}</a>
<a href={repoUrl}>{c.install.repoLabel}</a>
</div>
</div>
</div>
</section>
<footer class="site-footer">
<div class="shell">
<p>{c.footer.tagline}</p>
<p>{c.footer.license}</p>
</div>
</footer>
<style>
.landing-hero {
padding-block: var(--space-7) var(--space-9);
border-bottom: var(--line-width) solid var(--line);
}
.hero-grid {
display: grid;
grid-template-columns: minmax(0, 0.82fr) minmax(34rem, 1.18fr);
gap: var(--space-8);
align-items: center;
}
.hero-copy {
display: grid;
align-content: center;
min-width: 0;
}
.hero-copy h1 span { display: block; }
.hero-lead {
max-width: var(--measure-narrow);
margin-top: var(--space-6);
color: var(--ink-muted);
font-size: var(--step-1);
}
.hero-actions {
margin-top: var(--space-7);
display: flex;
align-items: center;
gap: var(--space-3);
flex-wrap: wrap;
}
.hero-actions :global(.cmd-shell) { width: min(100%, 31rem); }
.hero-actions .btn-text svg,
.section-link svg,
.audit-details summary svg,
.install-action li svg {
fill: none;
stroke: currentColor;
stroke-width: 1.5;
stroke-linecap: round;
stroke-linejoin: round;
flex: none;
}
.hero-visual {
display: flex;
justify-content: center;
min-width: 0;
}
.output-section,
.proof-section {
padding-block: var(--space-9);
}
.section-head {
display: grid;
grid-template-columns: minmax(0, 1fr) minmax(20rem, 0.82fr);
gap: var(--space-8);
align-items: start;
}
.section-head > div,
.section-head > p {
max-width: var(--measure-narrow);
color: var(--ink-muted);
}
.section-link {
min-height: var(--control-h);
width: fit-content;
display: inline-flex;
align-items: center;
gap: var(--space-2);
margin-top: var(--space-5);
color: var(--ink);
font-weight: var(--weight-medium);
}
.output-surface {
margin-top: var(--space-8);
}
.process-section {
padding-block: var(--space-9);
background: var(--surface-inverse);
color: var(--ink-inverse);
}
.process-section.grain::after {
mix-blend-mode: screen;
opacity: 0.035;
}
.process-grid {
display: grid;
grid-template-columns: minmax(18rem, 0.72fr) minmax(0, 1.28fr);
gap: var(--space-8);
align-items: start;
}
.process-head {
position: sticky;
top: calc(var(--header-h) + var(--space-6));
}
.process-head p {
max-width: var(--measure-narrow);
margin-top: var(--space-5);
color: var(--ink-muted-inverse);
}
.stage-list {
list-style: none;
margin: 0;
padding: 0;
border-top: var(--line-width) solid var(--line-inverse);
}
.stage-list li {
position: relative;
display: grid;
grid-template-columns: 2.5rem minmax(10rem, 0.62fr) minmax(0, 1fr);
gap: var(--space-4) var(--space-6);
align-items: baseline;
padding-block: var(--space-5);
border-bottom: var(--line-width) solid var(--line-inverse);
}
.stage-index {
color: var(--accent);
font-weight: var(--weight-medium);
}
.stage-list h3 { font-size: var(--step-1); }
.stage-list p {
color: var(--ink-muted-inverse);
font-size: var(--step-0);
}
@supports (animation-timeline: view()) {
@media (prefers-reduced-motion: no-preference) {
.stage-list li::after {
content: "";
position: absolute;
inset-inline-start: 0;
bottom: calc(var(--line-width) * -1);
width: 2.5rem;
height: var(--line-width);
background: var(--accent);
transform-origin: left center;
animation: stage-rail-register linear both;
animation-timeline: view(block);
animation-range: entry 12% cover 32%;
}
@keyframes stage-rail-register {
from { opacity: 0.25; transform: scaleX(0); }
to { opacity: 1; transform: scaleX(1); }
}
}
}
.proof-facts {
margin-top: var(--space-8);
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
border-block: var(--line-width) solid var(--line-strong);
}
.proof-facts > div {
min-width: 0;
padding: var(--space-6);
}
.proof-facts > div + div { border-left: var(--line-width) solid var(--line); }
.proof-facts dt { display: grid; gap: var(--space-2); }
.proof-value {
color: var(--accent);
font-size: clamp(2.5rem, 2rem + 2vw, 4rem);
font-weight: var(--weight-medium);
line-height: 1;
}
.proof-facts dd {
margin-top: var(--space-4);
color: var(--ink-muted);
font-size: var(--step--1);
}
.audit-details {
margin-top: var(--space-6);
border-bottom: var(--line-width) solid var(--line-strong);
}
.audit-details summary {
min-height: var(--control-h);
display: flex;
align-items: center;
justify-content: space-between;
gap: var(--space-4);
padding-block: var(--space-4);
font-weight: var(--weight-medium);
list-style: none;
}
.audit-details summary::-webkit-details-marker { display: none; }
.audit-details summary::marker { content: ""; }
.audit-details summary svg { transition: transform var(--dur-quick) var(--ease-out); }
.audit-details[open] summary svg { transform: rotate(180deg); }
.audit-details ol {
margin: 0;
padding: 0 0 var(--space-6);
list-style: none;
counter-reset: audit;
}
.audit-details li {
counter-increment: audit;
display: grid;
grid-template-columns: 2rem minmax(0, 1fr);
gap: var(--space-3);
padding-block: var(--space-3);
border-top: var(--line-width) solid var(--line);
color: var(--ink-muted);
}
.audit-details li::before {
content: counter(audit, decimal-leading-zero);
color: var(--accent);
font-family: var(--font-mono);
font-size: var(--mono-size);
}
.install-section {
padding-block: var(--space-9);
background: var(--surface-soft);
border-block: var(--line-width) solid var(--line);
}
.install-grid {
display: grid;
grid-template-columns: minmax(0, 0.95fr) minmax(28rem, 1.05fr);
gap: var(--space-8);
align-items: start;
}
.install-lead {
max-width: var(--measure-narrow);
margin-top: var(--space-5);
color: var(--ink-muted);
}
.install-action :global(.cmd-shell) { max-width: none; }
.install-action ul {
list-style: none;
margin: var(--space-6) 0 0;
padding: 0;
border-top: var(--line-width) solid var(--line);
}
.install-action li {
min-height: var(--control-h);
display: flex;
align-items: center;
gap: var(--space-3);
padding-block: var(--space-3);
border-bottom: var(--line-width) solid var(--line);
}
.install-action li svg { color: var(--accent); }
.install-links {
display: flex;
flex-wrap: wrap;
gap: var(--space-4) var(--space-6);
margin-top: var(--space-6);
}
.install-links a {
min-height: var(--control-h);
display: inline-flex;
align-items: center;
font-weight: var(--weight-medium);
}
.site-footer { padding-block: var(--space-7); }
.site-footer .shell {
display: flex;
align-items: flex-end;
justify-content: space-between;
gap: var(--space-6);
color: var(--ink-muted);
font-size: var(--step--1);
}
.site-footer p:first-child { max-width: 32rem; color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.audit-details summary svg { transition: none; }
}
@media (max-width: 68rem) {
.hero-grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-8); }
.hero-copy { max-width: 44rem; }
.process-grid { grid-template-columns: minmax(15rem, 0.62fr) minmax(0, 1.38fr); }
}
@media (max-width: 56rem) {
.hero-grid,
.section-head,
.process-grid,
.install-grid {
grid-template-columns: minmax(0, 1fr);
}
.hero-grid { gap: var(--space-8); }
.hero-copy { max-width: 44rem; }
.process-head { position: static; }
.section-head { gap: var(--space-5); }
.proof-facts { grid-template-columns: 1fr; }
.proof-facts > div + div { border-left: 0; border-top: var(--line-width) solid var(--line); }
}
@media (max-width: 47.5rem) {
.landing-hero { padding-top: var(--space-8); }
.hero-copy h1 { font-size: clamp(2.2rem, 11.2vw, 2.8125rem); }
:global(html[lang="en"]) .hero-copy h1 { font-size: clamp(2.25rem, 10.2vw, 2.65rem); }
.stage-list li {
grid-template-columns: 2rem minmax(0, 1fr);
gap: var(--space-2) var(--space-4);
}
.stage-list p { grid-column: 2; }
}
@media (max-width: 34rem) {
.hero-actions { align-items: stretch; }
.hero-actions :global(.cmd-shell),
.hero-actions .btn-text { width: 100%; }
.site-footer .shell { display: grid; align-items: start; }
}
</style>