Some checks are pending
ci / build (push) Waiting to run
Measured convergence before: split hero 13/19, top-bar nav 19/19, one-line notice footer 14/19, body Pretendard 17/21, 10 similarity pairs above 0.78. Each showcase got a pre-assigned hero family, nav form, footer form, type pair, background, accent hue, radius, motion grammar and material from outputs/rework-2026-10-06/plan.md; direction cards and the chosen reason are recorded in every design.md. After: 0 similarity warnings, 19 distinct display faces, 7 hero families, 5 nav forms, 5 footer forms, no scroll reveals, 5 showcases with SVG filter materials. Example contact values replace bracket placeholders under the existing fictional-brand notices. Thumbnails, OG images, card copy and three e2e assertions updated; dead CSS in dure-enrollment and hannam-jari removed; similarity.mjs learns the new font families.
989 lines
47 KiB
HTML
989 lines
47 KiB
HTML
<!doctype html>
|
||
<html lang="ko">
|
||
<head>
|
||
<meta charset="utf-8" />
|
||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
|
||
<title>새벽청과 — 오늘 새벽 경매 낙찰가</title>
|
||
<meta
|
||
name="description"
|
||
content="새벽 경매에서 낙찰받아 그날 아침에 보냅니다. 품목마다 산지, 등급, 당도, 규격과 오늘 낙찰가를 그대로 적는 청과 직거래."
|
||
/>
|
||
<meta property="og:title" content="새벽청과" />
|
||
<meta property="og:description" content="새벽 경매에서 받은 과일의 산지, 등급, 당도와 오늘 낙찰가를 공개하고 그날 아침 보내 드립니다." />
|
||
<meta property="og:type" content="website" />
|
||
<meta property="og:image" content="./og.png" />
|
||
<meta name="twitter:card" content="summary_large_image" />
|
||
<meta name="theme-color" content="#e4e8f4" />
|
||
|
||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||
<link
|
||
rel="stylesheet"
|
||
href="https://fonts.googleapis.com/css2?family=Gasoek+One&family=Noto+Sans+KR:wght@400;500;700&display=swap"
|
||
/>
|
||
<link rel="stylesheet" href="./styles/tokens.css?v=20261006" />
|
||
<link rel="stylesheet" href="./styles/main.css?v=20261006" />
|
||
<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' rx='4' fill='%23e4e8f4'/%3E%3Cpath d='M6 21h20' stroke='%2322673a' stroke-width='3'/%3E%3Ccircle cx='13' cy='13' r='4.5' fill='none' stroke='%23141a2b' stroke-width='2.5'/%3E%3C/svg%3E"
|
||
/>
|
||
</head>
|
||
|
||
<body>
|
||
<a class="skip-link" href="#main">본문으로 건너뛰기</a>
|
||
|
||
<header class="site-head">
|
||
<div class="wrap head-inner">
|
||
<a class="wordmark" href="#top">새벽청과</a>
|
||
<p class="hero-meta">
|
||
<time datetime="2026-10-06T02:00+09:00">10월 06일 02:00</time>
|
||
<span>경매 기준</span>
|
||
</p>
|
||
</div>
|
||
</header>
|
||
|
||
<main id="main">
|
||
<!-- 1 · 시세표가 첫 화면이다. 표제는 작고, 낙찰가 숫자가 가장 크다 -->
|
||
<section class="board-section" id="top" aria-labelledby="heroHeading">
|
||
<div class="wrap">
|
||
<div class="board-head">
|
||
<h1 id="heroHeading">오늘 새벽 경매 낙찰가</h1>
|
||
<p class="board-lead">
|
||
사과와 배는 08:30, 나머지 네 품목은 02:00 경매에서 받은 값입니다. 낙찰가에
|
||
선별, 포장, 배송비가 더해져 판매가가 되고, 두 가격은 따로 적습니다.
|
||
</p>
|
||
</div>
|
||
|
||
<div class="tabs" role="tablist" aria-label="시세 보기">
|
||
<button
|
||
class="tab"
|
||
type="button"
|
||
role="tab"
|
||
id="tabItems"
|
||
aria-selected="true"
|
||
aria-controls="panelItems"
|
||
>품목별 시세</button>
|
||
<button
|
||
class="tab"
|
||
type="button"
|
||
role="tab"
|
||
id="tabDates"
|
||
aria-selected="false"
|
||
aria-controls="panelDates"
|
||
tabindex="-1"
|
||
>일자별 변동</button>
|
||
</div>
|
||
|
||
<div class="panel" id="panelItems" role="tabpanel" aria-labelledby="tabItems">
|
||
<div class="board-scroll">
|
||
<table class="board">
|
||
<caption class="sr-only">
|
||
오늘 낙찰 품목 여섯 가지. 산지, 등급, 당도, 규격, 낙찰가, 전일 대비
|
||
</caption>
|
||
<thead>
|
||
<tr>
|
||
<th scope="col" class="col-name">품목</th>
|
||
<th scope="col" class="col-origin">산지</th>
|
||
<th scope="col" class="c-num col-grade">등급</th>
|
||
<th scope="col" class="c-num col-brix">당도</th>
|
||
<th scope="col" class="c-num col-pack">규격</th>
|
||
<th scope="col" class="c-num col-price">낙찰가</th>
|
||
<th scope="col" class="c-num col-delta">전일 대비</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<th scope="row" class="col-name">
|
||
<button
|
||
class="board-select"
|
||
type="button"
|
||
data-market-row
|
||
data-name="백도 복숭아"
|
||
data-origin="경북 청도"
|
||
data-grade="특 등급, 12.5 Bx"
|
||
data-pack="4.5 kg"
|
||
data-price="38,000원"
|
||
data-delta="▲ 2,000원"
|
||
data-auction="02:00 경매"
|
||
aria-pressed="true"
|
||
>백도 복숭아</button>
|
||
</th>
|
||
<td class="col-origin">경북 청도</td>
|
||
<td class="c-num col-grade">특</td>
|
||
<td class="c-num col-brix">12.5<span class="unit">Bx</span></td>
|
||
<td class="c-num col-pack">4.5<span class="unit">kg</span></td>
|
||
<td class="c-num col-price"><span class="price" data-from="36000" data-to="38000">38,000</span></td>
|
||
<td class="c-num col-delta delta up">▲ 2,000</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row" class="col-name">
|
||
<button
|
||
class="board-select"
|
||
type="button"
|
||
data-market-row
|
||
data-name="샤인머스캣"
|
||
data-origin="경북 상주"
|
||
data-grade="특 등급, 18.2 Bx"
|
||
data-pack="2 kg"
|
||
data-price="26,500원"
|
||
data-delta="▼ 1,500원"
|
||
data-auction="02:00 경매"
|
||
aria-pressed="false"
|
||
>샤인머스캣</button>
|
||
</th>
|
||
<td class="col-origin">경북 상주</td>
|
||
<td class="c-num col-grade">특</td>
|
||
<td class="c-num col-brix">18.2<span class="unit">Bx</span></td>
|
||
<td class="c-num col-pack">2<span class="unit">kg</span></td>
|
||
<td class="c-num col-price"><span class="price" data-from="28000" data-to="26500">26,500</span></td>
|
||
<td class="c-num col-delta delta down">▼ 1,500</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row" class="col-name">
|
||
<button
|
||
class="board-select"
|
||
type="button"
|
||
data-market-row
|
||
data-name="캠벨얼리"
|
||
data-origin="충북 영동"
|
||
data-grade="상 등급, 15.4 Bx"
|
||
data-pack="5 kg"
|
||
data-price="31,000원"
|
||
data-delta="보합"
|
||
data-auction="02:00 경매"
|
||
aria-pressed="false"
|
||
>캠벨얼리</button>
|
||
</th>
|
||
<td class="col-origin">충북 영동</td>
|
||
<td class="c-num col-grade">상</td>
|
||
<td class="c-num col-brix">15.4<span class="unit">Bx</span></td>
|
||
<td class="c-num col-pack">5<span class="unit">kg</span></td>
|
||
<td class="c-num col-price"><span class="price" data-from="31000" data-to="31000">31,000</span></td>
|
||
<td class="c-num col-delta delta flat">보합</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row" class="col-name">
|
||
<button
|
||
class="board-select"
|
||
type="button"
|
||
data-market-row
|
||
data-name="홍로 사과"
|
||
data-origin="경북 영주"
|
||
data-grade="특 등급, 14.1 Bx"
|
||
data-pack="5 kg"
|
||
data-price="44,000원"
|
||
data-delta="▲ 3,500원"
|
||
data-auction="08:30 경매"
|
||
aria-pressed="false"
|
||
>홍로 사과</button>
|
||
</th>
|
||
<td class="col-origin">경북 영주</td>
|
||
<td class="c-num col-grade">특</td>
|
||
<td class="c-num col-brix">14.1<span class="unit">Bx</span></td>
|
||
<td class="c-num col-pack">5<span class="unit">kg</span></td>
|
||
<td class="c-num col-price"><span class="price" data-from="40500" data-to="44000">44,000</span></td>
|
||
<td class="c-num col-delta delta up">▲ 3,500</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row" class="col-name">
|
||
<button
|
||
class="board-select"
|
||
type="button"
|
||
data-market-row
|
||
data-name="원황 배"
|
||
data-origin="전남 나주"
|
||
data-grade="상 등급, 12.8 Bx"
|
||
data-pack="7.5 kg"
|
||
data-price="52,000원"
|
||
data-delta="▼ 2,000원"
|
||
data-auction="08:30 경매"
|
||
aria-pressed="false"
|
||
>원황 배</button>
|
||
</th>
|
||
<td class="col-origin">전남 나주</td>
|
||
<td class="c-num col-grade">상</td>
|
||
<td class="c-num col-brix">12.8<span class="unit">Bx</span></td>
|
||
<td class="c-num col-pack">7.5<span class="unit">kg</span></td>
|
||
<td class="c-num col-price"><span class="price" data-from="54000" data-to="52000">52,000</span></td>
|
||
<td class="c-num col-delta delta down">▼ 2,000</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row" class="col-name">
|
||
<button
|
||
class="board-select"
|
||
type="button"
|
||
data-market-row
|
||
data-name="무화과"
|
||
data-origin="전남 영암"
|
||
data-grade="특 등급, 당도 표기 대상 아님"
|
||
data-pack="1.2 kg"
|
||
data-price="24,000원"
|
||
data-delta="▲ 1,000원"
|
||
data-auction="02:00 경매"
|
||
aria-pressed="false"
|
||
>무화과</button>
|
||
</th>
|
||
<td class="col-origin">전남 영암</td>
|
||
<td class="c-num col-grade">특</td>
|
||
<td class="c-num col-brix blank"><span class="sr-only">당도 표기 대상 아님</span><span aria-hidden="true">—</span></td>
|
||
<td class="c-num col-pack">1.2<span class="unit">kg</span></td>
|
||
<td class="c-num col-price"><span class="price" data-from="23000" data-to="24000">24,000</span></td>
|
||
<td class="c-num col-delta delta up">▲ 1,000</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
|
||
<div class="lot-inspector" aria-live="polite" aria-atomic="true">
|
||
<div class="lot-title">
|
||
<p class="lot-label">선택한 품목</p>
|
||
<p class="lot-name" id="lotName">백도 복숭아</p>
|
||
<p class="lot-origin" id="lotOrigin">경북 청도</p>
|
||
</div>
|
||
<dl class="lot-spec">
|
||
<div>
|
||
<dt>등급과 당도</dt>
|
||
<dd id="lotGrade">특 등급, 12.5 Bx</dd>
|
||
</div>
|
||
<div>
|
||
<dt>규격</dt>
|
||
<dd id="lotPack">4.5 kg</dd>
|
||
</div>
|
||
<div>
|
||
<dt>경매</dt>
|
||
<dd id="lotAuction">02:00 경매</dd>
|
||
</div>
|
||
<div>
|
||
<dt>전일 대비</dt>
|
||
<dd id="lotDelta">▲ 2,000원</dd>
|
||
</div>
|
||
</dl>
|
||
<p class="lot-price">
|
||
<span class="lot-price-label">낙찰가</span>
|
||
<span class="lot-price-value" id="lotPrice">38,000원</span>
|
||
</p>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="panel" id="panelDates" role="tabpanel" aria-labelledby="tabDates" hidden>
|
||
<div class="board-scroll">
|
||
<table class="board board-dates">
|
||
<caption class="sr-only">품목별 전일 낙찰가와 오늘 낙찰가, 차이</caption>
|
||
<thead>
|
||
<tr>
|
||
<th scope="col" class="col-name">품목</th>
|
||
<th scope="col" class="col-origin">경매</th>
|
||
<th scope="col" class="c-num">전일</th>
|
||
<th scope="col" class="c-num col-price">오늘</th>
|
||
<th scope="col" class="c-num col-delta">차이</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<th scope="row" class="col-name">백도 복숭아</th>
|
||
<td class="col-origin">02:00</td>
|
||
<td class="c-num">36,000</td>
|
||
<td class="c-num col-price"><span class="price" data-from="36000" data-to="38000">38,000</span></td>
|
||
<td class="c-num col-delta delta up">▲ 2,000</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row" class="col-name">샤인머스캣</th>
|
||
<td class="col-origin">02:00</td>
|
||
<td class="c-num">28,000</td>
|
||
<td class="c-num col-price"><span class="price" data-from="28000" data-to="26500">26,500</span></td>
|
||
<td class="c-num col-delta delta down">▼ 1,500</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row" class="col-name">캠벨얼리</th>
|
||
<td class="col-origin">02:00</td>
|
||
<td class="c-num">31,000</td>
|
||
<td class="c-num col-price"><span class="price" data-from="31000" data-to="31000">31,000</span></td>
|
||
<td class="c-num col-delta delta flat">보합</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row" class="col-name">홍로 사과</th>
|
||
<td class="col-origin">08:30</td>
|
||
<td class="c-num">40,500</td>
|
||
<td class="c-num col-price"><span class="price" data-from="40500" data-to="44000">44,000</span></td>
|
||
<td class="c-num col-delta delta up">▲ 3,500</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row" class="col-name">원황 배</th>
|
||
<td class="col-origin">08:30</td>
|
||
<td class="c-num">54,000</td>
|
||
<td class="c-num col-price"><span class="price" data-from="54000" data-to="52000">52,000</span></td>
|
||
<td class="c-num col-delta delta down">▼ 2,000</td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row" class="col-name">무화과</th>
|
||
<td class="col-origin">02:00</td>
|
||
<td class="c-num">23,000</td>
|
||
<td class="c-num col-price"><span class="price" data-from="23000" data-to="24000">24,000</span></td>
|
||
<td class="c-num col-delta delta up">▲ 1,000</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<p class="board-note">
|
||
전일 낙찰가는 오늘 낙찰가에서 전일 대비를 뺀 값입니다. 단위는 원이고 규격은 품목별 시세와
|
||
같습니다.
|
||
</p>
|
||
</div>
|
||
|
||
<ul class="board-notes">
|
||
<li>
|
||
당도 칸의 <strong>—</strong>는 값이 없다는 뜻이 아니라 표시가 허용되지 않는 품목이라는
|
||
뜻입니다. 무화과는 당도 표기 대상 13개 품목에 들어 있지 않습니다.
|
||
</li>
|
||
<li>
|
||
이 표의 품목, 가격, 시간은 이해를 돕기 위한 예시 낙찰가입니다. 실제 주문과 납품은 받지
|
||
않습니다.
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 2 · 읽는 법 + 유통 단계. 새벽 통로 사진을 왼쪽 가장자리로 흘린다 -->
|
||
<section class="section section-grade" id="grade" aria-labelledby="gradeHeading">
|
||
<div class="bleed-row">
|
||
<figure class="bleed bleed-left">
|
||
<img
|
||
src="./assets/dawn-aisle.webp"
|
||
width="1600"
|
||
height="900"
|
||
loading="lazy"
|
||
decoding="async"
|
||
alt="새벽 두 시, 형광등이 켜진 도매시장 통로에 과일 상자가 양쪽으로 쌓여 있습니다"
|
||
/>
|
||
<figcaption>02:00 경매가 열리는 도매시장 통로</figcaption>
|
||
</figure>
|
||
<div class="bleed-body">
|
||
<h2 id="gradeHeading">등급, 당도, 규격은 농산물 표준규격 기준으로 적습니다</h2>
|
||
<dl class="terms">
|
||
<div>
|
||
<dt>등급 <span class="term-en">특, 상, 보통</span></dt>
|
||
<dd>
|
||
크기가 고른지, 흠이 없는지, 색이 제대로 들었는지를 봅니다. 기준은 농산물 표준규격에
|
||
품목별로 정해져 있습니다. <strong>당도를 표시할 수 있는 것은 특과 상 등급뿐</strong>입니다.
|
||
</dd>
|
||
</div>
|
||
<div>
|
||
<dt>당도 <span class="term-en">Brix</span></dt>
|
||
<dd>
|
||
용액 100g에 든 당이 몇 g인지를 나타냅니다. 굴절당도계에 과즙 한 방울을 올려 잽니다.
|
||
당도가 높다고 늘 맛있는 것은 아니고 산도와의 균형에 따라 맛이 달라지므로, 당도 숫자만
|
||
강조하지 않습니다.
|
||
</dd>
|
||
</div>
|
||
<div>
|
||
<dt>선과</dt>
|
||
<dd>
|
||
기계로 골라내는 일입니다. 드럼식은 지름으로, 중량식은 무게로 나눕니다. 그래서 한 상자
|
||
안의 과일 크기가 고릅니다.
|
||
</dd>
|
||
</div>
|
||
<div>
|
||
<dt>규격 <span class="term-en">kg</span></dt>
|
||
<dd>
|
||
상자 단위입니다. 사과는 2, 5, 7.5, 10kg, 포도는 2, 3, 4, 5kg로 거래됩니다. 같은
|
||
가격이라도 규격이 다르면 비교할 수 없어서 시세표에 함께 적습니다.
|
||
</dd>
|
||
</div>
|
||
</dl>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="wrap route-wrap" id="route">
|
||
<h3 id="routeHeading">산지에서 배송까지 다섯 단계 가운데 새벽청과는 넷째 단계인 낙찰을 맡습니다</h3>
|
||
<ol class="route">
|
||
<li>
|
||
<h4>출하</h4>
|
||
<p>산지에서 따고 골라 담아 시장으로 보냅니다.</p>
|
||
</li>
|
||
<li>
|
||
<h4>수집</h4>
|
||
<p>도매법인이 그날 들어온 물량을 받아 경매에 올립니다.</p>
|
||
</li>
|
||
<li>
|
||
<h4>경매</h4>
|
||
<p>새벽 2시 경매에서 가격이 정해집니다. 이때 낙찰된 가격이 경락가격입니다.</p>
|
||
</li>
|
||
<li class="route-here">
|
||
<h4>낙찰</h4>
|
||
<p>중도매인 자격으로 직접 낙찰받습니다. 어느 산지의 어떤 등급을 얼마에 받았는지 위 시세표에 그대로 올립니다.</p>
|
||
</li>
|
||
<li>
|
||
<h4>그날 아침 배송</h4>
|
||
<p>창고에 따로 보관하지 않고, 경매장에서 받은 상자를 그날 아침 바로 보냅니다.</p>
|
||
</li>
|
||
</ol>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 3 · 오늘 입고 사진(흘림) + 제철 달력 -->
|
||
<section class="section section-today" id="today" aria-labelledby="todayHeading">
|
||
<div class="wrap">
|
||
<h2 id="todayHeading">오늘 들어온 나주 배와 영동 포도, 당도는 굴절당도계로 잽니다</h2>
|
||
</div>
|
||
|
||
<figure class="bleed-row bleed-figure">
|
||
<div class="bleed bleed-right">
|
||
<img
|
||
src="./assets/pear-crate.webp"
|
||
width="1100"
|
||
height="825"
|
||
loading="lazy"
|
||
decoding="async"
|
||
alt="흰 그물망에 하나씩 싼 배가 얕은 나무 상자에 담겨 있고, 한 알은 상자 옆에 꺼내 놓여 있습니다"
|
||
/>
|
||
</div>
|
||
<figcaption class="bleed-body">
|
||
<p class="card-name">원황 배 <span class="card-origin">전남 나주</span></p>
|
||
<dl class="card-spec">
|
||
<div><dt>등급</dt><dd>상</dd></div>
|
||
<div><dt>당도</dt><dd>12.8 Bx</dd></div>
|
||
<div><dt>규격</dt><dd>7.5 kg</dd></div>
|
||
</dl>
|
||
<p class="card-note">
|
||
나주 배는 과즙이 많고 단맛이 뒤에 올라옵니다. 그물망은 배가 눌리지 않게 감싸는
|
||
포장재입니다.
|
||
</p>
|
||
</figcaption>
|
||
</figure>
|
||
|
||
<figure class="bleed-row bleed-figure bleed-figure-rev">
|
||
<div class="bleed bleed-left bleed-portrait">
|
||
<img
|
||
src="./assets/grape-bloom.webp"
|
||
width="900"
|
||
height="1200"
|
||
loading="lazy"
|
||
decoding="async"
|
||
alt="흰 종이 위에 놓인 진자주색 포도 송이. 껍질에 하얀 과분이 그대로 남아 있습니다"
|
||
/>
|
||
</div>
|
||
<figcaption class="bleed-body">
|
||
<p class="card-name">캠벨얼리 <span class="card-origin">충북 영동</span></p>
|
||
<dl class="card-spec">
|
||
<div><dt>등급</dt><dd>상</dd></div>
|
||
<div><dt>당도</dt><dd>15.4 Bx</dd></div>
|
||
<div><dt>규격</dt><dd>5 kg</dd></div>
|
||
</dl>
|
||
<p class="card-note">
|
||
껍질의 흰 가루는 과분이라는 천연 성분입니다. 과분이 많이 남아 있을수록 손을 덜 탄
|
||
포도입니다.
|
||
</p>
|
||
</figcaption>
|
||
</figure>
|
||
|
||
<figure class="bleed-row bleed-figure">
|
||
<div class="bleed bleed-right">
|
||
<img
|
||
src="./assets/refractometer.webp"
|
||
width="1100"
|
||
height="825"
|
||
loading="lazy"
|
||
decoding="async"
|
||
alt="스테인리스 작업대 위 굴절당도계의 프리즘 판에 과즙 한 방울이 올려져 있습니다"
|
||
/>
|
||
</div>
|
||
<figcaption class="bleed-body">
|
||
<p class="card-name">당도는 이렇게 잽니다</p>
|
||
<p class="card-note">
|
||
굴절당도계에 과즙을 한 방울 올려 빛이 꺾이는 정도를 읽습니다. 상자마다 재지 않고 입고된
|
||
로트에서 표본을 뽑아 재므로, 시세표의 당도는 해당 로트의 표본값입니다.
|
||
</p>
|
||
</figcaption>
|
||
</figure>
|
||
|
||
<div class="wrap season-wrap" id="season">
|
||
<h3 id="seasonHeading">제철 품목만 들여오므로, 칸이 채워진 달에만 그 품목이 시세표에 올라갑니다</h3>
|
||
|
||
<div class="season-control">
|
||
<div class="season-buttons" role="group" aria-label="제철 달 선택">
|
||
<button type="button" data-season-dir="-1">이전 달</button>
|
||
<button type="button" data-season-dir="1">다음 달</button>
|
||
</div>
|
||
<p class="season-status" aria-live="polite" aria-atomic="true">
|
||
<output id="seasonMonth">10월</output>
|
||
<span id="seasonCount">제철 품목을 읽는 중입니다</span>
|
||
</p>
|
||
</div>
|
||
|
||
<div class="season-scroll">
|
||
<table class="season">
|
||
<caption class="sr-only">품목별 제철 달력. 가로축은 1월부터 12월</caption>
|
||
<thead>
|
||
<tr>
|
||
<th scope="col" class="season-item">품목</th>
|
||
<th scope="col" data-m="1">1</th>
|
||
<th scope="col" data-m="2">2</th>
|
||
<th scope="col" data-m="3">3</th>
|
||
<th scope="col" data-m="4">4</th>
|
||
<th scope="col" data-m="5">5</th>
|
||
<th scope="col" data-m="6">6</th>
|
||
<th scope="col" data-m="7">7</th>
|
||
<th scope="col" data-m="8">8</th>
|
||
<th scope="col" data-m="9">9</th>
|
||
<th scope="col" data-m="10">10</th>
|
||
<th scope="col" data-m="11">11</th>
|
||
<th scope="col" data-m="12">12</th>
|
||
</tr>
|
||
</thead>
|
||
<tbody>
|
||
<tr>
|
||
<th scope="row">딸기</th>
|
||
<td class="on" data-m="1"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="2"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="3"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="4"><span class="sr-only">제철</span></td>
|
||
<td data-m="5"></td><td data-m="6"></td><td data-m="7"></td><td data-m="8"></td>
|
||
<td data-m="9"></td><td data-m="10"></td><td data-m="11"></td>
|
||
<td class="on" data-m="12"><span class="sr-only">제철</span></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">참외</th>
|
||
<td data-m="1"></td><td data-m="2"></td><td data-m="3"></td>
|
||
<td class="on" data-m="4"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="5"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="6"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="7"><span class="sr-only">제철</span></td>
|
||
<td data-m="8"></td><td data-m="9"></td><td data-m="10"></td>
|
||
<td data-m="11"></td><td data-m="12"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">복숭아</th>
|
||
<td data-m="1"></td><td data-m="2"></td><td data-m="3"></td>
|
||
<td data-m="4"></td><td data-m="5"></td>
|
||
<td class="on" data-m="6"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="7"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="8"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="9"><span class="sr-only">제철</span></td>
|
||
<td data-m="10"></td><td data-m="11"></td><td data-m="12"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">포도</th>
|
||
<td data-m="1"></td><td data-m="2"></td><td data-m="3"></td>
|
||
<td data-m="4"></td><td data-m="5"></td><td data-m="6"></td>
|
||
<td class="on" data-m="7"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="8"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="9"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="10"><span class="sr-only">제철</span></td>
|
||
<td data-m="11"></td><td data-m="12"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">무화과</th>
|
||
<td data-m="1"></td><td data-m="2"></td><td data-m="3"></td>
|
||
<td data-m="4"></td><td data-m="5"></td><td data-m="6"></td>
|
||
<td data-m="7"></td>
|
||
<td class="on" data-m="8"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="9"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="10"><span class="sr-only">제철</span></td>
|
||
<td data-m="11"></td><td data-m="12"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">사과</th>
|
||
<td data-m="1"></td><td data-m="2"></td><td data-m="3"></td>
|
||
<td data-m="4"></td><td data-m="5"></td><td data-m="6"></td>
|
||
<td data-m="7"></td>
|
||
<td class="on" data-m="8"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="9"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="10"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="11"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="12"><span class="sr-only">제철</span></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">배</th>
|
||
<td data-m="1"></td><td data-m="2"></td><td data-m="3"></td>
|
||
<td data-m="4"></td><td data-m="5"></td><td data-m="6"></td>
|
||
<td data-m="7"></td>
|
||
<td class="on" data-m="8"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="9"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="10"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="11"><span class="sr-only">제철</span></td>
|
||
<td data-m="12"></td>
|
||
</tr>
|
||
<tr>
|
||
<th scope="row">감귤</th>
|
||
<td class="on" data-m="1"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="2"><span class="sr-only">제철</span></td>
|
||
<td data-m="3"></td><td data-m="4"></td><td data-m="5"></td>
|
||
<td data-m="6"></td><td data-m="7"></td><td data-m="8"></td>
|
||
<td data-m="9"></td>
|
||
<td class="on" data-m="10"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="11"><span class="sr-only">제철</span></td>
|
||
<td class="on" data-m="12"><span class="sr-only">제철</span></td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<p class="season-note">
|
||
굵은 세로선이 이번 달입니다. 산지와 그해 날씨에 따라 2주 정도 앞당겨지거나 늦어질 수
|
||
있습니다.
|
||
</p>
|
||
</div>
|
||
</section>
|
||
|
||
<!-- 4 · 납품 조건 + 수량 계산 -->
|
||
<section class="section section-wholesale" id="wholesale" aria-labelledby="wsHeading">
|
||
<div class="wrap">
|
||
<h2 id="wsHeading">매장 납품은 전날 21:00에 마감하고 품목당 3상자부터 받습니다</h2>
|
||
<div class="ws-grid">
|
||
<div class="ws-body">
|
||
<p class="lead">
|
||
카페, 베이커리, 식당처럼 매일 같은 품질이 필요한 곳은 소매와 다른 조건으로 납품합니다.
|
||
이런 곳에는 가격보다 <strong>품질 편차</strong>가 더 중요하기 때문입니다.
|
||
</p>
|
||
<dl class="ws-rows">
|
||
<div>
|
||
<dt>주문 마감</dt>
|
||
<dd>전날 21:00. 새벽 경매 물량을 확보하기 위한 마감입니다.</dd>
|
||
</div>
|
||
<div>
|
||
<dt>배송</dt>
|
||
<dd>같은 날 오전. 수도권은 직접 배송하고, 그 외 지역은 새벽 배송 업체로 보냅니다.</dd>
|
||
</div>
|
||
<div>
|
||
<dt>등급 고정</dt>
|
||
<dd>등급을 계약으로 묶습니다. 그날 시세가 올라도 등급을 낮춰 값을 맞추지 않습니다.</dd>
|
||
</div>
|
||
<div>
|
||
<dt>시세 공유</dt>
|
||
<dd>낙찰가를 그대로 전달합니다. 마진은 별도 항목으로 적습니다.</dd>
|
||
</div>
|
||
<div>
|
||
<dt>최소 물량</dt>
|
||
<dd>품목당 상자 3개부터.</dd>
|
||
</div>
|
||
</dl>
|
||
</div>
|
||
|
||
<section class="order-draft" aria-labelledby="orderDraftHeading">
|
||
<h3 id="orderDraftHeading">수량별 기준 금액 보기</h3>
|
||
<div class="order-controls">
|
||
<label>
|
||
<span>품목</span>
|
||
<select id="orderItem">
|
||
<option value="백도 복숭아" data-price="38000" data-pack="4.5 kg">백도 복숭아, 특, 4.5 kg</option>
|
||
<option value="샤인머스캣" data-price="26500" data-pack="2 kg">샤인머스캣, 특, 2 kg</option>
|
||
<option value="캠벨얼리" data-price="31000" data-pack="5 kg">캠벨얼리, 상, 5 kg</option>
|
||
<option value="홍로 사과" data-price="44000" data-pack="5 kg">홍로 사과, 특, 5 kg</option>
|
||
<option value="원황 배" data-price="52000" data-pack="7.5 kg">원황 배, 상, 7.5 kg</option>
|
||
<option value="무화과" data-price="24000" data-pack="1.2 kg">무화과, 특, 1.2 kg</option>
|
||
</select>
|
||
</label>
|
||
<label>
|
||
<span>상자 수</span>
|
||
<input id="orderQty" type="number" min="3" max="50" step="1" value="3" inputmode="numeric" />
|
||
</label>
|
||
</div>
|
||
<dl class="order-summary">
|
||
<div>
|
||
<dt>규격</dt>
|
||
<dd id="orderPack">4.5 kg × 3상자</dd>
|
||
</div>
|
||
<div>
|
||
<dt>표시된 낙찰가 합계</dt>
|
||
<dd class="order-total" id="orderTotal">114,000원</dd>
|
||
</div>
|
||
</dl>
|
||
<p class="order-fine">
|
||
위 합계는 표에 적힌 예시 낙찰가만 더한 값입니다. 선별, 포장, 배송과 실제 납품가는 포함하지
|
||
않습니다.
|
||
</p>
|
||
<div class="order-actions">
|
||
<button class="btn" id="copyOrder" type="button">계산 내용 복사</button>
|
||
<p class="order-status" id="orderStatus" role="status"></p>
|
||
</div>
|
||
</section>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<!-- 푸터 = 연락처·영업시간 카드. 경매 시간과 영업시간이 마지막에 찾는 사실이다 -->
|
||
<footer class="site-foot" id="contact">
|
||
<div class="wrap">
|
||
<div class="foot-card">
|
||
<div class="foot-brand">
|
||
<p class="foot-name">새벽청과</p>
|
||
<p class="foot-line">새벽 경매에서 받아 그날 아침에 보냅니다.</p>
|
||
</div>
|
||
<dl class="foot-rows">
|
||
<div>
|
||
<dt>경매 시간</dt>
|
||
<dd>02:00 복숭아, 포도, 무화과 등<br />08:30 사과, 배</dd>
|
||
</div>
|
||
<div>
|
||
<dt>영업시간</dt>
|
||
<dd>새벽 01:30 – 낮 12:00<br />일요일 휴무</dd>
|
||
</div>
|
||
<div>
|
||
<dt>주문 마감</dt>
|
||
<dd>전날 21:00</dd>
|
||
</div>
|
||
<div>
|
||
<dt>시장 위치</dt>
|
||
<dd>가락시장 청과동 2층 214호</dd>
|
||
</div>
|
||
<div>
|
||
<dt>전화</dt>
|
||
<dd>02-000-5230</dd>
|
||
</div>
|
||
<div>
|
||
<dt>메일</dt>
|
||
<dd>order@saebyeok.example</dd>
|
||
</div>
|
||
</dl>
|
||
</div>
|
||
<p class="foot-fine">
|
||
이 페이지의 품목, 가격, 시간은 이해를 돕기 위한 예시이며 실제 주문과 납품 서비스가 아닙니다.
|
||
점포 위치, 전화, 메일도 예시이며 실제로 연결되지 않습니다. 경매 시각, 등급, 당도 표시
|
||
규정 등 제도에 관한 설명은 실제 농산물 표준규격과 도매시장 운영 방식을 따릅니다.
|
||
</p>
|
||
</div>
|
||
</footer>
|
||
|
||
<script>
|
||
(() => {
|
||
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
||
|
||
/* 날짜 도장 — 한국 시간 오늘을 머리줄에 적는다. */
|
||
const marketTime = new Date();
|
||
const dateParts = Object.fromEntries(
|
||
new Intl.DateTimeFormat("en-CA", {
|
||
timeZone: "Asia/Seoul",
|
||
year: "numeric",
|
||
month: "2-digit",
|
||
day: "2-digit",
|
||
})
|
||
.formatToParts(marketTime)
|
||
.filter((part) => part.type !== "literal")
|
||
.map((part) => [part.type, part.value]),
|
||
);
|
||
const currentMonth = Number(dateParts.month);
|
||
const heroMetaTime = document.querySelector(".hero-meta time");
|
||
if (heroMetaTime) {
|
||
heroMetaTime.dateTime = `${dateParts.year}-${dateParts.month}-${dateParts.day}T02:00+09:00`;
|
||
heroMetaTime.textContent = `${dateParts.month}월 ${dateParts.day}일 02:00`;
|
||
}
|
||
|
||
/* 낙찰가 카운터 — 전일가에서 오늘가로 올라가거나 내려간다.
|
||
감소 모션 설정이면 최종값이 이미 마크업에 있으므로 아무것도 하지 않는다. */
|
||
const counted = new WeakSet();
|
||
function countPrices(root) {
|
||
if (!root) return;
|
||
for (const node of root.querySelectorAll(".price[data-from][data-to]")) {
|
||
if (counted.has(node)) continue;
|
||
counted.add(node);
|
||
const from = Number(node.dataset.from);
|
||
const to = Number(node.dataset.to);
|
||
if (reduceMotion || from === to || !Number.isFinite(from) || !Number.isFinite(to)) continue;
|
||
const duration = 600;
|
||
const start = performance.now();
|
||
const step = (now) => {
|
||
const t = Math.min(1, (now - start) / duration);
|
||
const eased = 1 - (1 - t) * (1 - t) * (1 - t);
|
||
const value = Math.round((from + (to - from) * eased) / 100) * 100;
|
||
node.textContent = (t >= 1 ? to : value).toLocaleString("ko-KR");
|
||
if (t < 1) requestAnimationFrame(step);
|
||
};
|
||
node.textContent = from.toLocaleString("ko-KR");
|
||
requestAnimationFrame(step);
|
||
}
|
||
}
|
||
|
||
/* 탭 — 품목별 / 일자별. 화살표·Home·End로 옮기고 포커스 즉시 전환한다(APG Tabs). */
|
||
const tabs = [...document.querySelectorAll('[role="tab"]')];
|
||
function selectTab(tab, focus) {
|
||
for (const item of tabs) {
|
||
const on = item === tab;
|
||
item.setAttribute("aria-selected", String(on));
|
||
item.tabIndex = on ? 0 : -1;
|
||
const panel = document.getElementById(item.getAttribute("aria-controls"));
|
||
if (panel) panel.hidden = !on;
|
||
if (on && panel) countPrices(panel);
|
||
}
|
||
if (focus) tab.focus();
|
||
}
|
||
tabs.forEach((tab, index) => {
|
||
tab.addEventListener("click", () => selectTab(tab, false));
|
||
tab.addEventListener("keydown", (event) => {
|
||
const last = tabs.length - 1;
|
||
let next = null;
|
||
if (event.key === "ArrowRight") next = index === last ? 0 : index + 1;
|
||
else if (event.key === "ArrowLeft") next = index === 0 ? last : index - 1;
|
||
else if (event.key === "Home") next = 0;
|
||
else if (event.key === "End") next = last;
|
||
if (next === null) return;
|
||
event.preventDefault();
|
||
selectTab(tabs[next], true);
|
||
});
|
||
});
|
||
countPrices(document.getElementById("panelItems"));
|
||
|
||
/* 표의 한 행을 고르면 같은 값으로 선택 로트가 바뀐다. */
|
||
const marketRows = [...document.querySelectorAll("[data-market-row]")];
|
||
const lotFields = {
|
||
auction: document.getElementById("lotAuction"),
|
||
name: document.getElementById("lotName"),
|
||
origin: document.getElementById("lotOrigin"),
|
||
grade: document.getElementById("lotGrade"),
|
||
pack: document.getElementById("lotPack"),
|
||
price: document.getElementById("lotPrice"),
|
||
delta: document.getElementById("lotDelta"),
|
||
};
|
||
|
||
function showLot(button) {
|
||
for (const row of marketRows) row.setAttribute("aria-pressed", String(row === button));
|
||
for (const [key, field] of Object.entries(lotFields)) {
|
||
if (field) field.textContent = button.dataset[key] || "";
|
||
}
|
||
if (orderItem) orderItem.value = button.dataset.name || orderItem.value;
|
||
updateOrder();
|
||
}
|
||
|
||
for (const row of marketRows) row.addEventListener("click", () => showLot(row));
|
||
|
||
/* 제철 달력은 이번 달에서 시작하지만 앞뒤 달도 직접 읽을 수 있다. */
|
||
let selectedMonth = currentMonth;
|
||
const season = document.querySelector(".season");
|
||
const seasonScroll = document.querySelector(".season-scroll");
|
||
const seasonMonth = document.getElementById("seasonMonth");
|
||
const seasonCount = document.getElementById("seasonCount");
|
||
|
||
function showMonth(month, moveViewport) {
|
||
selectedMonth = month;
|
||
season?.querySelectorAll(".is-focus").forEach((cell) => cell.classList.remove("is-focus"));
|
||
season?.querySelectorAll("[aria-current='date']").forEach((cell) => cell.removeAttribute("aria-current"));
|
||
season?.querySelectorAll(`[data-m="${month}"]`).forEach((cell) => cell.classList.add("is-focus"));
|
||
|
||
const head = season?.querySelector(`thead [data-m="${month}"]`);
|
||
if (month === currentMonth) head?.setAttribute("aria-current", "date");
|
||
|
||
const items = [...(season?.querySelectorAll("tbody tr") || [])]
|
||
.filter((row) => row.querySelector(`td.on[data-m="${month}"]`))
|
||
.map((row) => row.querySelector("th")?.textContent.trim())
|
||
.filter(Boolean);
|
||
|
||
if (seasonMonth) seasonMonth.textContent = `${month}월`;
|
||
if (seasonCount) seasonCount.textContent = `${items.length}품목: ${items.join(", ")}`;
|
||
|
||
if (moveViewport && head && seasonScroll) {
|
||
const left = Math.max(0, head.offsetLeft - seasonScroll.clientWidth / 2 + head.clientWidth / 2);
|
||
seasonScroll.scrollTo({ left, behavior: reduceMotion ? "auto" : "smooth" });
|
||
}
|
||
}
|
||
|
||
document.querySelectorAll("[data-season-dir]").forEach((button) => {
|
||
button.addEventListener("click", () => {
|
||
const next = ((selectedMonth - 1 + Number(button.dataset.seasonDir) + 12) % 12) + 1;
|
||
showMonth(next, true);
|
||
});
|
||
});
|
||
showMonth(currentMonth, true);
|
||
|
||
/* 가로로 넘치는 표만 키보드 포커스를 받게 한다 — 넘치지 않는 폭에서는 탭 정지점을 만들지 않는다 */
|
||
const scrollers = [...document.querySelectorAll(".board-scroll, .season-scroll")];
|
||
function syncScrollFocus() {
|
||
for (const box of scrollers) {
|
||
const overflowing = box.scrollWidth > box.clientWidth + 1;
|
||
if (overflowing) {
|
||
box.tabIndex = 0;
|
||
box.setAttribute("role", "region");
|
||
box.setAttribute("aria-label", box.classList.contains("season-scroll") ? "제철 달력, 가로로 넘깁니다" : "시세표, 가로로 넘깁니다");
|
||
} else {
|
||
box.removeAttribute("tabindex");
|
||
box.removeAttribute("role");
|
||
box.removeAttribute("aria-label");
|
||
}
|
||
}
|
||
}
|
||
syncScrollFocus();
|
||
window.addEventListener("resize", syncScrollFocus);
|
||
|
||
/* 낙찰가 예시로 발주 메모를 만든다. 납품가처럼 보이지 않게 항목을 분리한다. */
|
||
const orderItem = document.getElementById("orderItem");
|
||
const orderQty = document.getElementById("orderQty");
|
||
const orderPack = document.getElementById("orderPack");
|
||
const orderTotal = document.getElementById("orderTotal");
|
||
const orderStatus = document.getElementById("orderStatus");
|
||
|
||
function orderValues() {
|
||
const option = orderItem?.selectedOptions[0];
|
||
const quantity = Math.min(50, Math.max(3, Number(orderQty?.value) || 3));
|
||
const price = Number(option?.dataset.price) || 0;
|
||
return {
|
||
name: option?.value || "",
|
||
pack: option?.dataset.pack || "",
|
||
quantity,
|
||
total: price * quantity,
|
||
};
|
||
}
|
||
|
||
function updateOrder() {
|
||
const value = orderValues();
|
||
if (orderPack) orderPack.textContent = `${value.pack} × ${value.quantity}상자`;
|
||
if (orderTotal) orderTotal.textContent = `${value.total.toLocaleString("ko-KR")}원`;
|
||
if (orderStatus) orderStatus.textContent = "";
|
||
}
|
||
|
||
orderItem?.addEventListener("change", updateOrder);
|
||
orderQty?.addEventListener("input", updateOrder);
|
||
orderQty?.addEventListener("change", () => {
|
||
if (orderQty) orderQty.value = String(orderValues().quantity);
|
||
updateOrder();
|
||
});
|
||
|
||
async function copyText(text) {
|
||
if (navigator.clipboard?.writeText) {
|
||
try {
|
||
await Promise.race([
|
||
navigator.clipboard.writeText(text),
|
||
new Promise((_, reject) => window.setTimeout(() => reject(new Error("clipboard timeout")), 1200)),
|
||
]);
|
||
return true;
|
||
} catch {
|
||
// 권한 대화상자가 없거나 응답하지 않는 브라우저는 아래 선택 복사로 전환합니다.
|
||
}
|
||
}
|
||
|
||
const field = document.createElement("textarea");
|
||
field.value = text;
|
||
field.setAttribute("readonly", "");
|
||
field.style.position = "fixed";
|
||
field.style.inset = "0 auto auto -9999px";
|
||
document.body.append(field);
|
||
field.select();
|
||
const copied = document.execCommand("copy");
|
||
field.remove();
|
||
return copied;
|
||
}
|
||
|
||
document.getElementById("copyOrder")?.addEventListener("click", async () => {
|
||
const value = orderValues();
|
||
const memo = [
|
||
"새벽청과 예시 발주 메모",
|
||
`품목: ${value.name}`,
|
||
`규격: ${value.pack}`,
|
||
`수량: ${value.quantity}상자`,
|
||
`표시된 낙찰가 합계: ${value.total.toLocaleString("ko-KR")}원`,
|
||
"실제 납품가는 선별, 포장, 배송 조건을 확인한 뒤 정합니다.",
|
||
].join("\n");
|
||
try {
|
||
const copied = await copyText(memo);
|
||
if (orderStatus) {
|
||
orderStatus.textContent = copied
|
||
? "계산 내용을 복사했습니다."
|
||
: "복사하지 못했습니다. 브라우저의 클립보드 권한을 확인해 주세요.";
|
||
}
|
||
} catch {
|
||
if (orderStatus) orderStatus.textContent = "복사하지 못했습니다. 브라우저의 클립보드 권한을 확인해 주세요.";
|
||
}
|
||
});
|
||
|
||
updateOrder();
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|