/* ==========================================================================
   stop&loss — 요금제 페이지(pricing.html) 전용 스타일
   2026-08 개편 2차: 참고 구현 v6 이식 — 좌 카피 · 우 유리 카드(슬라이더 내장) +
   WebGL 프리즘 스테이지

   pricing.html 하나만 이 파일을 싣는다(전체 grep 으로 확인). 모든 신규 클래스가
   .pr- 접두사라, 여기를 통째로 지워도 다른 페이지와 관리자 콘솔은 픽셀 하나 안 바뀐다.

   색은 style.css 토큰 계열만 쓴다 — 새 브랜드 색을 만들지 않는다.
     배경 #040407(--bg) · 본문 #f7f7fa(--text) · 포인트 청록 #3de9ff(--primary)
   참고 구현의 액센트(#22D3EE)는 전부 우리 청록으로 바꿨다. 글꼴도 사이트 공용
   시스템 스택(--font · --font-mono) 그대로다 — 이 경로는 CSP(style-src 'self' ·
   font-src 'self')가 웹폰트를 막으므로 참고 구현의 Pretendard 는 애초에 못 쓴다.

   구조 (pricing.html)
     .pr-stage   — 한 화면짜리 히어로. WebGL 프리즘 캔버스가 이 안에만 깔린다
                   (예전처럼 페이지 전체 fixed 가 아니다 — 아래 표 · 폼은 민무늬 배경).
                   ⚠ 배경이 폭에 따라 두 벌이다. 1040px 이상은 프리즘, 그 미만은
                   .is-lite — 셰이더를 끄고 카드가 단계에 따라 빛난다(1-b절).
     .pr-card    — 유리 카드. 참고 구현의 blur(44px) 유리를 그대로 쓰되,
                   backdrop-filter 미지원이면 거의 불투명한 판으로 물러난다.
     .pr-grid    — 전체 요금제 표. 카드 슬라이더와 양방향 연동(이전 개편 그대로).
     .consult-*  — 상담 신청. 폼 로직은 static/app.js 가 그대로 맡는다.

   가독성 규칙
     참고 구현은 카드가 반투명(44%)이라 뒤의 컬러 워시가 비쳐 보이는 것이 의도다.
     대신 카드 안에 어두운 그라디언트 한 겹(::before)과 글자 그림자를 깔아
     무지개가 가장 밝은 순간에도 글자가 또렷하게 남는다 — 이 두 겹을 지우면
     밝은 워시 위에서 보조 글자가 묻히니 지우지 말 것.
   ========================================================================== */

/* ---------- 1. 프리즘 스테이지 ---------- */

.pr-stage {
  /*
   * 요금제 단계 세기(0~1). static/pricing.js 의 render() 가 CSSOM 으로 갱신한다.
   * 좁은 화면에서 카드의 후광과 테두리 빛이 이 값 하나로 커진다(아래 1-b절).
   *
   * 기본값은 첫 화면 단계(통합 = 5/6)와 같다 — JS 가 죽어도 값이 비지 않는다.
   * 카드가 아니라 여기에 두는 이유: 판과 카드가 함께 읽을 수 있어야 하고,
   * 카드에 기본값을 선언해 두면 그 선언이 상속을 가려 두 곳이 어긋난다.
   */
  --pr-tier: .833;
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  overflow: hidden;
  min-height: 560px;
  min-height: calc(100dvh - var(--header-h));
  background: var(--bg);
}

.pr-canvas {
  position: absolute;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  opacity: 0;
  transition: opacity 1.1s ease;
}

/* 첫 프레임이 실제로 나온 뒤에만 드러난다(pricing.js 가 is-live 를 단다). */
.pr-stage.is-live .pr-canvas { opacity: 1; }

/*
 * 정적 폴백 — WebGL 이 없거나 그리다 죽었을 때(pricing.js 가 is-static 을 단다).
 * 참고 구현의 no-gl 폴백을 우리 팔레트로 옮겼다. 어떤 실패에서도 화면이 비지 않는다.
 */
.pr-stage.is-static .pr-canvas { display: none; }

.pr-stage.is-static::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background:
    radial-gradient(38% 52% at 24% 50%, rgba(255, 255, 255, .08), transparent 60%),
    radial-gradient(58% 66% at 58% 38%, rgba(180, 140, 255, .12), transparent 65%),
    radial-gradient(58% 66% at 66% 62%, rgba(61, 233, 255, .11), transparent 65%);
}

/*
 * 아래 경계 봉합선. 셰이더의 톤매핑 때문에 캔버스 바닥이 페이지 배경(#040407)보다
 * 아주 살짝 밝게 끝나는데, 그대로 두면 스테이지와 다음 섹션 사이에 가로줄이 보인다.
 * 배경색으로 흘려보내는 띠 하나로 어떤 톤에서도 이음매가 사라진다.
 */
.pr-stage::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 140px;
  z-index: 1;
  pointer-events: none;
  background: linear-gradient(to bottom, rgba(4, 4, 7, 0), var(--bg));
}

/* ---------- 1-b. 좁은 화면 — 카드가 곧 빛이다 ---------- */

/*
 * 1040px 미만에서 pricing.js 가 .is-lite 를 단다. 셰이더는 아예 켜지지 않는다.
 *
 * 왜 이 방향인가 (2026-08-30)
 *   1열에서는 카피와 카드가 세로로 쌓여, 화면 어디에 구체를 놓아도 그 자리에 글자가
 *   있다. 두 번 옮겨 봤고 두 번 다 글자를 못 읽게 만들었다(pricing.js ⓪절에 기록).
 *   카드는 사정이 다르다 — 이미 어두운 유리판이고(::before 가독성 오버레이 + 글자
 *   그림자) 그 위의 글자는 뒤가 밝아져도 읽힌다. 그래서 빛을 그 판의 '둘레'로
 *   내보낸다. 어떤 글자도 가리지 않으면서, 요금제가 오를수록 밝아지는 것이 보인다.
 *
 * 커지는 것은 --pr-tier(0~1) 하나다. 후광(box-shadow)과 테두리 빛(::after)이 같은
 * 값을 읽으므로 슬라이더를 밀면 둘이 함께 자란다. 판의 바탕 빛은 일부러 고정이다 —
 * 움직이는 것이 카드 하나뿐이어야 '카드가 세기를 말한다'가 읽힌다.
 *
 * 클래스로 켜는 이유(미디어쿼리가 아니라): 폭 판정을 JS 한 곳에서만 한다.
 * 여기와 pricing.js 가 각자 폭을 재면, 둘이 어긋나는 좁은 띠에서 셰이더는 안 도는데
 * 카드도 안 빛나는 — 배경이 통째로 검정인 구간이 생긴다.
 * JS 가 통째로 죽으면 이 모드가 안 켜져 배경이 검정으로 남는다. 그 상황에서는
 * 카드 내용도 HTML 폴백(통합 요금제 고정)이라, 배경은 그때 걱정할 일이 아니다.
 *
 * 되살리려는 사람에게: 좁은 화면에 구체를 다시 세우려거든 pricing.js ⓪절부터 읽을 것.
 * 자리를 옮기는 것으로 끝나는 문제가 아니다.
 */

.pr-stage.is-lite .pr-canvas { display: none; }

/* 실패 폴백(.is-static)의 그라디언트와 겹치지 않게 한다. 좁은 화면에서는 셰이더를
   시작조차 하지 않으므로 평소엔 만날 일이 없고, 데스크톱에서 창을 줄였을 때만 겹친다. */
.pr-stage.is-lite.is-static::before { display: none; }

/*
 * 판의 바탕 빛. 셋 다 아래쪽(= 카드가 서는 자리)에 모아 둔다.
 * 위쪽은 거의 검정이라 제목 · 설명 · 안내 문구가 어떤 단계에서도 온전히 읽힌다.
 * 여기에 층을 하나 더 올리고 싶어지면, 그 좌표가 카피 영역(대략 위 45%)에
 * 걸치지 않는지부터 볼 것 — 이번 개편이 고친 것이 정확히 그 문제다.
 */
.pr-stage.is-lite {
  background:
    radial-gradient(94% 38% at 50% 76%, rgba(180, 140, 255, .13), transparent 68%),
    radial-gradient(58% 22% at 92% 62%, rgba(255, 45, 92, .09), transparent 66%),
    radial-gradient(58% 22% at 8% 88%, rgba(61, 233, 255, .09), transparent 66%),
    var(--bg);
}

/*
 * 카드 후광.
 *
 * box-shadow 를 쓰는 이유: 카드에 overflow: hidden 이 걸려 있어 안쪽 겹(::before ·
 * ::after)은 바깥으로 한 픽셀도 못 나간다. box-shadow 만이 그 클립에 잘리지 않는다.
 *
 * 세 색은 히어로 렌즈 색분산과 같은 값이고, 흰 알약 CTA 의 호버 글로우
 * (6px 2px 28px rgba(255,45,92,.4) · -6px -2px 28px rgba(61,233,255,.35))와 같은
 * 문법이다 — 이 사이트에서 '빛난다'는 언제나 이 두 색으로 말한다.
 *
 * 앞의 두 줄(바닥 그림자 · 상단 반사선)은 위 .pr-card 의 값 그대로 다시 적었다.
 * box-shadow 는 통째로 덮어쓰는 속성이라, 빠뜨리면 카드가 바닥에서 떠 있는 느낌과
 * 유리 윗변의 반사선을 함께 잃는다.
 */
.pr-stage.is-lite .pr-card {
  border-color: rgba(255, 255, 255, calc(.12 + .14 * var(--pr-tier)));
  box-shadow:
    0 60px 130px -45px rgba(0, 0, 0, .9),
    inset 0 1px 0 rgba(255, 255, 255, .13),
    -14px -10px calc(26px + 64px * var(--pr-tier)) rgba(61, 233, 255, calc(.10 + .22 * var(--pr-tier))),
     16px  10px calc(26px + 64px * var(--pr-tier)) rgba(255, 45, 92, calc(.08 + .19 * var(--pr-tier))),
     0     22px calc(34px + 82px * var(--pr-tier)) rgba(180, 140, 255, calc(.06 + .17 * var(--pr-tier)));
  transition: box-shadow .32s ease, border-color .32s ease;
}

/*
 * 테두리 빛. padding + mask-composite 는 '테두리만 칠하는' 표준 수법이다
 * (faq.css 의 카드 테두리 빛과 같은 문법).
 *
 * @supports 로 감싸는 이유가 중요하다 — mask-composite 를 모르는 브라우저에서는
 * 이 겹이 카드 전체를 스펙트럼으로 덮어 글자를 통째로 가린다. 모르면 아예 그리지
 * 않는 편이 맞다. 그때도 위의 후광과 테두리 밝기는 그대로라 '빛이 커진다'는 남는다.
 *
 * z-index 를 주지 않는다. 카드 안의 내용(.pr-card > *)이 position: relative 이지만
 * 이 겹은 트리 순서상 마지막이라 그 위에 그려진다 — 1px 테두리이므로 그게 맞다.
 * 움직이는 것이 opacity 하나뿐이라 슬라이더를 끌어도 합성 단계에서 끝난다.
 */
@supports ((-webkit-mask-composite: xor) or (mask-composite: exclude)) {
  .pr-stage.is-lite .pr-card::after {
    content: '';
    position: absolute;
    inset: 0;
    padding: 1px;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(135deg,
      rgba(61, 233, 255, .95),
      rgba(180, 140, 255, .8) 46%,
      rgba(255, 45, 92, .9));
    -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    -webkit-mask-composite: xor;
    mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
    mask-composite: exclude;
    opacity: calc(.14 + .64 * var(--pr-tier));
    transition: opacity .32s ease;
  }
}

/* ---------- 2. 스테이지 레이아웃 · 왼쪽 카피 ---------- */

/*
 * 좌우 여백은 여기서 정하지 않는다 — padding 이 아니라 padding-block 이다.
 *
 * 이 요소는 class="container pr-wrap" 라 두 규칙이 같은 상자에 걸린다. 예전의
 * `padding: 44px 0 56px` 는 .container 와 무게가 같고(단일 클래스) pricing.css 가
 * 뒤에 실리므로 이겨서, .container 의 좌우 20px 을 통째로 0 으로 덮었다.
 * 넓은 화면에서는 max-width(1140px)가 남는 폭을 먹어 티가 안 났지만, 모바일에서는
 * 카피도 카드도 화면 양 끝에 딱 붙어 여백이 사라졌다(사용자 지적 · 스크린샷).
 *
 * 세로만 지정하면 좌우는 .container 값이 그대로 남는다 — 사이트에서 가장자리
 * 여백을 정하는 규칙이 한 벌만 있게 된다. 여기에 padding 단축 속성을 되살리지 말 것.
 * 되살리려면 헤더 · 푸터와 같은 값을 손으로 맞춰 적어야 하고, 그 값은 반드시 어긋난다.
 */
.pr-wrap {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 44px;
  align-items: center;
  padding-block: 44px 56px;
}

.pr-copy { min-width: 0; max-width: 560px; }

/*
 * 카피 세 줄의 글자 그림자.
 *
 * 검정 배경에서는 보이지 않는다. 넓은 화면에서 빛줄기가 글자 뒤를 지날 때만 일한다 —
 * 구체 왼쪽의 빔이 카피 영역을 가로지르므로, 없으면 빛이 밝은 순간 제목과 보조 문장의
 * 대비가 4.5:1 아래로 떨어진다. 카드 안의 글자들이 이미 같은 수법을 쓴다
 * (.pr-head-value · .pr-amount 등).
 *
 * 좁은 화면에서는 카피 뒤에 빛을 두지 않으므로(1-b절) 이 그림자가 할 일이 없다.
 * 그래도 지우지 않는다 — 검정 위에서는 보이지도 않고, 폭에 따라 규칙이 갈리면
 * 나중에 한쪽만 고쳐진다.
 */
.pr-title {
  margin: 14px 0 20px;
  font-size: clamp(38px, 5vw, 60px);
  font-weight: 800;
  line-height: 1.08;
  letter-spacing: -.045em;
  color: #fff;
  text-shadow: 0 2px 22px rgba(0, 0, 0, .6);
}

.pr-sub {
  max-width: 36ch;
  color: rgba(255, 255, 255, .7);
  font-size: 16px;
  line-height: 1.7;
  text-shadow: 0 1px 14px rgba(0, 0, 0, .6);
}

.pr-fine {
  max-width: 48ch;
  margin-top: 14px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: .01em;
  line-height: 1.7;
  color: rgba(255, 255, 255, .42);
  text-shadow: 0 1px 12px rgba(0, 0, 0, .6);
}

/* 월/연 전환 — 참고 구현의 유리 알약. 선택된 쪽만 살짝 밝은 유리가 된다. */
.billing-switch {
  display: inline-flex;
  gap: 2px;
  margin-top: 28px;
  padding: 4px;
  background: rgba(8, 9, 13, .5);
  border: 1px solid rgba(255, 255, 255, .13);
  border-radius: 9999px;
}

@supports ((backdrop-filter: blur(12px)) or (-webkit-backdrop-filter: blur(12px))) {
  .billing-switch {
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
  }
}

.billing-opt {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  padding: 8px 16px;
  background: transparent;
  border: 0;
  border-radius: 9999px;
  color: rgba(255, 255, 255, .45);
  font-size: 13px;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--ease), background var(--ease);
}

.billing-opt:hover { color: rgba(255, 255, 255, .8); }

.billing-opt.is-active {
  background: rgba(255, 255, 255, .11);
  color: #fff;
}

.billing-save {
  padding: 1px 6px;
  border-radius: 9999px;
  background: var(--primary);
  color: #04121a;
  font-size: 11px;
  font-weight: 800;
}

/* ---------- 3. 유리 카드 ---------- */

/*
 * 기본값은 거의 불투명(94%) — backdrop-filter 미지원 폴백을 겸한다.
 * 유리(44% + blur 44px)는 @supports 안에서만 켠다. 순서를 뒤집으면 미지원
 * 환경에서 프리즘 워시가 글자 뒤로 그대로 비쳐 가독성이 무너진다.
 *
 * --pad 하나로 패딩과 구분선 번짐(.pr-rule 의 음수 마진)을 함께 정한다 —
 * 패딩을 바꿀 때 구분선이 카드 끝까지 닿지 않는 실수를 막는다.
 */
.pr-card {
  --pad: 26px;
  position: relative;
  min-width: 0;
  padding: var(--pad);
  background: rgba(10, 11, 16, .94);
  border: 1px solid rgba(255, 255, 255, .15);
  border-radius: 24px;
  box-shadow:
    0 60px 130px -45px rgba(0, 0, 0, .9),
    inset 0 1px 0 rgba(255, 255, 255, .13);
  overflow: hidden;
}

@supports ((backdrop-filter: blur(44px)) or (-webkit-backdrop-filter: blur(44px))) {
  .pr-card {
    background: rgba(12, 13, 18, .44);
    -webkit-backdrop-filter: blur(44px) saturate(1.25);
    backdrop-filter: blur(44px) saturate(1.25);
  }
}

/* 가독성 오버레이 — 워시가 비쳐도 글자 밑은 언제나 한 단계 어둡다. */
.pr-card::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(4, 4, 7, .13), rgba(4, 4, 7, .33));
}

/* 오버레이(::before) 위에 내용이 서도록 전부 한 층 올린다. */
.pr-card > * { position: relative; }

.pr-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 16px;
}

.pr-head-label {
  color: rgba(255, 255, 255, .88);
  font-size: 13.5px;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .55);
}

.pr-head-value {
  font-family: var(--font-mono);
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -.04em;
  font-variant-numeric: tabular-nums;
  color: #fff;
  white-space: nowrap;
  text-shadow: 0 2px 14px rgba(0, 0, 0, .7);
}

.pr-head-value small {
  margin-left: 7px;
  font-family: var(--font);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0;
  color: rgba(255, 255, 255, .72);
}

/* 카드 끝까지 닿는 머리카락 구분선. */
.pr-rule {
  height: 1px;
  margin: 20px calc(-1 * var(--pad));
  background: rgba(255, 255, 255, .16);
}

/* ---------- 4. 카드 안 슬라이더 ---------- */

/*
 * 채움 표시는 CSS 변수(--pr-fill) 하나로 정한다. pricing.js 가 CSSOM 으로
 * 값만 바꾼다 — CSP(style-src 'self')는 인라인 style 속성을 막지만
 * CSSOM 지정은 막지 않는다.
 */
.pr-range {
  --pr-fill: 83.333%;
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 32px;
  margin: 0;
  padding: 0;
  background: transparent;
  cursor: pointer;
}

.pr-range::-webkit-slider-runnable-track {
  height: 4px;
  border-radius: 9999px;
  background: linear-gradient(90deg,
    rgba(255, 255, 255, .95) var(--pr-fill),
    rgba(255, 255, 255, .24) var(--pr-fill));
}

.pr-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 20px;
  height: 20px;
  margin-top: -8px;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 3px 12px rgba(0, 0, 0, .6);
  transition: transform .15s ease;
}

.pr-range:active::-webkit-slider-thumb { transform: scale(1.12); }

.pr-range::-moz-range-track {
  height: 4px;
  border-radius: 9999px;
  background: rgba(255, 255, 255, .24);
}

.pr-range::-moz-range-progress {
  height: 4px;
  border-radius: 9999px;
  background: rgba(255, 255, 255, .95);
}

.pr-range::-moz-range-thumb {
  width: 20px;
  height: 20px;
  border: 0;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 3px 12px rgba(0, 0, 0, .6);
}

.pr-range:focus-visible {
  outline: 2px solid rgba(255, 255, 255, .85);
  outline-offset: 8px;
  border-radius: 9999px;
}

/*
 * 눈금. 좌우 여백 10px 은 썸 반지름 몫이다 — 썸 중심의 이동 범위와 눈금 위치를
 * 맞추기 위한 값이라, 썸 크기(20px)를 바꾸면 여기도 함께 바꿔야 한다.
 */
.pr-ticks {
  position: relative;
  height: 38px;
  margin: 6px 10px 0;
}

.pr-tick {
  position: absolute;
  top: 0;
  transform: translateX(-50%);
  display: grid;
  justify-items: center;
  gap: 3px;
  padding: 2px 4px;
  background: transparent;
  border: 0;
  color: rgba(255, 255, 255, .42);
  cursor: pointer;
  transition: color var(--ease);
}

.pr-tick b {
  font-family: var(--font-mono);
  font-size: 11.5px;
  font-weight: 500;
  font-variant-numeric: tabular-nums;
  text-shadow: 0 1px 6px rgba(0, 0, 0, .6);
}

.pr-tick i {
  font-style: normal;
  font-size: 10.5px;
  white-space: nowrap;
  opacity: .72;
}

.pr-tick:hover { color: rgba(255, 255, 255, .78); }
.pr-tick.is-current { color: #fff; }

.pr-tick:nth-child(1) { left: 0; }
.pr-tick:nth-child(2) { left: 16.6667%; }
.pr-tick:nth-child(3) { left: 33.3333%; }
.pr-tick:nth-child(4) { left: 50%; }
.pr-tick:nth-child(5) { left: 66.6667%; }
.pr-tick:nth-child(6) { left: 83.3333%; }
.pr-tick:nth-child(7) { left: 100%; }

/* ---------- 5. 가격 · CTA ---------- */

.pr-money {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
}

.pr-price { min-width: 0; }

/* tabular-nums 가 없으면 단계 전환마다 숫자 폭이 달라져 금액이 좌우로 흔들린다. */
.pr-amount-row {
  display: flex;
  align-items: baseline;
  gap: 7px;
  font-variant-numeric: tabular-nums;
}

.pr-amount {
  font-size: clamp(34px, 4.2vw, 44px);
  font-weight: 800;
  letter-spacing: -.045em;
  line-height: 1;
  color: #fff;
  text-shadow: 0 3px 18px rgba(0, 0, 0, .75);
}

.pr-unit {
  color: rgba(255, 255, 255, .72);
  font-size: 15px;
  font-weight: 600;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .55);
}

.pr-unit[hidden] { display: none; }

.pr-billing {
  margin-top: 10px;
  color: rgba(255, 255, 255, .62);
  font-size: 12.5px;
  line-height: 1.6;
  text-shadow: 0 1px 8px rgba(0, 0, 0, .55);
}

/* 단계 전환 마이크로 애니메이션 — pricing.js 가 클래스를 잠깐 달았다 뗀다. */
.pr-price.is-roll { animation: pr-roll .24s ease; }

@keyframes pr-roll {
  from { opacity: .2; transform: translateY(7px); }
}

/* 흰 알약 CTA — 참고 구현 그대로. 이 화면의 유일한 흰 알약이다(폼 전송 버튼은 화면 밖). */
.pr-cta {
  flex: 0 0 auto;
  padding: 14px 26px;
  background: #fff;
  border: 0;
  border-radius: 9999px;
  color: #0a0c10;
  font-size: 14.5px;
  font-weight: 700;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: 0 12px 34px -12px rgba(0, 0, 0, .8);
  transition: transform var(--ease), box-shadow var(--ease);
}

.pr-cta:hover { transform: translateY(-1px); }

.pr-cta:focus-visible {
  outline: 2px solid var(--primary);
  outline-offset: 3px;
}

/* ---------- 6. 기능 목록 ---------- */

.pr-feats {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 12px 22px;
}

.pr-feats li {
  position: relative;
  padding-left: 24px;
  color: rgba(255, 255, 255, .93);
  font-size: 13.5px;
  line-height: 1.5;
  text-shadow: 0 1px 10px rgba(0, 0, 0, .6);
}

/* 체크 표시 — 참고 구현처럼 흰색. 청록은 거래소 역할 배지가 맡는다. */
.pr-feats li::before {
  content: '';
  position: absolute;
  left: 0;
  top: .18em;
  width: 14px;
  height: 14px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M20 6L9 17l-5-5' fill='none' stroke='%23ffffff' stroke-opacity='.95' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 14px 14px;
}

/* ---------- 7. 연동 거래소 칩 ---------- */

.pr-exchanges { margin-top: 22px; }

.pr-ex-title {
  margin-bottom: 11px;
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .16em;
  color: rgba(255, 255, 255, .5);
  text-shadow: 0 1px 6px rgba(0, 0, 0, .6);
}

.pr-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 7px;
}

.pr-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 11px;
  background: rgba(0, 0, 0, .16);
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 9px;
  color: rgba(255, 255, 255, .38);
  font-size: 12px;
  transition: border-color var(--ease), background var(--ease), color var(--ease);
}

.pr-chip b { font-weight: 600; color: inherit; }

/* 포함 — 밝은 유리로 켜진다. */
.pr-chip.is-on {
  background: rgba(255, 255, 255, .14);
  border-color: rgba(255, 255, 255, .46);
  color: #fff;
  text-shadow: 0 1px 6px rgba(0, 0, 0, .5);
}

/* 선택 풀 — 상담에서 확정하는 자리. 점선이 '아직 안 정해짐'을 말한다. */
.pr-chip.is-pick {
  border-style: dashed;
  border-color: rgba(61, 233, 255, .45);
  color: rgba(255, 255, 255, .72);
}

/* 역할 배지(자동 · 재정). 켜진 역할만 청록으로 산다. */
.pr-role {
  padding: 1px 5px;
  border-radius: 4px;
  background: rgba(255, 255, 255, .08);
  font-size: 10px;
  font-weight: 600;
  opacity: .5;
}

.pr-role.is-on {
  background: rgba(61, 233, 255, .26);
  color: #b7f4ff;
  opacity: 1;
}

.pr-role.is-pick {
  outline: 1px dashed rgba(61, 233, 255, .5);
  background: rgba(61, 233, 255, .08);
  color: #9adfef;
  opacity: 1;
}

.pr-note {
  margin-top: 12px;
  padding: 9px 12px;
  background: rgba(61, 233, 255, .05);
  border: 1px solid rgba(61, 233, 255, .18);
  border-radius: var(--radius-sm);
  color: rgba(255, 255, 255, .7);
  font-size: 12px;
  line-height: 1.65;
  text-shadow: 0 1px 6px rgba(0, 0, 0, .5);
}

.pr-note[hidden] { display: none; }

/* ---------- 8. 전체 요금제 표 ---------- */

/*
 * 원장(ledger) 문법이다.
 *
 * 예전에는 카드 격자를 얇게 만든 것에 가까웠다 — 판 하나에 행을 쌓고 테두리만
 * 둘렀는데, 위의 유리 카드와 언어가 달라 페이지가 두 개로 갈라져 보였다.
 * 지금은 위 카드와 같은 문법(반투명 검정 + blur + 상단 sheen 1줄 + 머리카락 선)을
 * 쓰고, 숫자는 전부 mono · tabular 로 세로줄을 맞춘다. 관리자 콘솔의 표와도
 * 같은 결이라 사이트 안에서 처음 보는 물건이 되지 않는다.
 */
.pr-table-sec { position: relative; padding: 64px 0 40px; }

.pr-table-head {
  max-width: 920px;
  margin: 0 auto 18px;
}

.pr-table-head .col-title { font-size: 22px; }

.pr-grid {
  position: relative;
  max-width: 920px;
  margin: 0 auto;
  background: rgba(9, 10, 15, .82);
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 20px;
  box-shadow: 0 32px 80px -48px rgba(0, 0, 0, .9);
  overflow: hidden;
}

@supports ((backdrop-filter: blur(18px)) or (-webkit-backdrop-filter: blur(18px))) {
  .pr-grid {
    background: rgba(9, 10, 15, .62);
    -webkit-backdrop-filter: blur(18px) saturate(1.15);
    backdrop-filter: blur(18px) saturate(1.15);
  }
}

/* 거울 반사 한 줄. 위 유리 카드의 inset 하이라이트와 같은 역할이다. */
.pr-grid::before {
  content: '';
  position: absolute;
  top: 0;
  left: 12%;
  right: 12%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .28), transparent);
  pointer-events: none;
}

/* 열 제목 줄. 좁은 화면에서는 행이 세로로 재배열되므로 감춘다(아래 반응형). */
.pr-head-row {
  display: none;
  padding: 11px 20px;
  border-bottom: 1px solid rgba(255, 255, 255, .1);
  font-family: var(--font-mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: .14em;
  color: rgba(255, 255, 255, .38);
}

.pr-row {
  position: relative;
  display: grid;
  grid-template-columns: 1fr auto;
  grid-template-areas:
    'pick price'
    'mix mix'
    'cta cta';
  gap: 6px 14px;
  align-items: center;
  padding: 15px 20px;
  border-bottom: 1px solid rgba(255, 255, 255, .07);
  transition: background var(--ease);
}

.pr-row:last-child { border-bottom: 0; }
.pr-row:hover { background: rgba(255, 255, 255, .035); }

/* 슬라이더와 양방향으로 연동되는 현재 단계 표시. */
.pr-row.is-current {
  background: rgba(61, 233, 255, .07);
  box-shadow: inset 2px 0 0 var(--primary);
}

.pr-row.is-current:hover { background: rgba(61, 233, 255, .1); }

/*
 * 현재 단계는 배지가 아니라 '판 전체'로 말한다 — 청록 워시 + 왼쪽 2px 막대 +
 * 권한 칩 · 상담 버튼 테두리가 함께 밝아진다.
 *
 * '현재 선택' 같은 꼬리표를 행 안에 넣지 않는 이유: 이 행은 클릭으로 바뀌는데,
 * 글자가 하나 늘면 그 행만 높아져 표가 아래로 밀린다. 방금 누른 자리가 움직이는
 * 화면은 잘못 눌렀다는 인상을 준다.
 */

.pr-row-pick {
  grid-area: pick;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  min-height: 30px;
  padding: 0;
  background: transparent;
  border: 0;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.pr-row-pick b {
  font-size: 15px;
  font-weight: 700;
  letter-spacing: -.01em;
}

/* 권한 수는 '값'이라 mono 알약으로 세운다. 이름 옆의 회색 글씨로 두면
   구성 설명과 섞여 어느 것이 숫자인지 한눈에 안 잡힌다. */
.pr-row-perms {
  padding: 2px 9px;
  background: rgba(255, 255, 255, .05);
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 9999px;
  color: rgba(255, 255, 255, .62);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.pr-row.is-current .pr-row-perms {
  border-color: rgba(61, 233, 255, .3);
  color: rgba(255, 255, 255, .85);
}

.pr-row-flag {
  padding: 2px 9px;
  background: #fff;
  border-radius: 9999px;
  color: #0a0a12;
  font-size: 10.5px;
  font-weight: 800;
  white-space: nowrap;
}

.pr-row-mix {
  grid-area: mix;
  color: rgba(255, 255, 255, .55);
  font-size: 13px;
  line-height: 1.6;
}

.pr-row-price {
  grid-area: price;
  justify-self: end;
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

/* 카드의 큰 금액과 같은 mono 계열. 두 곳의 숫자가 다른 글꼴이면
   같은 값인데도 다른 값처럼 읽힌다. */
.pr-row-amount {
  font-family: var(--font-mono);
  font-size: 17px;
  font-weight: 600;
  letter-spacing: -.02em;
  color: #fff;
}

.pr-row-unit {
  margin-left: 3px;
  color: rgba(255, 255, 255, .45);
  font-size: 12px;
}

.pr-row-cta {
  grid-area: cta;
  justify-self: stretch;
  padding: 8px 16px;
  background: rgba(255, 255, 255, .04);
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 9999px;
  color: rgba(255, 255, 255, .72);
  font-size: 12.5px;
  font-weight: 600;
  text-align: center;
  white-space: nowrap;
  transition: border-color var(--ease), color var(--ease), background var(--ease);
}

.pr-row-cta:hover {
  border-color: rgba(255, 255, 255, .5);
  background: rgba(255, 255, 255, .1);
  color: #fff;
}

.pr-row.is-current .pr-row-cta {
  border-color: rgba(61, 233, 255, .4);
  color: #fff;
}

.pr-row.is-current .pr-row-cta:hover {
  border-color: var(--primary);
  background: rgba(61, 233, 255, .12);
}

/* ---------- 9. 공통 안내 ---------- */

/*
 * 표와 같은 폭(920px) · 같은 유리다. 여기만 다른 판을 쓰면 세 블록이
 * 위에서 아래로 서로 다른 재질로 이어져 페이지가 이어붙인 것처럼 보인다.
 */
.pr-common-sec { position: relative; padding: 18px 0 10px; }

.price-common {
  max-width: 920px;
  margin: 0 auto;
  padding: 22px 24px;
  background: rgba(9, 10, 15, .82);
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 20px;
}

@supports ((backdrop-filter: blur(18px)) or (-webkit-backdrop-filter: blur(18px))) {
  .price-common {
    background: rgba(9, 10, 15, .6);
    -webkit-backdrop-filter: blur(18px);
    backdrop-filter: blur(18px);
  }
}

/* 항목 앞에 청록 점 하나. 세 줄이 나란히 있을 때 문단이 아니라 목록으로 읽힌다. */
.price-common .info-list li {
  position: relative;
  padding-left: 16px;
}

.price-common .info-list li::before {
  content: '';
  position: absolute;
  left: 2px;
  top: .62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--primary);
  opacity: .75;
}

.price-disclaimer {
  padding-top: 16px;
  margin-top: 4px;
  border-top: 1px solid rgba(255, 255, 255, .08);
  color: rgba(255, 255, 255, .4);
  font-size: 12.5px;
  line-height: 1.75;
}

/* ---------- 10. 상담 신청 ---------- */

.pr-consult-sec { position: relative; padding-top: 56px; }

.consult-grid {
  display: grid;
  gap: 28px;
  max-width: 1000px;
  margin: 0 auto;
}

/* 카드 CTA 가 여기로 스크롤한다. 헤더에 가리지 않게 여백을 둔다. */
.price-consult { scroll-margin-top: calc(var(--header-h) + 16px); }

.consult-copy .col-title { font-size: 22px; }

/*
 * 진행 순서 — 원장(ledger) 줄.
 *
 * 예전에는 판 하나에 '1. 접수 확인' 처럼 번호를 글자로 적어 넣은 목록이었다.
 * 번호가 본문과 같은 굵기라 눈이 순서를 세지 못했고, 판이 하나 더 생겨
 * 오른쪽 폼 카드와 나란히 두 개의 상자가 됐다.
 * 지금은 판을 없애고 머리카락 선으로만 나눈다. 번호는 CSS 카운터가 만들어
 * mono 로 세운다 — HTML 에 '01' 을 적어 두면 항목을 넣고 뺄 때마다 손으로 고쳐야 한다.
 */
.consult-steps {
  display: grid;
  gap: 0;
  margin-top: 24px;
  counter-reset: consult-step;
}

.consult-steps li {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr);
  gap: 2px 14px;
  align-items: start;
  padding: 14px 0;
  border-top: 1px solid rgba(255, 255, 255, .08);
  counter-increment: consult-step;
}

.consult-steps li:last-child { border-bottom: 1px solid rgba(255, 255, 255, .08); }

/* 세 칸의 자리를 못박는다. 자동 배치에 맡기면 행을 걸친 번호 때문에
   제목과 설명이 어느 칸으로 흘러갈지 브라우저마다 달라진다. */
.consult-steps li::before {
  content: counter(consult-step, decimal-leading-zero);
  grid-column: 1;
  grid-row: 1 / span 2;
  color: rgba(255, 255, 255, .3);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  /* 제목과 같은 줄높이라 두 글자의 윗선이 맞는다. */
  line-height: 1.7;
  font-variant-numeric: tabular-nums;
}

.consult-steps b {
  grid-column: 2;
  grid-row: 1;
  color: var(--text);
  font-size: 14px;
  font-weight: 600;
  line-height: 1.7;
  letter-spacing: -.01em;
}

.consult-steps span {
  grid-column: 2;
  grid-row: 2;
  color: rgba(255, 255, 255, .5);
  font-size: 12.5px;
  line-height: 1.65;
}

/* 상담 폼 카드 — 위 유리 카드와 같은 문법(폴백 먼저, 블러는 지원 시). */
.consult-card {
  position: relative;
  padding: 26px;
  background: rgba(9, 10, 15, .92);
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 24px;
  box-shadow: 0 40px 90px -50px rgba(0, 0, 0, .95);
  overflow: hidden;
}

@supports ((backdrop-filter: blur(24px)) or (-webkit-backdrop-filter: blur(24px))) {
  .consult-card {
    background: rgba(9, 10, 15, .74);
    -webkit-backdrop-filter: blur(24px) saturate(1.15);
    backdrop-filter: blur(24px) saturate(1.15);
  }
}

/* 히어로 카드와 같은 거울 반사 한 줄. 두 카드가 같은 재질로 읽히게 한다. */
.consult-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 14%;
  right: 14%;
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, .3), transparent);
  pointer-events: none;
}

.consult-card > * { position: relative; }

/* 폼 머리. 카드 안에 제목이 없으면 왼쪽 카피에서 눈을 옮겼을 때
   여기가 무엇을 적는 칸인지 다시 왼쪽을 봐야 한다. */
.consult-card-head {
  padding-bottom: 16px;
  margin-bottom: 20px;
  border-bottom: 1px solid rgba(255, 255, 255, .08);
}

.consult-card-title {
  color: #fff;
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -.01em;
}

.consult-card-desc {
  margin-top: 6px;
  color: rgba(255, 255, 255, .5);
  font-size: 13px;
  line-height: 1.65;
}

.consult-form {
  display: grid;
  gap: 16px;
}

/* 포커스는 사이트 공통(흰 링) 위에 포인트 색 전환을 얹는다 — 로그인 카드와 같은 규칙. */
.consult-card .input:focus {
  border-color: rgba(61, 233, 255, .55);
  box-shadow: 0 0 0 3px rgba(61, 233, 255, .12);
}

/* ---------- 11. 반응형 ---------- */

@media (max-width: 559px) {
  /* 좁은 화면에서는 눈금 이름이 서로 겹친다. 숫자만 남긴다(이름은 aria-label 에 있다). */
  .pr-tick i { display: none; }
  .pr-ticks { height: 26px; }

  /* 가격과 CTA 를 세로로 쌓고 버튼을 전폭으로 편다 — 참고 구현의 모바일 동작. */
  .pr-money { flex-direction: column; align-items: stretch; }
  .pr-cta { width: 100%; text-align: center; }

  /*
   * 카드 안쪽 여백을 한 단계 줄인다.
   *
   * 바깥 여백(.container 20px)이 되살아나면서 카드가 그만큼 좁아졌다. 안쪽까지
   * 26px 그대로면 360px 화면에서 글이 268px 안에 갇혀 '거래소 권한 수' 같은 라벨이
   * 두 줄로 꺾인다. 바깥을 벌린 만큼 안쪽을 줄여, 글이 쓰는 폭은 예전과 비슷하게 둔다.
   * 구분선(.pr-rule)은 이 변수를 음수 마진으로 되쓰므로 함께 따라온다.
   */
  .pr-card { --pad: 20px; }
}

@media (min-width: 560px) {
  .pr-feats { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 640px) {
  .pr-card { --pad: 32px; }
  .consult-card { padding: 30px 32px; }
  .pr-table-head .col-title,
  .consult-copy .col-title { font-size: 24px; }

  /*
   * 표를 한 줄 격자로 편다 — 가로 스크롤 없이 셀이 제자리를 잡는 폭이다.
   * 열 제목 줄(.pr-head-row)이 같은 격자를 써야 제목과 값이 같은 세로선에 선다.
   * 한쪽만 고치면 '월 요금' 이 금액이 아니라 구성 설명 위에 뜬다.
   */
  .pr-row,
  .pr-head-row {
    grid-template-columns: minmax(170px, .9fr) minmax(0, 1.5fr) minmax(120px, auto) 92px;
    grid-template-areas: 'pick mix price cta';
    gap: 6px 16px;
    align-items: center;
  }

  .pr-head-row > span:nth-child(3) { text-align: right; }

  .pr-row-cta { justify-self: end; width: 100%; }
}

/* 열 제목은 행이 한 줄로 펴진 뒤에만 뜻이 있다. 그 전에는 숨긴 채로 둔다. */
@media (min-width: 720px) {
  .pr-head-row { display: grid; }
}

@media (min-width: 900px) {
  .consult-grid {
    grid-template-columns: minmax(0, .9fr) minmax(0, 1.1fr);
    align-items: start;
    gap: 32px;
  }
}

/*
 * 좌 카피 + 우 카드 2열. 카드 폭 540px 은 참고 구현 값이다.
 *
 * 1040px 은 pricing.js 의 WIDE_MIN_WIDTH 와 같은 값이어야 한다. 여기가 곧
 * '구체가 카드 뒤로 숨는 배치' 의 시작점이자 배경 모드가 갈리는 지점이라,
 * 한쪽만 고치면 카드는 이미 아래로 내려갔는데 프리즘은 아직 카드 오른쪽 자리를
 * 잡고 있게 된다(또는 그 반대로, 2열인데 카드가 혼자 빛나는 모드로 남는다).
 */
@media (min-width: 1040px) {
  .pr-wrap {
    grid-template-columns: minmax(0, 1fr) minmax(0, 540px);
    gap: 64px;
    /* 위 .pr-wrap 과 같은 이유로 세로만 지정한다. 좌우는 .container 몫이다. */
    padding-block: 56px 64px;
  }
}

/* ---------- 12. 접근성: 모션 최소화 ---------- */

/*
 * DOM 마이크로 애니메이션만 끈다. 프리즘 캔버스는 그대로 돈다 — 성능 목적으로 창
 * 애니메이션을 꺼 둔 Windows PC 가 전부 reduce 로 보고되기 때문이다(메인 히어로 ·
 * 로그인 유체와 같은 규칙). 내용을 모션 뒤에 숨기지 않는 것이 이 사이트의 원칙이다.
 */
@media (prefers-reduced-motion: reduce) {
  .pr-price.is-roll { animation: none; }
  .pr-canvas { transition: none; }
  .pr-cta,
  .pr-range::-webkit-slider-thumb { transition: none; }

  /* 카드 후광 · 테두리 빛은 그대로 켜 두고 '자라나는 과정'만 없앤다.
     단계를 바꾸면 새 밝기로 즉시 바뀐다 — 빛 자체를 끄면 좁은 화면에서
     요금제가 오르는 것을 알려 주는 유일한 신호가 사라진다. */
  .pr-stage.is-lite .pr-card,
  .pr-stage.is-lite .pr-card::after { transition: none; }
}
