/* ========================================================================== 청온 케어 — 메인 스타일시트 공통 셸(머리·하단 행동 바·푸터·컨트롤)과 첫 페이지 섹션. 토큰은 tokens.css 한 곳에서만 정의한다. 2차 페이지(protocol/)는 이 파일 + protocol.css 를 쓴다. ========================================================================== */ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } html { font-size: 16px; background-color: var(--surface); color: var(--ink); font-family: var(--font-body); font-synthesis-style: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; scroll-padding-top: var(--space-6); } body { min-height: 100dvh; line-height: var(--leading-normal); overflow-x: clip; background: var(--surface); color: var(--ink); font-variant-numeric: tabular-nums; } /* 한글 조판 정본(typography §6-5) */ :lang(ko) { word-break: keep-all; overflow-wrap: anywhere; line-break: strict; } :lang(ko) :is(p, li, dd, dt, figcaption) { line-height: var(--leading-normal); letter-spacing: 0; } :lang(ko) :is(h1, h2, h3) { line-height: var(--leading-tight); text-wrap: balance; } :lang(ko) :is(em, i, cite, dfn, var, address) { font-style: normal; } :lang(ko) a { text-underline-position: under; } img { display: block; max-width: 100%; height: auto; } a { color: inherit; text-decoration: none; } button, input, select, textarea, output { font: inherit; color: inherit; } button { cursor: pointer; border: none; background: none; } fieldset { border: 0; min-width: 0; } legend { padding: 0; } .wrap { width: min(100% - 2 * var(--pad-inline), var(--container)); margin-inline: auto; } .num { font-variant-numeric: tabular-nums; } /* 사용자가 줄 값의 자리 — 대괄호 표기 + 점선 밑줄 한 가지 표식 */ .placeholder { color: var(--placeholder-ink); text-decoration: underline dotted; text-underline-offset: 0.2em; } /* ── 접근성 ── */ .skip-link { position: fixed; top: 1rem; left: 1rem; z-index: 1000; padding: 0.5rem 1rem; background: var(--surface-inverse); color: var(--ink-inverse); border-radius: var(--radius); transform: translateY(-200%); font-weight: var(--weight-medium); } .skip-link:focus { transform: translateY(0); } :where(a, button, input, select, textarea, [tabindex]):focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; } /* ── 공통 셸: 머리 — 내비 없음. 상호와 행동 하나 ── */ .site-head { background: var(--head-bg); border-bottom: 1px solid var(--line); padding-block: var(--space-3); } .head-inner { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); min-height: var(--control-block); } .wordmark { font-size: var(--step-1); font-weight: var(--weight-strong); letter-spacing: -0.01em; white-space: nowrap; color: var(--ink); display: inline-flex; align-items: center; min-height: var(--control-block); } .head-action { display: inline-flex; align-items: center; justify-content: center; min-height: var(--control-block); padding-inline: var(--space-4); border-radius: var(--radius); background: var(--accent); color: var(--accent-ink); font-weight: var(--weight-strong); font-size: var(--step--1); white-space: nowrap; transition: background-color var(--dur-quick) var(--ease-soft); } .head-action:hover { background: var(--accent-hover); } /* ── 버튼 ── */ .btn-primary { display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2); min-height: var(--control-block); padding: 0 var(--space-4); background: var(--accent); color: var(--accent-ink); border-radius: var(--radius); font-weight: var(--weight-strong); font-size: var(--step-0); white-space: nowrap; transition: background-color var(--dur-quick) var(--ease-soft); } .btn-primary:hover { background: var(--accent-hover); } .btn-small { min-height: 2.25rem; font-size: var(--step--1); padding-inline: var(--space-3); } .text-link { display: inline-flex; align-items: center; min-height: var(--control-block); color: var(--accent); font-weight: var(--weight-strong); text-decoration: underline; text-underline-offset: 0.25em; white-space: nowrap; } .text-link:hover { color: var(--accent-hover); } .action-btn { display: inline-flex; align-items: center; justify-content: center; min-height: 2.25rem; padding-inline: var(--control-pad-inline); border: 1px solid var(--line-strong); border-radius: var(--radius); font-size: var(--step--1); font-weight: var(--weight-medium); background: var(--surface-raised); color: var(--ink); white-space: nowrap; transition: border-color var(--dur-quick) var(--ease-soft), color var(--dur-quick) var(--ease-soft); } .action-btn:hover { border-color: var(--accent); color: var(--accent); } .icon-btn { display: inline-flex; align-items: center; justify-content: center; width: var(--control-block); height: var(--control-block); border-radius: var(--radius); font-size: var(--step-1); color: var(--ink-muted); } .icon-btn:hover { background: var(--surface-card); color: var(--ink); } /* ── 섹션 공통 ── */ .section-title { font-size: var(--step-2); font-weight: var(--weight-strong); letter-spacing: -0.015em; color: var(--ink); max-width: 24em; } .section-head { display: flex; justify-content: space-between; align-items: flex-end; flex-wrap: wrap; gap: var(--space-2) var(--space-4); margin-bottom: var(--space-5); } /* ── 1. 첫 화면: 견적 계산기 ── */ .quote { padding-block: var(--space-5) var(--space-7); } .quote-grid { display: grid; grid-template-columns: minmax(0, 4fr) minmax(0, 8fr); gap: var(--space-6); align-items: start; } .quote-title { font-size: var(--step-2); font-weight: var(--weight-strong); letter-spacing: -0.015em; color: var(--ink); margin-bottom: var(--space-4); max-width: 18em; } .facts { display: grid; gap: 0; border-top: 1px solid var(--line-strong); } .fact { display: grid; grid-template-columns: 6em minmax(0, 1fr); gap: var(--space-3); padding-block: var(--space-2); border-bottom: 1px solid var(--line); font-size: var(--step-0); } .fact dt { color: var(--ink-muted); font-weight: var(--weight-medium); } .fact dd { color: var(--ink); } /* 작업 패널: 입력과 합계가 한 상자 안에 있다 */ .quote-tool { display: grid; grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); background: var(--surface-raised); border: 1px solid var(--line); border-radius: var(--radius); box-shadow: var(--shadow-panel); overflow: hidden; } .quote-form { padding: var(--space-5); min-width: 0; } .form-group + .form-group { margin-top: var(--space-5); } .form-label { display: block; font-size: var(--step--1); font-weight: var(--weight-strong); color: var(--ink); margin-bottom: var(--space-2); } .type-selector { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-2); } .type-btn { min-height: var(--control-block); padding: var(--space-2); border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface-raised); color: var(--ink-muted); font-weight: var(--weight-medium); font-size: var(--step--1); text-align: center; transition: background-color var(--dur-quick) var(--ease-soft), border-color var(--dur-quick) var(--ease-soft), color var(--dur-quick) var(--ease-soft); } .type-btn:hover { border-color: var(--accent); color: var(--ink); } .type-btn.is-active { border-color: var(--accent); background: var(--accent-light); color: var(--accent-hover); font-weight: var(--weight-strong); } .slider-header { display: flex; justify-content: space-between; align-items: baseline; gap: var(--space-3); } .slider-val { font-size: var(--step-1); font-weight: var(--weight-strong); color: var(--accent); } .range-input { display: block; width: 100%; min-height: var(--control-block); accent-color: var(--accent); cursor: pointer; } .slider-scale { display: flex; justify-content: space-between; font-size: var(--step--1); color: var(--ink-faint); } .addon-grid { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--space-2); } .addon-label { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: var(--space-2); min-height: var(--control-block); padding: var(--space-2) var(--control-pad-inline); border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface-raised); font-size: var(--step--1); color: var(--ink-muted); cursor: pointer; transition: background-color var(--dur-quick) var(--ease-soft), border-color var(--dur-quick) var(--ease-soft), color var(--dur-quick) var(--ease-soft); } .addon-label input { accent-color: var(--accent); width: 1.1rem; height: 1.1rem; } .addon-price { color: var(--ink-faint); white-space: nowrap; } .addon-label:has(input:checked) { border-color: var(--accent); background: var(--accent-light); color: var(--ink); } .addon-label:has(input:checked) .addon-price { color: var(--accent-hover); } /* 합계 패널 — 숫자가 페이지에서 가장 큰 글자다 */ .quote-summary { padding: var(--space-5); background: var(--surface-card); border-left: 1px solid var(--line); min-width: 0; display: flex; flex-direction: column; } .summary-title { font-size: var(--step--1); font-weight: var(--weight-strong); color: var(--ink-muted); margin-bottom: var(--space-3); } .summary-list { display: grid; gap: var(--space-2); } .summary-row { display: flex; justify-content: space-between; gap: var(--space-3); font-size: var(--step--1); color: var(--ink-muted); } .summary-row dd { color: var(--ink); font-weight: var(--weight-medium); text-align: right; } .summary-total { margin-top: var(--space-4); padding-top: var(--space-3); border-top: 1px solid var(--line-strong); } .summary-total-label { display: block; font-size: var(--step--1); font-weight: var(--weight-strong); color: var(--ink-muted); } .total-amount { display: block; font-size: var(--step-3); font-weight: var(--weight-strong); letter-spacing: -0.02em; line-height: 1.1; white-space: nowrap; color: var(--accent-hover); margin-top: var(--space-1); } .summary-cta { margin-top: var(--space-4); width: 100%; } .summary-note { margin-top: var(--space-2); font-size: var(--step--1); color: var(--ink-muted); } /* ── 2. 절차 ── */ .steps { padding-block: var(--space-7); border-top: 1px solid var(--line); } .step-list { list-style: none; counter-reset: step; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0 var(--space-6); border-top: 1px solid var(--line-strong); } .step { counter-increment: step; display: grid; grid-template-columns: 3rem minmax(0, 1fr); gap: var(--space-3); padding-block: var(--space-4); border-bottom: 1px solid var(--line); } .step::before { grid-row: 1 / span 2; content: counter(step, decimal-leading-zero); font-size: var(--step-1); font-weight: var(--weight-strong); color: var(--accent); line-height: var(--leading-tight); padding-top: 0.1em; } .step h3, .step p { grid-column: 2; } .step h3 { font-size: var(--step-0); font-weight: var(--weight-strong); color: var(--ink); } .step p { margin-top: var(--space-1); font-size: var(--step--1); color: var(--ink-muted); max-width: var(--measure); } /* ── 3. 장비 — 사진은 누끼처럼. 배경을 곱하기 합성으로 바탕에 녹이고 가장자리는 마스크로 지운다 ── */ .gear { padding-block: var(--space-7); border-top: 1px solid var(--line); } .gear-grid { display: grid; grid-template-columns: minmax(0, 6fr) minmax(0, 5fr); gap: var(--space-6); align-items: center; } .gear-cutout { margin: 0; } .gear-cutout img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; object-position: 40% 60%; mix-blend-mode: multiply; mask-image: radial-gradient(ellipse 58% 54% at 46% 58%, var(--ink) 55%, transparent 100%); -webkit-mask-image: radial-gradient(ellipse 58% 54% at 46% 58%, var(--ink) 55%, transparent 100%); } .gear-cutout figcaption { margin-top: var(--space-2); font-size: var(--step--1); color: var(--ink-muted); text-align: center; } .gear-text .section-title { margin-bottom: var(--space-4); } .record-list { display: grid; border-top: 1px solid var(--line-strong); } .record { display: grid; grid-template-columns: 4em minmax(0, 1fr); gap: var(--space-3); padding-block: var(--space-3); border-bottom: 1px solid var(--line); } .record dt { font-weight: var(--weight-strong); color: var(--accent); } .record dd { color: var(--ink-muted); } /* ── 운영 화면 예시 ── */ .admin-view { display: none; padding-block: var(--space-5) var(--space-7); } [data-view="admin"] .client-view { display: none; } [data-view="admin"] .admin-view { display: block; } [data-view="admin"] .request { display: none; } .admin-header { display: flex; justify-content: space-between; align-items: flex-start; margin-bottom: var(--space-5); flex-wrap: wrap; gap: var(--space-3); } .demo-notice { max-width: var(--measure); margin-top: var(--space-3); padding: var(--space-3) var(--space-4); border-left: 3px solid var(--accent); background: var(--accent-light); color: var(--ink-muted); font-size: var(--step--1); border-radius: 0 var(--radius) var(--radius) 0; } .admin-kpis { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--space-3); margin-bottom: var(--space-5); } .kpi-card { background: var(--surface-raised); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-4); } .kpi-label { font-size: var(--step--1); color: var(--ink-muted); font-weight: var(--weight-medium); } .kpi-val { font-size: var(--step-2); font-weight: var(--weight-strong); color: var(--ink); margin-top: var(--space-1); } .kpi-val.accent { color: var(--accent); } .admin-table-card { background: var(--surface-raised); border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; } .table-header { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: var(--space-2); padding: var(--space-3) var(--space-4); border-bottom: 1px solid var(--line); background: var(--surface-card); } .table-title { font-size: var(--step--1); font-weight: var(--weight-strong); color: var(--ink); } .table-filter-tabs { display: flex; gap: var(--space-1); } .filter-tab { min-height: 2.25rem; padding-inline: var(--control-pad-inline); border-radius: var(--radius); font-size: var(--step--1); font-weight: var(--weight-medium); background: var(--surface-raised); border: 1px solid var(--line-strong); color: var(--ink-muted); } .filter-tab.is-active { background: var(--accent); color: var(--accent-ink); border-color: var(--accent); } .table-scroll { overflow-x: auto; } .admin-table { width: 100%; border-collapse: collapse; font-size: var(--step--1); text-align: left; white-space: nowrap; } .admin-table th { background: var(--surface-card); padding: var(--space-2) var(--space-3); font-weight: var(--weight-medium); color: var(--ink-muted); border-bottom: 1px solid var(--line); } .admin-table td { padding: var(--space-3); border-bottom: 1px solid var(--line); vertical-align: middle; } .cell-sub { color: var(--ink-muted); font-size: var(--step--1); } .cell-strong { font-weight: var(--weight-strong); } .cell-accent { color: var(--accent); } .row-fresh { background: var(--accent-light); } .status-pill { display: inline-flex; align-items: center; padding: 0.125rem var(--space-2); border-radius: var(--radius); font-size: var(--step--1); font-weight: var(--weight-strong); } .status-pill.new { background: var(--status-new-bg); color: var(--status-new-ink); } .status-pill.progress { background: var(--status-progress-bg); color: var(--status-progress-ink); } .status-pill.done { background: var(--status-done-bg); color: var(--status-done-ink); } /* 화면 전환 */ .view-switch { display: flex; align-items: center; gap: var(--space-3); padding-block: var(--space-4); border-top: 1px solid var(--line); } .view-switch-label { font-size: var(--step--1); color: var(--ink-muted); font-weight: var(--weight-medium); } .mode-toggle { display: inline-flex; background: var(--surface-card); border: 1px solid var(--line); border-radius: var(--radius); padding: 2px; gap: 2px; } .mode-btn { min-height: var(--control-block); padding-inline: var(--control-pad-inline); border-radius: calc(var(--radius) - 2px); font-size: var(--step--1); font-weight: var(--weight-medium); color: var(--ink-muted); white-space: nowrap; transition: background-color var(--dur-quick) var(--ease-soft), color var(--dur-quick) var(--ease-soft); } .mode-btn.is-active { background: var(--surface-raised); color: var(--ink); font-weight: var(--weight-strong); } /* ── 다이얼로그 ── */ .qc-dialog, .call-dialog { position: fixed; inset: 0; margin: auto; width: min(90vw, 34rem); max-height: calc(100dvh - 2 * var(--space-4)); background: var(--surface-raised); border: 1px solid var(--line); border-radius: var(--radius); padding: var(--space-5); overflow: auto; overscroll-behavior: contain; box-shadow: var(--shadow-panel); color: var(--ink); } .qc-dialog::backdrop, .call-dialog::backdrop { background: var(--scrim); } .qc-head { display: flex; justify-content: space-between; align-items: center; gap: var(--space-3); margin-bottom: var(--space-3); } .qc-title { font-size: var(--step-1); font-weight: var(--weight-strong); } .qc-list { list-style: none; display: grid; gap: var(--space-1); } .qc-item label { display: flex; align-items: center; gap: var(--space-2); min-height: var(--control-block); font-size: var(--step--1); cursor: pointer; } .qc-item input { accent-color: var(--accent); width: 1.1rem; height: 1.1rem; } .qc-note { margin-top: var(--space-3); font-size: var(--step--1); color: var(--ink-muted); } .qc-actions { display: flex; justify-content: flex-end; gap: var(--space-2); margin-top: var(--space-4); } .call-dialog { width: min(90vw, 24rem); } .call-number { margin-top: var(--space-3); font-size: var(--step-2); font-weight: var(--weight-strong); } .call-note { margin-top: var(--space-2); font-size: var(--step--1); color: var(--ink-muted); } html:has(dialog[open]) { overflow: hidden; } /* ── 공통 셸: 푸터 — 다음 행동 하나(견적 요청)가 대부분이다 ── */ .site-foot { border-top: 1px solid var(--line-strong); background: var(--surface-raised); } .request { padding-block: var(--space-7); display: grid; grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: var(--space-6); align-items: start; } .request-title { font-size: var(--step-2); font-weight: var(--weight-strong); letter-spacing: -0.015em; } .request-lead { margin-top: var(--space-3); color: var(--ink-muted); max-width: var(--measure); } .request-total { font-weight: var(--weight-strong); color: var(--accent-hover); } .request-form { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-3); } .field-wide { grid-column: 1 / -1; } .text-input { display: block; width: 100%; min-width: 0; min-height: var(--control-block); padding-inline: var(--control-pad-inline); border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface-raised); font-size: var(--step-0); transition: border-color var(--dur-quick) var(--ease-soft); } .text-input::placeholder { color: var(--ink-faint); } .text-input:hover { border-color: var(--ink-faint); } .calc-submit { grid-column: 1 / -1; width: 100%; min-height: 3.5rem; background: var(--accent); color: var(--accent-ink); font-weight: var(--weight-strong); font-size: var(--step-1); border-radius: var(--radius); transition: background-color var(--dur-quick) var(--ease-soft); } .calc-submit:hover { background: var(--accent-hover); } .request-note { grid-column: 1 / -1; font-size: var(--step--1); color: var(--ink-muted); } .foot-meta { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--space-2) var(--space-5); padding-block: var(--space-4); border-top: 1px solid var(--line); font-size: var(--step--1); color: var(--ink-muted); } .foot-brand { font-weight: var(--weight-strong); color: var(--ink); } .foot-notice { flex-basis: 100%; } /* ── 모바일 하단 고정 행동 바 — 넓은 화면에서는 없다 ── */ .action-bar { display: none; } /* ── 반응형 ── */ @media (max-width: 60em) { .quote-grid, .gear-grid, .request { grid-template-columns: minmax(0, 1fr); gap: var(--space-5); } .quote-tool { grid-template-columns: minmax(0, 1fr); } .quote-summary { border-left: 0; border-top: 1px solid var(--line); } .step-list { grid-template-columns: minmax(0, 1fr); } /* 패널이 한 열이 되면 옵션은 두 열이 들어간다 */ .addon-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } .admin-kpis { grid-template-columns: repeat(2, minmax(0, 1fr)); } .gear-grid { grid-template-columns: minmax(0, 1fr); } .gear-cutout { order: 2; } /* 하단 행동 바: safe area 를 더하고 본문 끝에 그만큼 자리를 비운다 */ body { padding-bottom: calc(var(--action-bar-height) + var(--safe-bottom)); } .head-action { display: none; } .action-bar { position: fixed; inset-inline: 0; bottom: 0; z-index: 90; display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); gap: var(--space-2); padding: var(--space-2) calc(var(--space-3) + var(--safe-right)) calc(var(--space-2) + var(--safe-bottom)) calc(var(--space-3) + var(--safe-left)); background: var(--surface-raised); border-top: 1px solid var(--line); box-shadow: var(--shadow-bar); } .action-bar-call, .action-bar-quote { display: inline-flex; align-items: center; justify-content: center; min-height: 3.25rem; border-radius: var(--radius); font-weight: var(--weight-strong); font-size: var(--step-0); } .action-bar-call { border: 1px solid var(--line-strong); background: var(--surface-raised); color: var(--ink); } .action-bar-quote { background: var(--accent); color: var(--accent-ink); } .qc-dialog, .call-dialog { max-height: calc(100dvh - 2 * var(--space-4) - var(--action-bar-height)); } } @media (max-width: 37.5em) { .type-selector, .addon-grid, .request-form { grid-template-columns: minmax(0, 1fr); } .admin-kpis { grid-template-columns: minmax(0, 1fr); } .quote-form, .quote-summary { padding: var(--space-4); } .fact { grid-template-columns: 5em minmax(0, 1fr); font-size: var(--step--1); } /* 좁은 폭에서는 옵션 이름이 세 줄로 접히지 않게 가격을 아랫줄로 내린다 */ .addon-label { grid-template-columns: auto minmax(0, 1fr); row-gap: 0; } .addon-price { grid-column: 2; } .step { grid-template-columns: 2.5rem minmax(0, 1fr); } } @media (prefers-reduced-motion: reduce) { *, *::before, *::after { transition-duration: 1ms !important; animation-duration: 1ms !important; animation-iteration-count: 1 !important; scroll-behavior: auto !important; } }