PageSourceSearch

https://riontech.kr/homepage/

html riontech.kr collected 2026-10-02 01:59:16 UTC 65,767 bytes, 1,194 lines download raw bytes

1<!doctype html>
2<html lang="ko">
3<head>
4<meta charset="UTF-8">
5<meta name="viewport" content="width=device-width, initial-scale=1.0">
6<title>홈페이지 제작 | ㈜리온</title>
7<meta name="description" content="㈜리온 홈페이지 제작 안내. 가격과 진행 기준을 먼저 공개하고, 선택한 범위 그대로 진행합니다. 베이직 150만원, 스탠다드 300만원.">
8<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/orioncactus/[email protected]/dist/web/static/pretendard.min.css">
9<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/fonts-archive/Paperlogy/subsets/Paperlogy-dynamic-subset.css">
10<script src="https://pay.nicepay.co.kr/v1/js/"></script>
10
11<style>
12  * { margin: 0; padding: 0; box-sizing: border-box; }
13  :root {
14    --navy: #0f172a;
15    --blue: #2563eb;
16    --blue-soft: #eff6ff;
17    --gray-soft: #f8fafc;
18    --text: #334155;
19    --text-sub: #64748b;
20    --line: #e2e8f0;
21    --radius: 16px;
22    --shadow: 0 4px 24px rgba(15, 23, 42, 0.06);
23  }
24  html { scroll-behavior: smooth; }
25  body {
26    font-family: 'Paperlogy', 'Pretendard', 'Malgun Gothic', sans-serif;
27    background: #ffffff;
28    color: var(--text);
29    letter-spacing: -0.01em;
30    line-height: 1.5;
31  }
32  .wrap { max-width: 1040px; margin: 0 auto; }
33  .sec { padding: 56px 24px; }
34  .sec.gray { background: var(--gray-soft); }
35  .sec.blue { background: var(--blue-soft); }
36  .sec.navy { background: var(--navy); }
37  .sec-title { font-size: 26px; font-weight: 700; color: var(--navy); letter-spacing: -0.02em; margin-bottom: 6px; }
38  .sec-sub { font-size: 15px; color: var(--text-sub); margin-bottom: 26px; }
39
40  /* 상단 바 */
41  .topbar { border-bottom: 1px solid var(--line); background: #fff; position: sticky; top: 0; z-index: 50; }
42  .topbar .wrap { display: flex; align-items: center; justify-content: space-between; padding: 14px 24px; }
43  .topbar .home { font-size: 14px; font-weight: 700; color: var(--navy); text-decoration: none; }
44  .topbar .home span { color: var(--blue); }
45  .topbar .cta { background: var(--blue); color: #fff; font-size: 13.5px; font-weight: 600; text-decoration: none; padding: 9px 18px; border-radius: 999px; }
46
47  /* 히어로 */
48  .hero { padding: 64px 24px 52px; }
49  .hero .brand { display: inline-block; background: var(--blue-soft); color: var(--blue); font-size: 13px; font-weight: 600; padding: 7px 16px; border-radius: 999px; margin-bottom: 20px; }
50  .hero h1 { font-size: clamp(28px, 5vw, 40px); font-weight: 700; color: var(--navy); letter-spacing: -0.02em; line-height: 1.35; }
51  .hero h1 span { color: var(--blue); }
52  .hero .sub { margin-top: 14px; font-size: 16.5px; line-height: 1.7; color: var(--text); }
53  .hero .chips { margin-top: 22px; display: flex; gap: 8px; flex-wrap: wrap; }
54  .chip { background: var(--gray-soft); color: var(--text-sub); font-size: 12.5px; font-weight: 600; padding: 7px 14px; border-radius: 999px; }
55
56  /* 제작 사례 */
57  .works { display: flex; gap: 20px; flex-wrap: wrap; }
58  .work { flex: 1 1 320px; background: #fff; border-radius: var(--radius); box-shadow: var(--shadow); overflow: hidden; }
59  .work img { width: 100%; height: 240px; object-fit: cover; object-position: top; display: block; }
60  .work .cap { padding: 20px 24px 22px; }
61  .work .cap .name { font-size: 17px; font-weight: 700; color: var(--navy); }
62  .work .cap .name em { font-style: normal; font-size: 12px; font-weight: 600; color: var(--blue); background: var(--blue-soft); border-radius: 999px; padding: 4px 10px; margin-left: 8px; vertical-align: 2px; }
63  .work .cap .desc { margin-top: 7px; font-size: 13.5px; line-height: 1.65; color: var(--text-sub); }
64
65  /* 패키지 카드 */
66  .plans { display: flex; gap: 18px; align-items: stretch; flex-wrap: wrap; }
67  .plan { flex: 1 1 260px; background: var(--gray-soft); border-radius: var(--radius); padding: 30px 26px; box-shadow: var(--shadow); position: relative; display: flex; flex-direction: column; }
68  .plan.featured { background: var(--navy); }
69  .plan .badge { position: absolute; top: -12px; left: 26px; background: var(--blue); color: #fff; font-size: 12px; font-weight: 600; padding: 5px 13px; border-radius: 999px; }
70  .plan .p-name { font-size: 18px; font-weight: 700; color: var(--navy); }
71  .plan .p-use { font-size: 12.5px; color: var(--text-sub); margin-top: 3px; }
72  .plan .p-price { margin: 16px 0 4px; font-size: 30px; font-weight: 700; color: var(--blue); letter-spacing: -0.02em; }
73  .plan .p-vat { font-size: 12px; color: var(--text-sub); margin-bottom: 16px; }
74  .plan ul { list-style: none; }
75  .plan li { font-size: 13.5px; line-height: 1.6; color: var(--text); padding-left: 16px; position: relative; margin-bottom: 8px; }
76  .plan li::before { content: '✓'; position: absolute; left: 0; color: var(--blue); font-weight: 700; font-size: 12px; }
77  .plan .p-meta { margin-top: 14px; font-size: 12.5px; color: var(--text-sub); line-height: 1.7; }
78  .plan .p-btn { margin-top: auto; padding-top: 18px; }
79  .plan .p-btn a { display: block; text-align: center; background: var(--blue); color: #fff; font-size: 14px; font-weight: 700; text-decoration: none; padding: 13px 0; border-radius: 10px; }
80  .plan .p-btn a.ghost { background: transparent; border: 1.5px solid var(--blue); color: var(--blue); }
81  .plan.featured .p-name { color: #fff; }
82  .plan.featured .p-use { color: #93c5fd; }
83  .plan.featured .p-price { color: #60a5fa; }
84  .plan.featured .p-vat { color: #94a3b8; }
85  .plan.featured li { color: #e2e8f0; }
86  .plan.featured li::before { color: #60a5fa; }
87  .plan.featured .p-meta { color: #94a3b8; }
88  .plan.featured .p-btn a.ghost { border-color: #60a5fa; color: #60a5fa; }
89  .plans-note { margin-top: 18px; font-size: 13px; color: var(--text-sub); }
90
91  /* 기획 상담 띠 */
92  .consult-strip {
93    display: flex; align-items: center; justify-content: space-between; gap: 24px; flex-wrap: wrap;
94    background: var(--blue-soft); border-radius: var(--radius);
95    padding: 24px 28px; margin-bottom: 26px;
96  }
97  .consult-strip .cs-tag { font-size: 12px; font-weight: 700; color: var(--blue); letter-spacing: .02em; margin-bottom: 6px; }
98  .consult-strip .cs-name { font-size: 18px; font-weight: 700; color: var(--navy); }
99  .consult-strip .cs-name b { color: var(--blue); }
100  .consult-strip .cs-desc { margin-top: 8px; font-size: 13.5px; line-height: 1.7; color: var(--text); }
101  .consult-strip .cs-desc b { color: var(--navy); font-weight: 700; }
102  .consult-strip .cs-btn {
103    flex-shrink: 0; background: var(--navy); color: #fff; text-decoration: none;
104    font-size: 14px; font-weight: 700; padding: 14px 28px; border-radius: 10px;
105  }
106
107  /* 공통 포함 / 별도 */
108  .cols { display: flex; gap: 18px; flex-wrap: wrap; }
109  .col { flex: 1 1 300px; background: #fff; border-radius: var(--radius); padding: 26px 28px; box-shadow: var(--shadow); }
110  .col h3 { font-size: 16px; font-weight: 700; color: var(--navy); margin-bottom: 14px; }
111  .col ul { list-style: none; }
112  .col li { font-size: 14px; line-height: 1.65; padding-left: 15px; position: relative; margin-bottom: 8px; color: var(--text); }
113  .col li::before { content: '·'; position: absolute; left: 2px; color: var(--blue); font-weight: 700; }
114
115  /* 진행 기준 */
116  .policy { display: flex; flex-direction: column; gap: 12px; }
117  .p-row { display: flex; gap: 16px; background: var(--gray-soft); border-radius: 14px; padding: 18px 22px; box-shadow: var(--shadow); }
118  .p-chip { flex-shrink: 0; width: 96px; text-align: center; background: var(--blue-soft); color: var(--blue); border-radius: 999px; font-size: 13px; font-weight: 700; padding: 8px 0; height: fit-content; margin-top: 2px; }
119  .p-txt { font-size: 14px; line-height: 1.65; color: var(--text); }
120  .p-txt b { color: var(--blue); }
121  @media (max-width: 560px) { .p-row { flex-direction: column; gap: 8px; } .p-chip { width: 108px; } }
122
123  /* 진행 절차 */
124  .sec.navy .sec-title { color: #fff; }
125  .sec.navy .sec-sub { color: #93c5fd; }
126  .flow { display: flex; gap: 6px; align-items: stretch; flex-wrap: wrap; }
127  .step { flex: 1 1 100px; background: rgba(255,255,255,0.07); border-radius: 12px; padding: 14px 6px; text-align: center; }
128  .step .n { font-size: 11px; font-weight: 700; color: #60a5fa; margin-bottom: 4px; }
129  .step .t { font-size: 13.5px; font-weight: 600; color: #fff; line-height: 1.4; }
130  .step .d { font-size: 11px; color: #94a3b8; margin-top: 3px; }
131  .step.hl { background: var(--blue); }
132  .step.hl .n { color: #bfdbfe; }
133  .step.hl .d { color: #bfdbfe; }
134
135  /* 유지관리 */
136  .cares { display: flex; gap: 18px; flex-wrap: wrap; }
137  .care { flex: 1 1 300px; background: #fff; border-radius: var(--radius); padding: 24px 28px; box-shadow: var(--shadow); }
138  .care .c-name { font-size: 15px; font-weight: 700; color: var(--navy); }
139  .care .c-price { font-size: 24px; font-weight: 700; color: var(--blue); margin: 8px 0 10px; }
140  .care .c-desc { font-size: 13.5px; line-height: 1.7; color: var(--text); }
141  .cares-note { margin-top: 16px; font-size: 13px; color: var(--text-sub); }
142
143  /* ===== 주문 섹션 ===== */
144  .order-grid { display: flex; gap: 24px; align-items: flex-start; flex-wrap: wrap; }
145  .order-main { flex: 1 1 480px; min-width: 0; }
146  .order-side { flex: 0 1 340px; position: sticky; top: 76px; }
147  @media (max-width: 900px) { .order-side { position: static; flex: 1 1 100%; } }
148
149  .ostep { background: #fff; border-radius: var(--radius); box-shadow: var(--shadow); padding: 26px 28px; margin-bottom: 18px; }
150  .ostep h3 { font-size: 16.5px; font-weight: 700; color: var(--navy); margin-bottom: 4px; }
151  .ostep h3 .num { display: inline-block; background: var(--blue); color: #fff; font-size: 12px; font-weight: 700; width: 22px; height: 22px; line-height: 22px; text-align: center; border-radius: 999px; margin-right: 8px; vertical-align: 2px; }
152  .ostep .hint { font-size: 13px; color: var(--text-sub); margin-bottom: 16px; }
153
154  .pick { display: flex; gap: 12px; flex-wrap: wrap; }
155  .pick label { flex: 1 1 140px; cursor: pointer; }
156  .pick input { position: absolute; opacity: 0; }
157  .pick .card { border: 1.5px solid var(--line); border-radius: 12px; padding: 16px 18px; transition: border-color .15s, background .15s; }
158  .pick input:checked + .card { border-color: var(--blue); background: var(--blue-soft); }
159  .pick .card .t { font-size: 15px; font-weight: 700; color: var(--navy); }
160  .pick .card .pr { font-size: 14px; font-weight: 700; color: var(--blue); margin-top: 4px; }
161  .pick .card .d { font-size: 12.5px; color: var(--text-sub); margin-top: 4px; line-height: 1.5; }
162
163  .opt-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 0; border-bottom: 1px solid var(--line); flex-wrap: wrap; }
164  .opt-row:last-child { border-bottom: none; }
165  .opt-row .o-name { font-size: 14.5px; font-weight: 600; color: var(--navy); }
166  .opt-row .o-desc { font-size: 12.5px; color: var(--text-sub); margin-top: 2px; }
167  .opt-row .o-price { font-size: 14.5px; font-weight: 700; color: var(--blue); white-space: nowrap; }
168  label.opt-row { cursor: pointer; }
169  .opt-left { display: flex; gap: 12px; align-items: flex-start; }
170  .opt-left input[type=checkbox] { width: 18px; height: 18px; accent-color: var(--blue); flex-shrink: 0; margin-top: 3px; }
171  .opt-group { margin-top: 8px; }
172  .opt-group > .g-name { font-size: 12.5px; font-weight: 700; color: var(--blue); background: var(--blue-soft); display: inline-block; padding: 5px 12px; border-radius: 999px; margin: 14px 0 2px; }
173  .opt-row.on { background: var(--blue-soft); border-radius: 10px; padding-left: 12px; padding-right: 12px; }
174  .opt-tail { display: flex; align-items: center; gap: 12px; }
175  .stepper { display: flex; align-items: center; gap: 0; border: 1.5px solid var(--line); border-radius: 10px; overflow: hidden; }
176  .stepper button { width: 38px; height: 38px; border: none; background: var(--gray-soft); color: var(--navy); font-size: 18px; font-weight: 700; cursor: pointer; }
177  .stepper .val { width: 64px; text-align: center; font-size: 14.5px; font-weight: 700; color: var(--navy); }
178  select.care-sel { border: 1.5px solid var(--line); border-radius: 10px; padding: 9px 12px; font-size: 14px; font-family: inherit; color: var(--navy); background: #fff; }
179
180  /* 범위 확인 */
181  .scope-box { border: 1.5px solid var(--line); border-radius: 12px; padding: 18px 20px; margin-bottom: 14px; }
182  .scope-box h4 { font-size: 13.5px; font-weight: 700; color: var(--navy); margin-bottom: 10px; }
183  .scope-box ul { list-style: none; }
184  .scope-box li { font-size: 13.5px; line-height: 1.6; padding-left: 18px; position: relative; margin-bottom: 6px; color: var(--text); }
185  .scope-box li.inc::before { content: '✓'; position: absolute; left: 0; color: var(--blue); font-weight: 700; }
186  .scope-box li.exc::before { content: '✕'; position: absolute; left: 0; color: #dc2626; font-weight: 700; }
187  .scope-box li.fee::before { content: '₩'; position: absolute; left: 0; color: var(--text-sub); font-weight: 700; }
188  .agree { display: flex; gap: 10px; align-items: flex-start; padding: 12px 14px; background: var(--gray-soft); border-radius: 10px; margin-bottom: 10px; cursor: pointer; }
189  .agree input { margin-top: 3px; width: 16px; height: 16px; accent-color: var(--blue); flex-shrink: 0; }
190  .agree span { font-size: 13.5px; line-height: 1.6; color: var(--text); }
191  .agree b { color: var(--navy); }
192
193  /* 폼 */
194  .frm { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
195  .frm .full { grid-column: 1 / -1; }
196  @media (max-width: 560px) { .frm { grid-template-columns: 1fr; } }
197  .frm label { display: block; font-size: 13px; font-weight: 600; color: var(--navy); margin-bottom: 6px; }
198  .frm label em { font-style: normal; color: #dc2626; }
199  .frm input, .frm textarea { width: 100%; border: 1.5px solid var(--line); border-radius: 10px; padding: 11px 13px; font-size: 14.5px; font-family: inherit; color: var(--navy); }
200  .frm input:focus, .frm textarea:focus { outline: none; border-color: var(--blue); }
201  .frm textarea { min-height: 88px; resize: vertical; }
202  .privacy-note {
203    margin-top: 16px; padding: 13px 15px; background: var(--gray-soft); border-radius: 10px;
204    font-size: 12.5px; line-height: 1.7; color: var(--text-sub);
205  }
206  .privacy-note a { color: var(--blue); font-weight: 600; }
207
208  /* 견적 요약 */
209  .quote { background: var(--navy); border-radius: var(--radius); padding: 26px 28px; color: #e2e8f0; }
210  .quote h3 { font-size: 16px; font-weight: 700; color: #fff; margin-bottom: 16px; }
211  .q-row { display: flex; justify-content: space-between; gap: 10px; font-size: 14px; padding: 7px 0; }
212  .q-row .k { color: #94a3b8; }
213  .q-row .v { font-weight: 600; color: #e2e8f0; text-align: right; }
214  .q-div { border-top: 1px solid rgba(255,255,255,0.15); margin: 10px 0; }
215  .q-row.total .k { color: #93c5fd; font-weight: 700; }
216  .q-row.total .v { color: #fff; font-weight: 700; }
217  .q-row.deposit { background: var(--blue); margin: 12px -12px 0; padding: 13px 12px; border-radius: 10px; }
218  .q-row.deposit .k { color: #dbeafe; font-weight: 700; font-size: 14.5px; }
219  .q-row.deposit .v { color: #fff; font-weight: 700; font-size: 18px; }
220  .q-note { margin-top: 14px; font-size: 12px; line-height: 1.7; color: #94a3b8; }
221  .q-submit { display: block; width: 100%; margin-top: 18px; background: #fff; color: var(--navy); border: none; border-radius: 12px; padding: 15px 0; font-size: 15.5px; font-weight: 700; font-family: inherit; cursor: pointer; }
222  .q-submit:disabled { opacity: .45;
222 cursor: not-allowed; }
223  .q-err { margin-top: 10px; font-size: 13px; color: #fca5a5; display: none; }
224
225  /* 접수 완료 */
226  .done { display: none; background: #fff; border-radius: var(--radius); box-shadow: var(--shadow); padding: 34px 32px; }
227  .done h3 { font-size: 20px; font-weight: 700; color: var(--navy); margin-bottom: 10px; }
228  .done p { font-size: 14.5px; line-height: 1.75; color: var(--text); margin-bottom: 8px; }
229  .done .sum { background: var(--gray-soft); border-radius: 12px; padding: 18px 20px; margin: 16px 0; font-size: 13.5px; line-height: 1.8; white-space: pre-wrap; color: var(--navy); }
230  .done .btns { display: flex; gap: 10px; flex-wrap: wrap; }
231  .done .btns a, .done .btns button { flex: 1 1 160px; text-align: center; text-decoration: none; border-radius: 10px; padding: 13px 0; font-size: 14px; font-weight: 700; font-family: inherit; cursor: pointer; }
232  .done .btns .mail { background: var(--blue); color: #fff; border: none; }
233  .done .btns .copy { background: #fff; color: var(--blue); border: 1.5px solid var(--blue); }
234
235  /* 푸터 */
236  .footer { background: var(--navy); padding: 34px 24px 38px; color: #cbd5e1; }
237  .footer .co { font-size: 16px; font-weight: 700; color: #fff; margin-bottom: 8px; }
238  .footer .line { font-size: 13px; line-height: 1.8; }
239  .footer .line a { color: #60a5fa; }
240  .footer .caveat { margin-top: 12px; font-size: 12px; color: #64748b; line-height: 1.6; }
241</style>
242</head>
243<body>
244
245<!-- 상단 바 -->
246<div class="topbar">
247  <div class="wrap">
248    <a class="home" href="/">㈜리온 <span>RION</span></a>
249    <a class="cta" href="#order">제작 신청하기</a>
250  </div>
251</div>
252
253<!-- 히어로 -->
254<div class="hero">
255  <div class="wrap">
256    <div class="brand">㈜리온 · 홈페이지 제작</div>
257    <h1>기획부터 오픈까지,<br><span>대표 개발자가 직접</span> 만듭니다</h1>
258    <div class="sub">평소 고민하시던 부분을 홈페이지 또는 제품으로 구현해 드립니다.<br>가격과 진행 기준을 먼저 보여드리고, 선택하신 범위 그대로 진행합니다.</div>
259    <div class="chips">
260      <span class="chip">벤처기업(혁신성장유형)</span>
261      <span class="chip">여성기업 확인</span>
262      <span class="chip">오산대학교 창업보육센터 입주기업</span>
263    </div>
264  </div>
265</div>
266
267<!-- 제작 사례 -->
268<div class="sec gray">
269  <div class="wrap">
270    <div class="sec-title">직접 만든 사이트</div>
271    <div class="sec-sub">용도와 톤이 다른 다섯 가지 예시입니다. 주소가 적힌 곳은 지금 접속해서 확인하실 수 있습니다.</div>
272    <div class="works">
273      <div class="work">
274        <img src="site_korpang.jpg" alt="글자팡">
275        <div class="cap">
276          <div class="name">글자팡 <em>korpang.com</em></div>
277          <div class="desc">K-pop · 드라마로 한국어를 배우는 웹 게임. 밝고 가벼운 톤의 서비스 예시입니다.</div>
278        </div>
279      </div>
280      <div class="work">
281        <img src="site_anbu.jpg" alt="저수지 안부">
282        <div class="cap">
283          <div class="name">저수지 안부 <em>anbu.riontech.kr</em></div>
284          <div class="desc">전국 3,422곳 저수지의 저수율 · 안전정보 서비스. 차분하고 신뢰감 있는 톤의 예시입니다.</div>
285        </div>
286      </div>
287      <div class="work">
288        <img src="site_moonfc.jpg" alt="MOON FC">
289        <div class="cap">
290          <div class="name">MOON FC <em>dalnuri.co.kr</em></div>
291          <div class="desc">유소년 축구 교육공동체 소개 사이트. 인사말 · 교육과정 · 소식 구성의 단체 소개형 예시입니다.</div>
292        </div>
293      </div>
294      <div class="work">
295        <img src="site_osanvoice.jpg" alt="시민 참여 플랫폼">
296        <div class="cap">
297          <div class="name">시민 참여 플랫폼 <em>의뢰 제작</em></div>
298          <div class="desc">의견을 받아 지도와 통계로 보여주는 참여형 사이트. 기능 개발이 들어간 예시입니다.</div>
299        </div>
300      </div>
301      <div class="work">
302        <img src="site_mayor.jpg" alt="인물 소개 사이트">
303        <div class="cap">
304          <div class="name">인물 소개 사이트 <em>의뢰 제작</em></div>
305          <div class="desc">소개 · 이력 · 분야별 계획을 한 흐름으로 읽히게 구성한 예ì‹
305œìž…니다.</div>
306        </div>
307      </div>
308    </div>
309    <div class="plans-note">※ 의뢰인 요청에 따라 일부 사이트는 상호 · 인물 정보를 가려 표시합니다.</div>
310  </div>
311</div>
312
313<!-- 패키지 -->
314<div class="sec">
315  <div class="wrap">
316    <div class="sec-title">제작 패키지</div>
317    <div class="sec-sub">용도에 맞는 것을 고르시면 됩니다. 아래 신청 화면에서 옵션을 더해 최종 금액을 확인할 수 있습니다.</div>
318
319    <div class="consult-strip">
320      <div class="cs-left">
321        <div class="cs-tag">먼저 정하고 싶다면</div>
322        <div class="cs-name">기획 상담 <b>30분 5만원</b></div>
323        <div class="cs-desc">무엇을 만들지부터 같이 정합니다. 필요한 기능과 예산 범위를 정리해 <b>요구사항 문서와 견적서</b>로 보내드립니다.<br>제작으로 이어지면 <b>상담료 전액을 제작비에서 차감</b>해 드립니다.</div>
324      </div>
325      <a class="cs-btn" href="#order" data-pick="consult">상담 신청</a>
326    </div>
327
328    <div class="plans">
329      <div class="plan">
330        <div class="p-name">베이직</div>
331        <div class="p-use">회사 · 기관 소개용</div>
332        <div class="p-price">150만원</div>
333        <div class="p-vat">부가세 포함 165만원</div>
334        <ul>
335          <li>5페이지 이내</li>
336          <li>검증된 템플릿 기반 맞춤 디자인</li>
337          <li>문의폼 · 지도 · 전화 연결</li>
338          <li>무상 수정 2회</li>
339        </ul>
340        <div class="p-meta">제작 기간 2~3주</div>
341        <div class="p-btn"><a href="#order" data-pick="basic">베이직으로 신청</a></div>
342      </div>
343      <div class="plan featured">
344        <div class="badge">가장 많이 선택</div>
345        <div class="p-name">스탠다드</div>
346        <div class="p-use">소개 + 콘텐츠 운영</div>
347        <div class="p-price">300만원</div>
348        <div class="p-vat">부가세 포함 330만원</div>
349        <ul>
350          <li>10페이지 이내</li>
351          <li>전용 디자인, 시안 2종 중 선택</li>
352          <li>베이직 전체 + 갤러리 · 공지 관리</li>
353          <li>방문 통계</li>
354          <li>무상 수정 3회</li>
355        </ul>
356        <div class="p-meta">제작 기간 4~6주</div>
357        <div class="p-btn"><a href="#order" data-pick="standard">스탠다드로 신청</a></div>
358      </div>
359      <div class="plan">
360        <div class="p-name">맞춤형</div>
361        <div class="p-use">옵션 목록 밖의 기능</div>
362        <div class="p-price">상담 견적</div>
363        <div class="p-vat">요구 기능 확정 후 산정</div>
364        <ul>
365          <li>기존 시스템 · 외부 서비스 연동</li>
366          <li>업무용 관리 프로그램</li>
367          <li>규모 · 기간 협의</li>
368        </ul>
369        <div class="p-meta">예약 · 회원 · 결제 · 쇼핑몰은 아래 신청 화면의 옵션에서 바로 선택하실 수 있습니다.</div>
370        <div class="p-btn"><a href="#order" data-pick="custom" class="ghost">상담 신청</a></div>
371      </div>
372    </div>
373    <div class="plans-note">※ 페이지 추가 · 예약 · 회원 · 결제 · 쇼핑몰 등 20여 종의 기능 옵션은 아래 신청 화면에서 고르면 금액이 바로 계산됩니다.</div>
374  </div>
375</div>
376
377<!-- 공통 포함 / 별도 -->
378<div class="sec blue">
379  <div class="wrap">
380    <div class="sec-title">모든 패키지 공통</div>
381    <div class="sec-sub">기본으로 챙겨드리는 것과, 실비로 구분되는 것입니다.</div>
382    <div class="cols">
383      <div class="col">
384        <h3>기본 포함</h3>
385        <ul>
386          <li>반응형 제작(PC · 모바일 · 태블릿)</li>
387          <li>SSL 보안 인증 적용(https)</li>
388          <li>네이버 · 구글 검색 등록</li>
389          <li>오픈 후 1개월 무상 하자보수(오류 수정)</li>
390        </ul>
391      </div>
392      <div class="col">
393        <h3>별도 비용(실비)</h3>
394        <ul>
395          <li>도메인 등록 연 2만원 안팎</li>
396          <li>서버 호스팅 월 1~2만원 안팎</li>
397          <li>유료 이미지 · 폰트 구매 시 실비</li>
398          <li>문구 · 사진 원고는 의뢰인 제공(작성 대행은 협의)</li>
399        </ul>
400      </div>
401    </div>
402  </div>
403</div>
404
405<!-- 진행 기준 -->
406<div class="sec">
407  <div class="wrap">
408    <div class="sec-title">진행 기준</div>
409    <div class="sec-sub">서로 오해 없이 진행하기 위해 계약 전에 미리 알려드리는 기준입니다.</div>
410    <div class="policy">
411      <div class="p-row">
412        <div class="p-chip">무상 수정</div>
413        <div class="p-txt">패키지별 횟수 내 무상 진행. <b>수정 1회 = 요청 사항을 모아 한 번에 전달</b>하는 것을 기준으로 하며 텍스트 · 이미지 교체와 부분 조정이 대상입니다.</div>
414      </div>
415      <div class="p-row">
416        <div class="p-chip">초과 수정</div>
417        <div class="p-txt">무상 횟수 초과분은 <b>회당 5만원</b>(단순 수정 기준)으로 진행합니다.</div>
418      </div>
419      <div class="p-row">
420        <div class="p-chip">범위 변경</div>
421        <div class="p-txt">레이아웃 · 디자인 컨셉 변경, 페이지 추가, 기능 추가는 <b>범위 변경에 해당하여 별도 견적</b> 대상입니다. 시안 확정 후 컨셉 전면 변경은 재계약으로 진행합니다.</div>
422      </div>
423      <div class="p-row">
424        <div class="p-chip">원고 제공</div>
425        <div class="p-txt">문구 · 사진 등 원고 제공이 늦어지면 <b>제작 일정도 같은 기간만큼 순연</b>됩니다.</div>
426      </div>
427    </div>
428  </div>
429</div>
430
431<!-- 진행 절차 -->
432<div class="sec navy">
433  <div class="wrap">
434    <div class="sec-title">진행 절차</div>
435    <div class="sec-sub">신청 접수 후 1영업일 안에 확인 연락을 드리고, 착수금 결제 링크를 보내드립니다.</div>
436    <div class="flow">
437      <div class="step"><div class="n">01</div><div class="t">신청</div><div class="d">범위 확인 · 접수</div></div>
438      <div class="step"><div class="n">02</div><div class="t">확인 연락</div><div class="d">1영업일 내</div></div>
439      <div class="step"><div class="n">03</div><div class="t">착수금 결제</div><div class="d">결제 링크 발송</div></div>
440      <div class="step"><div class="n">04</div><div class="t">시안 제작</div><div class="d">디자인 확인</div></div>
441      <div class="step hl"><div class="n">05</div><div class="t">시안 확정</div><div class="d">범위 확정</div></div>
442      <div class="step"><div class="n">06</div><div class="t">제작 · 검수</div><div class="d">무상 수정 반영</div></div>
443      <div class="step"><div class="n">07</div><div class="t">오픈</div><div class="d">잔금 결제</div></div>
444      <div class="step"><div class="n">08</div><div class="t">하자보수</div><div class="d">1개월 무상</div></div>
445    </div>
446  </div>
447</div>
448
449<!-- 유지관리 -->
450<div class="sec gray">
451  <div class="wrap">
452    <div class="sec-title">오픈 후 유지관리(선택)</div>
453    <div class="sec-sub">홈페이지는 오픈 이후에도 손이 갑니다. 매달 정해진 요금으로 관리해 드립니다.</div>
454    <div class="cares">
455      <div class="care">
456        <div class="c-name">베이직 케어</div>
457        <div class="c-price">월 5만원</div>
458        <div class="c-desc">월 수정 2건(텍스트 · 이미지 교체) · 정기 백업 · 장애 대응</div>
459      </div>
460      <div class="care">
461        <div class="c-name">스탠다드 케어</div>
462        <div class="c-price">월 10만원</div>
463        <div class="c-desc">월 수정 5건 · 콘텐츠 등록 대행 · 보안 업데이트 · 정기 백업 · 장애 대응</div>
464      </div>
465    </div>
466    <div class="cares-note">※ 유지관리 미가입 시 오픈 후 수정은 개별 요청 1건당 3만원부터 진행합니다. 유지관리 요금은 오픈 시점부터 월 단위 별도 청구입니다.</div>
467  </div>
468</div>
469
470<!-- ===== 주문 ===== -->
471<div class="sec blue" id="order">
472  <div class="wrap">
473    <div class="sec-title">제작 신청</div>
474    <div class="sec-sub">패키지와 옵션을 고르면 착수금이 바로 계산됩니다. 신청 접수 후 1영업일 안에 확인 연락과 함께 착수금 결제 링크(카카오톡 · 문자)를 보내드립니다.</div>
475
476    <div class="order-grid" id="orderGrid">
477      <div class="order-main">
478
479        <!-- 1. 패키지 -->
480        <div class="ostep">
481          <h3><span class="num">1</span>패키지 선택</h3>
482          <div class="hint">맞춤형(예약 · 회원 · 결제 등 기능 개발)은 요구 기능 확정 후 견적이 나오므로 상담으로 진행합니다.</div>
483          <div class="pick" id="pkgPick">
484            <label>
485              <input type="radio" name="pkg" value="consult">
486              <div class="card">
487                <div class="t">기획 상담</div>
488                <div class="pr">5만원 <small style="font-weight:400;color:var(--text-sub)">(부가세 별도)</small></div>
489                <div class="d">30분 상담 · 요구사항 문서와 견적서 · 제작 시 전액 차감</div>
490              </div>
491            </label>
492            <label>
493              <input type="radio" name="pkg" value="basic" checked>
494              <div class="card">
495                <div class="t">베이직</div>
496                <div class="pr">150만원 <small style="font-weight:400;color:var(--text-sub)">(부가세 별도)</small></div>
497                <div class="d">5페이지 · 템플릿 기반 · 무상 수정 2회 · 2~3주</div>
498              </div>
499            </label>
500            <label>
501              <input type="radio" name="pkg" value="standard">
502              <div class="card">
503                <div class="t">스탠다드</div>
504                <div class="pr">300만원 <small style="font-weight:400;color:var(--text-sub)">(부가세 별도)</small></div>
505                <div class="d">10페이지 · 전용 디자인 · 무상 수정 3회 · 4~6주</div>
506              </div>
507            </label>
508            <label>
509              <input type="radio" name="pkg" value="custom">
510              <div class="card">
511                <div class="t">맞춤형 (상담)</div>
512                <div class="pr">상담 견적</div>
513                <div class="d">아래 옵션 목록에 없는 기능 · 외부 시스템 연동</div>
514              </div>
515            </label>
516          </div>
517        </div>
518
519        <!-- 2. 옵션 -->
520        <div class="ostep" id="stepOptions">
521          <h3><span class="num">2</span>옵션 추가</h3>
522          <div class="hint">필요한 것만 고르시면 금액이 바로 더해집니다. 목록에 없는 기능은 아래 요청 사항에 적어 주시면 별도 견적으로 안내드립니다.</div>
523          <div id="featList"></div>
524          <div class="opt-row">
525            <div>
526              <div class="o-name">오픈 후 유지관리</div>
527              <div class="o-desc">오픈 시점부터 월 단위 별도 청구 · 착수금에 포함되지 않습니다</div>
528            </div>
529            <select class="care-sel" id="careSel">
530              <option value="none">신청 안 함</option>
531              <option value="basic">베이직 케어 · 월 5만원</option>
532              <option value="standard">스탠다드 케어 · 월 10만원</option>
533            </select>
534          </div>
535        </div>
536
537        <!-- 3. 범위 확인 -->
538        <div class="ostep" id="stepScope">
539          <h3><span class="num">3</span>범위 확인</h3>
540          <div class="hint">신청 전에 포함 범위와 불포함 항목을 확인해 주세요. 이 내용 그대로 진행됩니다.</div>
541          <div class="scope-box">
542            <h4>포함</h4>
543            <ul id="scopeInc"></ul>
544          </div>
545          <div class="scope-box">
546            <h4 id="scopeExcTitle">포함되지 않음 (진행 중 추가 시 별도 견적)</h4>
547            <ul id="scopeExcFeat"></ul>
548            <ul id="scopeExcFixed">
549              <li class="exc">선택한 페이지 수를 넘는 페이지 추가 (1페이지 15만원)</li>
550              <li class="exc">옵션 목록에 없는 기능 (요청 시 별도 견적)</li>
551              <li class="exc">시안 확정 후 레이아웃 · 디자인 컨셉 전면 변경 (재계약)</li>
552              <li class="exc">문구 · 사진 원고 작성 (의뢰인 제공, 작성 대행은 협의)</li>
553            </ul>
554          </div>
555          <div class="scope-box" id="scopeFeeBox">
556            <h4>실비 별도</h4>
557            <ul>
558              <li class="fee">도메인 등록 연 2만원 안팎 · 서버 호스팅 월 1~2만원 안팎</li>
559              <li class="fee">유료 이미지 · 폰트 구매 시 실비</li>
560            </ul>
561          </div>
562          <label class="agree">
563            <input type="checkbox" id="agreeScope">
564            <span id="agreeScopeText"><b>[필수]</b> 위 포함 범위와 무상 수정 횟수를 확인했습니다.</span>
565          </label>
566          <label class="agree">
567            <input type="checkbox" id="agreeChange">
568            <span id="agreeChangeText"><b>[필수]</b> 페이지 · 기능 추가와 컨셉 변경은 범위 변경으로 별도 견적 대상임에 동의합니다.</span>
569          </label>
570        </div>
571
572        <!-- 4. 신청 정보 -->
573        <div class="ostep">
574          <h3><span class="num">4</span>신청 정보</h3>
575          <div class="hint">확인 연락과 진행 안내에 사용합니다.</div>
576          <div class="frm">
577            <div>
578              <label for="fCompany">상호 · 기관명 <em>*</em></label>
579              <input type="text" id="fCompany" placeholder="예: 오산상사">
580            </div>
581            <div>
582              <label for="fName">담당자 성함 <em>*</em></label>
583              <input type="text" id="fName" placeholder="예: 홍길동">
584            </div>
585            <div>
586              <label for="fPhone">연락처 <em>*</em></label>
587              <input type="tel" id="fPhone" placeholder="010-0000-0000">
588            </div>
589            <div>
590              <label for="fEmail">이메일</label>
591              <input type="email" id="fEmail" placeholder="[email protected]">
592            </div>
593            <div>
594              <label for="fDue">희망 오픈 시기</label>
595              <input type="month" id="fDue">
596            </div>
597            <div class="full">
598              <label for="fMemo">참고 사이트 · 요청 사항</label>
599              <textarea id="fMemo" placeholder="참고하고 싶은 사이트 주소, 홈페이지 용도, 꼭 들어가야 하는 내용 등을 적어 주세요."></textarea>
600            </div>
601          </div>
602          <div class="privacy-note">
603            입력하신 정보는 제작 · 상담 계약의 진행과 결제 처리에만 사용하고, 그 밖의 목적으로는 쓰지 않습니다.
604            보관 기간과 처리 절차는 <a href="/privacy/" target="_blank" rel="noopener">개인정보 처리방침</a>에서 확인하실 수 있습니다.
605          </div>
606        </div>
607      </div>
608
609      <!-- 견적 요약 -->
610      <div class="order-side">
611        <div class="quote" id="quoteBox">
612          <h3 id="qTitle">견적 요약</h3>
613          <div id="qBody">
614            <div class="q-row"><span class="k" id="qPkgName">베이직</span><span class="v" id="qPkgPrice">150만원</span></div>
615            <div id="qFeatRows"></div>
616            <div class="q-div"></div>
617            <div class="q-row"><span class="k">제작비 합계 (부가세 별도)</span><span class="v" id="qSupply">150만원</span></div>
618            <div class="q-row"><span class="k">부가세 (10%)</span><span class="v" id="qVat">15만원</span></div>
619            <div class="q-row total"><span class="k">총액 (부가세 포함)</span><span class="v" id="qTotal">165만원</span></div>
620            <div class="q-row deposit"><span class="k" id="qDepositLabel">착수금 (50%)</span><span class="v" id="qDeposit">82만5,000원</span></div>
621            <div class="q-row" id="qBalanceRow"><span class="k">잔금 (오픈 시)</span><span class="v" id="qBalance">82만5,000원</span></div>
622            <div class="q-row" id="qCareRow" style="display:none"><span class="k" id="qCareName"></span><span class="v" id="qCarePrice"></span></div>
623          </div>
624          <div id="qCustomBody" style="display:none">
625            <div class="q-note" style="margin-top:0;font-size:13.5px;color:#e2e8f0;line-height:1.7">맞춤형은 요구 기능을 확인한 뒤 견적을 드립니다. 아래 신청 정보를 남겨 주시면 1영업일 안에 연락드립니다.</div>
626          </div>
627          <div class="q-note" id="qNote">신청 접수 후 1영업일 안에 확인 연락을 드리고, 착수금 결제 링크(카카오톡 · 문자)를 보내드립니다. 착수금 입금 확인 시점부터 제작이 시작됩니다. 시안 제작 착수 전에는 착수금 전액이 환불됩니다.</div>
628          <button class="q-submit" id="btnSubmit">신청 접수하기</button>
629          <div class="q-err" id="qErr"></div>
630        </div>
631      </div>
632    </div>
633
634    <!-- 접수 완료 -->
635    <div class="done" id="doneBox">
636      <h3>신청 내용이 준비되었습니다</h3>
637      <p>아래 내용을 <b>[email protected]</b>로 보내 주시면 접수가 완료됩니다. 버튼을 누르면 메일 앱이 열리고 내용이 자동으로 채워집니다.</p>
638      <p>접수 확인 후 1영업일 안에 연락드리고, 착수금 결제 링크를 카카오톡 · 문자로 보내드립니다.</p>
639      <div class="sum" id="doneSum"></div>
640      <div class="btns">
641        <a class="mail" id="doneMail" href="#">메일 앱으로 보내기</a>
642        <button class="copy" id="doneCopy" type="button">내용 복사하기</button>
643      </div>
644    </div>
645  </div>
646</div>
647
648<!-- 푸터 -->
649<div class="footer">
650  <div class="wrap">
651    <div class="co">주식회사 리온 (RION Co., Ltd.)</div>
652    <div class="line">대표 조혜련 · 사업자등록번호 802-81-04003</div>
653    <div class="line">경기도 오산시 청학로 45, 오산대학교 지성1관 B504호</div>
654    <div class="line">문의 <a href="mailto:[email protected]">[email protected]</a></div>
655    <div class="line"><a href="/terms/">이용약관</a> · <a href="/privacy/">개인정보 처리방침</a></div>
656    <div class="caveat">
657      표시 가격은 2026년 8월 기준 표준 요금이며 부가세 포함 총액을 함께 표시합니다. 결제는 이 화면에서 카드로 진행되고, 결제 내역은 등록하신 연락처로 안내드립니다.<br>
658      환불 기준은 제작의 경우 시안 제작 착수 전 착수금 전액 환불, 착수 후에는 진행 단계에 따라 기성분을 공제하고 정산합니다. 기획 상담은 상담 진행 전까지 전액 환불됩니다.
659    </div>
660  </div>
661</div>
662
663<script>
664(function () {
665  // ===== 연동 설정 =====
666  // ORDER_ENDPOINT : 주문 저장·결제 승인 서버(API Gateway) 주소. 비우면 메일 접수로 동작한다.
667  // NICEPAY_CLIENT_ID : 나이스페이 클라이언트 키(Server 승인 모델). 둘 다 채워야 결제창이 열린다.
668  var ORDER_ENDPOINT = 'https://dlk3hq1rlf.execute-api.ap-northeast-2.amazonaws.com';
669  var NICEPAY_CLIENT_ID = 'R2_5728844a3bcd4346b23888812481a2d6';
670
671  // >>> CATALOG START. 단가 정의. 서버(rion-pay-api/catalog.js)와 값이 일치해야 하며
672  //     check_catalog.js가 두 곳을 대조한다. 값을 고치면 반드시 양쪽을 함께 고칠 것.
673  var PKG = {
674    // fullPay = 착수금·잔금으로 나누지 않고 전액 결제
675    consult:  { label: '기획 상담', base: 50000, fullPay: true, pages: '30분 상담(전화 또는 화상)', design: '필요한 기능 정리', extra: '예산 범위 산정', rev: '요구사항 문서 · 견적서 제공', weeks: '신청 후 3영업일 이내 진행' },
676    basic:    { label: '베이직',  base: 1500000, pages: '5페이지 이내',  design: '검증된 템플릿 기반 맞춤 디자인', extra: '문의폼 · 지도 · 전화 연결', rev: '무상 수정 2회', weeks: '제작 기간 2~3주' },
677    standard: { label: '스탠다드', base: 3000000, pages: '10페이지 이내', design: '전용 디자인, 시안 2종 중 선택',  extra: '갤러리 · 공지 관리, 방문 통계', rev: '무상 수정 3회', weeks: '제작 기간 4~6주' },
678    custom:   { label: '맞춤형 (상담)', base: 0 }
679  };
680
681  // 기능 옵션 카탈로그 (금액은 부가세 별도)
682  //  type 'count' = 수량 선택 · 'check' = 선택/해제
683  //  includes  = 이 옵션에 흡수되어 중복 청구하지 않는 옵션
684  //  requires  = 이 옵션을 켜면 함께 켜지는 선행 옵션
685  //  freeIn    = 해당 패키지에서는 기본 포함이라 목록에서 감춤
686  var GROUPS = [
687    { name: '페이지 · 원고', items: [
688      { id: 'page',    type: 'count', name: '페이지 추가',        price: 150000, unit: '페이지', max: 20, desc: '선택한 패키지 페이지 수를 넘는 분량' },
689      { id: 'copy',    type: 'count', name: '문구(원고) 작성 대행', price: 100000, unit: '페이지', max: 20, desc: '제공해 주신 자료를 바탕으로 페이지 문구 작성' },
690      { id: 'lang',    type: 'count', name: '영문 페이지 추가',     price:  80000, unit: '페이지', max: 20, desc: '영문 번역본 · 언어 전환 버튼' }
691    ]},
692    { name: '디자인 · 연출', items: [
693      { id: 'anim',    type: 'check', name: '화면 연출 · 애니메이션', price:  500000, desc: '스크롤 등장 효과, 배너 슬라이드, 마우스 반응 연출' },
694      { id: 'video',   type: 'check', name: '메인 영상 배경',        price:  300000, desc: '제공해 주신 영상을 첫 화면 배경으로 적용' },
695      { id: 'logo',    type: 'check', name: '로고 제작',            price:  400000, desc: '시안 3종 제안 · 확정본 파일 일체 제공' },
696      { id: 'pwa',     type: 'check', name: '휴대폰 설치형(앱처럼 실행)', price: 600000, desc: '홈 화면에 아이콘으로 설치되는 형태로 제작' }
697    ]},
698    { name: '콘텐츠 운영', items: [
699      { id: 'board',   type: 'check', name: '게시판 · 공지 관리자',  price:  600000, desc: '직접 글 · 이미지를 올리고 고치는 관리자 화면', freeIn: ['standard'] },
700      { id: 'gallery', type: 'check', name: '사진 갤러리 관리',     price:  400000, desc: '앨범 단위 사진 등록 · 정렬', freeIn: ['standard'] },
701      { id: 'files',   type: 'check', name: '자료실 · 파일 내려받기', price:  400000, desc: '문서 파일 등록과 내려받기 목록' },
702      { id: 'popup',   type: 'check', name: '팝업 · 배너 관리',     price:  300000, desc: '기간을 정해 여닫는 첫 화면 팝업과 배너' }
703    ]},
704    { name: '고객 접점', items: [
705      { id: 'notify',  type: 'check', name: '문의 접수 알림',       price:  300000, desc: '문의가 들어오면 메일 · 문자로 즉시 알림' },
706      { id: 'kakao',   type: 'check', name: '카카오톡 상담 연결',    price:  200000, desc: '카카오톡 채널 상담 버튼 연결' },
707      { id: 'booking', type: 'check', name: '예약 · 접수 관리',      price: 1500000, desc: '달력 예약 신청, 접수 목록 관리, 알림 발송' }
708    ]},
709    { name: '판매 · 회원', items: [
710      { id: 'member',  type: 'check', name: '회원가입 · 로그인',     price: 2000000, desc: '회원 가입 · 로그인 · 회원 목록 관리' },
711      { id: 'pay',     type: 'check', name: '온라인 결제 연동',      price: 3000000, desc: '카드 결제창 연동과 결제 내역 관리 (PG 가맹 계약은 의뢰인 명의)' },
712      { id: 'shop',    type: 'check', name: '상품 판매 · 재고 관리',  price: 5000000, desc: '상품 등록, 재고 현황, 장바구니, 주문 · 결제까지 포함', includes: ['pay'] },
713      { id: 'subs',    type: 'check', name: '정기 결제(구독)',       price: 2000000, desc: '월 단위 자동 결제와 구독 관리', requires: ['pay'] }
714    ]},
715    { name: '마케팅 · 분석', items: [
716      { id: 'ga',      type: 'check', name: '방문 통계 리포트',      price:  300000, desc: '방문자 · 유입 경로 분석 도구 설치와 보는 법 안내', freeIn: ['standard'] },
717      { id: 'seo',     type: 'check', name: '검색 노출 강화 설정',    price:  400000, desc: '페이지별 검색 정보 정리, 검색 등록 상태 점검' },
718      { id: 'news',    type: 'check', name: '뉴스레터 발송',        price:  800000, desc: '구독자 수집과 메일 발송 화면' }
719    ]}
720  ];
721
722  var CARE = {
723    none:     { label: '신청 안 함', monthly: 0 },
724    basic:    { label: '베이직 케어', monthly: 50000 },
725    standard: { label: '스탠다드 케어', monthly: 100000 }
726  };
727  // <<< CATALOG END
728
729  var FEATURES = [];
730  GROUPS.forEach(function (g) { g.items.forEach(function (f) { FEATURES.push(f); }); });
731  var FEAT = {};
732  FEATURES.forEach(function (f) { FEAT[f.id] = f; });
733
734  // sel[id] = 체크형이면 true/false, 수량형이면 개수
735  var state = { pkg: 'basic', care: 'none', sel: {} };
736
737  var $ = function (id) { return document.getElementById(id); };
738
739  function won(n) {
740    var man = Math.floor(n / 10000);
741    var rest = n % 10000;
742    if (man === 0) return n.toLocaleString('ko-KR') + '원';
743    if (rest === 0) return man.toLocaleString('ko-KR') + '만원';
744    return man.toLocaleString('ko-KR') + '만' + rest.toLocaleString('ko-KR') + '원';
745  }
746
747  function isOn(id) { return !!state.sel[id]; }
748  function qtyOf(id) { return state.sel[id] || 0; }
749
750  // 패키지에 기본 포함되어 청구하지 않는 옵션
751  function isFreeInPkg(f) { return !!(f.freeIn && f.freeIn.indexOf(state.pkg) >= 0); }
752
753  // 상위 옵션에 흡수된 옵션 → {id: 흡수한 옵션명}
754  function absorbed() {
755    var set = {};
756    FEATURES.forEach(function (f) {
757      if (isOn(f.id) && f.includes) {
758        f.includes.forEach(function (id) { set[id] = f.name; });
759      }
760    });
761    return set;
762  }
763
764  // 실제 청구 대상 = 선택됨 + 패키지 기본포함 아님 + 상위 옵션에 흡수되지 않음
765  function billed() {
766    var abs = absorbed();
767    return FEATURES.filter(function (f) {
768      return isOn(f.id) && !abs[f.id] && !isFreeInPkg(f);
769    }).map(function (f) {
770      var qty = f.type === 'count' ? qtyOf(f.id) : 1;
771      return { f: f, qty: qty, amount: f.price * qty };
772    });
773  }
774
775  function calc() {
776    var optSum = billed().reduce(function (s, b) { return s + b.amount; }, 0);
777    var supply = PKG[state.pkg].base + optSum;
778    var vat = Math.round(supply * 0.1);
779    var total = supply + vat;
780    var fullPay = !!PKG[state.pkg].fullPay;
781    var deposit = fullPay ? total : Math.round(total / 2);
782    return { supply: supply, vat: vat, total: total, deposit: deposit, balance: total - deposit, fullPay: fullPay };
783  }
784
785  // ===== 옵션 목록 렌더 =====
786  function buildFeatureList() {
787    var html = GROUPS.map(function (g) {
788      var rows = g.items.map(function (f) {
789        var tail = f.type === 'count'
790          ? '<div class="opt-tail"><div class="stepper">'
791            + '<button type="button" data-dec="' + f.id + '" aria-label="줄이기">−</button>'
792            + '<div class="val"><span data-qty="' + f.id + '">0</span>' + (f.unit === '페이지' ? 'p' : '') + '</div>'
793            + '<button type="button" data-inc="' + f.id + '" aria-label="늘리기">+</button>'
794            + '</div><div class="o-price" data-price="' + f.id + '">+' + won(f.price) + '</div></div>'
795          : '<div class="o-price" data-price="' + f.id + '">+' + won(f.price) + '</div>';
796        var left = f.type === 'count'
797          ? '<div class="opt-left"><div><div class="o-name">' + f.name + '</div><div class="o-desc" data-desc="' + f.id + '">' + f.desc + '</div></div></div>'
798          : '<div class="opt-left"><input type="checkbox" data-cb="' + f.id + '"><div><div class="o-name">' + f.name + '</div><div class="o-desc" data-desc="' + f.id + '">' + f.desc + '</div></div></div>';
799        var tag = f.type === 'count' ? 'div' : 'label';
800        return '<' + tag + ' class="opt-row" data-row="' + f.id + '">' + left + tail + '</' + tag + '>';
801      }).join('');
802      return '<div class="opt-group" data-group="' + g.name + '"><div class="g-name">' + g.name + '</div>' + rows + '</div>';
803    }).join('');
804    $('featList').innerHTML = html;
805
806    $('featList').querySelectorAll('input[data-cb]').forEach(function (cb) {
807      cb.addEventListener('change', function () {
808        var id = cb.getAttribute('data-cb');
809        state.sel[id] = cb.checked;
810        var f = FEAT[id];
811        if (cb.checked && f.requires) {
812          f.requires.forEach(function (r) { state.sel[r] = true; });
813        }
814        render();
815      });
816    });
817    $('featList').querySelectorAll('[data-inc]').forEach(function (b) {
818      b.addEventListener('click', function () {
819        var id = b.getAttribute('data-inc');
820        state.sel[id] = Math.min(FEAT[id].max, qtyOf(id) + 1);
821        render();
822      });
823    });
824    $('featList').querySelectorAll('[data-dec]').forEach(function (b) {
825      b.addEventListener('click', function () {
826        var id = b.getAttribute('data-dec');
827        state.sel[id] = Math.max(0, qtyOf(id) - 1);
828        render();
829      });
830    });
831  }
832
833  function render() {
834    var isCustom = state.pkg === 'custom';
835    var isConsult = state.pkg === 'consult';
836    var canPay = NICEPAY_CLIENT_ID && ORDER_ENDPOINT;
837    // 상담은 옵션이 없다. 옵션 단계만 숨기고 범위 확인은 상담 조건으로 바꿔 보여준다.
838    $('stepOptions').style.display = (isCustom || isConsult) ? 'none' : '';
839    $('stepScope').style.display = isCustom ? 'none' : '';
840    $('qBody').style.display = isCustom ? 'none' : '';
841    $('qCustomBody').style.display = isCustom ? '' : 'none';
842    $('qNote').style.display = isCustom ? 'none' : '';
843    $('qTitle').textContent = isCustom ? '상담 신청' : (isConsult ? '상담 신청' : '견적 요약');
844    $('btnSubmit').textContent = isCustom ? '상담 신청하기'
845      : (canPay ? (isConsult ? '상담료 결제하고 예약하기' : '착수금 결제하고 신청하기') : '신청 접수하기');
846    $('qNote').textContent = isConsult
847      ? '결제 후 3영업일 안에 상담 일정을 잡아 연락드립니다. 상담이 끝나면 요구사항 문서와 견적서를 보내드리고, 제작으로 이어지면 상담료 전액을 제작비에서 차감합니다. 상담 전에는 전액 환불됩니다.'
848      : '신청 접수 후 1영업일 안에 확인 연락을 드립니다. 착수금 입금 확인 시점부터 제작이 시작됩니다. 시안 제작 착수 전에는 착수금 전액이 환불됩니다.';
849    if (isCustom) return;
850
851    var p = PKG[state.pkg];
852    var c = calc();
853    var abs = absorbed();
854
855    // 옵션 행 상태 갱신
856    FEATURES.forEach(function (f) {
857      var row = document.querySelector('[data-row="' + f.id + '"]');
858      var priceEl = document.querySelector('[data-price="' + f.id + '"]');
859      var descEl = document.querySelector('[data-desc="' + f.id + '"]');
860      var cb = document.querySelector('[data-cb="' + f.id + '"]');
861      var qtyEl = document.querySelector('[data-qty="' + f.id + '"]');
862      if (!row) return;
863
864      if (isFreeInPkg(f)) {
865        row.style.display = 'none';
866        return;
867      }
868      row.style.display = '';
869      if (qtyEl) qtyEl.textContent = qtyOf(f.id);
870      if (cb) cb.checked = isOn(f.id);
871
872      var on = f.type === 'count' ? qtyOf(f.id) > 0 : isOn(f.id);
873      row.classList.toggle('on', on && !abs[f.id]);
874
875      if (abs[f.id]) {
876        priceEl.textContent = '포함';
877        priceEl.style.color = 'var(--text-sub)';
878        descEl.textContent = '「' + abs[f.id] + '」에 포함되어 따로 청구하지 않습니다';
879        if (cb) { cb.checked = true; cb.disabled = true; }
880      } else {
881        if (cb) cb.disabled = false;
882        descEl.textContent = f.desc;
883        priceEl.style.color = 'var(--blue)';
884        if (f.type === 'count') {
885          priceEl.textContent = qtyOf(f.id) > 0
886            ? won(f.price * qtyOf(f.id))
887            : '+' + won(f.price) + ' / ' + f.unit;
888        } else {
889          priceEl.textContent = '+' + won(f.price);
890        }
891      }
892    });
893
894    // 견적 요약
895    $('qPkgName').textContent = p.label + ' 패키지';
896    $('qPkgPrice').textContent = won(p.base);
897    $('qFeatRows').innerHTML = billed().map(function (b) {
898      var label = b.f.name + (b.f.type === 'count' ? ' × ' + b.qty : '');
899      return '<div class="q-row"><span class="k">' + label + '</span><span class="v">' + won(b.amount) + '</span></div>';
900    }).join('');
901    $('qSupply').textContent = won(c.supply);
902    $('qVat').textContent = won(c.vat);
903    $('qTotal').textContent = won(c.total);
904    $('qDepositLabel').textContent = c.fullPay ? '결제 금액 (전액)' : '착수금 (50%)';
905    $('qDeposit').textContent = won(c.deposit);
906    $('qBalance').textContent = won(c.balance);
907    $('qBalanceRow').style.display = c.fullPay ? 'none' : '';
908
909    var careRow = $('qCareRow');
910    if (state.care !== 'none') {
911      careRow.style.display = '';
912      $('qCareName').textContent = '유지관리 · ' + CARE[state.care].label + ' (오픈 후 별도)';
913      $('qCarePrice').textContent = '월 ' + won(CARE[state.care].monthly);
914    } else {
915      careRow.style.display = 'none';
916    }
917
918    // 범위 확인: 상담 상품은 제작 기준이 아니라 상담 조건을 보여준다
919    if (isConsult) {
920      $('scopeInc').innerHTML = [p.pages, p.design, p.extra, p.rev, p.weeks,
921        '제작 계약으로 이어지면 상담료 전액을 제작비에서 차감'
922      ].map(function (t) { return '<li class="inc">' + t + '</li>'; }).join('');
923      $('scopeExcTitle').textContent = '포함되지 않음';
924      $('scopeExcFeat').innerHTML = '';
925      $('scopeExcFixed').innerHTML = [
926        '디자인 시안 · 개발 등 실제 제작 작업 (별도 계약)',
927        '상담 시간을 넘기는 추가 상담 (30분 단위로 별도 신청)'
928      ].map(function (t) { return '<li class="exc">' + t + '</li>'; }).join('');
929      $('scopeFeeBox').style.display = 'none';
930      $('agreeScopeText').innerHTML = '<b>[필수]</b> 상담 시간(30분)과 결과물(요구사항 문서 · 견적서)을 확인했습니다.';
931      $('agreeChangeText').innerHTML = '<b>[필수]</b> 이 상담에는 실제 제작 작업이 포함되지 않음에 동의합니다.';
932      return;
933    }
934    $('scopeExcTitle').textContent = '포함되지 않음 (진행 중 추가 시 별도 견적)';
935    $('scopeFeeBox').style.display = '';
936    $('agreeScopeText').innerHTML = '<b>[필수]</b> 위 포함 범위와 무상 수정 횟수를 확인했습니다.';
937    $('agreeChangeText').innerHTML = '<b>[필수]</b> 페이지 · 기능 추가와 컨셉 변경은 범위 변경으로 별도 견적 대상임에 동의합니다.';
938    $('scopeExcFixed').innerHTML = [
939      '선택한 페이지 수를 넘는 페이지 추가 (1페이지 15만원)',
940      '옵션 목록에 없는 기능 (요청 시 별도 견적)',
941      '시안 확정 후 레이아웃 · 디자인 컨셉 전면 변경 (재계약)',
942      '문구 · 사진 원고 작성 (의뢰인 제공, 작성 대행은 협의)'
943    ].map(function (t) { return '<li class="exc">' + t + '</li>'; }).join('');
944
945    var pageOpt = billed().filter(function (b) { return b.f.id === 'page'; })[0];
946    var inc = [
947      p.pages + (pageOpt ? ' + 추가 ' + pageOpt.qty + '페이지' : ''),
948      p.design,
949      p.extra,
950      '반응형 제작 · SSL 적용 · 네이버 · 구글 검색 등록',
951      p.rev + ' (수정 1회 = 요청을 모아 한 번에 전달)',
952      p.weeks,
953      '오픈 후 1개월 무상 하자보수'
954    ];
955    billed().forEach(function (b) {
956      if (b.f.id === 'page') return;
957      inc.push('[선택 옵션] ' + b.f.name + (b.f.type === 'count' ? ' ' + b.qty + b.f.unit : '') + ' (' + b.f.desc + ')');
958    });
959    $('scopeInc').innerHTML = inc.map(function (t) { return '<li class="inc">' + t + '</li>'; }).join('');
960
961    var notPicked = FEATURES.filter(function (f) {
962      if (isFreeInPkg(f) || abs[f.id]) return false;
963      return f.type === 'count' ? qtyOf(f.id) === 0 : !isOn(f.id);
964    });
965    $('scopeExcFeat').innerHTML = notPicked.length
966      ? '<li class="exc">선택하지 않은 옵션 기능: ' + notPicked.map(function (f) { return f.name; }).join(' · ') + '</li>'
967      : '';
968  }
969
970  // ===== 입력 배선 =====
971  document.querySelectorAll('input[name="pkg"]').forEach(function (r) {
972    r.addEventListener('change', function () { state.pkg = r.value; render(); });
973  });
974  document.querySelectorAll('[data-pick]').forEach(function (a) {
975    a.addEventListener('click', function () {
976      var v = a.getAttribute('data-pick');
977      var r = document.querySelector('input[name="pkg"][value="' + v + '"]');
978      if (r) { r.checked = true; state.pkg = v; render(); }
979    });
980  });
981  $('careSel').addEventListener('change', function (e) { state.care = e.target.value; render(); });
982
983  // ===== 주문 데이터 =====
984  function orderPayload() {
985    var isCustom = state.pkg === 'custom';
986    var c = isCustom ? null : calc();
987    return {
988      pkg: state.pkg,
989      pkgLabel: PKG[state.pkg].label,
990      options: isCustom ? [] : billed().map(function (b) {
991        return { id: b.f.id, name: b.f.name, qty: b.qty, amount: b.amount };
992      }),
993      care: state.care,
994      careMonthly: CARE[state.care].monthly,
995      supply: c ? c.supply : 0,
996      vat: c ? c.vat : 0,
997      total: c ? c.total : 0,
998      deposit: c ? c.deposit : 0,
999      balance: c ? c.balance : 0,
1000      agreedAt: isCustom ? null : new Date().toISOString(),
1001      // 결제창이 열리는 주문인지 서버에 알린다. false면 서버가 접수 즉시 알림 메일을 보낸다.
1002      payNow: !isCustom && !!(NICEPAY_CLIENT_ID && typeof AUTHNICE !== 'undefined'),
1003      customer: {
1004        company: $('fCompany').value.trim(),
1005        name: $('fName').value.trim(),
1006        phone: $('fPhone').value.trim(),
1007        email: $('fEmail').value.trim(),
1008        due: $('fDue').value,
1009        memo: $('fMemo').value.trim()
1010      }
1011    };
1012  }
1013
1014  function buildSummary() {
1015    var isCustom = state.pkg === 'custom';
1016    var o = orderPayload();
1017    var lines = [];
1018    lines.push('[홈페이지 제작 ' + (isCustom ? '상담' : '신청') + ']');
1019    lines.push('패키지: ' + o.pkgLabel);
1020    if (!isCustom) {
1021      o.options.forEach(function (op) {
1022        lines.push('옵션: ' + op.name + (op.qty > 1 ? ' × ' + op.qty : '') + ' (' + won(op.amount) + ')');
1023      });
1024      if (state.care !== 'none') lines.push('유지관리: ' + CARE[state.care].label + ' 월 ' + won(o.careMonthly) + ' (오픈 후 별도 청구)');
1025      var isConsultOrder = state.pkg === 'consult';
1026      lines.push((isConsultOrder ? '상담료' : '제작비 합계') + ': ' + won(o.supply) + ' (부가세 별도)');
1027      lines.push('부가세 포함 총액: ' + won(o.total));
1028      if (isConsultOrder) {
1029        lines.push('결제 금액(전액): ' + won(o.deposit));
1030        lines.push('범위 확인: 상담 30분 · 결과물(요구사항 문서 · 견적서) 확인, 제작 작업 불포함 동의 (' + new Date().toLocaleString('k
1030o-KR') + ')');
1031      } else {
1032        lines.push('착수금(50%): ' + won(o.deposit));
1033        lines.push('잔금(오픈 시): ' + won(o.balance));
1034        lines.push('범위 확인: 포함 범위 · 무상 수정 횟수 확인, 범위 변경 별도 견적 동의 (' + new Date().toLocaleString('ko-KR') + ')');
1035      }
1036    }
1037    lines.push('');
1038    lines.push('상호 · 기관명: ' + o.customer.company);
1039    lines.push('담당자: ' + o.customer.name);
1040    lines.push('연락처: ' + o.customer.phone);
1041    if (o.customer.email) lines.push('이메일: ' + o.customer.email);
1042    if (o.customer.due) lines.push('희망 오픈 시기: ' + o.customer.due);
1043    if (o.customer.memo) lines.push('요청 사항: ' + o.customer.memo);
1044    return lines.join('\n');
1045  }
1046
1047  function showError(msg) {
1048    var el = $('qErr');
1049    el.textContent = msg;
1050    el.style.display = 'block';
1051  }
1052
1053  function validate() {
1054    $('qErr').style.display = 'none';
1055    var isCustom = state.pkg === 'custom';
1056    if (!isCustom && (!$('agreeScope').checked || !$('agreeChange').checked)) {
1057      showError('범위 확인의 필수 체크 2건에 동의해 주세요.');
1058      $('stepScope').scrollIntoView({ behavior: 'smooth', block: 'center' });
1059      return false;
1060    }
1061    if (!$('fCompany').value.trim() || !$('fName').value.trim() || !$('fPhone').value.trim()) {
1062      showError('상호, 담당자 성함, 연락처를 입력해 주세요.');
1063      return false;
1064    }
1065    return true;
1066  }
1067
1068  // ===== 접수 · 결제 =====
1069  $('btnSubmit').addEventListener('click', function () {
1070    if (!validate()) return;
1071
1072    var isCustom = state.pkg === 'custom';
1073    var summary = buildSummary();
1074    var payload = orderPayload();
1075    payload.summary = summary;
1076
1077    // 서버가 없으면 메일 접수로 마무리
1078    if (!ORDER_ENDPOINT) { finish(summary, false); return; }
1079
1080    var btn = $('btnSubmit');
1081    var label = btn.textContent;
1082    btn.disabled = true;
1083    btn.textContent = '접수 중…';
1084
1085    fetch(ORDER_ENDPOINT + '/orders', {
1086      method: 'POST',
1087      headers: { 'Content-Type': 'application/json' },
1088      body: JSON.stringify(payload)
1089    }).then(function (res) {
1090      if (!res.ok) throw new Error('order failed');
1091      return res.json();
1092    }).then(function (data) {
1093      // 상담 건이거나 결제 미설정이면 접수 완료로 끝낸다
1094      if (isCustom || !NICEPAY_CLIENT_ID) { finish(summary, true); return; }
1095      openPayment(data.orderId, payload);
1096    }).catch(function () {
1097      btn.disabled = false;
1098      btn.textContent = label;
1099      finish(summary, false);
1100    });
1101  });
1102
1103  // 나이스페이 결제창은 화면 전체를 덮는 iframe(#newPayIframe) 안에 660x825로 그려진다.
1104  // 노트북처럼 세로가 825보다 짧은 화면에서는 결제 버튼이 잘리므로,
1105  // iframe 높이를 결제창 실제 높이로 고정하고 바깥 레이어에 스크롤을 준다.
1106  var PAY_MIN_H = 860;
1107  function fitPayLayer() {
1108    var layer = document.getElementById('newDivLayer');
1109    var frame = document.getElementById('newPayIframe');
1110    if (!layer || !frame) return;
1111    layer.style.overflowY = 'auto';
1112    layer.style.overflowX = 'hidden';
1113    layer.style.webkitOverflowScrolling = 'touch';
1114    if (window.innerHeight < PAY_MIN_H) {
1115      frame.style.position = 'relative';
1116      frame.style.display = 'block';
1117      frame.style.bottom = 'auto';
1118      frame.style.height = PAY_MIN_H + 'px';
1119    } else {
1120      frame.style.position = 'absolute';
1121      frame.style.bottom = '0';
1122      frame.style.height = '100%';
1123    }
1124  }
1125  window.addEventListener('resize', fitPayLayer);
1126
1127  function openPayment(orderId, payload) {
1128    if (typeof AUTHNICE === 'undefined') { finish(payload.summary, true); return; }
1129    // 결제창은 같은 화면 위에 뜬다. 고객이 창을 닫고 돌아왔을 때 버튼이 멈춰 있지 않도록 되돌린다.
1130    setTimeout(function () {
1131      $('btnSubmit').disabled = false;
1132      $('btnSubmit').textContent = '착수금 결제하고 신청하기';
1133    }, 2000);
1134    AUTHNICE.requestPay({
1135      clientId: NICEPAY_CLIENT_ID,
1136      method: 'cardAndEasyPay',
1137      orderId: orderId,
1138      amount: payload.deposit,
1139      goodsName: payload.pkg === 'consult'
1140        ? '홈페이지 기획 상담(30분)'
1141        : '홈페이지 제작 착수금(' + payload.pkgLabel + ')',
1142      returnUrl: ORDER_ENDPOINT + '/payments/return',
1143      buyerName: payload.customer.name,
1144      buyerTel: payload.customer.phone.replace(/[^0-9]/g, ''),
1145      buyerEmail: payload.customer.email,
1146      // 결제창이 떠 있는 동안 뒤 페이지는 고정한다(높이 보정은 fitPayLayer가 맡는다).
1147      disableScroll: true,
1148      zIdxHigher: true,
1149      fnError: function (result) {
1150        $('btnSubmit').disabled = false;
1151        $('btnSubmit').textContent = '착수금 결제하고 신청하기';
1152        showError('결제창 오류: ' + (result.errorMsg || '') + ' 접수는 저장되었으니 연락드리겠습니다.');
1153      }
1154    });
1155    // 결제창 iframe은 requestPay 안에서 바로 만들어진다. 그 직후 높이를 맞춘다.
1156    fitPayLayer();
1157  }
1158
1159  function finish(summary, sent) {
1160    var box = $('doneBox');
1161    box.style.display = 'block';
1162    $('doneSum').textContent = summary;
1163    if (sent) {
1164      box.querySelector('h3').textContent = '신청이 접수되었습니다';
1165      box.querySelectorAll('p')[0].style.display = 'none';
1166      $('doneMail').style.display = 'none';
1167      $('doneCopy').style.display = 'none';
1168      $('orderGrid').style.display = 'none';
1169    } else {
1170      var mail = 'mailto:[email protected]?subject='
1171        + encodeURIComponent('[홈페이지 제작 신청] ' + $('fCompany').value.trim())
1172        + '&body=' + encodeURIComponent(summary);
1173      $('doneMail').setAttribute('href', mail);
1174    }
1175    box.scrollIntoView({ behavior: 'smooth', block: 'start' });
1176  }
1177
1178  $('doneCopy').addEventListener('click', function () {
1179    var text = $('doneSum').textContent;
1180    if (navigator.clipboard && navigator.clipboard.writeText) {
1181      navigator.clipboard.writeText(text).then(function () {
1182        $('doneCopy').textContent = '복사되었습니다';
1183        setTimeout(function () { $('doneCopy').textContent = '내용 복사하기'; }, 2000);
1184      });
1185    }
1186  });
1187
1188  buildFeatureList();
1189  render();
1190})();
1191</script>
1191
1192
1193</body>
1194</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.