/* ============================================================================
   oc-components.css — OneCast 컴포넌트 CSS (제품 배포본 · 클래스 접두 oc-)
   원본: design/onecast-design-showcase.html  <style> "OneCast Component CSS" 구간
         (v1.0.0 · 2026-08-30 · ui-designer)
   이전: 2026-08-30 · web-publisher (Phase A)
   전제: 이 파일보다 먼저 oc-tokens.css 를 로드해야 한다(모든 값이 --oc-* 변수 참조).
   ---------------------------------------------------------------------------
   [쇼케이스 → 제품 변환 내역]
   1. `sc-*`(쇼케이스 전용) 규칙 전량 제외.
   2. 상태 시뮬레이션 헬퍼 `.is-hover / .is-focus / .is-active` 8줄 제외
      (제품은 :hover / :focus-visible / :active 만 사용).
      ※ `.is-open`(툴팁·모바일 메뉴) · `.is-over`(글자수 초과) · `.is-off`(플랜 미포함)
        · `.is-loading` · `.is-right/.is-center`(표 정렬) 는 제품 동작이므로 유지.
   3. `@container frame (max-width: 960px|640px)` → `@media (max-width: 960px|640px)`.
   4. `@font-face`(Pretendard 셀프호스팅, font-display: swap) 를 상단에 추가.
   5. `@supports not (backdrop-filter: blur(1px))` 글래스 폴백 추가(05_디자인시스템 §9-9).
   6. 스텝퍼 라벨 `white-space: nowrap` 보정(좁은 폭 세로 깨짐 방지).
   7. 산문(약관·정책) 이스케이프 해치 추가 — 전역 `p{margin:0}` / `ul,ol{margin:0;padding:0}`
      은 .oc-* 컴포넌트 전제라 유지하되, `.oc-prose` / `.legal-doc` 안에서는 되돌린다.
   8. 전역 리셋은 원본 그대로 최소 유지. `input` 전역 리셋 없음, `button` 은 font/color 상속만.
      → Thymeleaf 폼(오류 메시지 `.oc-error`, CSRF hidden input, name/id)과 충돌하지 않는다.

   [목차]
   0.  @font-face (Pretendard)
   1.  전역 리셋 · 타이포 · 유틸 (.sr-only .oc-num .oc-i .oc-spin .oc-muted …)
   2.  레이아웃 유틸 (.oc-stack .oc-row .oc-grid-2/3/4 .oc-divider)
   3.  로고 (.oc-logo)
   4.  버튼 (.oc-btn --primary/--secondary/--ghost/--danger, --sm/--lg/--block/--icon)
   5.  폼 (.oc-field .oc-label .oc-input .oc-select .oc-textarea .oc-check .oc-switch
          .oc-seg .oc-chip .oc-code .oc-codeblock .oc-error .oc-help .oc-input-group)
   6.  카드 · 글래스 (.oc-card .oc-glass .oc-section .oc-page-head)
   7.  배지 · 점 (.oc-badge .oc-badge-btn .oc-dot)
   8.  배너 (.oc-banner)
   9.  테이블 (.oc-table .oc-table-wrap)
   10. 영상×연결 매트릭스 (.oc-matrix .oc-video .oc-thumb)
   11. 툴팁 (.oc-tip)
   12. 스텝퍼 (.oc-stepper .oc-step)
   13. 플랫폼 심볼 · 카드 (.oc-pf .oc-pfcard)
   14. 플랜 카드 (.oc-plans .oc-plan)
   15. 빈 상태 (.oc-empty)
   16. 모달 · 토스트 (.oc-overlay .oc-dialog .oc-toasts .oc-toast)
   17. 게이지 · 통계 (.oc-gauge .oc-stats .oc-stat)
   18. 앱 셸 (.oc-screen .oc-appbar .oc-shell .oc-sidebar .oc-nav__* .oc-main
          .oc-tabbar .oc-app-footer .oc-avatar)
   19. 공개 헤더 · 푸터 (.oc-topbar .oc-container .oc-footer)
   20. 랜딩 (.oc-hero .oc-flow .oc-pfrow .oc-landing-section .oc-steps .oc-faq .oc-cta-band)
   21. 마법사 · 라우트 · 결제 (.oc-preview .oc-result .oc-guide .oc-wizard .oc-routes
          .oc-route-cell .oc-mini .oc-msg .oc-count .oc-billing-current .oc-kv
          .oc-legal-box .oc-cardmask .oc-noti)
   22. 반응형 @media 960 / 640
   23. 제품 보정(글래스 폴백 · 스텝퍼 라벨 · 산문 해치)
   ========================================================================== */

/* ---------- 0. @font-face — Pretendard 셀프호스팅(외부 CDN 금지) ---------- */
/* 파일: static/fonts/PretendardStdVariable.woff2 (KS X 1001 서브셋 · 285KB)
   라이선스: SIL Open Font License 1.1 — static/fonts/LICENSE-Pretendard.txt
   서브셋에 없는 희귀 음절/외국어는 --oc-font-sans 폴백 스택이 받는다. */
@font-face {
  font-family: "Pretendard Variable";
  src: url("../fonts/PretendardStdVariable.woff2") format("woff2-variations");
  font-weight: 45 920;
  font-style: normal;
  font-display: swap;
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;font-family:var(--oc-font-sans);font-size:var(--oc-fs-body);line-height:var(--oc-lh-body);color:var(--oc-text);background:var(--oc-bg-canvas);background-attachment:fixed;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;word-break:keep-all;overflow-wrap:break-word}
h1,h2,h3,h4,h5{margin:0;line-height:1.3;letter-spacing:var(--oc-tracking-tight);color:var(--oc-text)}
h1{font-size:var(--oc-fs-h1);line-height:var(--oc-lh-h1);font-weight:var(--oc-fw-heavy)}
h2{font-size:var(--oc-fs-h2);line-height:var(--oc-lh-h2);font-weight:var(--oc-fw-bold)}
h3{font-size:var(--oc-fs-h3);line-height:var(--oc-lh-h3);font-weight:var(--oc-fw-bold)}
h4{font-size:var(--oc-fs-h4);line-height:var(--oc-lh-h4);font-weight:var(--oc-fw-semibold)}
p{margin:0}
a{color:var(--oc-primary);text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
a:hover{color:var(--oc-primary-hover)}
ul,ol{margin:0;padding:0}
img,svg{max-width:100%;display:block}
button{font:inherit;color:inherit}
code,kbd{font-family:var(--oc-font-mono)}
:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
::selection{background:var(--oc-primary-soft);color:var(--oc-text)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.oc-num{font-variant-numeric:tabular-nums}
.oc-i{width:1em;height:1em;display:inline-block;vertical-align:-.15em;flex-shrink:0;fill:none;stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.oc-i--fill{fill:currentColor;stroke:none}
.oc-spin{animation:oc-rotate 1s linear infinite}
@keyframes oc-rotate{to{transform:rotate(360deg)}}
.oc-muted{color:var(--oc-text-2)}
.oc-subtle{color:var(--oc-text-3)}
.oc-caption{font-size:var(--oc-fs-caption);line-height:var(--oc-lh-caption)}
.oc-small{font-size:var(--oc-fs-sm);line-height:var(--oc-lh-sm)}
.oc-strong{font-weight:var(--oc-fw-bold)}
.oc-gradient-text{background:var(--oc-accent-text-gradient);-webkit-background-clip:text;background-clip:text;color:transparent}
.oc-topbar.is-open .oc-topbar__nav{display:flex;position:absolute;top:100%;left:0;right:0;flex-direction:column;gap:2px;margin:0;padding:8px;background:var(--oc-surface);border-bottom:1px solid var(--oc-border);box-shadow:var(--oc-shadow-md)}
.oc-topbar.is-open .oc-topbar__nav a{min-height:var(--oc-touch)}
.oc-stack{display:flex;flex-direction:column;gap:var(--oc-sp-4)}
.oc-row{display:flex;align-items:center;gap:var(--oc-sp-3);flex-wrap:wrap}
.oc-row--between{justify-content:space-between}
.oc-row--end{justify-content:flex-end}
.oc-grid-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--oc-sp-5)}
.oc-grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--oc-sp-5)}
.oc-grid-4{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--oc-sp-4)}
.oc-divider{height:1px;background:var(--oc-divider);border:0;margin:var(--oc-sp-4) 0}

/* ---------- 로고 ---------- */
.oc-logo{display:inline-flex;align-items:center;gap:10px;text-decoration:none;color:var(--oc-text);flex-shrink:0;white-space:nowrap}
.oc-logo__mark{width:36px;height:36px;flex-shrink:0;filter:drop-shadow(0 4px 10px var(--oc-accent-glow))}
.oc-logo__word{font-size:22px;font-weight:var(--oc-fw-medium);letter-spacing:-0.03em;line-height:1;white-space:nowrap;overflow-wrap:normal}
.oc-logo__word b{font-weight:var(--oc-fw-heavy)}
.oc-logo--lg .oc-logo__mark{width:56px;height:56px}
.oc-logo--lg .oc-logo__word{font-size:34px}
.oc-logo--sm .oc-logo__mark{width:28px;height:28px}
.oc-logo--sm .oc-logo__word{font-size:18px}

/* ---------- 버튼 ---------- */
.oc-btn{position:relative;display:inline-flex;align-items:center;justify-content:center;gap:8px;min-height:var(--oc-control-h);min-width:var(--oc-touch);padding:0 20px;border-radius:var(--oc-r-md);border:1px solid transparent;font-size:var(--oc-fs-body);font-weight:var(--oc-fw-semibold);line-height:1.2;color:var(--oc-text);background:transparent;cursor:pointer;text-decoration:none;white-space:nowrap;user-select:none;-webkit-tap-highlight-color:transparent;transition:transform var(--oc-dur-2) var(--oc-ease),box-shadow var(--oc-dur-2) var(--oc-ease),background-color var(--oc-dur-2) var(--oc-ease),color var(--oc-dur-2) var(--oc-ease),border-color var(--oc-dur-2) var(--oc-ease),filter var(--oc-dur-2) var(--oc-ease)}
.oc-btn::before{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--oc-sheen);pointer-events:none;opacity:0;transition:opacity var(--oc-dur-2)}
.oc-btn .oc-i{width:18px;height:18px}
.oc-btn:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
.oc-btn--primary{color:var(--oc-text-on-accent);background:var(--oc-accent-gradient);border-color:rgba(255,255,255,.10);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-accent)}
.oc-btn--primary::before{opacity:1}
.oc-btn--primary:hover{filter:brightness(1.06);transform:translateY(-1px);box-shadow:var(--oc-gloss-inset),0 14px 30px -10px var(--oc-accent-glow)}
.oc-btn--primary:active{transform:translateY(0);filter:brightness(.96);box-shadow:inset 0 2px 4px rgba(0,0,0,.28)}
.oc-btn--primary:focus-visible{box-shadow:var(--oc-gloss-inset),0 0 0 4px var(--oc-focus-halo)}
.oc-btn--secondary{color:var(--oc-primary);background:var(--oc-surface-gradient);border-color:var(--oc-border-strong);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-xs)}
.oc-btn--secondary:hover{border-color:var(--oc-primary);background:var(--oc-primary-soft);color:var(--oc-primary-hover);transform:translateY(-1px);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-sm)}
.oc-btn--secondary:active{transform:translateY(0);box-shadow:inset 0 1px 3px var(--oc-glass-ring)}
.oc-btn--ghost{color:var(--oc-text-2)}
.oc-btn--ghost:hover{background:var(--oc-surface-3);color:var(--oc-text)}
.oc-btn--ghost:active{background:var(--oc-border)}
.oc-btn--danger{color:var(--oc-danger-text);border-color:var(--oc-danger-border);background:transparent}
.oc-btn--danger:hover{background:var(--oc-danger-bg)}
.oc-btn--sm{min-height:var(--oc-control-h-sm);padding:0 14px;font-size:var(--oc-fs-sm);border-radius:var(--oc-r-sm)}
/* 소형 버튼(40px)의 터치 영역을 44px 로 넓힌다. .oc-btn 은 1px 테두리가 있어
   의사요소의 컨테이닝 블록이 패딩 박스(38px)다 → -2px 이면 42px 밖에 안 된다.
   -3px 이라야 44px 이 채워진다(P4-D 배치2 실브라우저 히트테스트로 확인). */
.oc-btn--sm::after{content:"";position:absolute;left:0;right:0;top:-3px;bottom:-3px}
.oc-btn--sm .oc-i{width:16px;height:16px}
.oc-btn--lg{min-height:56px;padding:0 28px;font-size:17px;border-radius:var(--oc-r-lg)}
.oc-btn--block{width:100%}
.oc-btn--icon{padding:0;width:var(--oc-touch);min-width:var(--oc-touch)}
.oc-btn--icon .oc-i{width:20px;height:20px}
.oc-btn[disabled]{opacity:.5;cursor:not-allowed;transform:none;filter:none;box-shadow:none}
/* QA: aria-disabled 는 네이티브 disabled 와 달리 WCAG 대비 예외 대상이 아니다.
   opacity 로 누르면 2.3:1 까지 떨어지므로, 대비를 지키는 토큰 색으로 "비활성"을 표현한다. */
.oc-btn[aria-disabled="true"]{cursor:not-allowed;transform:none;filter:none;box-shadow:none;
  background:var(--oc-surface-3);color:var(--oc-text-2);border-color:var(--oc-border)}
.oc-btn.is-loading{pointer-events:none}

/* ---------- 폼 ---------- */
.oc-field{display:flex;flex-direction:column;gap:6px}
.oc-form{display:flex;flex-direction:column;gap:var(--oc-sp-4)}
.oc-label{font-size:var(--oc-fs-sm);line-height:var(--oc-lh-sm);font-weight:var(--oc-fw-semibold);color:var(--oc-text)}
.oc-label .opt{font-weight:var(--oc-fw-regular);color:var(--oc-text-3)}
.oc-req{color:var(--oc-danger-solid);margin-left:2px}
.oc-input,.oc-select,.oc-textarea{width:100%;min-height:var(--oc-control-h);padding:0 14px;font:inherit;font-size:var(--oc-fs-body);color:var(--oc-text);background:var(--oc-surface);border:1px solid var(--oc-border-strong);border-radius:var(--oc-r-md);box-shadow:inset 0 1px 2px var(--oc-glass-ring);transition:border-color var(--oc-dur-2),box-shadow var(--oc-dur-2),background-color var(--oc-dur-2)}
.oc-input::placeholder,.oc-textarea::placeholder{color:var(--oc-text-3)}
.oc-input:hover,.oc-select:hover,.oc-textarea:hover{border-color:var(--oc-text-3)}
.oc-input:focus,.oc-select:focus,.oc-textarea:focus{border-color:var(--oc-primary);box-shadow:0 0 0 4px var(--oc-focus-halo)}
/* QA: 이 규칙이 outline:none 이라 폼 컨트롤만 포커스 링을 잃었다(버튼·링크는 2px 링).
   halo 는 대비 1.4~1.8:1 이라 KWCAG 6.4.2 를 만족하지 못한다 — 전역과 같은 2px 링을 명시한다. */
.oc-input:focus-visible,.oc-select:focus-visible,.oc-textarea:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
.oc-input[aria-invalid="true"],.oc-textarea[aria-invalid="true"]{border-color:var(--oc-danger-solid)}
.oc-input[aria-invalid="true"]:focus{box-shadow:0 0 0 4px rgba(220,38,38,.18)}
.oc-input[readonly]{background:var(--oc-surface-3);color:var(--oc-text-2)}
.oc-input[disabled],.oc-select[disabled]{opacity:.55;cursor:not-allowed}
.oc-textarea{padding:12px 14px;min-height:120px;line-height:var(--oc-lh-body);resize:vertical}
.oc-input--mono{font-family:var(--oc-font-mono);font-size:var(--oc-fs-sm);letter-spacing:.01em}
.oc-select-wrap{position:relative}
.oc-select{appearance:none;-webkit-appearance:none;padding-right:44px;cursor:pointer}
.oc-select-wrap .oc-i{position:absolute;right:14px;top:50%;transform:translateY(-50%);pointer-events:none;color:var(--oc-text-3);width:18px;height:18px}
.oc-help{font-size:var(--oc-fs-caption);line-height:var(--oc-lh-caption);color:var(--oc-text-3)}
.oc-help code{font-size:12px;padding:1px 5px;border-radius:5px;background:var(--oc-surface-3);border:1px solid var(--oc-border)}
.oc-error{font-size:var(--oc-fs-caption);line-height:var(--oc-lh-caption);color:var(--oc-danger-text);display:flex;gap:6px;align-items:flex-start;font-weight:var(--oc-fw-medium)}
.oc-error .oc-i{width:15px;height:15px;margin-top:1px}
.oc-input-group{position:relative}
.oc-input-group .oc-input{padding-right:52px}
/* P4-D 배치2 QA: 종전에는 40×40 박스 + ::after{inset:-3px} 로 히트 영역만 44px 를 만들었다.
   보이는 상자 자체가 44px 미만이면 실측 스크립트·수동 검수 모두에서 결함으로 잡히고,
   ::after 확장은 스크롤 밖 요소에서 elementFromPoint 로 확인할 수도 없다.
   입력 높이가 --oc-control-h(48px) 이라 --oc-touch(44px) 상자가 그대로 들어간다(위아래 2px 여유). */
.oc-input-group .oc-btn--icon{position:absolute;right:2px;top:50%;transform:translateY(-50%);width:var(--oc-touch);min-width:var(--oc-touch);min-height:var(--oc-touch);height:var(--oc-touch);border-radius:var(--oc-r-sm)}
.oc-check{display:flex;gap:10px;align-items:flex-start;min-height:var(--oc-touch);padding:8px 0;cursor:pointer;font-size:var(--oc-fs-sm);line-height:var(--oc-lh-sm);color:var(--oc-text)}
.oc-check input{appearance:none;-webkit-appearance:none;width:22px;height:22px;flex-shrink:0;margin:-1px 0 0;border:1.5px solid var(--oc-border-strong);border-radius:6px;background:var(--oc-surface);box-shadow:inset 0 1px 2px var(--oc-glass-ring);display:grid;place-items:center;cursor:pointer;transition:background var(--oc-dur-2),border-color var(--oc-dur-2)}
.oc-check input:checked{background:var(--oc-accent-gradient);border-color:transparent;box-shadow:var(--oc-gloss-inset)}
.oc-check input:checked::after{content:"";width:11px;height:6px;border:2.5px solid #fff;border-top:0;border-right:0;transform:translateY(-1px) rotate(-45deg)}
.oc-check input[type="radio"]{border-radius:50%}
.oc-check input[type="radio"]:checked::after{width:8px;height:8px;border:0;border-radius:50%;background:#fff;transform:none}
.oc-check input:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
.oc-check input[aria-invalid="true"]{border-color:var(--oc-danger-solid)}
.oc-switch{display:inline-flex;align-items:center;gap:10px;min-height:var(--oc-touch);cursor:pointer;font-size:var(--oc-fs-sm);color:var(--oc-text)}
.oc-switch input{appearance:none;-webkit-appearance:none;width:46px;height:26px;margin:0;border-radius:999px;background:var(--oc-border-strong);position:relative;flex-shrink:0;cursor:pointer;box-shadow:inset 0 1px 3px rgba(0,0,0,.18);transition:background var(--oc-dur-2)}
.oc-switch input::after{content:"";position:absolute;top:3px;left:3px;width:20px;height:20px;border-radius:50%;background:#fff;box-shadow:0 1px 3px rgba(0,0,0,.30),inset 0 -1px 0 rgba(0,0,0,.08);transition:transform var(--oc-dur-2) var(--oc-ease-spring)}
.oc-switch input:checked{background:var(--oc-accent-gradient-h);box-shadow:inset 0 1px 0 rgba(255,255,255,.3)}
.oc-switch input:checked::after{transform:translateX(20px)}
.oc-switch input:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
.oc-switch input[disabled]{opacity:.5;cursor:not-allowed}
.oc-switch__state{font-weight:var(--oc-fw-bold);min-width:2em;color:var(--oc-text-3)}
.oc-switch input:checked~.oc-switch__state{color:var(--oc-primary)}
.oc-seg{display:inline-flex;padding:4px;border-radius:var(--oc-r-pill);background:var(--oc-surface-3);box-shadow:inset 0 1px 2px var(--oc-glass-ring);gap:2px}
.oc-seg button{position:relative;min-height:36px;padding:0 16px;border:0;border-radius:var(--oc-r-pill);background:transparent;color:var(--oc-text-2);font-size:var(--oc-fs-sm);font-weight:var(--oc-fw-semibold);cursor:pointer;transition:background var(--oc-dur-2),color var(--oc-dur-2),box-shadow var(--oc-dur-2)}
.oc-seg button[aria-pressed="true"]{background:var(--oc-surface);color:var(--oc-text);box-shadow:var(--oc-shadow-sm),var(--oc-gloss-inset)}
/* 세그먼트 버튼은 36px 이지만 .oc-seg 의 padding 4px 을 포함해 44px 터치 영역을 갖는다.
   테두리가 없어 컨테이닝 블록이 곧 36px 이므로 위아래 -4px 이면 44px 이다. */
.oc-seg button::after{content:"";position:absolute;left:0;right:0;top:-4px;bottom:-4px}
.oc-seg button:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:1px}
.oc-chip{display:inline-flex;align-items:center;gap:4px;min-height:32px;padding:0 12px;border-radius:var(--oc-r-pill);border:1px solid var(--oc-border-strong);background:var(--oc-surface);font-size:var(--oc-fs-caption);font-weight:var(--oc-fw-semibold);color:var(--oc-text-2);cursor:pointer;font-family:var(--oc-font-mono);transition:background var(--oc-dur-2),color var(--oc-dur-2),border-color var(--oc-dur-2)}
.oc-chip:hover{border-color:var(--oc-primary);color:var(--oc-primary);background:var(--oc-primary-soft)}
.oc-chip::after{content:"";position:absolute}
.oc-code{font-family:var(--oc-font-mono);font-size:13px;padding:2px 6px;border-radius:6px;background:var(--oc-surface-3);border:1px solid var(--oc-border);color:var(--oc-text)}
.oc-codeblock{position:relative;font-family:var(--oc-font-mono);font-size:13px;line-height:20px;padding:12px 52px 12px 14px;border-radius:var(--oc-r-md);background:var(--oc-surface-inverse);color:var(--oc-text-inverse);white-space:pre-wrap;box-shadow:var(--oc-shadow-xs)}
.oc-codeblock .oc-btn{position:absolute;right:6px;top:6px;color:var(--oc-text-inverse);width:36px;min-width:36px;height:36px;min-height:36px}
.oc-codeblock .oc-btn:hover{background:rgba(255,255,255,.12)}
.oc-codeblock .oc-btn::after{content:"";position:absolute;inset:-4px}

/* ---------- 카드 · 글래스 ---------- */
.oc-card{position:relative;background:var(--oc-surface-gradient);border:1px solid var(--oc-border);border-radius:var(--oc-r-lg);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-sm);padding:var(--oc-sp-5);isolation:isolate}
.oc-card::before{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--oc-gloss-top);opacity:.5;pointer-events:none;z-index:-1}
.oc-card--hover{transition:transform var(--oc-dur-2) var(--oc-ease),box-shadow var(--oc-dur-2) var(--oc-ease)}
.oc-card--hover:hover{transform:translateY(-2px);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-md)}
.oc-card--flat{box-shadow:none}
.oc-card__title{font-size:var(--oc-fs-h4);line-height:var(--oc-lh-h4);font-weight:var(--oc-fw-bold);margin-bottom:4px}
.oc-card__head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:var(--oc-sp-4);flex-wrap:wrap}
.oc-glass{position:relative;background:var(--oc-glass-bg);-webkit-backdrop-filter:blur(var(--oc-glass-blur)) saturate(150%);backdrop-filter:blur(var(--oc-glass-blur)) saturate(150%);border:1px solid var(--oc-glass-border);border-radius:var(--oc-r-xl);box-shadow:0 0 0 1px var(--oc-glass-ring),var(--oc-glass-shadow);padding:var(--oc-sp-6);isolation:isolate}
.oc-glass::before{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--oc-gloss-top);pointer-events:none;z-index:-1}
.oc-section{margin-bottom:var(--oc-sp-6);scroll-margin-top:calc(var(--oc-header-h) + var(--oc-sp-4))}
.oc-section__head{display:flex;align-items:flex-end;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:var(--oc-sp-4)}
.oc-section__head h2{font-size:var(--oc-fs-h3);line-height:var(--oc-lh-h3)}
.oc-section__head p{color:var(--oc-text-3);font-size:var(--oc-fs-sm)}
.oc-page-head{display:flex;align-items:flex-start;justify-content:space-between;gap:16px;flex-wrap:wrap;margin-bottom:var(--oc-sp-6)}
.oc-page-head h1{font-size:28px;line-height:36px}
.oc-page-head p{color:var(--oc-text-2);font-size:var(--oc-fs-sm);margin-top:4px}

/* ---------- 배지 ---------- */
.oc-badge{display:inline-flex;align-items:center;gap:5px;height:24px;padding:0 9px;border-radius:var(--oc-r-pill);font-size:var(--oc-fs-micro);font-weight:var(--oc-fw-bold);line-height:1;letter-spacing:.01em;white-space:nowrap;border:1px solid transparent;box-shadow:inset 0 1px 0 rgba(255,255,255,.25);vertical-align:middle}
.oc-badge .oc-i{width:13px;height:13px;stroke-width:2.5}
.oc-badge--success{background:var(--oc-success-bg);color:var(--oc-success-text);border-color:var(--oc-success-border)}
.oc-badge--info{background:var(--oc-info-bg);color:var(--oc-info-text);border-color:var(--oc-info-border)}
.oc-badge--warning{background:var(--oc-warning-bg);color:var(--oc-warning-text);border-color:var(--oc-warning-border)}
.oc-badge--danger{background:var(--oc-danger-bg);color:var(--oc-danger-text);border-color:var(--oc-danger-border)}
.oc-badge--attention{background:var(--oc-attention-bg);color:var(--oc-attention-text);border-color:var(--oc-attention-border)}
.oc-badge--neutral{background:var(--oc-neutral-bg);color:var(--oc-neutral-text);border-color:var(--oc-neutral-border)}
.oc-badge--accent{background:var(--oc-accent-gradient);color:#fff;box-shadow:var(--oc-gloss-inset)}
.oc-badge--outline{background:transparent;border-color:var(--oc-border-strong);color:var(--oc-text-2);box-shadow:none}
.oc-badge--lg{height:28px;padding:0 12px;font-size:var(--oc-fs-caption)}
.oc-badge-btn{appearance:none;border:0;background:transparent;padding:0;cursor:pointer;border-radius:var(--oc-r-pill);display:inline-flex;position:relative}
.oc-badge-btn::after{content:"";position:absolute;left:0;right:0;top:-10px;bottom:-10px}
.oc-badge-btn:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:3px}
.oc-dot{width:8px;height:8px;border-radius:50%;display:inline-block;background:var(--oc-neutral-solid);flex-shrink:0}
.oc-dot--success{background:var(--oc-success-solid)}.oc-dot--warning{background:var(--oc-warning-solid)}.oc-dot--danger{background:var(--oc-danger-solid)}.oc-dot--attention{background:var(--oc-attention-solid)}.oc-dot--info{background:var(--oc-info-solid)}

/* ---------- 배너(인라인 알림) ---------- */
.oc-banner{display:flex;gap:12px;align-items:flex-start;padding:12px 16px;border-radius:var(--oc-r-md);border:1px solid;font-size:var(--oc-fs-sm);line-height:var(--oc-lh-sm)}
.oc-banner .oc-i{width:20px;height:20px;flex-shrink:0;margin-top:0}
.oc-banner__body{flex:1;min-width:0}
.oc-banner__title{font-weight:var(--oc-fw-bold);display:block}
.oc-banner .oc-btn{margin-left:auto;flex-shrink:0}
.oc-banner--info{background:var(--oc-info-bg);color:var(--oc-info-text);border-color:var(--oc-info-border)}
.oc-banner--success{background:var(--oc-success-bg);color:var(--oc-success-text);border-color:var(--oc-success-border)}
.oc-banner--warning{background:var(--oc-warning-bg);color:var(--oc-warning-text);border-color:var(--oc-warning-border)}
.oc-banner--danger{background:var(--oc-danger-bg);color:var(--oc-danger-text);border-color:var(--oc-danger-border)}
.oc-banner--attention{background:var(--oc-attention-bg);color:var(--oc-attention-text);border-color:var(--oc-attention-border)}
.oc-banner a{color:inherit;font-weight:var(--oc-fw-bold)}
.oc-banner .oc-btn--sm{color:inherit;border-color:currentColor;background:transparent}

/* ---------- 테이블 ---------- */
.oc-table-wrap{overflow-x:auto;border:1px solid var(--oc-border);border-radius:var(--oc-r-lg);background:var(--oc-surface);box-shadow:var(--oc-shadow-xs);-webkit-overflow-scrolling:touch}
.oc-table{width:100%;border-collapse:separate;border-spacing:0;font-size:var(--oc-fs-sm);line-height:var(--oc-lh-sm);min-width:640px}
.oc-table th,.oc-table td{padding:12px 16px;text-align:left;vertical-align:middle;border-bottom:1px solid var(--oc-divider)}
.oc-table thead th{position:sticky;top:0;z-index:1;background:var(--oc-surface-3);color:var(--oc-text-2);font-weight:var(--oc-fw-semibold);font-size:var(--oc-fs-caption);letter-spacing:.02em;white-space:nowrap}
.oc-table tbody tr:last-child td{border-bottom:0}
.oc-table tbody tr:hover td{background:var(--oc-surface-2)}
.oc-table td.is-right,.oc-table th.is-right{text-align:right}
.oc-table td.is-center,.oc-table th.is-center{text-align:center}
.oc-table .oc-table__actions{display:flex;gap:4px;justify-content:flex-end}
.oc-table caption{text-align:left;padding:12px 16px;font-weight:var(--oc-fw-bold);color:var(--oc-text)}
.oc-table--compact th,.oc-table--compact td{padding:8px 12px}

/* ---------- 영상×연결 매트릭스 ---------- */
.oc-matrix-wrap{overflow:auto;border:1px solid var(--oc-border);border-radius:var(--oc-r-lg);background:var(--oc-surface);box-shadow:var(--oc-shadow-xs);padding-bottom:2px}
.oc-matrix{border-collapse:separate;border-spacing:0;font-size:var(--oc-fs-sm);min-width:100%}
.oc-matrix th,.oc-matrix td{padding:10px 12px;border-bottom:1px solid var(--oc-divider);vertical-align:middle;white-space:nowrap}
.oc-matrix thead th{position:sticky;top:0;z-index:2;background:var(--oc-surface-3);text-align:center;font-weight:var(--oc-fw-semibold);font-size:var(--oc-fs-caption);color:var(--oc-text-2)}
.oc-matrix thead th:first-child,.oc-matrix tbody th{position:sticky;left:0;z-index:3;text-align:left;background:var(--oc-surface);box-shadow:1px 0 0 var(--oc-divider)}
.oc-matrix thead th:first-child{background:var(--oc-surface-3);z-index:4}
.oc-matrix tbody th{font-weight:var(--oc-fw-regular)}
.oc-matrix td{text-align:center}
.oc-matrix tbody tr:last-child th,.oc-matrix tbody tr:last-child td{border-bottom:0}
.oc-matrix tbody tr:hover td{background:var(--oc-surface-2)}
.oc-matrix__conn{display:inline-flex;flex-direction:column;align-items:center;gap:6px;min-width:96px}
.oc-matrix__conn .oc-pf{width:36px;height:36px;border-radius:10px}
.oc-matrix__conn .oc-pf .oc-i{width:18px;height:18px}
.oc-matrix__conn-name{font-size:var(--oc-fs-caption);font-weight:var(--oc-fw-semibold);color:var(--oc-text);max-width:120px;overflow:hidden;text-overflow:ellipsis}
.oc-video{display:flex;gap:12px;align-items:center;min-width:280px;text-align:left}
.oc-video__meta{min-width:0}
.oc-video__title{font-weight:var(--oc-fw-semibold);color:var(--oc-text);display:block;max-width:300px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;text-decoration:none}
.oc-video__title:hover{color:var(--oc-primary);text-decoration:underline}
.oc-video__sub{font-size:var(--oc-fs-caption);color:var(--oc-text-3);display:flex;gap:8px;align-items:center;margin-top:2px}
.oc-thumb{width:72px;height:40px;border-radius:8px;flex-shrink:0;position:relative;overflow:hidden;background:linear-gradient(135deg,#1E293B,#475569);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-xs);display:grid;place-items:center;color:#fff}
.oc-thumb .oc-i{width:16px;height:16px;opacity:.9;filter:drop-shadow(0 1px 2px rgba(0,0,0,.4))}
.oc-thumb--1{background:linear-gradient(135deg,#7C3AED,#DB2777)}
.oc-thumb--2{background:linear-gradient(135deg,#0EA5E9,#2456E6)}
.oc-thumb--3{background:linear-gradient(135deg,#F59E0B,#EF4444)}
.oc-thumb--4{background:linear-gradient(135deg,#10B981,#0EA5E9)}
.oc-thumb--5{background:linear-gradient(135deg,#6366F1,#0EA5E9)}
.oc-thumb--shorts{width:36px;height:56px}
.oc-thumb--lg{width:120px;height:68px;border-radius:10px}

/* ---------- 툴팁 ---------- */
.oc-tip{position:relative;display:inline-flex}
.oc-tip__box{position:absolute;bottom:calc(100% + 10px);left:50%;transform:translateX(-50%) translateY(4px);width:max-content;min-width:200px;max-width:280px;padding:10px 12px;border-radius:10px;background:var(--oc-surface-inverse);color:var(--oc-text-inverse);font-size:var(--oc-fs-caption);line-height:var(--oc-lh-caption);font-weight:var(--oc-fw-regular);text-align:left;white-space:normal;box-shadow:var(--oc-shadow-lg);opacity:0;visibility:hidden;pointer-events:none;z-index:var(--oc-z-dropdown);transition:opacity var(--oc-dur-2) var(--oc-ease),transform var(--oc-dur-2) var(--oc-ease),visibility 0s linear var(--oc-dur-2)}
.oc-tip__box::after{content:"";position:absolute;top:100%;left:50%;margin-left:-6px;border:6px solid transparent;border-top-color:var(--oc-surface-inverse)}
.oc-tip__box b{display:block;margin-bottom:2px;font-weight:var(--oc-fw-bold)}
.oc-tip:hover .oc-tip__box,.oc-tip:focus-within .oc-tip__box,.oc-tip.is-open .oc-tip__box{opacity:1;visibility:visible;transform:translateX(-50%) translateY(0);transition-delay:0s}
.oc-tip--below .oc-tip__box{bottom:auto;top:calc(100% + 10px);transform:translateX(-50%) translateY(-4px)}
.oc-tip--below .oc-tip__box::after{top:auto;bottom:100%;border-top-color:transparent;border-bottom-color:var(--oc-surface-inverse)}
.oc-tip--below:hover .oc-tip__box,.oc-tip--below:focus-within .oc-tip__box,.oc-tip--below.is-open .oc-tip__box{transform:translateX(-50%) translateY(0)}
.oc-tip--left .oc-tip__box{left:auto;right:0;transform:translateX(0) translateY(4px)}
.oc-tip--left .oc-tip__box::after{left:auto;right:16px;margin-left:0}
.oc-tip--left:hover .oc-tip__box,.oc-tip--left:focus-within .oc-tip__box,.oc-tip--left.is-open .oc-tip__box{transform:translateX(0) translateY(0)}

/* ---------- 스텝퍼 ---------- */
.oc-stepper{display:flex;list-style:none;padding:0;margin:0;gap:0}
.oc-step{flex:1;display:flex;align-items:center;gap:10px;min-width:0}
.oc-step::after{content:"";flex:1;height:2px;min-width:16px;margin:0 12px;border-radius:1px;background:var(--oc-border)}
.oc-step:last-child{flex:0 0 auto}
.oc-step:last-child::after{display:none}
.oc-step--done::after{background:var(--oc-success-solid)}
.oc-step__btn{display:flex;align-items:center;gap:10px;background:transparent;border:0;padding:6px 4px;border-radius:var(--oc-r-sm);cursor:pointer;min-height:var(--oc-touch);min-width:0;text-align:left}
.oc-step__btn:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
.oc-step__dot{width:32px;height:32px;border-radius:50%;display:grid;place-items:center;font-size:13px;font-weight:var(--oc-fw-bold);border:2px solid var(--oc-border-strong);color:var(--oc-text-3);background:var(--oc-surface);flex-shrink:0;transition:background var(--oc-dur-2),box-shadow var(--oc-dur-2)}
.oc-step__dot .oc-i{width:16px;height:16px;stroke-width:3}
.oc-step--done .oc-step__dot{background:var(--oc-success-solid);border-color:transparent;color:#fff}
.oc-step--current .oc-step__dot{background:var(--oc-accent-gradient);border-color:transparent;color:#fff;box-shadow:var(--oc-gloss-inset),0 0 0 4px var(--oc-focus-halo)}
.oc-step__label{display:flex;flex-direction:column;min-width:0}
.oc-step__label b{font-size:var(--oc-fs-sm);font-weight:var(--oc-fw-semibold);color:var(--oc-text-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.oc-step__label span{font-size:var(--oc-fs-micro);color:var(--oc-text-3)}
.oc-step--current .oc-step__label b{color:var(--oc-text)}
.oc-step__panel[hidden]{display:none}

/* ---------- 플랫폼 심볼 · 카드 ---------- */
.oc-pf{display:inline-grid;place-items:center;width:44px;height:44px;border-radius:12px;background:var(--oc-surface-3);color:var(--oc-text-2);box-shadow:var(--oc-gloss-inset);flex-shrink:0;position:relative;isolation:isolate}
.oc-pf::before{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--oc-gloss-top);opacity:.5;z-index:-1}
.oc-pf .oc-i{width:22px;height:22px}
.oc-pf--lg{width:56px;height:56px;border-radius:16px}
.oc-pf--lg .oc-i{width:28px;height:28px}
.oc-pf--sm{width:32px;height:32px;border-radius:9px}
.oc-pf--sm .oc-i{width:16px;height:16px}
.oc-pf--accent{background:var(--oc-accent-gradient);color:#fff}
.oc-pf--youtube{background:linear-gradient(135deg,#FF3D3D,#C4161C);color:#fff}
/* 플랫폼 심볼 겹치기 — 한 번의 연결로 두 플랫폼이 함께 붙는 카드에만 쓴다
   (Meta 원클릭 = 인스타그램 릴스 + Facebook 페이지). 앞 심볼이 주(主)이고 뒤 심볼은
   오른쪽 아래에 작게 겹쳐 "부속으로 함께 붙는다" 를 보여 준다.
   바깥 폭은 주 심볼(44px)과 같아 옆 카드들과 아이콘 열이 어긋나지 않는다. */
.oc-pf-pair{position:relative;display:inline-flex;flex-shrink:0}
.oc-pf-pair>.oc-pf--sm{position:absolute;right:-6px;bottom:-6px;width:26px;height:26px;border-radius:8px;
  box-shadow:var(--oc-gloss-inset),0 0 0 2px var(--oc-surface)}
.oc-pf-pair>.oc-pf--sm .oc-i{width:14px;height:14px}
.oc-pfcard{display:flex;gap:14px;align-items:flex-start;padding:16px;border-radius:var(--oc-r-lg);border:1px solid var(--oc-border);background:var(--oc-surface-gradient);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-xs);text-decoration:none;color:inherit;transition:transform var(--oc-dur-2) var(--oc-ease),box-shadow var(--oc-dur-2) var(--oc-ease),border-color var(--oc-dur-2);position:relative;isolation:isolate}
.oc-pfcard:hover{transform:translateY(-2px);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-md);border-color:var(--oc-border-strong)}
.oc-pfcard:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
.oc-pfcard__body{flex:1;min-width:0}
.oc-pfcard__name{font-weight:var(--oc-fw-bold);font-size:var(--oc-fs-body);display:flex;align-items:center;gap:8px;flex-wrap:wrap}
.oc-pfcard__desc{font-size:var(--oc-fs-caption);color:var(--oc-text-3);margin-top:2px}
.oc-pfcard__meta{display:flex;gap:6px;flex-wrap:wrap;margin-top:10px}
.oc-pfcard__go{align-self:center;color:var(--oc-text-3)}
.oc-pfcard--locked{opacity:.85}
.oc-pfcard--locked .oc-pf{color:var(--oc-text-3)}

/* ---------- 플랜 카드 ---------- */
.oc-plans{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--oc-sp-5);align-items:stretch}
.oc-plan{position:relative;display:flex;flex-direction:column;gap:var(--oc-sp-4);padding:var(--oc-sp-6);border-radius:var(--oc-r-xl);background:var(--oc-surface-gradient);border:1px solid var(--oc-border);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-sm);isolation:isolate}
.oc-plan::before{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--oc-gloss-top);opacity:.5;pointer-events:none;z-index:-1}
.oc-plan--featured{border:2px solid transparent;background:linear-gradient(var(--oc-surface),var(--oc-surface)) padding-box,var(--oc-accent-gradient) border-box;box-shadow:var(--oc-shadow-lg),0 12px 40px -18px var(--oc-accent-glow)}
.oc-plan--featured::before{opacity:.35}
.oc-plan__ribbon{position:absolute;top:-14px;left:50%;transform:translateX(-50%)}
.oc-plan__name{font-size:var(--oc-fs-h4);font-weight:var(--oc-fw-bold);color:var(--oc-text-2);display:flex;align-items:center;gap:8px}
.oc-plan__price{display:flex;align-items:baseline;gap:4px;font-variant-numeric:tabular-nums}
.oc-plan__price b{font-size:36px;line-height:1;font-weight:var(--oc-fw-heavy);letter-spacing:-.03em;color:var(--oc-text)}
.oc-plan__price>span{font-size:var(--oc-fs-sm);font-weight:var(--oc-fw-semibold);color:var(--oc-text-3)}
.oc-plan__year{font-size:var(--oc-fs-caption);color:var(--oc-text-3);margin-top:-8px}
.oc-plan__desc{font-size:var(--oc-fs-sm);color:var(--oc-text-2)}
.oc-plan__specs{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:8px;font-size:var(--oc-fs-sm)}
.oc-plan__specs li{display:flex;gap:8px;align-items:flex-start;color:var(--oc-text-2)}
.oc-plan__specs li b{color:var(--oc-text);font-weight:var(--oc-fw-semibold)}
.oc-plan__specs .oc-i{width:16px;height:16px;color:var(--oc-success-solid);margin-top:2px;stroke-width:2.5}
.oc-plan__specs li.is-off{color:var(--oc-text-3)}
.oc-plan__specs li.is-off .oc-i{color:var(--oc-text-3)}
.oc-plan__legal{font-size:var(--oc-fs-micro);line-height:var(--oc-lh-micro);color:var(--oc-text-3);margin-top:auto}
.oc-plan__legal a{color:inherit}

/* ---------- 빈 상태 ---------- */
.oc-empty{display:flex;flex-direction:column;align-items:center;text-align:center;gap:var(--oc-sp-3);padding:var(--oc-sp-10) var(--oc-sp-5);border:1px dashed var(--oc-border-strong);border-radius:var(--oc-r-lg);background:var(--oc-surface-2)}
.oc-empty__icon{width:64px;height:64px;border-radius:20px;background:var(--oc-primary-soft);color:var(--oc-primary);display:grid;place-items:center;box-shadow:var(--oc-gloss-inset)}
.oc-empty__icon .oc-i{width:30px;height:30px}
.oc-empty h2{font-size:var(--oc-fs-h4);line-height:var(--oc-lh-h4);font-weight:var(--oc-fw-semibold)}
.oc-empty p{color:var(--oc-text-2);font-size:var(--oc-fs-sm);max-width:46ch}
.oc-empty .oc-row{justify-content:center;margin-top:4px}

/* ---------- 모달 · 토스트 ---------- */
.oc-overlay{position:absolute;inset:0;background:rgba(10,15,30,.55);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);display:grid;place-items:center;padding:16px;z-index:var(--oc-z-modal)}
.oc-dialog{width:min(480px,100%);background:var(--oc-surface-gradient);border:1px solid var(--oc-border);border-radius:var(--oc-r-xl);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-xl);padding:var(--oc-sp-6);color:var(--oc-text);margin:0}
dialog.oc-dialog{margin:auto;max-width:calc(100vw - 32px)}
dialog.oc-dialog::backdrop{background:rgba(10,15,30,.55);-webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px)}
.oc-dialog__head{display:flex;align-items:flex-start;gap:12px;margin-bottom:12px}
.oc-dialog__icon{width:40px;height:40px;border-radius:12px;display:grid;place-items:center;flex-shrink:0}
.oc-dialog__icon .oc-i{width:20px;height:20px}
.oc-dialog__icon--danger{background:var(--oc-danger-bg);color:var(--oc-danger-text)}
.oc-dialog__icon--info{background:var(--oc-info-bg);color:var(--oc-info-text)}
.oc-dialog h2{font-size:var(--oc-fs-h3);line-height:var(--oc-lh-h3)}
.oc-dialog__body{color:var(--oc-text-2);font-size:var(--oc-fs-sm);line-height:var(--oc-lh-sm)}
.oc-dialog__body p+p{margin-top:8px}
.oc-dialog__actions{display:flex;gap:10px;justify-content:flex-end;flex-wrap:wrap;margin-top:var(--oc-sp-5)}
.oc-toasts{position:fixed;right:16px;bottom:16px;display:flex;flex-direction:column;gap:10px;z-index:var(--oc-z-toast);width:min(380px,calc(100vw - 32px))}
.oc-toasts--static{position:static;width:100%}
.oc-toast{display:flex;gap:12px;align-items:flex-start;padding:12px 8px 12px 14px;border-radius:var(--oc-r-md);background:var(--oc-surface-inverse);color:var(--oc-text-inverse);box-shadow:var(--oc-shadow-lg);border-left:4px solid var(--oc-info-solid);font-size:var(--oc-fs-sm);line-height:var(--oc-lh-sm);animation:oc-toast-in var(--oc-dur-3) var(--oc-ease-out)}
.oc-toast .oc-i{width:20px;height:20px;flex-shrink:0;margin-top:1px}
.oc-toast__body{flex:1;min-width:0}
.oc-toast__title{font-weight:var(--oc-fw-bold);display:block}
.oc-toast__close{width:36px;height:36px;min-width:36px;min-height:36px;border-radius:8px;border:0;background:transparent;color:inherit;cursor:pointer;display:grid;place-items:center;margin:-6px -2px -6px 0;position:relative;opacity:.8}
.oc-toast__close::after{content:"";position:absolute;inset:-4px}
.oc-toast__close:hover{background:rgba(255,255,255,.12);opacity:1}
.oc-toast__close .oc-i{width:16px;height:16px;margin:0}
.oc-toast--success{border-left-color:var(--oc-success-solid)}.oc-toast--success>.oc-i{color:var(--oc-success-solid)}
.oc-toast--warning{border-left-color:var(--oc-warning-solid)}.oc-toast--warning>.oc-i{color:var(--oc-warning-solid)}
.oc-toast--danger{border-left-color:var(--oc-danger-solid)}.oc-toast--danger>.oc-i{color:var(--oc-danger-solid)}
.oc-toast--info>.oc-i{color:var(--oc-info-solid)}
/* QA: 다크 테마에서 --oc-surface-inverse 가 밝은색(#F3F5FA)으로 뒤집히는데 아이콘만
   다크용 밝은 색을 써서 대비가 1.38~2.47:1 까지 떨어졌다(실측).
   토스트 판은 두 테마 모두 "밝은 바탕"이므로 진한 상태색으로 고정한다. */
[data-theme="dark"] .oc-toast--success>.oc-i{color:#15803D}
[data-theme="dark"] .oc-toast--danger>.oc-i{color:#B91C1C}
[data-theme="dark"] .oc-toast--warning>.oc-i{color:#92400E}
[data-theme="dark"] .oc-toast--info>.oc-i{color:#1D4ED8}
@keyframes oc-toast-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* ---------- 게이지 · 통계 ---------- */
.oc-gauge{display:flex;flex-direction:column;gap:6px}
.oc-gauge__head{display:flex;justify-content:space-between;align-items:baseline;gap:8px;font-size:var(--oc-fs-sm)}
.oc-gauge__label{color:var(--oc-text-2);font-weight:var(--oc-fw-medium)}
.oc-gauge__val{font-weight:var(--oc-fw-bold);font-variant-numeric:tabular-nums;color:var(--oc-text)}
.oc-gauge__val span{color:var(--oc-text-3);font-weight:var(--oc-fw-regular)}
.oc-gauge__bar{height:10px;border-radius:999px;background:var(--oc-surface-3);box-shadow:inset 0 1px 2px var(--oc-glass-ring);overflow:hidden}
.oc-gauge__fill{height:100%;border-radius:inherit;background:var(--oc-accent-gradient-h);box-shadow:inset 0 1px 0 rgba(255,255,255,.35);transition:width var(--oc-dur-4) var(--oc-ease)}
.oc-gauge--warn .oc-gauge__fill{background:linear-gradient(90deg,var(--oc-warning-solid),var(--oc-attention-solid))}
.oc-gauge--danger .oc-gauge__fill{background:linear-gradient(90deg,var(--oc-attention-solid),var(--oc-danger-solid))}
.oc-gauge__hint{font-size:var(--oc-fs-caption);color:var(--oc-text-3)}
.oc-stats{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--oc-sp-4)}
.oc-stat{padding:16px 18px;display:flex;flex-direction:column;gap:6px}
.oc-stat__label{font-size:var(--oc-fs-caption);color:var(--oc-text-3);font-weight:var(--oc-fw-medium);display:flex;align-items:center;gap:6px}
.oc-stat__label .oc-i{width:16px;height:16px}
.oc-stat__value{font-size:28px;line-height:1.1;font-weight:var(--oc-fw-heavy);letter-spacing:-.02em;font-variant-numeric:tabular-nums;color:var(--oc-text)}
.oc-stat__value small{font-size:var(--oc-fs-sm);font-weight:var(--oc-fw-medium);color:var(--oc-text-3);letter-spacing:0}
.oc-stat__sub{font-size:var(--oc-fs-caption);color:var(--oc-text-3);display:flex;align-items:center;gap:6px}

/* ---------- 앱 셸 ---------- */
.oc-screen{color:var(--oc-text);background:var(--oc-bg-canvas);min-height:100%;display:flex;flex-direction:column;position:relative}
.oc-appbar{position:sticky;top:0;z-index:var(--oc-z-sticky);display:flex;align-items:center;gap:12px;height:var(--oc-header-h);padding:0 20px;background:var(--oc-glass-bg);-webkit-backdrop-filter:blur(var(--oc-glass-blur)) saturate(150%);backdrop-filter:blur(var(--oc-glass-blur)) saturate(150%);border-bottom:1px solid var(--oc-glass-border);box-shadow:0 1px 0 var(--oc-glass-ring)}
.oc-appbar__ws{display:flex;align-items:center;gap:8px;font-weight:var(--oc-fw-bold);font-size:var(--oc-fs-sm);color:var(--oc-text);min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.oc-appbar__spacer{flex:1}
.oc-appbar .oc-btn--icon{color:var(--oc-text-2)}
.oc-avatar{width:36px;height:36px;border-radius:50%;background:var(--oc-accent-gradient);color:#fff;display:grid;place-items:center;font-weight:var(--oc-fw-bold);font-size:14px;box-shadow:var(--oc-gloss-inset);flex-shrink:0}
.oc-notif-dot{position:absolute;top:8px;right:8px;width:8px;height:8px;border-radius:50%;background:var(--oc-danger-solid);box-shadow:0 0 0 2px var(--oc-surface)}
.oc-shell{display:grid;grid-template-columns:var(--oc-sidebar-w) minmax(0,1fr);flex:1;align-items:stretch}
.oc-sidebar{padding:16px 12px;border-right:1px solid var(--oc-border);display:flex;flex-direction:column;gap:2px;background:var(--oc-glass-bg);-webkit-backdrop-filter:blur(var(--oc-glass-blur));backdrop-filter:blur(var(--oc-glass-blur))}
.oc-nav__section{font-size:11px;font-weight:var(--oc-fw-bold);letter-spacing:.08em;color:var(--oc-text-3);padding:16px 12px 6px;text-transform:uppercase}
.oc-nav__link{position:relative;display:flex;align-items:center;gap:12px;min-height:var(--oc-touch);padding:0 12px;border-radius:var(--oc-r-md);color:var(--oc-text-2);text-decoration:none;font-size:15px;font-weight:var(--oc-fw-medium);transition:background var(--oc-dur-2),color var(--oc-dur-2)}
.oc-nav__link:hover{background:var(--oc-surface-3);color:var(--oc-text)}
.oc-nav__link[aria-current="page"]{background:var(--oc-primary-soft);color:var(--oc-primary-soft-text);font-weight:var(--oc-fw-bold);box-shadow:var(--oc-gloss-inset)}
.oc-nav__link[aria-current="page"]::before{content:"";position:absolute;left:0;top:10px;bottom:10px;width:3px;border-radius:2px;background:var(--oc-accent-gradient)}
.oc-nav__link .oc-i{width:20px;height:20px}
.oc-nav__link .oc-badge{margin-left:auto}
.oc-nav__foot{margin-top:auto;padding:12px}
.oc-main{padding:var(--oc-sp-6);max-width:var(--oc-container-app);width:100%;margin:0 auto;min-width:0}
.oc-tabbar{display:none;position:sticky;bottom:0;z-index:var(--oc-z-sticky);height:calc(var(--oc-tabbar-h) + env(safe-area-inset-bottom));padding:0 4px env(safe-area-inset-bottom);border-top:1px solid var(--oc-glass-border);background:var(--oc-glass-bg);-webkit-backdrop-filter:blur(var(--oc-glass-blur)) saturate(150%);backdrop-filter:blur(var(--oc-glass-blur)) saturate(150%);box-shadow:0 -1px 0 var(--oc-glass-ring)}
.oc-tabbar a{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:3px;min-height:var(--oc-touch);font-size:11px;font-weight:var(--oc-fw-semibold);color:var(--oc-text-3);text-decoration:none;border-radius:10px;margin:6px 2px}
.oc-tabbar a .oc-i{width:22px;height:22px}
.oc-tabbar a[aria-current="page"]{color:var(--oc-primary)}
.oc-tabbar a[aria-current="page"] .oc-i{filter:drop-shadow(0 2px 6px var(--oc-accent-glow))}
.oc-app-footer{padding:16px 24px;text-align:center;font-size:var(--oc-fs-caption);color:var(--oc-text-3);border-top:1px solid var(--oc-divider)}
.oc-app-footer a{color:inherit}

/* ---------- 공개 헤더 · 푸터 ---------- */
.oc-topbar{position:sticky;top:0;z-index:var(--oc-z-sticky);background:var(--oc-glass-bg);-webkit-backdrop-filter:blur(var(--oc-glass-blur)) saturate(150%);backdrop-filter:blur(var(--oc-glass-blur)) saturate(150%);border-bottom:1px solid var(--oc-glass-border);box-shadow:0 1px 0 var(--oc-glass-ring)}
.oc-topbar__in{max-width:var(--oc-container);margin:0 auto;padding:0 var(--oc-gutter);height:var(--oc-header-h);display:flex;align-items:center;gap:16px}
.oc-topbar__nav{display:flex;gap:4px;margin-left:12px}
.oc-topbar__nav a{display:inline-flex;align-items:center;min-height:var(--oc-touch);padding:0 12px;border-radius:var(--oc-r-sm);color:var(--oc-text-2);text-decoration:none;font-size:var(--oc-fs-sm);font-weight:var(--oc-fw-medium)}
.oc-topbar__nav a:hover{background:var(--oc-surface-3);color:var(--oc-text)}
.oc-topbar__actions{margin-left:auto;display:flex;gap:8px;align-items:center}
.oc-topbar__menu{display:none}
.oc-container{max-width:var(--oc-container);margin:0 auto;padding:0 var(--oc-gutter)}
.oc-footer{border-top:1px solid var(--oc-divider);padding:40px 0 32px;font-size:var(--oc-fs-caption);line-height:var(--oc-lh-caption);color:var(--oc-text-3)}
.oc-footer__grid{display:grid;grid-template-columns:1.4fr 1fr 1fr;gap:32px;margin-bottom:28px}
.oc-footer__h{font-size:var(--oc-fs-sm);line-height:var(--oc-lh-sm);font-weight:var(--oc-fw-semibold);color:var(--oc-text);margin-bottom:10px}
.oc-footer ul{list-style:none;display:flex;flex-direction:column;gap:6px}
.oc-footer a{color:var(--oc-text-2)}
.oc-footer a:hover{color:var(--oc-primary)}
.oc-footer__biz{display:flex;flex-direction:column;gap:4px}
.oc-footer__biz b{color:var(--oc-text-2);font-weight:var(--oc-fw-semibold)}
/* 공개 푸터에서는 로고 아래로 띄운다(예전 인라인 style 을 규칙으로 옮겼다). */
.oc-footer__grid .oc-footer__biz{margin-top:14px}
/* 앱 푸터(로그인 후)에도 같은 블록을 넣는다 — 결제 화면이 "서비스 푸터에서 확인"이라 안내한다.
   .oc-app-footer 는 가운데 정렬이라 폭만 잡아 주면 그대로 가운데로 놓인다. */
.oc-app-footer .oc-footer__biz{max-width:760px;margin:10px auto 0;gap:2px}
.oc-footer__bottom{display:flex;justify-content:space-between;gap:12px;flex-wrap:wrap;padding-top:20px;border-top:1px solid var(--oc-divider)}
.oc-footer__legal{display:flex;gap:14px;flex-wrap:wrap}
.oc-footer__legal a{font-weight:var(--oc-fw-semibold)}

/* ---------- 랜딩 ---------- */
.oc-hero{padding:72px 0 56px;position:relative;overflow:hidden}
.oc-hero__in{display:grid;grid-template-columns:1.05fr 1fr;gap:48px;align-items:center}
.oc-kicker{display:inline-flex;align-items:center;gap:8px;padding:6px 12px 6px 8px;border-radius:var(--oc-r-pill);background:var(--oc-glass-bg);border:1px solid var(--oc-glass-border);box-shadow:0 0 0 1px var(--oc-glass-ring),var(--oc-gloss-inset);font-size:var(--oc-fs-caption);font-weight:var(--oc-fw-semibold);color:var(--oc-text-2);margin-bottom:20px}
.oc-hero h1{font-size:var(--oc-fs-display);line-height:var(--oc-lh-display);font-weight:var(--oc-fw-heavy);letter-spacing:-.035em;margin-bottom:18px}
.oc-hero__lead{font-size:18px;line-height:28px;color:var(--oc-text-2);max-width:52ch;margin-bottom:28px}
.oc-hero__cta{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
.oc-hero__note{font-size:var(--oc-fs-caption);color:var(--oc-text-3);margin-top:14px;display:flex;gap:14px;flex-wrap:wrap}
.oc-hero__note span{display:inline-flex;align-items:center;gap:5px}
.oc-hero__note .oc-i{width:14px;height:14px;color:var(--oc-success-solid)}
.oc-hero__visual{position:relative}
.oc-flow{display:grid;grid-template-columns:minmax(132px,.8fr) auto minmax(0,1.25fr);gap:12px;align-items:center}
.oc-flow__src{min-width:0;padding:14px;border-radius:var(--oc-r-lg);background:var(--oc-surface-gradient);border:1px solid var(--oc-border);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-md)}
.oc-flow__src .oc-thumb{width:100%;height:auto;aspect-ratio:16/9;margin-bottom:10px}
.oc-flow__src b{font-size:var(--oc-fs-sm);display:block;margin-bottom:4px}
.oc-flow__src span{font-size:var(--oc-fs-caption);color:var(--oc-text-3);display:flex;gap:6px;align-items:center}
.oc-flow__beam{width:56px;height:2px;background:var(--oc-accent-gradient-h);border-radius:2px;position:relative}
.oc-flow__beam::before,.oc-flow__beam::after{content:"";position:absolute;top:50%;width:8px;height:8px;border-radius:50%;background:var(--oc-accent-to);transform:translateY(-50%);box-shadow:0 0 0 4px var(--oc-accent-glow)}
.oc-flow__beam::before{left:-4px;background:var(--oc-accent-from)}
.oc-flow__beam::after{right:-4px}
.oc-flow__dst{display:flex;flex-direction:column;gap:6px;min-width:0}
.oc-flow__row{display:flex;align-items:center;gap:10px;min-width:0;padding:8px 10px;border-radius:12px;background:var(--oc-surface);border:1px solid var(--oc-border);box-shadow:var(--oc-shadow-xs);font-size:var(--oc-fs-caption)}
.oc-flow__row .oc-pf{width:28px;height:28px;border-radius:8px}
.oc-flow__row .oc-pf .oc-i{width:14px;height:14px}
.oc-flow__row b{flex:1;min-width:0;font-weight:var(--oc-fw-semibold);overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.oc-flow__row .oc-badge{height:20px;padding:0 7px;font-size:11px}
.oc-pfrow{display:flex;gap:10px;flex-wrap:wrap;justify-content:center}
.oc-pfrow__item{display:flex;flex-direction:column;align-items:center;gap:6px;width:84px;font-size:var(--oc-fs-micro);color:var(--oc-text-2);font-weight:var(--oc-fw-medium);text-align:center}
.oc-pfrow__item .oc-badge{height:18px;padding:0 6px;font-size:10px}
.oc-landing-section{padding:56px 0}
.oc-landing-section--alt{background:var(--oc-surface-2)}
[data-theme="dark"] .oc-landing-section--alt{background:rgba(255,255,255,.02)}
.oc-landing-section__head{text-align:center;max-width:640px;margin:0 auto 32px}
.oc-landing-section__head h2{font-size:32px;line-height:40px;letter-spacing:-.03em;margin-bottom:10px}
.oc-landing-section__head p{color:var(--oc-text-2);font-size:var(--oc-fs-body)}
.oc-steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:20px}
.oc-stepcard{padding:24px}
.oc-stepcard__n{width:40px;height:40px;border-radius:12px;background:var(--oc-accent-gradient);color:#fff;display:grid;place-items:center;font-weight:var(--oc-fw-heavy);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-accent);margin-bottom:14px}
.oc-stepcard h3{font-size:var(--oc-fs-h4);margin-bottom:6px}
.oc-stepcard p{font-size:var(--oc-fs-sm);color:var(--oc-text-2)}
.oc-faq{max-width:760px;margin:0 auto;display:flex;flex-direction:column;gap:10px}
.oc-faq details{border:1px solid var(--oc-border);border-radius:var(--oc-r-lg);background:var(--oc-surface-gradient);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-xs)}
.oc-faq summary{list-style:none;display:flex;align-items:center;gap:12px;padding:16px 20px;min-height:56px;font-weight:var(--oc-fw-semibold);cursor:pointer;border-radius:inherit}
.oc-faq summary::-webkit-details-marker{display:none}
.oc-faq summary .oc-i{margin-left:auto;color:var(--oc-text-3);transition:transform var(--oc-dur-2)}
.oc-faq details[open] summary .oc-i{transform:rotate(180deg)}
.oc-faq summary:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
.oc-faq .oc-faq__a{padding:0 20px 18px;color:var(--oc-text-2);font-size:var(--oc-fs-sm);line-height:22px}
.oc-cta-band{padding:48px 0}
.oc-cta-band .oc-glass{text-align:center;padding:48px 24px}
.oc-cta-band h2{font-size:28px;line-height:36px;margin-bottom:10px}
.oc-cta-band p{color:var(--oc-text-2);margin-bottom:22px}

/* ---------- 채널 미리보기 · 마법사 · 라우트 · 결제 ---------- */
.oc-preview{display:flex;gap:16px;align-items:flex-start}
.oc-preview__avatar{width:56px;height:56px;border-radius:50%;background:linear-gradient(135deg,#F472B6,#7C3AED);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-sm);flex-shrink:0;display:grid;place-items:center;color:#fff;font-weight:var(--oc-fw-heavy);font-size:18px}
.oc-preview__list{list-style:none;display:flex;flex-direction:column;gap:8px;margin-top:12px}
.oc-preview__list li{display:flex;gap:10px;align-items:center;font-size:var(--oc-fs-sm)}
.oc-preview__list li .oc-thumb{width:56px;height:32px;border-radius:6px}
.oc-preview__list li>.oc-num{color:var(--oc-text-3);font-size:var(--oc-fs-caption);margin-left:auto;white-space:nowrap}
.oc-result{display:flex;gap:12px;align-items:flex-start;padding:14px 16px;border-radius:var(--oc-r-md);border:1px solid;font-size:var(--oc-fs-sm)}
.oc-result .oc-i{width:20px;height:20px;flex-shrink:0}
.oc-result b{display:block}
.oc-result--ok{background:var(--oc-success-bg);border-color:var(--oc-success-border);color:var(--oc-success-text)}
.oc-result--warn{background:var(--oc-attention-bg);border-color:var(--oc-attention-border);color:var(--oc-attention-text)}
.oc-result--err{background:var(--oc-danger-bg);border-color:var(--oc-danger-border);color:var(--oc-danger-text)}
.oc-guide{counter-reset:g;list-style:none;display:flex;flex-direction:column;gap:12px}
.oc-guide li{display:flex;gap:12px;align-items:flex-start;font-size:var(--oc-fs-sm);color:var(--oc-text-2)}
.oc-guide li::before{counter-increment:g;content:counter(g);width:24px;height:24px;border-radius:50%;background:var(--oc-primary-soft);color:var(--oc-primary-soft-text);font-size:12px;font-weight:var(--oc-fw-bold);display:grid;place-items:center;flex-shrink:0;margin-top:1px}
.oc-guide li b{color:var(--oc-text)}
.oc-wizard{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:24px;align-items:start}
.oc-wizard__aside{position:sticky;top:80px}
.oc-routes{display:grid;grid-template-columns:minmax(0,1fr) 360px;gap:24px;align-items:start}
.oc-route-cell{display:inline-flex;flex-direction:column;align-items:center;gap:6px}
/* QA: min-height:0 이 .oc-switch 의 44px 를 지워 라우트 화면의 유일한 주 컨트롤이 24px 였다.
   토글 그래픽은 작게(40x22) 두되 터치 타깃은 44px 를 지킨다. */
.oc-route-cell .oc-switch{min-height:var(--oc-touch)}
.oc-route-cell .oc-switch input{width:40px;height:22px}
.oc-route-cell .oc-switch input::after{width:16px;height:16px}
.oc-route-cell .oc-switch input:checked::after{transform:translateX(18px)}
.oc-mini{display:inline-flex;gap:4px}
.oc-mini button{min-width:28px;height:22px;padding:0 6px;border-radius:6px;border:1px solid var(--oc-border-strong);background:var(--oc-surface);font-size:11px;font-weight:var(--oc-fw-bold);color:var(--oc-text-3);cursor:pointer;position:relative}
.oc-mini button::after{content:"";position:absolute;inset:-11px -2px}
.oc-mini button[aria-pressed="true"]{background:var(--oc-primary-soft);border-color:var(--oc-primary);color:var(--oc-primary-soft-text)}
.oc-mini button:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
.oc-msg{border-radius:16px;padding:12px 14px;background:var(--oc-surface-3);font-size:var(--oc-fs-sm);line-height:21px;white-space:pre-wrap;color:var(--oc-text);box-shadow:var(--oc-gloss-inset)}
.oc-msg__link{color:var(--oc-primary);text-decoration:underline;word-break:break-all}
.oc-msg__card{margin-top:10px;border-radius:10px;overflow:hidden;border:1px solid var(--oc-border);background:var(--oc-surface)}
.oc-msg__card .oc-thumb{width:100%;height:auto;aspect-ratio:16/9;border-radius:0}
.oc-msg__card div{padding:8px 10px;font-size:var(--oc-fs-caption);color:var(--oc-text-2)}
.oc-msg__card div b{display:block;color:var(--oc-text);font-size:var(--oc-fs-sm)}
.oc-count{font-size:var(--oc-fs-caption);color:var(--oc-text-3);font-variant-numeric:tabular-nums;text-align:right}
.oc-count.is-over{color:var(--oc-danger-text);font-weight:var(--oc-fw-semibold)}
.oc-billing-current{display:grid;grid-template-columns:1.2fr 1fr;gap:24px;align-items:start}
.oc-kv{display:grid;grid-template-columns:auto 1fr;gap:8px 16px;font-size:var(--oc-fs-sm)}
.oc-kv dt{color:var(--oc-text-3);font-weight:var(--oc-fw-medium)}
.oc-kv dd{margin:0;color:var(--oc-text);font-weight:var(--oc-fw-semibold);font-variant-numeric:tabular-nums}
.oc-legal-box{padding:14px 16px;border-radius:var(--oc-r-md);background:var(--oc-surface-3);font-size:var(--oc-fs-caption);line-height:var(--oc-lh-caption);color:var(--oc-text-2)}
.oc-legal-box ul{padding-left:18px;display:flex;flex-direction:column;gap:4px;margin-top:6px}
.oc-legal-box b{color:var(--oc-text)}
.oc-cardmask{display:inline-flex;align-items:center;gap:8px;padding:8px 12px;border-radius:10px;background:var(--oc-surface-3);font-variant-numeric:tabular-nums;font-weight:var(--oc-fw-semibold);font-size:var(--oc-fs-sm)}
.oc-cardmask .oc-i{width:18px;height:18px;color:var(--oc-text-3)}
.oc-noti{display:flex;gap:12px;align-items:flex-start;padding:12px 0;border-bottom:1px solid var(--oc-divider);font-size:var(--oc-fs-sm)}
.oc-noti:last-child{border-bottom:0}
.oc-noti__icon{width:32px;height:32px;border-radius:10px;display:grid;place-items:center;flex-shrink:0}
.oc-noti__icon .oc-i{width:16px;height:16px}
.oc-noti__body{flex:1;min-width:0}
.oc-noti__body b{display:block}
.oc-noti__body span{color:var(--oc-text-3);font-size:var(--oc-fs-caption)}
.oc-noti__time{font-size:var(--oc-fs-micro);color:var(--oc-text-3);white-space:nowrap}

/* ---------- 컨테이너 쿼리(프레임/뷰포트 반응형) ---------- */
@media (max-width: 960px){
  .oc-shell{grid-template-columns:1fr}
  .oc-sidebar{display:none}
  .oc-tabbar{display:flex}
  .oc-main{padding:16px;padding-bottom:24px}
  .oc-stats{grid-template-columns:repeat(2,minmax(0,1fr))}
  .oc-wizard,.oc-routes,.oc-billing-current{grid-template-columns:1fr}
  .oc-wizard__aside{position:static}
  .oc-grid-3,.oc-grid-4{grid-template-columns:repeat(2,minmax(0,1fr))}
  .oc-hero__in{grid-template-columns:1fr}
  .oc-hero{padding:48px 0 40px}
  .oc-steps{grid-template-columns:1fr}
  .oc-footer__grid{grid-template-columns:1fr 1fr}
  .oc-topbar__nav{display:none}
  .oc-topbar__menu{display:inline-flex}
  .oc-plans{grid-template-columns:1fr;gap:28px}
}
@media (max-width: 640px){
  .oc-main{padding:16px 16px 24px}
  .oc-container{padding:0 16px}
  .oc-appbar{padding:0 12px}
  .oc-appbar__ws{display:none}
  .oc-topbar__in{padding:0 16px}
  .oc-hero h1{font-size:34px;line-height:42px}
  .oc-hero__lead{font-size:16px;line-height:24px}
  .oc-hero__cta .oc-btn{width:100%}
  .oc-flow{grid-template-columns:1fr}
  .oc-flow__beam{width:2px;height:28px;margin:0 auto;background:var(--oc-accent-gradient)}
  .oc-flow__beam::before{left:50%;top:-4px;transform:translateX(-50%)}
  .oc-flow__beam::after{right:auto;left:50%;top:auto;bottom:-4px;transform:translateX(-50%)}
  .oc-landing-section{padding:40px 0}
  .oc-landing-section__head h2{font-size:26px;line-height:34px}
  .oc-page-head h1{font-size:24px;line-height:32px}
  .oc-stats{grid-template-columns:1fr 1fr}
  .oc-stat__value{font-size:24px}
  .oc-grid-2,.oc-grid-3,.oc-grid-4{grid-template-columns:1fr}
  .oc-footer__grid{grid-template-columns:1fr}
  .oc-step__label{display:none}
  .oc-step--current .oc-step__label{display:flex}
  .oc-step::after{margin:0 6px}
  .oc-dialog{padding:20px}
  .oc-dialog__actions .oc-btn{flex:1}
  .oc-card{padding:16px}
  .oc-glass{padding:20px}
  .oc-plan{padding:20px}
  /* 640 이하에서 텍스트형 ghost 버튼(로그인)만 숨긴다.
     아이콘 버튼(테마 토글·햄버거)까지 숨기면 모바일에서 메뉴·테마 전환 수단이 사라진다. */
  .oc-topbar__actions .oc-btn--ghost:not(.oc-btn--icon){display:none}
  .oc-pfrow__item{width:72px}
  .oc-video{min-width:220px}
  .oc-video__title{max-width:180px}
  .oc-kv{grid-template-columns:1fr}
  .oc-kv dt{margin-top:6px}
  .oc-preview{flex-direction:column}
  .oc-table__actions{flex-direction:column}
}

/* ============================================================================
   23. 제품 보정 (쇼케이스에 없던 규칙 — 위 변환 내역 5·6·7 참조)
   ========================================================================== */

/* 5. 글래스 폴백 — backdrop-filter 미지원 브라우저에서 반투명 배경 위 글자가
      배경과 겹쳐 대비가 무너지는 것을 막는다. (05_디자인시스템 §9-9) */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .oc-glass,
  .oc-appbar,
  .oc-sidebar,
  .oc-tabbar,
  .oc-topbar,
  .oc-kicker { background: var(--oc-surface); }
  .oc-overlay { background: rgba(10, 15, 30, .78); }
  dialog.oc-dialog::backdrop { background: rgba(10, 15, 30, .78); }
}

/* 6. 스텝퍼 라벨 — 좁은 폭에서 "채널 연결" 같은 짧은 라벨이 세로로 깨지는 것을 막는다.
      (05_디자인시스템 §10-1 줄바꿈 규칙) */
.oc-step__label { white-space: nowrap; }
.oc-step__label span { white-space: nowrap; }

/* 6-b. 640px 이하에서 현재 단계 라벨이 연결선(::after flex:1)에 밀려
        "토." 처럼 잘리던 문제 보정 — 현재 단계에만 남는 폭을 준다.
        (설계 의도: "640px 이하는 현재 단계 라벨만 표시" — 05_디자인시스템 §4-7) */
@media (max-width: 640px) {
  .oc-step { flex: 0 0 auto; }
  .oc-step--current { flex: 1 1 auto; min-width: 0; }
  .oc-step--current .oc-step__btn { min-width: 0; }
}

/* 7. 산문 이스케이프 해치 — 전역 p / ul,ol 리셋은 .oc-* 컴포넌트 전제이므로 유지하되,
      약관·개인정보처리방침·환불규정 같은 긴 산문에서는 브라우저 기본 여백을 되살린다.
      .legal-doc 은 기존 templates/legal 하위 화면이 이미 쓰는 클래스(호환 브리지). */
.oc-prose p,
.legal-doc p { margin: 0 0 var(--oc-sp-3); }
.oc-prose ul, .oc-prose ol,
.legal-doc ul, .legal-doc ol { margin: 0 0 var(--oc-sp-3); padding-left: 22px; }
.oc-prose li,
.legal-doc li { margin-bottom: var(--oc-sp-1); }
.oc-prose h2, .oc-prose h3,
.legal-doc h2, .legal-doc h3 { margin-top: var(--oc-sp-6); margin-bottom: var(--oc-sp-2); }

/* 7-b. 스킵 링크 — 기존 레이아웃 3종이 .skip-link 를 이미 쓰고 있어 토큰으로 재정의한다. */
.skip-link {
  position: absolute; left: var(--oc-sp-4); top: -60px; z-index: calc(var(--oc-z-toast) + 1);
  display: inline-flex; align-items: center; min-height: var(--oc-touch);
  padding: 0 var(--oc-sp-4); border-radius: var(--oc-r-md);
  background: var(--oc-surface); color: var(--oc-text);
  border: 1px solid var(--oc-border-strong); box-shadow: var(--oc-shadow-md);
  font-weight: var(--oc-fw-bold); text-decoration: none;
  transition: top var(--oc-dur-2) var(--oc-ease);
}
.skip-link:focus { top: var(--oc-sp-2); }

/* 7-d. 320px 무가로스크롤 보정 (05_디자인시스템 §5 브레이크포인트 요구사항)
   실측: 320px 뷰포트에서 .oc-topbar__actions 가 42px 넘쳐 가로 스크롤이 생겼다.
   (로고 36px 마크 + 22px 워드마크 + primary CTA + 햄버거 44px 합이 폭을 초과)
   쇼케이스는 375px 프레임 기준이라 드러나지 않던 결함이다. */
@media (max-width: 400px) {
  .oc-topbar__in { gap: var(--oc-sp-2); padding: 0 var(--oc-sp-3); }
  .oc-topbar__actions { gap: var(--oc-sp-1); }
  .oc-logo__mark { width: 28px; height: 28px; }
  .oc-logo__word { font-size: 18px; }
  .oc-appbar { gap: var(--oc-sp-2); }
  .oc-page-head { gap: var(--oc-sp-3); }
  /* 헤더 버튼 좌우 여백만 줄인다. 높이(40)·히트영역(::after 로 44)은 유지. */
  .oc-topbar__actions .oc-btn--sm { padding: 0 10px; }
}

/* 7-e. 좁은 폭 배너 — 우측 액션 버튼이 본문을 눌러 한 줄에 2~3글자만 남던 문제 보정.
   .oc-banner__body 에 min-width:0 이 있어 flex-wrap 만으로는 계속 줄어들기만 하므로,
   basis 를 "전체 폭 - 아이콘(20) - gap(12)" 으로 못박아 버튼이 반드시 다음 줄로 가게 한다. */
@media (max-width: 480px) {
  .oc-banner { flex-wrap: wrap; }
  .oc-banner__body { flex: 1 1 calc(100% - 32px); }
  .oc-banner .oc-btn { flex: 0 0 auto; margin-left: auto; margin-top: var(--oc-sp-1); }
}

/* 7-c. 모션 감소 — 토큰 0ms 로도 남는 keyframes 애니메이션을 정지한다. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
  .oc-spin { animation: none; }
}

/* ============================================================================
   24. Phase B 화면 적용 보정 (2026-08-31 · web-publisher)
   쇼케이스에는 없던 "실제 화면에만 있는" 조각들. 값은 전부 oc-tokens.css 변수로만.
   ========================================================================== */

/* ---------- 24-1. 인증 화면 (로그인·가입·인증·재설정) ---------- */
.oc-auth{display:flex;justify-content:center;padding-top:var(--oc-sp-12);padding-bottom:var(--oc-sp-16)}
.oc-auth__card{width:100%;max-width:460px;display:flex;flex-direction:column;gap:var(--oc-sp-4)}
.oc-auth__card--wide{max-width:620px}
.oc-auth__card h1{font-size:var(--oc-fs-h2);line-height:var(--oc-lh-h2)}
.oc-auth__foot{display:flex;flex-direction:column;gap:var(--oc-sp-2);align-items:center;
  padding-top:var(--oc-sp-4);border-top:1px solid var(--oc-divider);
  font-size:var(--oc-fs-sm);color:var(--oc-text-2);text-align:center}
@media (max-width:640px){
  .oc-auth{padding-top:var(--oc-sp-6);padding-bottom:var(--oc-sp-10)}
  .oc-auth__card{border-radius:var(--oc-r-lg)}
}

/* ---------- 24-2. 구분선(가운데 글자) ---------- */
.oc-sep{display:flex;align-items:center;gap:var(--oc-sp-3);color:var(--oc-text-3);
  font-size:var(--oc-fs-caption);line-height:var(--oc-lh-caption)}
.oc-sep::before,.oc-sep::after{content:"";flex:1;height:1px;background:var(--oc-divider)}

/* ---------- 24-3. SNS 간편 로그인/가입 ----------
   브랜드 가이드 색은 여기서 토큰으로 한 번만 선언하고, 규칙에서는 var() 로만 쓴다.
   상표 로고 이미지는 쓰지 않고 단색 레터마크로 표기한다(라이트·다크 동일 값). */
:root{
  --oc-sns-google-bg:#FFFFFF;
  --oc-sns-google-fg:#1F1F1F;
  --oc-sns-google-border:#DADCE0;
  --oc-sns-naver-bg:#03C75A;
  /* QA: 흰 글자 + #03C75A 는 2.25:1 로 KWCAG 1.4.3(4.5:1) 미달. 진한 글자로 9.32:1 확보.
     (배경은 브랜드 가이드 색 그대로) */
  --oc-sns-naver-fg:#191919;
  --oc-sns-kakao-bg:#FEE500;
  --oc-sns-kakao-fg:#191600;
}
.oc-sns{display:flex;flex-direction:column;gap:var(--oc-sp-3)}
.oc-sns__list{display:flex;flex-direction:column;gap:var(--oc-sp-2)}
.oc-sns__btn{display:flex;align-items:center;justify-content:center;gap:8px;
  min-height:var(--oc-control-h);padding:0 var(--oc-sp-4);border-radius:var(--oc-r-md);
  border:1px solid transparent;font-size:var(--oc-fs-sm);font-weight:var(--oc-fw-semibold);
  text-decoration:none;white-space:nowrap;
  background:var(--oc-surface-3);color:var(--oc-text);
  box-shadow:var(--oc-gloss-inset),var(--oc-shadow-xs);
  transition:transform var(--oc-dur-2) var(--oc-ease),box-shadow var(--oc-dur-2) var(--oc-ease),filter var(--oc-dur-2) var(--oc-ease)}
.oc-sns__btn:hover{filter:brightness(.97);box-shadow:var(--oc-gloss-inset),var(--oc-shadow-sm)}
.oc-sns__btn:active{transform:translateY(1px)}
.oc-sns__btn:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
.oc-sns__mark{display:grid;place-items:center;width:22px;height:22px;border-radius:50%;
  background:rgba(0,0,0,.08);font-weight:var(--oc-fw-heavy);font-size:13px;line-height:1;flex-shrink:0}
.oc-sns__label{font-weight:var(--oc-fw-bold)}
.oc-sns__btn--google{background:var(--oc-sns-google-bg);color:var(--oc-sns-google-fg);border-color:var(--oc-sns-google-border)}
.oc-sns__btn--naver{background:var(--oc-sns-naver-bg);color:var(--oc-sns-naver-fg)}
.oc-sns__btn--naver .oc-sns__mark{background:rgba(255,255,255,.22)}
.oc-sns__btn--kakao{background:var(--oc-sns-kakao-bg);color:var(--oc-sns-kakao-fg)}
.oc-sns__notice{text-align:center}

/* ---------- 24-4. 진행 표시 · 버튼 로딩 ----------
   전 팀 공통 UX 규칙(2026-08-31): 1초 이상 걸릴 수 있는 요청은
   버튼 is-loading + 단계 텍스트 + indeterminate 프로그레스바를 함께 보여준다. */
.oc-progress{display:flex;align-items:center;gap:10px;flex-wrap:wrap;
  padding:10px 12px;border-radius:var(--oc-r-md);
  background:var(--oc-surface-3);border:1px solid var(--oc-border);
  font-size:var(--oc-fs-sm);color:var(--oc-text-2)}
.oc-progress__text{flex:1;min-width:0}
.oc-progress__spin{width:18px;height:18px;border-radius:50%;flex-shrink:0;
  border:2px solid var(--oc-border-strong);border-top-color:var(--oc-primary);
  animation:oc-rotate .8s linear infinite}
.oc-progress__bar{flex:0 0 100%;height:4px;border-radius:2px;overflow:hidden;
  background:var(--oc-surface-2);box-shadow:var(--oc-gloss-inset)}
.oc-progress__fill{display:block;width:40%;height:100%;border-radius:2px;
  background:var(--oc-accent-gradient-h);animation:oc-indeterminate 1.4s var(--oc-ease) infinite}
@keyframes oc-indeterminate{
  0%{transform:translateX(-100%)}
  100%{transform:translateX(280%)}
}
.oc-progress--fail{background:var(--oc-danger-bg);border-color:var(--oc-danger-border);color:var(--oc-danger-text)}
.oc-btn__spin{width:15px;height:15px;border-radius:50%;flex-shrink:0;
  border:2px solid currentColor;border-top-color:transparent;opacity:.85;
  animation:oc-rotate .7s linear infinite}
.oc-btn.is-loading{pointer-events:none;opacity:.82}
@media (prefers-reduced-motion:reduce){
  /* QA: 100% 로 채우면 미결정 진행이 "완료"로 보인다. 폭은 유지하고 애니메이션만 끈다. */
  .oc-progress__fill{animation:none;width:40%}
  .oc-progress__spin,.oc-btn__spin{animation:none}
}

/* ---------- 24-5. 화면 내 결과 패널 [data-oc-result] ---------- */
.oc-result{position:relative;padding-right:44px}
.oc-result__close{position:absolute;top:8px;right:8px;
  width:28px;height:28px;display:grid;place-items:center;
  border:0;border-radius:var(--oc-r-sm);background:transparent;color:inherit;
  cursor:pointer;opacity:.7}
.oc-result__close::after{content:"";position:absolute;inset:-8px}   /* 터치 44px */
.oc-result__close:hover{opacity:1;background:var(--oc-surface-3)}
.oc-result__close .oc-i{width:16px;height:16px}
.oc-result__actions{margin-top:10px}
.oc-result[hidden]{display:none}

/* ---------- 24-6. 토스트 액션 버튼 ---------- */
.oc-toast__actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}
.oc-toast__actions .oc-btn{background:rgba(255,255,255,.14);color:var(--oc-text-inverse);
  border-color:rgba(255,255,255,.22)}
.oc-toast__actions .oc-btn:hover{background:rgba(255,255,255,.24)}
.oc-toast--sticky{border-left-width:5px}

/* ---------- 24-7. 접이식 도움말 (연결 폼) ---------- */
.oc-guide-details{border:1px solid var(--oc-border);border-radius:var(--oc-r-md);
  background:var(--oc-surface-2);overflow:hidden}
.oc-guide-details>summary{list-style:none;display:flex;align-items:center;gap:8px;
  min-height:var(--oc-touch);padding:8px 14px;cursor:pointer;
  font-size:var(--oc-fs-caption);font-weight:var(--oc-fw-semibold);color:var(--oc-text-2)}
.oc-guide-details>summary::-webkit-details-marker{display:none}
.oc-guide-details>summary .oc-i{margin-left:auto;width:16px;height:16px;color:var(--oc-text-3);
  transition:transform var(--oc-dur-2)}
.oc-guide-details[open]>summary .oc-i{transform:rotate(180deg)}
.oc-guide-details>summary:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:-2px}
.oc-guide-details__body{padding:4px 16px 16px;display:flex;flex-direction:column;gap:12px}
.oc-guide-details__body .oc-guide li{font-size:var(--oc-fs-sm);line-height:var(--oc-lh-sm)}

/* ---------- 24-8. 플랫폼 선택 카드를 <button> 으로 쓸 때 ---------- */
button.oc-pfcard{width:100%;text-align:left;font:inherit;cursor:pointer;-webkit-appearance:none;appearance:none}
.oc-pfcard[aria-pressed="true"],.oc-pfcard.is-selected{
  border-color:var(--oc-primary);box-shadow:var(--oc-gloss-inset),0 0 0 3px var(--oc-focus-halo)}

/* ---------- 24-9. 앱 셸 보정 ---------- */
.oc-appbar form{margin:0}
/* 같은 이유로 사이드바 비활성 항목도 opacity 대신 토큰 색을 쓴다(대비 4.5:1 이상 유지). */
.oc-nav__link[aria-disabled="true"]{color:var(--oc-text-3);cursor:default}
.oc-nav__link[aria-disabled="true"]:hover{background:transparent;color:var(--oc-text-3)}
/* 매트릭스 셀 전체를 링크로 — 밑줄 없이 배지만 보이게 하고 히트 영역은 셀 전체로 */
.oc-matrix__cell-link{display:flex;align-items:center;justify-content:center;
  min-height:var(--oc-touch);text-decoration:none;color:inherit;border-radius:var(--oc-r-sm)}
.oc-matrix__cell-link:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:-2px}
/* 라우트 셀은 스위치 밑에 상세(쇼츠/롱폼·템플릿)가 붙으므로 폭을 편다 */
.oc-route-cell{align-items:stretch;min-width:200px;width:100%}
.oc-route-cell .oc-switch{align-self:flex-start;min-height:var(--oc-touch)}
.oc-route-detail{display:flex;flex-direction:column}
.oc-route-detail .oc-check{min-height:var(--oc-touch);padding:0}
/* 채널 수정 행 — 표 안에 폼이 들어간다 */
.oc-edit-row>td{background:var(--oc-surface-2);padding:var(--oc-sp-5)}
/* 썸네일을 실제 <img> 로 쓸 때 */
img.oc-thumb{object-fit:cover}

/* ---------- 24-10. 필터바 · 페이지네이션 ---------- */
.oc-filterbar{flex-direction:row;flex-wrap:wrap;align-items:flex-end;gap:var(--oc-sp-3);
  margin-bottom:var(--oc-sp-5)}
.oc-filterbar .oc-field{min-width:180px}
.oc-pagination{display:flex;gap:8px;flex-wrap:wrap;margin-top:var(--oc-sp-4)}
.oc-pagination a[aria-current="page"]{background:var(--oc-primary-soft);
  color:var(--oc-primary-soft-text);font-weight:var(--oc-fw-bold)}

/* ---------- 24-11. 약관·정책 문서 ---------- */
.oc-legal{padding-top:var(--oc-sp-10);padding-bottom:var(--oc-sp-16);max-width:860px}
.oc-legal h1{margin-bottom:var(--oc-sp-2)}
.oc-legal__meta{margin-bottom:var(--oc-sp-4)}
.oc-legal .oc-banner{margin-bottom:var(--oc-sp-6)}
.oc-legal .oc-table-wrap{margin:var(--oc-sp-4) 0}

/* ---------- 24-12. 오류 페이지 ---------- */
.oc-errorpage{padding-top:var(--oc-sp-16);padding-bottom:var(--oc-sp-16);text-align:center;
  display:flex;flex-direction:column;align-items:center;gap:var(--oc-sp-4)}
.oc-errorpage__code{font-size:88px;line-height:1;font-weight:var(--oc-fw-heavy);
  letter-spacing:-.05em}
.oc-errorpage .oc-empty{border:0;background:transparent;padding:0;width:100%}
.oc-errorpage h1{font-size:var(--oc-fs-h2);line-height:var(--oc-lh-h2)}
@media (max-width:640px){.oc-errorpage__code{font-size:64px}}

/* ---------- 24-13. hidden 우선 ----------
   .oc-progress{display:flex} 같은 클래스 규칙(0,1,0)이 UA 의 [hidden]{display:none}(0,1,0)과
   같은 특이도라 나중에 선언된 우리 쪽이 이겨 hidden 요소가 보이는 문제가 있었다
   (Phase B 1차 촬영에서 빈 진행바가 화면에 그대로 노출됨). 전역으로 못박는다. */
[hidden]{display:none !important}

/* ---------- 24-14. 앱 본문 직계 배너 여백 ---------- */
.oc-main>.oc-banner{margin-bottom:var(--oc-sp-5)}

/* ---------- 24-15. 사이드바 항목 줄바꿈 방지 ---------- */
.oc-nav__link{white-space:nowrap;min-width:0}
.oc-nav__link>span:not(.oc-badge){overflow:hidden;text-overflow:ellipsis}
.oc-nav__link .oc-badge{flex-shrink:0;height:20px;padding:0 7px;font-size:11px}

/* ---------- 24-16. 단독 링크 터치 타깃(44px) ----------
   KWCAG/KRDS — 본문 안 인라인 링크는 예외지만, 로고·푸터 링크·인증 화면 보조 링크는
   단독 컨트롤이라 44px 를 확보한다.

   ※ ::after 로 히트 영역만 넓히는 방법은 여기서 쓰면 안 된다. 세로로 늘어선 링크 목록에서는
     44px 확장 영역이 위아래 이웃 링크를 덮어 **이웃의 클릭을 가로챈다**(실측으로 확인:
     .oc-footer ul a 의 실제 히트 대상이 이웃 링크의 ::after 였다). 실제 높이를 준다. */
.oc-logo{min-height:var(--oc-touch)}
.oc-footer__legal a,.oc-footer ul a,.oc-footer__biz a,.oc-auth__foot a{
  display:inline-flex;align-items:center;min-height:var(--oc-touch)}
.oc-footer ul{gap:0}
.oc-auth__foot{gap:0}

/* ---------- 24-17. 입력 + 버튼 한 줄 (좁은 폭에서 자동 줄바꿈) ---------- */
.oc-input-row{display:flex;gap:var(--oc-sp-3);align-items:stretch;flex-wrap:nowrap}
.oc-input-row>.oc-input,.oc-input-row>.oc-input-group{flex:1;min-width:0}
.oc-input-row>.oc-btn{flex-shrink:0}
@media (max-width:480px){
  .oc-input-row{flex-wrap:wrap}
  .oc-input-row>.oc-btn{width:100%}
}

/* ---------- 24-18. SNS 버튼 라벨 ----------
   .oc-sns__btn 의 flex gap(8px) 이 "Google" 과 "로 로그인" 사이에 끼어
   "Google 로 로그인" 처럼 조사가 떨어져 보이던 문제 — 텍스트를 한 덩어리로 묶는다. */
.oc-sns__text{display:inline}

/* ---------- 24-19. 아주 좁은 폭(≤480)의 공개 헤더 ----------
   실측: 320px 에서 로고 + 테마토글 + CTA(158px) + 햄버거(44px) 합이 382px 로 62px 넘쳤다.
   CTA 는 숨기고 로그인·가입 진입점을 햄버거 메뉴 안(.oc-topbar__nav-auth)으로 옮긴다. */
/* 특이도 주의: .oc-topbar__nav a 가 (0,2,1) 이라 .oc-topbar__nav-auth 단독(0,1,0)으로는 못 이긴다.
   데스크톱 내비에 로그인/가입이 중복 노출되던 문제 — 같은 문맥으로 맞춰 숨긴다. */
.oc-topbar__nav a.oc-topbar__nav-auth{display:none}
@media (max-width:960px){
  .oc-topbar.is-open .oc-topbar__nav a.oc-topbar__nav-auth{
    display:inline-flex;font-weight:var(--oc-fw-bold);color:var(--oc-primary)}
}
@media (max-width:480px){
  .oc-topbar__actions .oc-btn--primary{display:none}
}

/* ---------- 24-20. QA 반영 — 스크롤 컨테이너 포커스 · 고대비 모드 ---------- */

/* [중대] 가로 스크롤되는 표/매트릭스는 키보드로도 스크롤할 수 있어야 한다(KWCAG 2.1.1).
   템플릿에서 tabindex="0" role="region" aria-label 을 주고, 여기서 포커스를 보이게 한다.
   특히 약관·랜딩의 표는 내부에 포커스 가능한 요소가 하나도 없어 이 처리가 없으면
   키보드 사용자가 오른쪽 열을 볼 방법이 없었다. */
.oc-table-wrap:focus-visible,.oc-matrix-wrap:focus-visible{
  outline:2px solid var(--oc-focus-ring);outline-offset:-2px;border-radius:var(--oc-r-md)}

/* [경미] 윈도우 고대비(강제 색) 모드 — 그라데이션 배경과 box-shadow 로만 표현한 상태가 사라진다.
   테두리로 형태를 남기고, 선택/현재 상태는 시스템 색으로 표시한다. */
@media (forced-colors: active){
  .oc-btn,.oc-card,.oc-glass,.oc-input,.oc-select,.oc-textarea,.oc-badge,
  .oc-pfcard,.oc-plan,.oc-result,.oc-banner,.oc-progress{border:1px solid CanvasText}
  .oc-btn--primary,.oc-stepcard__n,.oc-avatar{forced-color-adjust:none;background:Highlight;color:HighlightText}
  .oc-nav__link[aria-current="page"],.oc-tabbar a[aria-current="page"],
  .oc-pagination a[aria-current="page"]{outline:2px solid Highlight;outline-offset:-2px}
  .oc-switch input:checked,.oc-check input:checked{forced-color-adjust:none;background:Highlight}
  .oc-gauge__fill,.oc-progress__fill{forced-color-adjust:none;background:Highlight}
}

/* ---------- 24-21. 도움말 링크 바 (연결 폼) ----------
   각 플랫폼 도움말 맨 위의 "실제로 가서 발급받는 곳" 칩 묶음.
   좁은 폭에서는 가로 스크롤되는 한 줄로 둔다(세로로 쌓이면 도움말이 너무 길어진다). */
/* min-width:0 이 없으면 flex 자식(기본 min-width:auto)이 내용만큼 넓어져서
   아래 @media 의 overflow-x:auto 가 아무 소용이 없다 — 320px 에서 칩이 화면 밖으로
   222px 삐져나갔다(도움말을 펼친 상태에서만 재현되어 1차 스윕에서 놓쳤다).
   가로 스크롤 스트립을 감싸는 세로 flex 컨테이너 체인 전체를 풀어 줘야 한다
   (.oc-form > .oc-field > details > .oc-guide-details__body > .oc-linkbar). */
.oc-form,.oc-field,.oc-stack,.oc-guide-details__body{min-width:0}
.oc-linkbar{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:4px;min-width:0;max-width:100%}
/* QA: .oc-chip 의 min-height:32px 를 그대로 물려받아 22개 칩이 전부 32px 였다.
   도움말 링크 바는 "실제로 눌러서 나가는" 단독 컨트롤이라 44px 를 지킨다. */
.oc-linkchip{text-decoration:none;gap:5px;min-height:var(--oc-touch);padding:0 12px}
.oc-linkchip .oc-i{width:12px;height:12px;opacity:.7}
.oc-linkchip--key{border-color:var(--oc-primary);color:var(--oc-primary-soft-text);background:var(--oc-primary-soft);font-weight:var(--oc-fw-bold)}
.oc-linkchip--signup{border-color:var(--oc-success-border);color:var(--oc-success-text);background:var(--oc-success-bg)}
@media (max-width:640px){
  /* 좁은 폭에서는 칩을 여러 줄로 접는다.
     처음에는 `flex-wrap:nowrap` + `overflow-x:auto` 한 줄 스크롤로 만들었는데,
     320px 에서 문서 전체가 222px 가로로 넘쳤다(칩이 스크롤 박스 밖으로 문서 폭을 밀어냄).
     줄바꿈은 넘침이 구조적으로 생길 수 없고 링크를 전부 한눈에 보여줘 더 낫다.
     칩 높이는 44px 를 유지하므로 터치도 문제없다. */
  .oc-linkbar{flex-wrap:wrap;overflow-x:visible}
  .oc-linkchip{flex:0 1 auto}
}
/* 터치 기기(html.is-mobile — oc-ui.js 가 pointer:coarse 로 판별)에서는 스토어 링크를 앞으로,
   데스크톱에서는 웹/데스크톱 링크를 앞으로 보낸다. 순서만 바꾸고 DOM 은 그대로 둔다. */
.oc-linkbar>*{order:2}
.oc-linkchip--key{order:0}
.oc-linkchip--web{order:1}
.oc-linkchip--store{order:3}
.is-mobile .oc-linkchip--store{order:1}
.is-mobile .oc-linkchip--web{order:3}

/* ============================================================================
   24. 연결 마법사 (P3-C · web-publisher)
       /app/connections/new/{platform} · /app/connections/oauth/{stateId} ·
       /app/connections 의 플랫폼 카드 확장.
       새 토큰은 만들지 않고 기존 --oc-* 만 쓴다(하드코딩 HEX 금지).
   ========================================================================== */

/* 24-1. 플랫폼 카드 셸 — 카드가 <button> 이라 그 안에 "자세히 안내받기" <a> 를 넣을 수 없다
        (button 안의 대화형 요소는 무효 마크업이고 클릭도 삼켜진다). 바깥에서 세로로 묶는다. */
.oc-pfcard-shell{display:flex;flex-direction:column;gap:8px;min-width:0;height:100%}
.oc-pfcard-shell>.oc-pfcard{flex:1 1 auto}

.oc-pfcard-guide{display:inline-flex;align-items:center;gap:6px;min-height:var(--oc-touch);
  padding:0 12px;border-radius:var(--oc-r-md);text-decoration:none;
  font-size:var(--oc-fs-caption);font-weight:var(--oc-fw-semibold);
  color:var(--oc-primary);background:var(--oc-primary-soft);
  border:1px solid transparent;transition:background var(--oc-dur-2),border-color var(--oc-dur-2)}
.oc-pfcard-guide:hover{border-color:var(--oc-primary);text-decoration:none}
.oc-pfcard-guide:focus-visible{outline:2px solid var(--oc-focus-ring);outline-offset:2px}
.oc-pfcard-guide .oc-i{width:14px;height:14px;flex-shrink:0}
.oc-pfcard-guide__go{margin-left:auto}

/* 24-2. 스텝 인디케이터(서버 주도) — oc-parts :: stepperStatic.
        <button> 대신 <span> 을 쓰므로 커서·호버는 없애고 높이만 스텝퍼와 맞춘다. */
.oc-stepper span.oc-step__btn{cursor:default}

/* 24-3. 후보 선택 목록 — OAuth 승인 뒤 "연결할 대상" 고르기.
        각 행이 체크박스 1개(+ 항목 옵션 1개)를 담는 카드다. */
.oc-fieldset{border:0;padding:0;margin:0;min-width:0}
.oc-fieldset>legend{padding:0;margin-bottom:4px}

.oc-pick-list{display:flex;flex-direction:column;gap:10px;margin-top:12px}
.oc-pick{padding:12px 14px;border:1px solid var(--oc-border);border-radius:var(--oc-r-md);
  background:var(--oc-surface);min-width:0}
.oc-pick:focus-within{border-color:var(--oc-primary);box-shadow:0 0 0 3px var(--oc-focus-halo)}
.oc-pick .oc-check>span{display:flex;flex-direction:column;gap:2px;min-width:0}
.oc-pick .oc-check b{font-weight:var(--oc-fw-semibold);word-break:break-word}
.oc-pick__opt{margin-left:32px;padding-top:0}
@media (max-width:640px){
  .oc-pick__opt{margin-left:0}
}

/* 24-4. 마법사 카드 안의 안내(oc-guide-details)는 카드 배경 위에 놓이므로 살짝 띄운다. */
.oc-card>.oc-guide-details,
.oc-section>.oc-guide-details{background:var(--oc-surface-3)}

/* 24-5. 읽기전용 콜백 URL 입력 — 값이 길어 좁은 폭에서 넘치지 않도록 줄인다. */
.oc-input[readonly]{background:var(--oc-surface-3);cursor:text}

/* 24-6. 넘침 차단 — 마법사에서 실측으로 잡은 것들 (360/768px, 2026-08-31)
   ① .oc-wizard 는 ≤960 에서 `grid-template-columns:1fr` 로 접히는데, grid 아이템의
      기본 min-width 는 auto 라 **내용이 넓으면 트랙 자체가 늘어난다**. 그래서 스텝퍼의
      긴 라벨("Meta (Facebook 페이지·Instagram) 승인")이 카드를 191px 밖으로 밀어냈다.
      minmax(0,1fr) + min-width:0 으로 트랙이 늘지 못하게 고정한다.
   ② 스텝 라벨의 부제(span)에도 말줄임을 준다 — b 에만 있어 부제가 그대로 삐져나갔다.
   ③ 카드 머리행(플랫폼 심볼 + 제목/설명)은 flex 체인 전체에 min-width:0 이 있어야
      긴 한국어 설명이 줄바꿈된다. */
@media (max-width:960px){
  .oc-wizard{grid-template-columns:minmax(0,1fr)}
}
.oc-wizard>*{min-width:0}
.oc-step__label span{overflow:hidden;text-overflow:ellipsis}

.oc-cardhead{flex:1 1 auto;min-width:0;flex-wrap:nowrap;align-items:flex-start}
.oc-cardhead__text{min-width:0}
.oc-cardhead__text h2{overflow-wrap:anywhere}

/* 24-7. 줄바꿈 허용 버튼 — .oc-btn 은 기본이 white-space:nowrap 이라 긴 라벨
   ("Meta (Facebook 페이지·Instagram) 계정으로 연결하기")이 360px 에서 41px 넘쳤다.
   마법사의 주 행동 버튼처럼 라벨이 길 수밖에 없는 곳에만 붙인다. */
.oc-btn--wrap{white-space:normal;text-align:left;padding-top:12px;padding-bottom:12px;
  height:auto;max-width:100%;min-width:0}
.oc-btn--wrap>span{min-width:0;overflow-wrap:anywhere}

/* 24-8. 마법사 2단 → 1단 전환을 1200px 로 앞당긴다.
   1024px 에서는 사이드바(256) + 옆 안내(320)를 빼면 본 카드가 ~386px 밖에 남지 않아
   스텝 인디케이터·후보 목록이 지나치게 눌린다(실측). 옆 안내는 아래로 내려간다. */
@media (max-width:1200px){
  .oc-wizard{grid-template-columns:minmax(0,1fr)}
  .oc-wizard__aside{position:static}
}

/* 24-9. 후보 항목 옵션 스위치 — 라벨이 길어 여러 줄이 되므로 켬/끔 텍스트를 오른쪽에 고정한다. */
.oc-pick__opt.oc-switch{display:flex;align-items:flex-start;gap:10px;width:100%}
.oc-pick__opt.oc-switch>span:not(.oc-switch__state){flex:1 1 auto;min-width:0}
.oc-pick__opt.oc-switch>.oc-switch__state{flex:0 0 auto;margin-left:auto;align-self:center}
.oc-pick__opt.oc-switch input{margin-top:9px}

/* 24-10. 좁은 폭 4단계 스텝퍼 — 연결선(::after 는 flex:1)이 공간을 다 먹어 현재 단계 라벨이
   "연" 한 글자로 잘렸다(360px 실측). Phase B 6-b 가 3단계에서 고친 것과 같은 계열이지만
   OAuth 마법사는 4단계라 연결선이 하나 더 있어 다시 터진다.
   → 연결선을 고정폭으로 바꾸고(늘어나지 않게) 점을 조금 줄여 현재 라벨에 공간을 넘긴다.
     부제는 숨기고, 현재 라벨은 말줄임 대신 줄바꿈으로 전부 읽히게 한다. */
@media (max-width:640px){
  .oc-step::after{flex:0 0 8px;min-width:8px;margin:0 5px}
  .oc-step__dot{width:28px;height:28px}
  .oc-step--current .oc-step__label span{display:none}
  .oc-step--current .oc-step__label b{white-space:normal;overflow:visible;text-overflow:clip;line-height:1.25}
}

/* 24-11. 단독으로 놓인 링크는 44px 를 지킨다(KWCAG 2.5.5).
   문장 속 인라인 링크는 예외지만, 옆 안내의 "…보기" 처럼 줄 하나를 통째로 차지하는 링크는
   단독 컨트롤이라 높이를 줘야 한다. Phase B QA 교훈대로 ::after 히트영역 확장은 쓰지 않는다
   (세로로 늘어선 링크에서 확장 영역이 이웃의 클릭을 가로챈다) — 실제 높이를 준다. */
.oc-link-block{display:inline-flex;align-items:center;min-height:var(--oc-touch)}

/* ============================================================================
   25. P4 결제 · 온보딩 게이트 · 본인인증 (2026-08-31 · web-publisher / P4-D)
   기존 규칙을 덮어쓰지 않고 새 클래스만 추가한다. 색은 전부 토큰 참조.
   ============================================================================ */

/* 25-1. 결제 화면 현재 플랜 이름 — 카드 안의 h3 라서 h2 보다 작게 두되 값처럼 크게 보인다.
   .oc-plan__price 와 나란히 놓이므로 줄바꿈을 막는다(플랜명은 짧다). */
.oc-billing-plan{font-size:var(--oc-fs-h2);line-height:var(--oc-lh-h2);font-weight:var(--oc-fw-heavy);
  letter-spacing:var(--oc-tracking-tight);color:var(--oc-text);white-space:nowrap}

/* 25-2. 플랜 카드 안의 월/연 CTA 묶음 — 세그먼트가 [data-monthnote]/[data-yearnote] 로 토글한다.
   버튼과 일할 차액 안내가 한 덩어리로 움직이도록 간격만 준다. */
.oc-plan>[data-monthnote],.oc-plan>[data-yearnote]{display:flex;flex-direction:column;gap:8px}
.oc-plan>[data-monthnote] .oc-plan__legal,.oc-plan>[data-yearnote] .oc-plan__legal{margin-top:0}
/* 빈 안내 문단(변경 종류가 CURRENT/NEW 라 내용이 없는 경우)은 자리를 차지하지 않게 한다. */
.oc-plan__legal:empty{display:none}

/* 25-3. 사이드바·탭바 온보딩 잠금 표시. 기본은 hidden 속성으로 꺼져 있고,
   pages/onboarding.js 가 step1Done=false 일 때만 켠다.
   [hidden] 이 flex 에 지지 않도록 display:none 을 명시한다. */
.oc-nav__lock{display:inline-flex;align-items:center;margin-left:auto;color:var(--oc-text-3);flex-shrink:0}
.oc-nav__lock[hidden]{display:none}
.oc-nav__lock .oc-i{width:16px;height:16px}
.oc-tabbar .oc-nav__lock{margin-left:0;position:absolute;top:6px;right:calc(50% - 20px)}
.oc-tabbar a{position:relative}
/* 잠긴 메뉴는 색만으로 구분되지 않는다 — 자물쇠 아이콘 + sr-only 텍스트가 함께 나간다. */
.oc-nav__link.is-locked{color:var(--oc-text-3)}
.oc-nav__link.is-locked .oc-nav__lock{color:var(--oc-attention-solid)}

/* 25-4. 채널 소유 확인 안내 목록 — 번호가 보이는 ol 로, 각 단계 안에 버튼/링크가 들어간다.
   .oc-help(13px) 를 상속하되 항목 간 간격을 넉넉히 준다. */
.oc-own-steps{padding-left:20px;display:flex;flex-direction:column;gap:10px;margin:8px 0 4px}
.oc-own-steps>li{padding-left:2px}
.oc-own-steps>li::marker{color:var(--oc-text-3);font-weight:var(--oc-fw-bold)}

/* 25-5. 다날 본인확인 중계 화면(IdentityController.page() 가 만드는 최소 HTML).
   레이아웃 없이 뜨는 팝업 창이라 여기서만 여백·폭을 준다. */
.oc-window-bridge{max-width:420px;margin:0 auto;padding:24px 20px;display:flex;flex-direction:column;
  gap:16px;color:var(--oc-text);background:var(--oc-bg);min-height:100vh}
.oc-window-bridge .oc-btn{width:100%}

/* 25-6. 게이트로 잠긴 컨트롤 — disabled 만으로 끝내지 않고 커서·투명도를 함께 준다.
   실제 차단은 서버(409)가 하며 이것은 UX 표시다. */
[data-oc-onboarding-gate][disabled],[data-oc-onboarding-gate][aria-disabled="true"]{cursor:not-allowed}

/* 25-7. 관리자 결제 표 — 빈 상태 행. */
tr[data-oc-empty-row]>td{padding:20px 16px;text-align:center;color:var(--oc-text-3)}

/* 25-8. 320px 대응 — 현재 구독 카드의 금액이 플랜명과 겹치지 않게 세로로 쌓는다. */
@media (max-width:480px){
  .oc-billing-plan{font-size:var(--oc-fs-h3);line-height:var(--oc-lh-h3);white-space:normal}
  .oc-card__head{flex-direction:column;align-items:flex-start;gap:10px}
  .oc-kv{grid-template-columns:1fr;gap:2px 0}
  .oc-kv dt{margin-top:8px}
}

/* ============================================================================
   25-9. 주 버튼 그림자 ↔ 바로 아래 설명문(캡션·도움말) 겹침 방지
         2026-08-31 · web-publisher · 대표 실측 지적(P2.5-F, /app/connections/new/google)
   [원인]
     ① .oc-btn--primary 는 --oc-shadow-accent 를 쓴다.
        기본  라이트 0 10px 24px -10px / 다크 0 10px 26px -10px
              → 버튼 아래로 약 12~13px 번진다(offset - spread + blur/2).
        hover 0 14px 30px -10px  → 약 19px 까지 번진다(+ translateY(-1px)).
        즉 버튼 행과 설명문 사이가 14px 미만이면 첫 줄이 그림자 안에 들어간다.
     ② .oc-btn 은 스펙큘러(::before) 때문에 position:relative 다. 위치지정 요소는
        뒤따르는 static 형제의 텍스트보다 "나중에" 그려지므로(CSS 페인팅 8단계 > 7단계),
        간격이 있어도 그림자가 글자 위에 덮여 흐릿해 보인다.
   [조치]
     ① 설명문류를 z-index 로 그림자 위에 올린다 — 레이아웃 영향 0.
     ② 버튼 행과 설명문 사이를 hover 번짐(19px) 이상인 20px(--oc-sp-5) 로 확보한다.
   [적용 규칙] 새 화면에서 주 버튼 아래에 안내 문구를 붙일 때는 버튼을 .oc-row 로 감싸고
     문구에 .oc-help / .oc-caption / .oc-small 중 하나를 쓰면 자동으로 적용된다.
   ============================================================================ */

/* ① 그림자 위로 올리기(레이아웃 불변). .oc-card 는 isolation:isolate 라 카드 내부로 한정된다. */
.oc-help,.oc-caption,.oc-small,.oc-error,
.oc-plan__legal,.oc-hero__note,.oc-sns,.oc-auth__foot{position:relative;z-index:1}

/* ② 버튼 행 → 설명문 간격 20px. 부모가 블록 흐름(gap 없음)일 때. */
.oc-row+.oc-help,.oc-row+.oc-caption,.oc-row+.oc-small,.oc-row+.oc-error{margin-top:var(--oc-sp-5)}
/* 세로 gap 이 이미 있는 컨테이너에서는 gap 과 합쳐 20px 이 되도록만 보탠다
   (.oc-form / .oc-stack = 16px → +4px, .oc-field = 6px → +14px). */
.oc-form>.oc-row+.oc-help,.oc-form>.oc-row+.oc-caption,.oc-form>.oc-row+.oc-small,
.oc-stack>.oc-row+.oc-help,.oc-stack>.oc-row+.oc-caption,.oc-stack>.oc-row+.oc-small{margin-top:var(--oc-sp-1)}
.oc-field>.oc-row+.oc-help,.oc-field>.oc-row+.oc-caption,.oc-field>.oc-row+.oc-small{margin-top:14px}

/* ③ 인증 화면(로그인·가입·재설정·이메일 인증) — 주 버튼이 .oc-form 의 마지막 자식이라
   그림자가 카드 스택의 다음 블록(SNS 로그인 구분선·하단 링크)에 닿는다.
   .oc-auth__card 의 세로 간격을 16 → 20px 로 올려 한 번에 해소한다. */
.oc-auth__card{gap:var(--oc-sp-5)}

/* ④ 플랜 카드 CTA → 일할 차액·법적 문구. [data-monthnote]/[data-yearnote] 의 gap 이 8px 라
   8 + 12 = 20px 가 되게 보탠다(주 버튼일 때만 — secondary 는 shadow-xs 라 번지지 않는다). */
.oc-plan>[data-monthnote] .oc-btn--primary+.oc-plan__legal,
.oc-plan>[data-yearnote] .oc-btn--primary+.oc-plan__legal{margin-top:12px}

/* ⑤ 랜딩 히어로 — CTA 아래 보조 문구(카드 등록 없이 시작 …)가 hover 시 그림자에 닿았다. */
.oc-hero__note{margin-top:var(--oc-sp-5)}

/* ============================================================================
   25-10. 좁은 폭에서 줄바꿈된 버튼 행 · 단계 안내 가독성 (같은 실측 건에서 함께 확인)
   ============================================================================ */

/* ① ≤640px 에서는 주 버튼이 한 줄을 다 쓰고 보조 버튼이 다음 줄로 내려간다.
   .oc-row 의 gap 은 12px 라 주 버튼 그림자(12~13px)가 아랫줄 버튼에 걸친다.
   가로 gap 은 그대로 두고 줄간 간격만 20px 로 넓힌다(한 줄일 때는 영향 없음). */
@media (max-width:640px){
  .oc-row{row-gap:var(--oc-sp-5)}
}

/* ② "계정이 없어요 / 처음이에요" 단계 안내 — 한 항목이 2~4줄짜리 문단이라
   14px/20px(1.43)은 좁다. KRDS 본문 권장(1.5 이상)에 맞춰 1.6 으로 올리고
   항목 사이도 조금 벌려 단계 구분이 보이게 한다. */
.oc-guide-details__body .oc-guide{gap:14px}
.oc-guide-details__body .oc-guide li{line-height:1.6}

/* ============================================================================
   26. 광고 슬롯 · 하우스 광고 (P4-K, 2026-09-01 대표 지시)
   ============================================================================
   무료 플랜이면서 유효한 유료 결제 이력이 없는 테넌트에게만 렌더된다(판정은 서버 AdService).
   마크업은 fragments/oc-ads.html, 배치는 layouts/app.html 이 소유한다.

   지키는 것
     · 표시광고 명시 의무 — 콘텐츠와 시각적으로 명확히 구분한다(점선 테두리 + 옅은 바탕)
       + "광고 / AD" 라벨을 항상 함께 낸다. 라벨은 색만으로 구분하지 않는다(KWCAG 1.4.1).
     · 하이그로시 토큰만 쓴다 — 하드코딩 색 0. 광고가 서비스 UI 보다 튀지 않게 surface-2 계열의
       낮은 채도 바탕을 쓰고, 강조는 CTA 버튼(기존 .oc-btn--secondary)에만 준다.
     · 44px 터치(.oc-btn--sm 의 ::after 확장으로 46px) · 가로스크롤 0(min-width 를 두지 않는다).
     · 외부 광고망이 켜지면 .oc-ad__frame 안에 그 망의 <ins>/<iframe> 이 들어온다. 크기는
       data-* 로 온 expectWidth/Height 를 인라인 스타일(style-src 'unsafe-inline' 허용)로 준다.
   ------------------------------------------------------------------------- */

.oc-ad{
  position:relative;display:block;
  border:1px dashed var(--oc-border-strong);border-radius:var(--oc-r-lg);
  background:var(--oc-surface-2);
  padding:var(--oc-sp-3);
  max-width:100%;min-width:0;
}

/* 라벨 줄 — "광고 / AD". 아이콘·텍스트·배지 셋을 함께 내 색맹 사용자도 구분할 수 있게 한다. */
.oc-ad__label{
  display:flex;align-items:center;gap:var(--oc-sp-2);
  margin-bottom:var(--oc-sp-2);
  font-size:var(--oc-fs-micro);line-height:var(--oc-lh-micro);
  color:var(--oc-text-3);letter-spacing:.04em;
}
.oc-ad__label .oc-i{width:14px;height:14px;flex-shrink:0}
.oc-ad__tag{
  display:inline-flex;align-items:center;height:18px;padding:0 6px;
  border:1px solid var(--oc-border-strong);border-radius:var(--oc-r-xs);
  background:var(--oc-surface-3);color:var(--oc-text-2);
  font-size:var(--oc-fs-micro);font-weight:var(--oc-fw-semibold);letter-spacing:.06em;
}

/* 하우스 광고 본문 */
.oc-ad__body{display:flex;flex-direction:column;gap:var(--oc-sp-2);min-width:0}
.oc-ad__title{
  margin:0;font-size:var(--oc-fs-sm);line-height:var(--oc-lh-sm);
  font-weight:var(--oc-fw-bold);color:var(--oc-text);
}
.oc-ad__text{
  margin:0;font-size:var(--oc-fs-caption);line-height:1.6;color:var(--oc-text-2);
  overflow-wrap:anywhere;
}
.oc-ad__actions{display:flex;flex-wrap:wrap;gap:var(--oc-sp-2);margin-top:var(--oc-sp-1)}

/* 외부 광고망 자리 — 망이 활성일 때만 렌더된다. 자리를 미리 잡아 레이아웃 이동을 막는다. */
.oc-ad__frame{
  display:flex;align-items:center;justify-content:center;
  width:100%;max-width:100%;overflow:hidden;
  border-radius:var(--oc-r-sm);background:var(--oc-surface-3);
}

/* 배치 변형 ------------------------------------------------------------- */
/* 사이드바 하단 — 폭이 232px(256 - padding)라 세로로 쌓는다. */
.oc-ad--app_sidebar{margin-top:var(--oc-sp-4)}
/* 본문 하단 — 본문 폭을 다 쓰되 위 콘텐츠와 충분히 떨어뜨린다. */
.oc-ad--app_content_bottom{margin-top:var(--oc-sp-8)}

/* ≥768px 에서 본문 하단 광고는 가로 배치가 읽기 좋다(제목/문구 | CTA). */
@media (min-width:768px){
  .oc-ad--app_content_bottom .oc-ad__body{
    flex-direction:row;align-items:center;gap:var(--oc-sp-4);
  }
  .oc-ad--app_content_bottom .oc-ad__copy{flex:1;min-width:0}
  .oc-ad--app_content_bottom .oc-ad__actions{margin-top:0;flex-shrink:0}
}

/* 사이드바는 항상 세로로(≤256px). 위 미디어쿼리와 충돌하지 않게 배치 변형별로만 준다. */
.oc-ad--app_sidebar .oc-ad__body{flex-direction:column}
