/* ==========================================================================
   VIP티클래스 (떼드영) — design tokens
   Adapted from a reference luxury-service design system: dark sage/charcoal
   palette, serif display + sans body + light-serif English accents, square
   corners, hairline grid dividers, slow fade-up reveals. No Tailwind build
   step — hand-written CSS mirroring the same token names/rhythm.
   ========================================================================== */

:root {
    --dark: #1C2621;
    --accent: #7D8A82;
    --base: #F5F5F3;
    --surface: #EFEEE8;
    --text: #23302A;
    --muted: #8B948C;
    --line: #E1E1D9;
    --gold: #B9975B;       /* VIP-only accent: used sparingly for invitation-tier moments */
    --gold-soft: #D9C79A;

    --font-sans: "Noto Sans KR", -apple-system, sans-serif;
    --font-serif: "Noto Serif KR", serif;
    --font-en: "Cormorant", serif;

    --container: 1200px;
    --space-section: 7rem;      /* py-28 */
    --space-section-sm: 5rem;   /* py-20 */
    --ease: cubic-bezier(0.25, 1, 0.5, 1);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; overflow-x: hidden; }
/* Lenis (assets/js/motion-gsap.js) takes over ALL scroll smoothing once it
   loads — running native CSS smooth-scroll at the same time makes the two
   systems fight over scroll position every frame (visible as violent
   shaking/jitter, reported 2026-08-20). .gsap-ready is only added after
   Lenis actually initializes, so this safely falls back to native smooth
   scroll if the library fails to load. */
.gsap-ready { scroll-behavior: auto !important; }
body {
    margin: 0;
    font-family: var(--font-sans);
    color: var(--text);
    background: var(--base);
    -webkit-font-smoothing: antialiased;
    overflow-x: hidden;
    /* 한국어 타이포그래피: 어절(공백) 단위로만 줄바꿈되게 함(음절 중간에서
       끊기는 것 방지). 다만 공백이 전혀 없는 문자열(예: "VIP고객초청티클래스"
       같은 SEO 압축 키워드)이 화면보다 길면 keep-all만으로는 넘칠 수 있어서
       overflow-wrap:break-word를 안전장치로 함께 둔다 — 평소엔 안 걸리고,
       진짜 넘칠 때만 개입한다. */
    word-break: keep-all;
    overflow-wrap: break-word;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
::selection { background: var(--dark); color: #fff; }

::-webkit-scrollbar { width: 8px; }
::-webkit-scrollbar-track { background: var(--base); }
::-webkit-scrollbar-thumb { background: var(--accent); border-radius: 3px; }

h1, h2, h3, h4 { font-family: var(--font-serif); font-weight: 300; line-height: 1.25; margin: 0; }
p { line-height: 1.85; margin: 0; }

.container { max-width: var(--container); margin: 0 auto; padding: 0 1.5rem; }
@media (min-width: 768px) { .container { padding: 0 3rem; } }

.font-en { font-family: var(--font-en); }
.eyebrow {
    font-family: var(--font-en);
    color: var(--accent);
    letter-spacing: 0.3em;
    font-size: 0.8rem;
    text-transform: uppercase;
    display: inline-block;
}
.underline-bar { width: 2rem; height: 1px; background: var(--accent); margin: 1rem 0; transform-origin: left; }

/* ---- scroll progress ---- */
#sp {
    position: fixed; top: 0; left: 0; height: 2px; background: var(--accent);
    z-index: 999; transform-origin: left; transform: scaleX(0); width: 100%;
}

/* ---- nav ---- */
.site-nav {
    position: fixed; top: 0; left: 0; width: 100%; z-index: 50;
    display: flex; align-items: center; justify-content: space-between;
    padding: 1.25rem 1.5rem;
    background: transparent; color: #fff;
    transition: background 0.5s var(--ease), color 0.5s var(--ease), padding 0.3s;
}
@media (min-width: 768px) { .site-nav { padding: 1.25rem 3rem; } }
.site-nav.scrolled { background: var(--base); color: var(--text); padding-top: 0.8rem; padding-bottom: 0.8rem; box-shadow: 0 1px 0 var(--line); }
.nav-logo { display: flex; align-items: center; gap: 0.6rem; }
.nav-logo img { height: 34px; width: auto; }
.nav-wordmark { font-family: var(--font-en); letter-spacing: 0.2em; text-transform: uppercase; font-size: 1.05rem; line-height: 1; }
.nav-wordmark small { display: block; font-family: var(--font-sans); font-size: 0.65rem; letter-spacing: 0; text-transform: none; opacity: 0.7; margin-top: 2px; }
.nav-menu { display: none; gap: 2rem; }
@media (min-width: 768px) { .nav-menu { display: flex; } }
.nav-menu a { font-size: 0.75rem; letter-spacing: 0.14em; text-transform: uppercase; font-weight: 300; transition: color 0.3s; }
.nav-cta {
    display: none;
    border: 1px solid rgba(255,255,255,0.4);
    padding: 0.5rem 1.25rem; font-size: 0.75rem; letter-spacing: 0.14em;
    transition: background 0.3s;
}
.site-nav.scrolled .nav-cta { border-color: var(--dark); }
@media (min-width: 640px) { .nav-cta { display: inline-flex; } }

/* ---- hero ---- */
.hero {
    position: relative; min-height: 100vh; display: flex; flex-direction: column; justify-content: flex-end;
    overflow: hidden; padding: 7rem 1.5rem 5rem;
}
@media (min-width: 768px) { .hero { padding-left: 3rem; padding-right: 3rem; padding-bottom: 7rem; } }
.hero-bg { position: absolute; inset: 0; z-index: -2; overflow: hidden; will-change: transform; }
.hero-bg img { width: 100%; height: 100%; object-fit: cover; object-position: center; transform: scale(1.12); }
/* NOTE: do NOT put a live CSS filter (contrast/brightness/saturate) on .hero-bg
   img — .hero-bg gets a continuous GSAP scroll-scrubbed transform (parallax),
   and animating transform + filter together forces the browser to repaint the
   filter every frame instead of just compositing, which reads as scroll jank
   ("버벅버벅", reported 2026-08-20). If a photo needs a punchier look, bake the
   adjustment into the image file itself (ImageMagick -brightness-contrast /
   -modulate) — see assets/img/hero-boucheron.webp for the pattern. */
.hero-overlay { position: absolute; inset: 0; z-index: -1; background: rgba(28,38,33,0.5); }
/* home hero only: no scrim at all — the photo runs at full clarity. Legibility
   comes from the dark card behind the text (.hero .hero-content) instead. */
.hero .hero-overlay { background: none; }
.hero .eyebrow { color: var(--gold-soft); }
.hero-gradient {
    position: absolute; inset: 0; z-index: -1;
    background: linear-gradient(to bottom,
        rgba(28,38,33,0.10) 0%, rgba(28,38,33,0.30) 40%,
        rgba(28,38,33,0.72) 70%, rgba(28,38,33,0.88) 85%, rgba(28,38,33,0.95) 100%);
}
.hero .hero-gradient { background: none; }
.hero-content { max-width: var(--container); margin: 0 auto; width: 100%; }
/* home hero only: text sits on its own dark card instead of a full-photo scrim */
.hero .hero-content {
    max-width: 34rem; width: auto; margin: 0;
    background: rgba(28,38,33,0.82);
    padding: 2.5rem 2.25rem;
}
.hero-text-shadow { text-shadow: 0 2px 16px rgba(0,0,0,0.45); }
.font-sans { font-family: var(--font-sans); }
.w-1_5 { display: inline-block; width: 6px; height: 6px; border-radius: 50%; }
/* .split-title has no visual rule of its own — it is a pure JS hook that
   assets/js/motion-gsap.js queries to run SplitText letter-stagger. */
.hero h1 { color: #fff; font-size: 2.4rem; margin-top: 1rem; }
@media (min-width: 768px) { .hero h1 { font-size: 4rem; } }
.hero p.desc { color: rgba(255,255,255,0.75); font-size: 0.9rem; line-height: 2; margin-top: 1.5rem; max-width: 34rem; }
.hero .btn { margin-top: 2rem; }
.hero-stats {
    display: flex; flex-wrap: wrap; gap: 2rem; margin-top: 3.5rem; padding-top: 2rem;
    border-top: 1px solid rgba(255,255,255,0.15);
}
.hero-stat .num { font-family: var(--font-serif); font-weight: 300; color: var(--gold-soft); font-size: 1.6rem; }
.hero-stat .lbl { color: rgba(255,255,255,0.4); font-size: 0.7rem; letter-spacing: 0.05em; margin-top: 0.25rem; }
.scroll-cue {
    position: absolute; bottom: 1.5rem; left: 50%; transform: translateX(-50%);
    display: flex; flex-direction: column; align-items: center; gap: 0.5rem; color: rgba(255,255,255,0.6);
    font-size: 0.7rem; letter-spacing: 0.1em;
}
.scroll-cue .bar { width: 1px; height: 2rem; background: rgba(255,255,255,0.4); animation: bounce 2s infinite; }
@keyframes bounce { 0%,100% { transform: translateY(0); } 50% { transform: translateY(8px); } }

/* ---- sections ---- */
.section { padding: var(--space-section) 0; }
.section-sm { padding: var(--space-section-sm) 0; }
.section-alt { background: var(--surface); }
.section-dark { background: var(--dark); color: #fff; }
.section-title-row { display: flex; flex-wrap: wrap; justify-content: space-between; align-items: flex-end; gap: 1.5rem; margin-bottom: 3rem; }
.section-desc { color: var(--muted); font-size: 0.85rem; max-width: 26rem; }
.section-dark .section-desc, .section-dark p { color: rgba(255,255,255,0.65); }

/* ---- grids ---- */
.grid { display: grid; gap: 2rem; }
.grid-2 { grid-template-columns: 1fr; }
.grid-3 { grid-template-columns: 1fr; }
.grid-4 { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 768px) {
    .grid-2 { grid-template-columns: repeat(2, 1fr); }
    .grid-3 { grid-template-columns: repeat(3, 1fr); }
    .grid-4 { grid-template-columns: repeat(4, 1fr); }
}
@media (min-width: 1024px) { .grid-lg-2 { grid-template-columns: repeat(2, 1fr); } }

.grid-hairline { background: var(--line); gap: 1px; }
.grid-hairline > * { background: var(--base); }
.section-dark .grid-hairline { background: rgba(255,255,255,0.15); }
.section-dark .grid-hairline > * { background: var(--dark); }

/* ---- cards ---- */
.card { background: var(--base); }
.img-wrap { overflow: hidden; position: relative; }
.img-wrap img { transition: transform 1.2s ease; width: 100%; height: 100%; object-fit: cover; }

.service-card .img-wrap { height: 20rem; }
.service-card .body { padding: 1.5rem 0.25rem; }
.service-card h3 { font-size: 1.15rem; margin: 0.5rem 0 0.75rem; }
.service-card p { color: var(--muted); font-size: 0.85rem; }
.service-card .more { display: inline-block; margin-top: 1rem; font-size: 0.75rem; letter-spacing: 0.14em; border-bottom: 1px solid var(--accent); }

.dark-card { background: var(--dark); color: #fff; padding: 2.5rem 2rem; display: flex; flex-direction: column; justify-content: center; }
.dark-card h3 { color: #fff; font-size: 1.3rem; margin-bottom: 0.75rem; }
.dark-card p { color: rgba(255,255,255,0.65); font-size: 0.85rem; margin-bottom: 1.5rem; }

.step-card { padding: 1.5rem; transition: background 0.3s; }
.step-card .step-no { font-family: var(--font-en); color: var(--accent); font-size: 1.5rem; }
.step-card h4 { font-size: 1rem; margin: 0.75rem 0 0.5rem; }
.step-card p { color: var(--muted); font-size: 0.8rem; }

.area-card { padding: 1.25rem 1rem; transition: background 0.3s, color 0.3s; }

/* ---- buttons ---- */
.btn {
    display: inline-block; font-size: 0.8rem; letter-spacing: 0.14em; padding: 1rem 2rem;
    border: 1px solid transparent; transition: background 0.3s, color 0.3s, border-color 0.3s;
    cursor: pointer;
}
.btn-accent { background: var(--accent); color: #fff; }
.btn-outline-dark { border-color: var(--dark); color: var(--dark); text-transform: uppercase; font-size: 0.7rem; padding: 1rem 2rem; }
.btn-outline-light { border-color: rgba(255,255,255,0.4); color: #fff; padding: 0.75rem 1.5rem; }
.btn-sm { padding: 0.75rem 1.5rem; font-size: 0.75rem; }
.btn-gold { border-color: var(--gold); color: var(--gold-soft); background: transparent; }

/* ---- VIP invitation-tier CTA banners ---- */
/* Two variants, used in rotation so the same visual doesn't repeat back-to-back:
   .vip-cta       — full-bleed photo banner, for the one strong mid-page moment.
   .vip-cta-plain — quiet dark+gold text-only close, for page-bottom "reserve" moments. */
.vip-cta {
    position: relative; padding: 7rem 0; overflow: hidden; color: #fff; text-align: center;
}
.vip-cta .hero-bg, .vip-cta .hero-overlay, .vip-cta .hero-gradient { position: absolute; inset: 0; }
.vip-cta .hero-bg { z-index: -3; }
.vip-cta .hero-overlay { z-index: -2; background: rgba(28,38,33,0.55); }
.vip-cta .hero-gradient { z-index: -1; background: linear-gradient(180deg, rgba(28,38,33,0.55) 0%, rgba(28,38,33,0.82) 100%); }
.vip-cta .vip-frame { max-width: 34rem; margin: 0 auto; }
.vip-cta .gold-rule { width: 2.5rem; height: 1px; background: var(--gold); margin: 1.1rem auto; transform-origin: center; }
.vip-cta .eyebrow { color: var(--gold-soft); }
.vip-cta h2 { color: #fff; font-size: 1.9rem; }
@media (min-width: 768px) { .vip-cta h2 { font-size: 2.4rem; } }
.vip-cta p { color: rgba(255,255,255,0.72); font-size: 0.9rem; margin-top: 1rem; }
.vip-cta .btn { margin-top: 2rem; }

.vip-cta-plain { background: var(--dark); color: #fff; padding: 5rem 0; text-align: center; }
.vip-cta-plain .gold-rule { width: 2.5rem; height: 1px; background: var(--gold); margin: 1.1rem auto; transform-origin: center; }
.vip-cta-plain .eyebrow { color: var(--gold-soft); }
.vip-cta-plain h2 { color: #fff; font-size: 1.6rem; }
.vip-cta-plain p { color: rgba(255,255,255,0.65); font-size: 0.88rem; margin-top: 0.75rem; }
.vip-cta-plain .btn { margin-top: 1.75rem; }

/* ---- tags / quote ---- */
.tag-pill { display: inline-block; border: 1px solid var(--line); padding: 0.3rem 0.9rem; font-size: 0.75rem; color: var(--muted); margin: 0 0.4rem 0.4rem 0; }
blockquote { border-left: 2px solid var(--accent); padding-left: 1.25rem; margin: 1.5rem 0; font-style: italic; color: var(--text); }

/* ---- stats band ---- */
.stat-band { display: grid; grid-template-columns: repeat(2, 1fr); gap: 2rem; text-align: center; }
@media (min-width: 768px) { .stat-band { grid-template-columns: repeat(4, 1fr); } }
.stat-band .num { font-family: var(--font-serif); font-size: 2rem; color: var(--accent); }
.stat-band .lbl { font-size: 0.75rem; color: var(--muted); margin-top: 0.4rem; }

/* ---- gallery ---- */
.gallery-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 0.5rem; }
@media (min-width: 768px) { .gallery-grid { grid-template-columns: repeat(4, 1fr); } }
.gallery-grid .img-wrap { aspect-ratio: 3/4; }

/* ---- inner page banner (shorter hero for detail pages) ---- */
.page-hero {
    position: relative; height: 46vh; min-height: 320px;
    display: flex; align-items: flex-end; overflow: hidden; margin-top: 0;
}
.page-hero .hero-bg, .page-hero .hero-overlay, .page-hero .hero-gradient { position: absolute; inset: 0; }
.page-hero .hero-bg { z-index: -2; }
.page-hero .hero-overlay { z-index: -1; background: rgba(28,38,33,0.55); }
.page-hero .hero-gradient { z-index: -1; background: linear-gradient(to bottom, rgba(28,38,33,0.15) 0%, rgba(28,38,33,0.55) 55%, rgba(28,38,33,0.92) 100%); }
.page-hero .container { padding-bottom: 2.5rem; }
.page-hero h1 { color: #fff; font-size: 1.9rem; margin-top: 0.75rem; }
@media (min-width: 768px) { .page-hero h1 { font-size: 2.6rem; } }
.page-hero .desc { color: rgba(255,255,255,0.75); font-size: 0.85rem; margin-top: 0.75rem; max-width: 34rem; }

.prose h2 { font-size: 1.4rem; margin: 2.5rem 0 1rem; }
.prose h3 { font-size: 1.1rem; margin: 2rem 0 0.75rem; }
.prose p { color: var(--text); font-size: 0.92rem; margin-bottom: 1rem; }
.prose ul { padding-left: 1.1rem; color: var(--text); font-size: 0.92rem; }
.prose li { margin-bottom: 0.5rem; }

/* ==========================================================================
   Editorial detail-page components (2026-08-20) — light intro without a
   full-bleed photo banner, breadcrumb as a small unobtrusive design element,
   varied light font-weights, one component per idea instead of plain <p>/<ul>
   prose. Piloted on vip-tea-class-cost.php; reusable for the other 9 keyword
   pages later. See site_architecture memory for the reference this is based on.
   ========================================================================== */

/* ---- light intro (replaces .page-hero for the editorial template) ---- */
/* breadcrumb (.breadcrumb, padding-top:8.5rem below) sits directly above this
   and already reserves the fixed-nav clearance — .detail-intro only needs a
   small gap after it, not another full nav-height of padding. */
.detail-intro { padding: 1.5rem 0 3rem; }
.detail-intro .pill-tag {
    display: inline-block; border: 1px solid var(--line); background: var(--surface);
    color: var(--muted); font-size: 0.72rem; letter-spacing: 0.04em; padding: 0.35rem 0.9rem;
    margin-bottom: 1.5rem;
}
.detail-intro .eyebrow { display: block; margin-bottom: 0.75rem; }
.detail-intro h1 { font-size: 2rem; font-weight: 200; letter-spacing: -0.01em; }
@media (min-width: 768px) { .detail-intro h1 { font-size: 2.75rem; } }
.detail-intro .desc { font-weight: 300; color: var(--muted); font-size: 0.95rem; margin-top: 1.25rem; max-width: 34rem; line-height: 1.9; }
/* two-tone heading: wrap the second line/phrase in this span to render it in
   the gold accent instead of the default dark text (echoes the reference's
   dark+pink split headings). Optional — only use where it reads naturally. */
.two-tone { color: var(--gold); }
.section-dark .two-tone, .vip-cta .two-tone { color: var(--gold-soft); }

/* ---- full-width editorial image block (not a text-over-photo hero) ---- */
.detail-figure { margin: 0 0 3rem; }
.detail-figure img { width: 100%; height: auto; max-height: 60vh; object-fit: cover; }
.detail-figure figcaption { font-size: 0.72rem; color: var(--muted); margin-top: 0.6rem; letter-spacing: 0.02em; }

/* ---- step / timeline list (D-180 style: numeral + caption | title + desc) ---- */
.step-list { border-top: 1px solid var(--line); }
.step-row {
    display: grid; grid-template-columns: 5.5rem 1fr; gap: 1rem;
    padding: 1.5rem 0; border-bottom: 1px solid var(--line);
}
.step-row .step-num { font-family: var(--font-en); font-weight: 300; font-size: 1.6rem; color: var(--accent); line-height: 1; }
.step-row .step-cap { font-size: 0.68rem; color: var(--muted); letter-spacing: 0.08em; margin-top: 0.3rem; }
.step-row h4 { font-size: 1.02rem; font-weight: 400; margin-bottom: 0.35rem; }
.step-row p { color: var(--muted); font-size: 0.85rem; margin: 0; }

/* ---- sparkle/star bullet list ---- */
.icon-list { list-style: none; padding: 0; margin: 1.5rem 0; }
.icon-list li { display: flex; gap: 0.75rem; padding: 0.6rem 0; font-size: 0.9rem; color: var(--text); }
.icon-list li::before { content: '✦'; color: var(--gold); flex-shrink: 0; font-size: 0.85rem; margin-top: 0.15rem; }

/* ---- checklist (check-mark bullet) ---- */
.check-list { list-style: none; padding: 0; margin: 1.5rem 0; }
.check-list li { display: flex; gap: 0.75rem; padding: 0.5rem 0; font-size: 0.9rem; color: var(--text); }
.check-list li::before { content: '✓'; color: var(--accent); flex-shrink: 0; font-weight: 600; }

/* ---- callout / key-point box ---- */
.callout { background: var(--surface); border-left: 2px solid var(--gold); padding: 1.5rem 1.75rem; margin: 2rem 0; }
.callout .callout-label { font-family: var(--font-en); color: var(--gold); font-size: 0.75rem; letter-spacing: 0.1em; text-transform: uppercase; display: block; margin-bottom: 0.5rem; }
.callout p { margin: 0; font-size: 0.9rem; color: var(--text); line-height: 1.8; }

/* ---- info rows: bordered numbered box list (grid-cell feel), meant to be
   paired against a text column via .split-grid below. Every row is boxed
   with a hairline border instead of a floating bullet — this is what
   actually reads as "an organized grid" (see wangji-bride-skin reference
   in site_architecture memory) rather than loose bulleted text. ---- */
.info-rows { list-style: none; padding: 0; margin: 0; border-top: 1px solid var(--line); }
.info-rows li { display: grid; grid-template-columns: 2.75rem 1fr; align-items: center; gap: 1rem; padding: 1.25rem; border: 1px solid var(--line); border-top: none; }
.info-rows .info-num { font-family: var(--font-en); font-style: italic; font-weight: 300; color: var(--gold); font-size: 1.15rem; }
.info-rows .info-text { font-size: 0.88rem; color: var(--text); }

/* ---- split-grid: disciplined 2-column pairing for a text block that DOES
   have a supporting column opposite it (e.g. .info-rows, an image). This
   is the correct place for asymmetry — a lone text block with nothing on
   the other side should stay in .editorial-col.align-left instead. ---- */
.split-grid { display: grid; grid-template-columns: 1fr; gap: 2.5rem; align-items: start; }
@media (min-width: 900px) { .split-grid { grid-template-columns: 1fr 1fr; gap: 4rem; } }

/* ---- two-up comparison cards ---- */
.compare-cards { display: grid; grid-template-columns: 1fr; gap: 1px; background: var(--line); margin: 2rem 0; }
@media (min-width: 640px) { .compare-cards { grid-template-columns: 1fr 1fr; } }
.compare-cards .compare-card { background: var(--base); padding: 1.75rem; }
.compare-cards h4 { font-size: 1rem; margin-bottom: 0.6rem; }
.compare-cards p { font-size: 0.85rem; color: var(--muted); margin: 0; }

/* ---- editorial column: text pinned to the LEFT edge of the wide 1200px
   .container instead of a centered narrow column (which reads as "compact/
   boxed-in the middle" at desktop widths). Use .align-left consistently
   for standalone text blocks that have nothing paired opposite them — a
   second reference (wangji-bride-skin) showed every text block anchored
   to the SAME edge throughout the page, never alternating. .align-right
   only belongs on a column that's genuinely paired with something on the
   other side (an image, a .info-rows box grid via .split-grid below) —
   flipping a lone text block's edge with no visual anchor is what reads
   as unorganized/"sprawled" rather than intentional (see site_architecture
   memory for both reference measurements). On mobile the column is wider
   than the viewport so the auto margin has nothing to distribute and it
   just reads as normal full-width. ---- */
.editorial-col { max-width: 40rem; }
.editorial-col.align-left { margin-right: auto; }
.editorial-col.align-right { margin-left: auto; }

/* ---- related pages: 3x2 photo card grid (internal linking) ---- */
.related-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.25rem; }
@media (min-width: 768px) { .related-grid { grid-template-columns: repeat(3, 1fr); } }
.related-grid .related-card .img-wrap { aspect-ratio: 4/3; }
.related-grid .related-card .num-eyebrow { font-family: var(--font-en); color: var(--accent); font-size: 0.7rem; letter-spacing: 0.08em; display: block; margin: 0.9rem 0 0.35rem; }
.related-grid .related-card h4 { font-size: 0.92rem; margin-bottom: 0.5rem; }
.related-grid .related-card .more { font-size: 0.72rem; letter-spacing: 0.08em; border-bottom: 1px solid var(--accent); }

/* ---- breadcrumb ---- */
.breadcrumb { font-size: 0.75rem; color: var(--muted); padding-top: 8.5rem; }

/* ---- faq ---- */
/* Reserves space for the tallest single open answer up front so opening a
   question never pushes the CTA/footer below it (measured: closed=279px,
   one item open=379px → +100px, at both 375px and desktop widths). Only one
   FAQ item can be open at a time (see main.js), so this is the true max.
   If FAQ copy gets meaningfully longer/more numerous, re-measure and update
   this value — it is not auto-calculated. */
.faq-list { min-height: 390px; }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-question { display: flex; justify-content: space-between; align-items: center; padding: 1.25rem 0; cursor: pointer; font-family: var(--font-serif); font-size: 1rem; }
.faq-icon { position: relative; width: 14px; height: 14px; flex-shrink: 0; margin-left: 1rem; }
.faq-icon::before, .faq-icon::after { content: ''; position: absolute; top: 50%; left: 50%; background: var(--dark); transition: transform 0.35s ease, opacity 0.35s ease; }
.faq-icon::before { width: 14px; height: 1px; transform: translate(-50%, -50%); }
.faq-icon::after { width: 1px; height: 14px; transform: translate(-50%, -50%); }
.faq-open .faq-icon::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }
.faq-body { max-height: 0; overflow: hidden; transition: max-height 0.4s var(--ease), padding 0.3s ease; color: var(--muted); font-size: 0.88rem; }
.faq-body.open { max-height: 400px; padding-bottom: 1.25rem; }

/* ---- footer ---- */
.site-footer { background: var(--dark); color: rgba(255,255,255,0.6); padding: 4rem 0 2rem; font-size: 0.82rem; }
.footer-grid { display: grid; gap: 2.5rem; margin-bottom: 3rem; }
@media (min-width: 768px) { .footer-grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.footer-grid h5 { color: #fff; font-family: var(--font-en); letter-spacing: 0.14em; text-transform: uppercase; font-size: 0.8rem; margin-bottom: 1rem; }
.footer-grid li { margin-bottom: 0.5rem; list-style: none; }
.footer-grid ul { padding: 0; margin: 0; }
.footer-bottom { border-top: 1px solid rgba(255,255,255,0.15); padding-top: 1.5rem; font-size: 0.72rem; display: flex; flex-wrap: wrap; justify-content: space-between; gap: 0.5rem; }

/* ---- scroll-driven motion system ----
   BASELINE (every browser): each motion class plays a one-time fade/slide-in
   automatically on paint (animation-fill-mode: both). This is the safety net
   — it guarantees content becomes fully visible with zero dependency on
   scrolling, JS, or feature support. A VIP staffer skimming fast, a link
   preview bot, a screenshot tool, or an older browser must still see
   everything. NEVER gate visibility behind a scroll/JS trigger with no
   plain-CSS fallback (see [[feedback-verify-with-real-browser]] memory /
   the 2026-08-20 incident where this exact mistake hid whole sections).

   ENHANCEMENT (browsers supporting CSS scroll-driven animations): inside the
   @supports block below, the SAME keyframes get re-driven by each element's
   own scroll position via animation-timeline: view() instead of wall-clock
   time. Different components use different motion classes on purpose so the
   page doesn't feel like one repeated fade — see markup for which class is
   used where (image blocks = motion-scale, two-col text/image pairs =
   motion-slide-l/r, gold/underline rule = motion-line, everything else =
   .reveal/motion-rise). */
.reveal, .motion-rise, .motion-scale, .motion-slide-l, .motion-slide-r, .motion-line {
    animation: motion-rise-kf 0.7s var(--ease) both;
}
.motion-scale { animation-name: motion-scale-kf; }
.motion-slide-l { animation-name: motion-slide-l-kf; }
.motion-slide-r { animation-name: motion-slide-r-kf; }
.motion-line { animation-name: motion-line-kf; animation-duration: 0.9s; }

.reveal.delay-1, .motion-rise.delay-1, .motion-scale.delay-1, .motion-slide-l.delay-1, .motion-slide-r.delay-1 { animation-delay: 0.05s; }
.reveal.delay-2, .motion-rise.delay-2, .motion-scale.delay-2, .motion-slide-l.delay-2, .motion-slide-r.delay-2 { animation-delay: 0.1s; }
.reveal.delay-3, .motion-rise.delay-3, .motion-scale.delay-3, .motion-slide-l.delay-3, .motion-slide-r.delay-3 { animation-delay: 0.15s; }
.reveal.delay-4, .motion-rise.delay-4, .motion-scale.delay-4, .motion-slide-l.delay-4, .motion-slide-r.delay-4 { animation-delay: 0.2s; }

@keyframes motion-rise-kf { from { opacity: 0; transform: translateY(24px); } to { opacity: 1; transform: translateY(0); } }
@keyframes motion-scale-kf { from { opacity: 0; transform: scale(1.08); } to { opacity: 1; transform: scale(1); } }
@keyframes motion-slide-l-kf { from { opacity: 0; transform: translateX(-32px); } to { opacity: 1; transform: translateX(0); } }
@keyframes motion-slide-r-kf { from { opacity: 0; transform: translateX(32px); } to { opacity: 1; transform: translateX(0); } }
@keyframes motion-line-kf { from { transform: scaleX(0); } to { transform: scaleX(1); } }
@keyframes motion-parallax-kf { from { transform: translateY(-5%); } to { transform: translateY(5%); } }

@supports (animation-timeline: view()) {
    .reveal, .motion-rise, .motion-scale, .motion-slide-l, .motion-slide-r, .motion-line {
        animation-timeline: view();
        animation-range: entry 0% entry 60%;
        animation-delay: 0s; /* per-element scroll position is the stagger now, not a clock delay */
    }
    .motion-line { animation-range: entry 15% entry 75%; }

    /* subtle per-banner parallax drift on hero/page-hero/vip-cta background photos */
    .hero-bg { animation: motion-parallax-kf linear both; animation-timeline: view(); animation-range: cover 0% cover 100%; }
}

/* When assets/js/motion-gsap.js confirms GSAP+ScrollTrigger loaded, it adds
   .gsap-ready to <html> and takes over these same classes with richer,
   scrubbed GSAP animation instead. Kill every CSS animation on them here so
   the two engines never fight over the same opacity/transform — but note
   .gsap-ready is only ever added AFTER a successful library load, so if the
   CDN scripts fail this rule never applies and the CSS baseline above stays
   fully in control. Do not delete the CSS baseline above "for cleanliness";
   it is the reliability fallback. */
.gsap-ready .reveal, .gsap-ready .motion-rise, .gsap-ready .motion-scale,
.gsap-ready .motion-slide-l, .gsap-ready .motion-slide-r, .gsap-ready .motion-line,
.gsap-ready .hero-bg {
    animation: none !important;
}

@media (prefers-reduced-motion: reduce) {
    .reveal, .motion-rise, .motion-scale, .motion-slide-l, .motion-slide-r, .motion-line, .hero-bg {
        animation: none !important; opacity: 1; transform: none;
    }
}

/* ---- floating cta ---- */
.floating-cta {
    position: fixed; right: 1.5rem; bottom: 1.5rem; z-index: 60;
    background: var(--dark); color: var(--gold-soft); width: 68px; height: 68px;
    display: flex; align-items: center; justify-content: center; text-align: center;
    font-size: 0.62rem; line-height: 1.4; letter-spacing: 0.01em;
    border: 1px solid var(--gold); transition: background 0.3s, color 0.3s;
}
/* NOTE: no `position` here on purpose — .floating-cta already has position:fixed,
   which is itself a positioning context for ::after. A generic `position:relative`
   on .pulse-ring previously clobbered .floating-cta's `position:fixed` (same
   specificity, later in source = wins), which sent the button to the bottom of
   the document instead of pinning it to the viewport. Do not re-add it here. */
.pulse-ring::after {
    content: ''; position: absolute; inset: -5px; border: 1px solid var(--gold);
    animation: pulse-ring 2.4s ease-in-out infinite;
}
@keyframes pulse-ring { 0% { transform: scale(1); opacity: 0.4; } 100% { transform: scale(1.6); opacity: 0; } }

.sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0,0,0,0); }
.skip-link:focus { position: fixed; top: 0.5rem; left: 0.5rem; width: auto; height: auto; background: #fff; color: var(--dark); padding: 0.6rem 1rem; z-index: 999; clip: auto; }

/* 모바일 호버 고착 방지 — 모든 :hover는 여기 안에서만 정의한다.
   (design_rules "모바일 호버 가드" 참고) */
@media (hover: hover) and (pointer: fine) {
  .nav-menu a:hover { color: var(--accent); }
  .nav-cta:hover { background: rgba(255,255,255,0.1); }
  .site-nav.scrolled .nav-cta:hover { background: var(--dark); color: #fff; }
  .img-wrap:hover img { transform: scale(1.04); }
  .service-card .more:hover { color: var(--accent); }
  .step-card:hover { background: #fff; }
  .section-dark .step-card:hover { background: rgba(255,255,255,0.05); }
  .area-card:hover { background: var(--surface); color: var(--accent); }
  .btn-accent:hover { background: var(--dark); }
  .btn-outline-dark:hover { background: var(--dark); color: #fff; }
  .btn-outline-light:hover { background: rgba(255,255,255,0.1); }
  .btn-gold:hover { background: var(--gold); color: var(--dark); border-color: var(--gold); }
  .breadcrumb a:hover { color: var(--accent); }
  .site-footer a:hover { color: var(--accent); }
  .floating-cta:hover { background: var(--gold); color: var(--dark); }
}
