feat: strengthen design skill and refresh all showcases
Some checks failed
ci / build (push) Has been cancelled

This commit is contained in:
Yun Chan 2026-09-12 18:16:33 +09:00
parent 69e5cc1efd
commit e09d4efb1c
257 changed files with 8196 additions and 2374 deletions

View file

@ -0,0 +1,31 @@
# 새벽청과 — 2026-09-12 화면 보정 기록
## 구도·타입·색 관찰
- 새벽 시장 사진과 제목은 시간·시장 맥락을 만들지만, 투명한 표는 사진의 명암 위에서 숫자 기준선을 잃는다.
- 낙찰가·단위·등락은 색보다 자리와 숫자 정렬로 먼저 읽혀야 한다.
- 종이·잉크·새벽 남색이라는 기존 `market-board` 토큰은 과일 사진의 색을 방해하지 않는 핵심 자산이다.
## 근거 확인 범위
- `outputs/full-showcase-upgrade-20260912/screenshots/saebyeok-cheonggwa/1440x1000-first.png`
- `index.html`, `styles/main.css`, 날짜·선택 로트·제철·납품 계산 스크립트
- 기존 표의 예시 시세·단위·거래 한계 라벨을 보존한다.
## 결정 / 기각 조건
- 사진과 제목은 어두운 상단에서 유지하고, 시세표·선택 로트·예시 안내는 불투명한 밝은 종이 표면으로 분리한다.
- 가격과 단위는 tabular 숫자와 우측 정렬을 유지하고, 표면 머리에서 예시 시세표임을 인접 표기한다.
- 사진 위 반투명 표, 숫자만 색으로 구분하는 변화, 모바일에서 정보를 버리는 축소는 기각한다.
## 토큰·규칙
- 기존 `--surface`, `--ink`, `--line`, `--accent`, `--dark-*`와 모노 서체만 사용한다.
- 모바일은 기존 라벨 카드 뷰를 유지해 모든 열 정보를 보존한다.
- 선택 상태는 `aria-pressed`, 키보드 focus, 좌측 신호선과 종이 표면의 대비로 함께 표시한다.
## 2026-09-12 현재 검증 기록
- `verify-final` 18개 묶음은 16개가 즉시 통과했다. 전체 묶음의 invariant·visual 검사는 Gaon·Dure를 대상으로 하며, 나머지 2개는 수정 뒤 release 독립 재실행에서 ALL PASS·ALL MATCH였다.
- root는 28개 모바일, 21개 데스크톱, 7개 하위 경로와 30개 앱 상태를 직접 검토해 수용했다. stress 112건은 hard failure 0이며, 가로 넘침 4건은 targeted fix 뒤 390px 재측정에서 0이다.
- 이 기록은 렌더·계약 범위의 현재 결과다. 모든 폭·키보드 경로·인쇄 등 개별 기능을 완전 재실행했다는 뜻이 아니며, 참여자 과업 효과도 미측정이다.

View file

@ -24,8 +24,8 @@
rel="stylesheet"
href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&display=swap"
/>
<link rel="stylesheet" href="./styles/tokens.css?v=2" />
<link rel="stylesheet" href="./styles/main.css?v=2" />
<link rel="stylesheet" href="./styles/tokens.css?v=20260912all" />
<link rel="stylesheet" href="./styles/main.css?v=20260912all" />
<link
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'%3E%3Crect width='32' height='32' fill='%2316181A'/%3E%3Cpath d='M6 20h20' stroke='%237FA8D9' stroke-width='2'/%3E%3Ccircle cx='13' cy='14' r='4.5' fill='none' stroke='%23F3F1EC' stroke-width='2'/%3E%3Cpath d='M13 9.5V7' stroke='%23F3F1EC' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E"
@ -80,8 +80,17 @@
값은 매일 바뀝니다. 바뀌는 값을 감추고 파는 대신, 오늘 얼마에 받아 왔는지를
먼저 적습니다.
</p>
</div>
<table class="board">
<div class="market-board-surface">
<div class="wrap">
<div class="market-board-head">
<p class="mono">오늘 경매 · 예시 시세표</p>
<p>낙찰가와 단위는 아래 표에서 함께 읽습니다.</p>
</div>
<div class="market-board-scroll" role="region" aria-label="오늘 낙찰 품목 예시 시세표" tabindex="0">
<table class="board">
<caption class="sr-only">
오늘 낙찰 품목 여섯 가지 — 산지, 등급, 당도, 규격, 낙찰가, 전일 대비
</caption>
@ -236,7 +245,8 @@
<td data-label="전일 대비" class="c-num mono delta up">▲ 1,000</td>
</tr>
</tbody>
</table>
</table>
</div>
<div class="lot-inspector" aria-live="polite" aria-atomic="true">
<div class="lot-inspector-head">
@ -284,11 +294,12 @@
두 값을 같은 것처럼 적지 않습니다.
</li>
<li class="note-demo">
위 표의 숫자는 <strong>이 쇼케이스를 위한 예시</strong>입니다. 실제 운영에서는
그날 경매 결과가 그대로 들어옵니다.
위 표의 숫자는 <strong>이 페이지의 예시 값</strong>입니다. 실제 경매 결과나
납품 정보가 아닙니다.
</li>
</ul>
</div>
</div>
</section>
<!-- ══════════════════════════════════════════════════════════
@ -638,8 +649,8 @@
<section class="order-draft" aria-labelledby="orderDraftHeading">
<div class="order-draft-head">
<h3 id="orderDraftHeading">발주 메모 만들기</h3>
<p class="mono">쇼케이스 예시</p>
<h3 id="orderDraftHeading">수량별 기준 금액 보기</h3>
<p class="mono">안내용 계산</p>
</div>
<div class="order-controls">
<label>
@ -664,15 +675,15 @@
<dd class="mono" id="orderPack">4.5 kg × 3상자</dd>
</div>
<div>
<dt>예시 낙찰가 합계</dt>
<dt>표시된 낙찰가 합계</dt>
<dd class="mono" id="orderTotal">114,000원</dd>
</div>
</dl>
<p class="order-fine">
위 합계는 판에 적힌 예시 낙찰가만 더합니다. 선별·포장·배송과 실제 납품가는 포함하지 않습니다.
위 합계는 표에 적힌 예시 낙찰가만 더한 값입니다. 선별·포장·배송과 실제 납품가는 포함하지 않습니다.
</p>
<div class="order-actions">
<button class="btn" id="copyOrder" type="button">발주 메모 복사</button>
<button class="btn" id="copyOrder" type="button">계산 내용 복사</button>
</div>
<p class="order-status" id="orderStatus" role="status"></p>
</section>
@ -700,12 +711,11 @@
</div>
<div>
<dt>메일</dt>
<dd><a class="mono" href="mailto:order@saebyeok-cheonggwa.example">order@saebyeok-cheonggwa.example</a></dd>
<dd>실제 주문 연락처는 정해지지 않았습니다</dd>
</div>
</dl>
<p class="contact-fine">
주소·전화·사업자 정보는 실제 상호가 정해진 뒤에 채웁니다.
지어낸 값을 임시로 적어 두지 않습니다.
이 페이지는 실제 주문을 받지 않습니다. 주소·전화·사업자 정보는 실제 상호가 정해진 뒤에만 안내합니다.
</p>
</div>
</div>
@ -717,8 +727,8 @@
<p class="foot-name">새벽청과</p>
<p class="foot-line">새벽 경매에서 받아 그날 아침에 보냅니다</p>
<p class="foot-fine">
이 페이지는 designpaca 쇼케이스입니다. 실제 영업하는 상호가 아니며,
판의 숫자는 화면 구성을 보이기 위한 예시입니다. 경매 시각·등급·당도 표시 규정 등
이 페이지의 품목·가격·시간은 이해를 돕기 위한 예시이며 실제 주문·납품 서비스가 아닙니다.
경매 시각·등급·당도 표시 규정 등
제도에 관한 설명은 실제 농산물 표준규격과 도매시장 운영 방식을 따릅니다.
</p>
</div>
@ -867,18 +877,18 @@
document.getElementById("copyOrder")?.addEventListener("click", async () => {
const value = orderValues();
const memo = [
"새벽청과 납품 문의",
"새벽청과 · 예시 발주 메모",
`품목: ${value.name}`,
`규격: ${value.pack}`,
`수량: ${value.quantity}상자`,
`예시 낙찰가 합계: ${value.total.toLocaleString("ko-KR")}원`,
`표시된 낙찰가 합계: ${value.total.toLocaleString("ko-KR")}원`,
"실제 납품가는 선별·포장·배송 조건을 확인한 뒤 정합니다.",
].join("\n");
try {
const copied = await copyText(memo);
if (orderStatus) {
orderStatus.textContent = copied
? "발주 메모를 복사했습니다."
? "계산 내용을 복사했습니다."
: "복사하지 못했습니다. 브라우저의 클립보드 권한을 확인해 주세요.";
}
} catch {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 KiB

After

Width:  |  Height:  |  Size: 264 KiB

Before After
Before After

View file

@ -83,6 +83,14 @@ h3 {
margin-inline: auto;
}
/* 넓은 화면에서는 시세판과 산지 정보에만 여유를 준다. 문장 길이는 기존
measure 제한을 그대로 유지해 거래판의 밀도만 개선한다. */
@media (min-width: 120rem) {
.wrap {
width: min(100% - 2 * var(--pad-inline), var(--container-wide));
}
}
/* ── 두 체제 ────────────────────────────────────────────────────── */
.band-light {
--band-surface: var(--surface);
@ -290,12 +298,12 @@ h3 {
.board th:first-child,
.board td:first-child {
padding-left: 0;
padding-left: var(--space-2);
}
.board th:last-child,
.board td:last-child {
padding-right: 0;
padding-right: var(--space-2);
}
.board thead th {
@ -313,6 +321,7 @@ h3 {
.board-select {
min-height: 40px;
padding-inline: var(--space-2);
border: 0;
background: transparent;
color: inherit;
@ -341,7 +350,7 @@ h3 {
.unit {
margin-left: 2px;
color: var(--band-ink-faint);
color: var(--band-ink-muted);
font-size: 0.85em;
}
@ -641,7 +650,7 @@ h3 {
.season th,
.season td {
border: 1px solid var(--band-line);
padding: var(--space-2) 0;
padding: var(--space-2) var(--space-1);
}
.season thead th {
@ -653,15 +662,16 @@ h3 {
.season tbody th {
text-align: left;
padding-inline: 0 var(--space-3);
padding-inline: var(--space-2) var(--space-3);
border-left: 0;
white-space: nowrap;
font-weight: 500;
}
.season-item {
.season .season-item {
text-align: left;
width: 6rem;
padding-inline: var(--space-2);
}
.season td.on {
@ -951,6 +961,79 @@ h3 {
}
/* ── 좁은 화면 ──────────────────────────────────────────────────── */
/* 사진은 시장의 시간대를, 불투명한 종이 표면은 숫자의 기준선을 맡는다. */
.market-board-surface {
position: relative;
z-index: 1;
padding-block: var(--space-5) var(--space-7);
background: var(--surface);
color: var(--ink);
box-shadow: 0 -1px 0 var(--line), 0 24px 64px rgb(0 0 0 / 14%);
}
.market-board-head {
display: flex;
justify-content: space-between;
gap: var(--space-4);
padding-bottom: var(--space-3);
border-bottom: 1px solid var(--line-strong);
color: var(--ink-muted);
font-size: var(--step--1);
}
.market-board-head p:first-child {
color: var(--accent);
}
.market-board-scroll {
overflow-x: auto;
}
.market-board-surface .board {
margin-top: var(--space-3);
}
.market-board-surface .board th,
.market-board-surface .board td {
border-color: var(--line);
}
.market-board-surface .board thead th,
.market-board-surface .board td,
.market-board-surface .board-notes li,
.market-board-surface .lot-title p:last-child,
.market-board-surface .lot-spec dt {
color: var(--ink-muted);
}
.market-board-surface .board tbody th,
.market-board-surface .price,
.market-board-surface .lot-spec dd,
.market-board-surface .board-notes strong {
color: var(--ink);
}
.market-board-surface .board-select[aria-pressed="true"],
.market-board-surface .lot-inspector-head p:last-child {
color: var(--accent);
}
.market-board-surface .unit,
.market-board-surface .lot-inspector-head p:first-child {
color: var(--ink);
}
.market-board-surface .board tbody tr:has(.board-select[aria-pressed="true"]) {
background: var(--accent-wash);
box-shadow: inset 2px 0 var(--accent);
}
.market-board-surface .lot-inspector,
.market-board-surface .lot-inspector-head,
.market-board-surface .note-demo {
border-color: var(--line-strong);
}
@media (max-width: 720px) {
.head-inner {
flex-wrap: wrap;
@ -973,6 +1056,15 @@ h3 {
/* 판은 일곱 칸이라 좁은 화면에서 표로 두면 못 읽는다.
행마다 라벨을 붙인 카드로 접는다 — 가로 스크롤로 미루지 않는다 */
.market-board-head {
align-items: flex-start;
flex-direction: column;
}
.market-board-scroll {
overflow: visible;
}
.board thead {
display: none;
}
@ -992,7 +1084,7 @@ h3 {
.board tbody th {
font-size: var(--step-1);
padding: 0;
padding-inline: var(--space-2);
border: 0;
}
@ -1001,7 +1093,7 @@ h3 {
}
.board td {
padding: var(--space-1) 0;
padding: var(--space-1) var(--space-2);
border: 0;
text-align: left;
display: flex;
@ -1009,6 +1101,10 @@ h3 {
gap: var(--space-3);
}
.board td:last-child {
padding-right: var(--space-2);
}
.board td::before {
content: attr(data-label);
color: var(--band-ink-faint);

View file

@ -119,6 +119,7 @@
--space-8: clamp(4.5rem, 3rem + 6vw, 9rem);
--container: 1120px;
--container-wide: 1360px;
--pad-inline: clamp(1.25rem, 1rem + 2.5vw, 4rem);
/* ── 모션 ── */