/* SalesBoost RMP — 기능 상세 페이지
   랜딩(solution/index.html)이 아니라 solution/features/* 만 쓴다.
   공통 크롬은 base.css, 목업은 mockups.css가 담당한다.

   **본문은 라이트, 마지막 CTA만 다크다**(2026-08-24 사용자).
   2026-08-21에는 면 전체를 다크로 가져갔었다 — 랜딩과 구성이 똑같아 보인다는 지적 때문에
   "다크 = 제품이 실제로 하는 일"이라는 축을 세웠던 것이다. 그런데 기능 상세의 주인공은
   결국 **플랫폼의 실제 화면 조각**이고, 실제 커머스 화면은 거의 전부 라이트다. 다크 면
   위에서는 그 조각들이 화면이 아니라 도식으로 읽혔고, 라이트 목업만 얹으니 이번엔 흰
   화면이 혼자 떠 보였다. 그래서 면을 목업 쪽에 맞춘다.
   랜딩과 구성이 같아 보이는 문제는 **구성**으로 푼다 — 상세는 카드 그리드가 아니라
   히어로 한 장(아키텍처 또는 포맷 갤러리) + 다크 챕터 어휘의 좌우 교차 챕터다.
   챕터 레이아웃(.chapter / .chapter-num / .is-flip)은 base.css가 랜딩과 공유하는데
   그쪽은 navy 전용 색을 들고 있으므로 색만 .fp 스코프에서 덮는다. */

/* --- 페이지 본문 전체가 하나의 라이트 면 ------------------------------- */
.fp {
    background: var(--white);
    color: var(--gray-900);
    /* 팔레트의 --gray-600은 --gray-500과 같은 값(#6B7684)이라 토큰을 한 단계 내려도
       소용이 없다. 그 색은 흰 바탕 4.62지만 회색 면(gray-50/100) 위에서 4.5에 못 미쳐
       (실측 4.42) 회색 면 위 보조 텍스트는 이 값으로 쓴다. */
}

/* base.css의 챕터 본문이 1.02rem=16.32px라 소수 픽셀이 된다 */
.fp .chapter-text > p { font-size: 16px; }

/* 히어로 면이 --gray-50으로 내려가면서 그 위 회색 텍스트가 4.5 아래로 떨어진다
   (--gray-500/600 = #6B7684 → 흰 바탕 4.62 / gray-50 위 4.42). 한 단계 어둡게. */
.fp-hero .crumb,
.fp-hero .crumb a { color: var(--gray-sub); }
.fp .fp-hero-copy p { color: #556070; }

/* 화이트 톤에서 목업 보조 텍스트가 9~12px로 아주 작게 쓰인다. --m-sub(#6B7684)는
   흰 바탕 4.62지만 카드 채움(--gray-50) 위 4.42, 블루 틴트 위 4.09로 4.5에 못 미친다(실측).
   팔레트의 --gray-600은 --gray-500과 같은 값이라 토큰을 한 단계 내려도 소용없어 값을 직접 준다.
   랜딩 목업도 같은 수치지만 그쪽은 건드리지 않았다 — 바꿀 때 함께 볼 것. */

/* base.css의 .chapter*는 랜딩 #how(navy) 기준이라 색을 여기서 되돌린다.
   레이아웃은 그대로 공유하므로 색만 건드릴 것 — 그리드·간격을 여기서 다시 잡으면
   랜딩과 상세가 조용히 갈라진다 */
.fp .chapter { border-top-color: var(--gray-200); }
.fp .chapter-num { border-color: var(--gray-300); color: var(--gray-500); }
.fp .chapter-text h3 { color: var(--gray-900); }
.fp .chapter-text h3 .accent { color: var(--blue-1); }
.fp .chapter-text > p { color: var(--gray-600); }

/* --- 히어로 — 아래 챕터로 그대로 이어지므로 바닥을 닫지 않는다 ---------- */
.fp-hero {
    padding: calc(72px + 3.4rem) 0 3.5rem;
    text-align: center;
    /* 면이 가장 어둡고 안으로 갈수록 밝다 — [면 gray-100] > [트레이 gray-50] > [카드 white].
       종전엔 면이 gray-50, 트레이가 gray-100이라 **컨테이너가 배경보다 진해** 위계가
       거꾸로였다(2026-08-24 사용자). 그라데이션은 얹지 않는다 — 옅은 블루 틴트는
       회색 면 위에서 얼룩으로 보인다 */
    background: var(--gray-100);
    border-bottom: 1px solid var(--gray-200);
}

/* 카피는 좁게, 아키텍처는 컨테이너 폭 전체를 쓴다 */
.fp-hero-copy { max-width: 800px; margin: 0 auto; }

.crumb {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 1.6rem;
    font-size: 14px;
    color: var(--gray-500);
}

.crumb a { color: var(--gray-500); text-decoration: none; transition: color var(--dur-fast) var(--ease-out); }
.crumb a:hover { color: var(--blue-1); }
.crumb span[aria-current] { color: var(--gray-700); font-weight: 600; }

.fp-hero h1 {
    font-size: clamp(32px, 4.2vw, 46px);
    font-weight: 800;
    line-height: 1.3;
    letter-spacing: -0.03em;
    color: var(--gray-900);
    margin-bottom: 1.3rem;
}

.fp-hero h1 .accent { color: var(--blue-1); }

/* 히어로에 버튼을 두지 않는다 — 기능을 설명하는 페이지인데 첫 화면부터
   파트너십 문의가 나오면 어색하다(2026-08-21 사용자). 전환은 마지막 CTA가 맡는다.
   `.fp-hero p`가 아니라 `.fp-hero-copy p`인 이유 — 아래 아키텍처 안의 .mock-note도
   <p>라서, 요소 셀렉터로 두면 특이도에서 밀려 각주가 본문 크기로 커진다. */
.fp-hero-copy p {
    max-width: 620px;
    margin: 0 auto;
    font-size: 17px;
    line-height: 1.75;
    color: var(--gray-600);
}

/* --- 하이라이트 아키텍처 (히어로) --------------------------------------
   기능 상세는 "이 기능이 어떻게 만들어져 있는지"를 첫 화면에서 보여준다(2026-08-21 사용자).
   네 페이지가 같은 골격을 재사용하도록 이름을 기능 중립으로 뒀다:
   [입력 신호] → [엔진] → [결과], 그리고 결과가 다시 신호로 도는 피드백.
   .mock.mock-dark를 같이 걸어 --m-* 토큰 위에서 그리므로 라이트 면에도 그대로 올라간다.
   열 사이 화살표는 gap 위에 얹히니 gap과 화살표 길이가 같은 변수를 봐야 어긋나지 않는다. */
.arch {
    --arch-gap: clamp(1.6rem, 3.2vw, 2.9rem);
    --arch-pad: 0.75rem;   /* 입력 묶음 안쪽 여백 — 엔진 .eng-block과 같은 값 */
    --arch-inset: 7px;     /* 화살표 양끝 들여쓰기 — 선이 상자에 딱 붙으면 테두리와 붙어 보인다 */
    /* 면 3단 — [히어로 면 gray-100] > [큰 컨테이너 gray-50] > [안쪽 카드 white].
       바깥이 가장 어둡고 안으로 갈수록 밝다 — 글자가 앉는 카드가 언제나 가장 밝다.
       종전에는 큰 컨테이너가 --m-surface(흰색)이고 안쪽 카드가 회색이라 위계가 뒤집혀
       있었고, 그걸 고치면서는 트레이(gray-100)가 면(gray-50)보다 진해져 이번엔
       배경보다 컨테이너가 어두웠다(2026-08-24 사용자). 두 번 다 단조롭지 않았던 게 원인이다. */
    --arch-tray: var(--gray-50);
    --arch-card: var(--white);
    --arch-bg: var(--gray-100);   /* 피드백 라벨이 선을 끊고 앉을 때 쓰는 바탕색 = 히어로 면 */
    /* 피드백 선은 --m-border로는 너무 옅어 사실상 안 보인다 — 흐름의 일부지 배경 장식이 아니다.
       **--blue-glow(#7FB2FF)는 base.css에 "다크 배경 위 하이라이트"로 정의된 색이라
       흰 면에서는 씻겨 나간다.** 라이트 톤에서는 --blue-1 계열 알파를 쓴다. */
    --arch-loop: rgba(5, 82, 204, 0.32);
    /* 루프 세로선은 **바깥 두 열의 중심**에서 오르내린다(2026-08-24 사용자).
       모서리에 두면 컨테이너의 둥근 모서리가 그 지점에서 이미 휘어 올라가 있어
       화살촉이 허공에 뜨고, 무엇에서 나온 선인지도 덜 분명하다.
       `.arch-feedback`은 열 전체(1/-1)를 차지하므로 **바깥 열 폭의 절반**만큼
       좌우를 들여야 가로선 양끝이 그 중심에 선다 — 아래 0.85/1.75/0.85 와 짝이다. */
    --arch-side-half: calc((100% - var(--arch-gap) * 2) * 0.85 / 3.45 / 2);
    /* 선이 컨테이너 바닥에 딱 붙으면 답답하다 — 살짝 띄운다 */
    --arch-loop-margin: 9px;
    display: grid;
    /* 엔진이 이 그림의 주인공이라 가운데를 넓게 준다 — 안에 컴포넌트가 3층으로 들어간다 */
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.75fr) minmax(0, 0.85fr);
    /* 행 간격까지 gap을 먹이면 피드백 선이 본체에서 한참 떨어져 따로 논다 */
    column-gap: var(--arch-gap);
    row-gap: 0;
    /* 열마다 [라벨 + 본체]를 한 덩어리로 세로 중앙에 둔다. 라벨을 열 맨 위에 절대배치해
       세 열의 머리말을 한 줄로 맞춰 봤더니, 엔진이 두 배 넘게 높아 라벨이 제 컨테이너에서
       한참 떨어져 무엇의 이름인지 멀어졌다(2026-08-24 사용자). 정렬보다 근접이 우선이다. */
    align-items: stretch;
    margin-top: 2.6rem;
    text-align: left;
}

.arch-col {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-width: 0;
}

/* 데이터 열만 grid다 — [위 여백][라벨][묶음][riser] 네 행으로 두면 라벨+묶음이 가운데 오면서
   남는 아래 공간을 riser가 통째로 차지한다. flex + justify-content:center로는 남는 공간이
   위아래로 갈려서 riser가 높이 0이 되고, 루프 화살표가 묶음에 닿지 못한다. */
.arch-in {
    display: grid;
    /* 열을 명시해야 한다 — .arch-col이 물려주는 justify-content:center가 grid에서는
       **트랙 정렬**로 작동해서, 암시적 열이 내용 폭으로 좁아진 뒤 가운데로 밀린다
       (1440에서 묶음이 10.3px 안쪽으로 들어가 riser가 피드백 상자 테두리와 어긋났다). */
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 1fr auto auto 1fr;
}

/* 광고 열도 같은 4행이다 — [위 여백][라벨][노드][riser]. 이 열에 riser가 없으면
   피드백 점선의 오른쪽 끝이 광고 컨테이너에 닿지 못하고 허공에서 시작한다. */
.arch-out {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 1fr auto auto 1fr;
}

.arch-in > .arch-col-label,
.arch-out > .arch-col-label { grid-row: 2; }
.arch-in > .arch-group,
.arch-out > .arch-node { grid-row: 3; }
.arch-in > .arch-riser,
.arch-out > .arch-riser { grid-row: 4; }

.arch-riser { position: relative; min-height: 0; }

/* 세로 선은 묶음 아래에서 시작해 피드백 상자 왼쪽 테두리와 만난다.
   .arch-feedback은 grid-column 1/-1이라 왼쪽 모서리 x가 이 열의 left:0과 같다.
   margin-top(0.6rem)만큼 더 내려야 선이 끊기지 않는다. */
.arch-riser::before {
    content: '';
    position: absolute;
    left: 50%;
    top: var(--arch-loop-margin);
    bottom: -0.6rem;
    border-left: 1px dashed var(--arch-loop);
}

/* 화살촉은 riser 위쪽 — 결과가 데이터로 되돌아간다는 방향을 여기서 보여준다 */
.arch-riser::after {
    content: '';
    position: absolute;
    left: calc(50% - 3.5px);
    top: var(--arch-loop-margin);
    border: 4px solid transparent;
    border-top: 0;
    border-bottom-color: var(--m-accent);
}

/* 오른쪽은 border-right 여야 한다 — border-left 로 두면 선이 중심보다 1px 오른쪽에
   그려져 피드백 상자의 오른쪽 테두리와 어긋난다 */
.arch-riser-out::before { left: auto; right: 50%; border-left: 0; border-right: 1px dashed var(--arch-loop); }
.arch-riser-out::after { content: none; }

.arch-col-label {
    display: block;
    /* 컨테이너 이름표라 바짝 붙어야 무엇의 이름인지 바로 읽힌다 */
    margin-bottom: 0.35rem;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: var(--m-sub);
}

.arch-node {
    position: relative;
    padding: 0.95rem 1.1rem;
    border: 1px solid var(--m-border);
    border-radius: 12px;
    background: var(--arch-card);
}

/* 입력 노드는 [제목 줄] + [그 신호를 실제로 보여주는 작은 목업]이다.
   아이콘 타일 + 한 줄 설명으로 뒀더니 여전히 글이라, 신호마다 생김새를 달리 줬다
   (2026-08-21 사용자: 행동은 아이콘 시퀀스 · 문맥은 검색창/카테고리 · 경쟁은 숫자). */
.arch-in .arch-node > b {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 0.7rem;
    font-size: 13px;
}

.arch-in .arch-node > b svg {
    width: 15px;
    height: 15px;
    flex: none;
    color: var(--m-accent);
}

/* 제목 줄 오른쪽 끝에 붙는 기간·단위 같은 보조 값 */
.arch-in .arch-node > b em {
    margin-left: auto;
    font-style: normal;
    font-size: 11px;
    /* 페이지의 보조 글자는 600 이다 — 여기만 500 이라 두 곳이 유독 얇았다(2026-08-25) */
    font-weight: 600;
    color: var(--m-sub);
}

/* 아이콘 타일 — 사이트 공통 라인 아이콘(24 viewBox / stroke 2)을 담는 그릇 */
.arch-ico {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    flex: none;
    border: 1px solid var(--m-border);
    border-radius: 9px;
    background: var(--m-surface-2);
    color: var(--m-accent);
}

.arch-ico svg { width: 17px; height: 17px; }

/* --- 신호 ① 행동 이력 — 조회 → 찜 → 구매 시퀀스 --- */
.act { display: flex; align-items: flex-start; }

.act-step {
    position: relative;
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.35rem;
}

/* 앞 단계 중심에서 이번 단계 중심까지 — 원이 선을 덮어 사이에서만 보인다 */
.act-step + .act-step::before {
    content: '';
    position: absolute;
    left: -50%;
    right: 50%;
    top: 14px;
    height: 1px;
    background: var(--m-border);
}

.act-ico {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border: 1px solid var(--m-border);
    border-radius: 50%;
    background: var(--m-surface-2);
    color: var(--m-sub);
}

.act-ico svg { width: 15px; height: 15px; }

.act-step i { font-style: normal; font-size: 10px; color: var(--m-sub); }

/* 가장 최근 행동만 켠다 — 시퀀스의 끝이 어디인지가 곧 "지금" 이다 */
.act-step.is-last .act-ico { border-color: var(--m-accent); background: var(--m-accent-soft); color: var(--m-accent); }
.act-step.is-last i { color: var(--m-accent); font-weight: 600; }

/* --- 신호 ② 현재 문맥 — 검색창 + 카테고리 목업 --- */
.arch-node .mock-search { margin: 0; font-size: 12px; }
.arch-node .mock-search svg { width: 14px; height: 14px; }

/* --- 신호 ③ 경쟁 상황 — 이름:값 두 줄 --- */
.kv {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.34rem 0;
    font-size: 12px;
    color: var(--m-sub);
}

.kv + .kv { border-top: 1px solid var(--m-border); }

.kv b {
    font-family: var(--font-number);
    font-size: 13px;
    font-weight: 700;
    color: var(--m-text);
}

.arch-node + .arch-node { margin-top: 0.7rem; }

/* 노출 이력 — 남은 자리를 점으로 센다. 경쟁 상황이 이미 숫자 두 줄(.kv)이라
   같은 생김새를 또 쓰면 두 노드가 한 덩어리로 보인다. */
.cap { display: flex; align-items: center; gap: 0.55rem; }

.cap-pips { display: inline-flex; gap: 0.28rem; flex: none; }

.cap-pips i {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    border: 1px solid var(--m-border);
}

.cap-pips i.is-on { border-color: var(--m-accent); background: var(--m-accent); }

.cap-label { font-size: 12px; color: var(--m-sub); }

/* `> b` / `> i`여야 한다 — 노드 안 목업(.kv b, .act-step i)까지 잡으면 뒤에 온다는 이유로
   그쪽 글자 크기를 덮어쓴다(특이도가 같다) */
.arch-node > b { display: block; font-size: 14px; font-weight: 700; color: var(--m-text); }

.arch-out .arch-node > i {
    display: block;
    margin-top: 0.25rem;
    font-style: normal;
    font-size: 12px;
    line-height: 1.5;
    color: var(--m-sub);
}

/* 입력 신호 묶음. 엔진 안의 .eng-block과 같은 어휘다 — 컨테이너가 "이 셋이 한 덩어리"라고 말한다.
   신호마다 화살표를 따로 그렸더니 그 셋이 엔진 3층(모델·로직·점수) 높이와 맞아떨어져
   **신호 하나가 층 하나로 들어가는 것처럼** 읽혔다(2026-08-21 사용자). 실제로는 세 신호가
   함께 한 요청을 이루고 세 층 전부가 그걸 같이 본다. 그래서 화살표는 묶음 중심에서 하나만 낸다. */
.arch-group {
    position: relative;
    padding: var(--arch-pad);
    border: 1px solid var(--m-border);
    border-radius: 14px;
    background: var(--arch-tray);
    box-shadow: 0 1px 2px rgba(16, 22, 35, 0.03);
}

/* 입력 묶음 → 엔진, 엔진 → 결과. 선은 gap을 가로지르고 화살촉은 그 끝에 선다 */
.arch-group::before,
.arch-group::after,
.arch-out .arch-node::before,
.arch-out .arch-node::after {
    content: '';
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
}

.arch-group::before {
    left: calc(100% + var(--arch-inset));
    width: calc(var(--arch-gap) - var(--arch-inset) * 2);
    height: 1px;
    background: var(--m-accent);
}

.arch-group::after {
    left: calc(100% + var(--arch-gap) - var(--arch-inset) - 4px);
    border: 4px solid transparent;
    border-right: 0;
    border-left-color: var(--m-accent);
}

/* 엔진 → 결과 */
.arch-out .arch-node::before {
    right: calc(100% + var(--arch-inset));
    width: calc(var(--arch-gap) - var(--arch-inset) * 2);
    height: 1px;
    background: var(--m-accent);
}

.arch-out .arch-node::after {
    right: calc(100% + var(--arch-inset));
    border: 4px solid transparent;
    border-right: 0;
    border-left-color: var(--m-accent);
}

.arch-out .arch-node {
    border-color: var(--m-accent);
    /* 결과 카드는 액센트 틴트지만 **면보다 어두워지면 안 된다** — --blue-tint 원색은
       L=0.88로 히어로 면(L=0.90)보다 낮아 혼자 움푹 들어가 보인다. 흰색과 섞어
       면과 카드 사이(L=0.93)에 앉힌다. `.arch`는 라이트 전용(.mock-dark를 걸지 않는다)이라
       흰색과의 혼합이 안전하다. */
    background: color-mix(in srgb, var(--m-accent-soft) 55%, var(--arch-card));
    box-shadow: 0 1px 2px rgba(16, 22, 35, 0.04), 0 6px 16px rgba(5, 82, 204, 0.10);
}

/* --- 엔진 --- */
.arch-core {
    position: relative;
    padding: 1rem 1.15rem 1.1rem;
    border: 1px solid rgba(5, 82, 204, 0.32);
    box-shadow: 0 1px 2px rgba(16, 22, 35, 0.03), 0 10px 28px rgba(5, 82, 204, 0.08);
    border-radius: 16px;
    /* 컨테이너 안쪽 그라데이션은 쓰지 않는다(2026-08-24 사용자) — 면은 평평하게 두고
       주목도는 테두리·그림자·제목 색으로 만든다 */
    background: var(--arch-tray);
}

/* 엔진 내부 — 순서대로 걸러지는 파이프라인이 아니라 **컴포넌트 구성**이다
   (2026-08-21 사용자: "로직 기반보다 컴포넌트 기반으로"). 위에서 아래로 3층:
   [분석 모델 3종] → [그 모델들을 조합한 로직 중 하나 선택] → [상품별 점수].
   세 층을 관통하는 건 하나의 샘플 요청이다 — 어떤 로직이 골라졌고 그 로직이 상품마다
   몇 점을 매겼는지가 이어져야 "이해가 쉬운 예시"가 된다. **1층은 이름만 센다** —
   모델마다 뽑아낸 값을 달았더니 예시가 세 층에 다 깔려 오히려 흐려졌다(2026-08-24 사용자). */
.eng {
    /* 층 사이 화살표가 모델 카드 열 중심에 서려면 블록 안쪽 여백과 같은 값을 봐야 한다 */
    --eng-pad: 0.75rem;
    margin-top: 0.2rem;
}

/* --- 1층: 분석 모델 --- */
.eng-models {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.5rem;
}

.eng-model {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.45rem;
    min-width: 0;
    padding: 0.9rem 0.5rem;
    border: 1px solid var(--m-border);
    border-radius: 11px;
    background: var(--arch-card);
    text-align: center;
}

.eng-model-body { min-width: 0; }
.eng-model b { display: block; font-size: 12px; font-weight: 700; color: var(--m-text); }

/* --- 층 사이 화살표. 열 수만큼 놓아 어느 컴포넌트가 흘러드는지 보이게 한다.
       모델 카드가 블록 안으로 들어갔으므로 열 정의(여백·gap)를 그대로 따라가야 중심이 맞는다 --- */
.eng-join {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.5rem;
    /* 화살표가 위아래 상자에 딱 붙으면 답답하다(2026-08-24 사용자) — 구간을 늘리고
       선 자체는 위아래로 들여 그려 양쪽에 숨 쉴 틈을 준다 */
    height: 26px;
    padding: 0 calc(var(--eng-pad) + 1px);
}

.eng-join.is-one { grid-template-columns: minmax(0, 1fr); }
.eng-join > span { position: relative; }

.eng-join > span::before {
    content: '';
    position: absolute;
    left: 50%;
    top: 7px;
    bottom: 10px;
    /* 엔진 안 흐름도 경로다 — 회색 테두리색이면 칸 나누는 선처럼 보인다 */
    border-left: 1px solid rgba(5, 82, 204, 0.45);
}

.eng-join > span::after {
    content: '';
    position: absolute;
    left: 50%;
    bottom: 7px;
    transform: translateX(-50%);
    border: 4px solid transparent;
    border-bottom: 0;
    border-top-color: rgba(5, 82, 204, 0.45);
}

/* --- 2·3층 블록 --- */
.eng-block {
    padding: 0.6rem var(--eng-pad) 0.65rem;
    border: 1px solid var(--m-border);
    border-radius: 11px;
    background: var(--arch-card);
}

/* 주인공은 테두리만 액센트로 — 면을 칠하면 안쪽 행들의 대비가 깎인다 */
/* 층을 따로 강조하지 않는다(2026-08-24 사용자) — 세 층은 같은 껍데기로 나란히 두고,
   무엇이 골라졌는지는 행 단위(.lg.is-on)가 이미 말한다 */

.eng-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 0.45rem;
}

.eng-head b { font-size: 12px; font-weight: 700; color: var(--m-text); }
.eng-block.is-key .eng-head b { color: var(--m-accent); }
.eng-head em { font-style: normal; font-size: 10px; color: var(--m-sub); white-space: nowrap; }

/* --- 2층: 로직 목록 — 이름만이 아니라 **어떤 모델을 쓰는 로직인지**까지 보여준다 --- */
.lg {
    display: grid;
    grid-template-columns: 11px minmax(0, 1fr) auto;
    align-items: center;
    gap: 0.55rem;
    padding: 0.3rem 0;
}

.lg + .lg { border-top: 1px solid var(--m-border); }

.lg-dot {
    width: 11px;
    height: 11px;
    border-radius: 50%;
    border: 1px solid var(--m-border);
}

.lg.is-on .lg-dot {
    border-color: var(--m-accent);
    background: var(--m-accent);
    box-shadow: inset 0 0 0 2px var(--m-surface);
}

.lg > b { font-size: 11px; font-weight: 600; color: var(--m-sub); }
.lg.is-on > b { color: var(--m-accent); font-weight: 700; }

.lg-src { display: flex; gap: 0.22rem; }

.lg-src span {
    padding: 0.1rem 0.36rem;
    border: 1px solid var(--m-border);
    border-radius: var(--radius-pill);
    background: var(--m-surface-2);
    font-size: 10px;
    font-weight: 600;
    color: var(--m-sub);
    white-space: nowrap;
}

.lg.is-on .lg-src span { border-color: var(--m-accent); color: var(--m-accent); }

/* --- 3층: 상품별 점수 — 숫자만 두면 크기 비교가 안 돼 막대를 같이 둔다 --- */
/* 세 줄이 **한 그리드의 열**을 같이 쓴다. 줄마다 별개 그리드로 두면 상품명 열이
   이름 길이만큼 제각각 넓어져 막대 시작점이 줄마다 어긋난다(2026-08-24 사용자).
   상품명 열을 고정 fr 로 박으면 정렬은 맞지만 짧은 이름 뒤에 빈 칸이 크게 남고
   긴 EN 이름은 잘린다 — max-content 는 세 이름 중 가장 긴 것에 딱 맞춘다. */
.eng-block.is-scores {
    display: grid;
    grid-template-columns: 26px minmax(0, max-content) minmax(70px, 1fr) auto;
    column-gap: 0.55rem;
}

.eng-block.is-scores > .eng-head { grid-column: 1 / -1; }

.sc {
    display: grid;
    grid-column: 1 / -1;
    grid-template-columns: subgrid;
    align-items: center;
    gap: 0.55rem;
    padding: 0.32rem 0;
}

.sc + .sc { border-top: 1px solid var(--m-border); }

.sc img { width: 26px; height: 26px; border-radius: 6px; object-fit: cover; }

.sc-name {
    min-width: 0;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
    font-size: 11px;
    color: var(--m-sub);
}

.sc-bar {
    height: 6px;
    border-radius: var(--radius-pill);
    background: var(--m-track);
    overflow: hidden;
}

.sc-bar i { display: block; height: 100%; background: rgba(5, 82, 204, 0.32); }

.sc-val {
    font-family: var(--font-number);
    font-size: 11px;
    font-weight: 700;
    /* 비례 숫자면 0.87/0.75/0.66 폭이 미세하게 달라 fr 열이 0.4px씩 어긋난다 */
    font-variant-numeric: tabular-nums;
    color: var(--m-sub);
}

/* 1위만 켠다 — 오른쪽 열에 실제로 나가는 그 광고다 */
.sc.is-win .sc-name { color: var(--m-text); font-weight: 600; }
.sc.is-win .sc-bar i { background: var(--m-accent); }
.sc.is-win .sc-val { color: var(--m-accent); }

/* 로직 후보 — 이 요청에 실제로 쓰인 하나만 켜진다 */
.arch-models {
    display: flex;
    flex-wrap: wrap;
    gap: 0.28rem;
    margin-top: 0.5rem;
}

.arch-model {
    display: inline-flex;
    align-items: center;
    gap: 0.24rem;
    padding: 0.22rem 0.55rem;
    border: 1px solid var(--m-border);
    border-radius: var(--radius-pill);
    background: var(--m-surface-2);
    font-size: 11px;
    font-weight: 600;
    color: var(--m-sub);
    white-space: nowrap;
}

.arch-model.is-on {
    border-color: var(--m-accent);
    background: var(--m-accent-soft);
    color: var(--m-accent);
}

.arch-model.is-on::before { content: '✓'; font-size: 10px; }

/* 히어로 자리라 목업 기본 치수보다 한 단계 키운다 — 첫 화면에서 읽혀야 한다 */
.arch-core .mock-panel-title { font-size: 15px; color: var(--m-accent); }
.arch-core .mock-latency { font-size: 11px; padding: 3px 10px; }
.arch-core .mock-note { font-size: 12px; }
.arch-core .mock-note svg { width: 14px; height: 14px; }

/* --- 결과 지면 ---
   상품명을 줄줄이 적으면 좁은 열에서 잘린다(EN `Noise-cancelling headphones`가 1024부터
   말줄임). 이름을 빼고 **진열 그대로** 썸네일 3칸으로 두면 잘릴 것도 없고 챕터 ①의
   캐러셀과 같은 그림이 된다 — 첫 칸만 광고다. */
.arch-shelf {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    gap: 0.45rem;
    margin-top: 0.8rem;
}

.arch-shelf-item {
    position: relative;
    aspect-ratio: 1;
    border: 1px solid var(--m-border);
    border-radius: 9px;
    overflow: hidden;
    background: var(--arch-card);
}

.arch-shelf-item img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* 광고 칸만 액센트 — 테두리 1px로는 다크에서 약해 안쪽 라인을 한 겹 더 얹는다 */
.arch-shelf-item.is-ad {
    border-color: var(--m-accent);
    box-shadow: inset 0 0 0 1px var(--m-accent);
}

.arch-shelf-badge {
    position: absolute;
    left: 5px;
    top: 5px;
    padding: 1px 5px;
    border-radius: 4px;
    background: var(--m-accent);
    font-family: var(--font-number);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.02em;
    color: var(--m-surface);
}

/* --- 피드백 루프 — 결과가 다시 왼쪽 신호로 돌아온다 --- */
.arch-feedback {
    grid-column: 1 / -1;
    position: relative;
    height: 2.4rem;
    margin: 0.6rem var(--arch-side-half) 0;
    border: 1px dashed var(--arch-loop);
    border-top: 0;
    border-radius: 0 0 14px 14px;
}

/* `> span`이어야 한다 — 안쪽 라벨 span까지 잡으면 그것도 absolute가 되어
   아이콘만 선 위에 남고 글자가 아래로 떨어진다(실제로 그렇게 렌더됐다) */
.arch-feedback > span {
    position: absolute;
    left: 50%;
    top: 100%;
    transform: translate(-50%, -50%);
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0 0.75rem;
    background: var(--arch-bg);
    font-size: 11px;
    color: var(--gray-sub);
    white-space: nowrap;
}

.arch-feedback svg {
    width: 13px;
    height: 13px;
    flex: none;
    color: var(--m-accent);
}

/* 1열로 접혔을 때만 나오는 세로 흐름 표시 */
.arch-flow { display: none; }

/* 좁아지면 분석 모델 3장을 나란히 못 놓는다 — 세로로 눕히고(아이콘 왼쪽) 층 사이
   화살표도 하나만 남긴다. 화살표 세 개는 열이 셋일 때만 뜻이 있다. */
@media (max-width: 620px) {
    .eng-models { grid-template-columns: minmax(0, 1fr); gap: 0.4rem; }

    .eng-model {
        flex-direction: row;
        align-items: center;
        gap: 0.7rem;
        padding: 0.6rem 0.7rem;
        text-align: left;
    }

    .eng-join { grid-template-columns: minmax(0, 1fr); }
    .eng-join > span + span { display: none; }

    /* 좁으면 이름을 먼저 줄인다 — 막대는 짧아지면 길이 비교가 안 된다 */
    .eng-block.is-scores { grid-template-columns: 24px minmax(0, 1fr) 56px auto; column-gap: 0.45rem; }
    .sc { gap: 0.45rem; }
}


/* --- 챕터 ------------------------------------------------------------- */
.fp-chapters { padding-bottom: var(--space-2xl); }

/* 두 고객의 진열을 나란히 놓는다 — 위아래로 쌓으면 챕터 하나가 다른 챕터의
   두 배 높이가 되어 리듬이 깨진다 */
.compare {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
    width: 100%;
}

.compare > * { min-width: 0; }

.compare-label {
    display: block;
    margin-bottom: 0.7rem;
    font-size: 12px;
    font-weight: 700;
    color: var(--blue-1);
    text-align: center;
}

/* --- FAQ — 같은 다크지만 한 톤 올려 챕터와 갈라 준다 -------------------- */
/* 마지막 챕터가 아래 테두리를 갖지 않으므로 FAQ가 갈라 주는 선을 들고 온다 */
.fp-faq {
    background: var(--white);
    border-top: 1px solid var(--gray-200);
    padding: var(--space-2xl) 0;
}

.fp-faq h2 {
    max-width: 760px;
    margin: 0 auto 2.5rem;
    text-align: center;
    font-size: clamp(1.5rem, 2.6vw, 2rem);
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--gray-900);
}

.fp-faq-list { max-width: 760px; margin: 0 auto; }

.fp-faq details { border-top: 1px solid var(--gray-200); }
.fp-faq details:last-child { border-bottom: 1px solid var(--gray-200); }

.fp-faq summary {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 1rem;
    padding: 1.4rem 0.25rem;
    /* base.css `.faq-item summary` 와 같은 이유로 16px — 17px 이면 390px 에서 질문이 한 줄 늘어난다 */
    font-size: 16px;
    font-weight: 600;
    color: var(--gray-900);
    cursor: pointer;
    list-style: none;
}

.fp-faq summary::-webkit-details-marker { display: none; }

/* 마커 타이포는 base.css `.faq-item summary::after` 와 같은 값이다 */
.fp-faq summary::after {
    content: '+';
    flex: none;
    font-family: var(--font-number);
    font-size: 20px;
    font-weight: 400;
    color: var(--gray-500);
}

.fp-faq details[open] summary::after { content: '−'; }

.fp-faq p {
    padding: 0 0.25rem 1.4rem;
    font-size: 15px;
    line-height: 1.75;
    color: var(--gray-600);
}

/* --- 반응형 ---------------------------------------------------------- */
/* 3열을 유지할 수 있는 하한이 대략 900px다. 그 아래는 위→아래 흐름으로 접고
   가로 화살표를 끄지 않으면 노드 오른쪽에 잘린 선이 남는다 */
@media (max-width: 900px) {
    .arch {
        grid-template-columns: minmax(0, 1fr);
        column-gap: 0;
        max-width: 460px;
        margin-inline: auto;
    }


    .arch-group::before,
    .arch-group::after,
    .arch-out .arch-node::before,
    .arch-out .arch-node::after { display: none; }

    /* 1열에서는 열 높이가 곧 본문 높이라 riser가 설 자리가 없다 */
    .arch-in,
    .arch-out { display: flex; }
    .arch-riser { display: none; }

    .arch-flow {
        display: block;
        width: 0;
        height: 0;
        margin: 0.9rem auto;
        border: 5px solid transparent;
        border-bottom: 0;
        border-top-color: var(--m-accent);
    }

    /* U자 선은 3열일 때만 뜻이 통한다 — 접히면 한 줄 메모로 바꾼다 */
    .arch-feedback {
        height: auto;
        margin: 1.25rem 0 0;
        padding: 0.65rem 0.9rem;
        border: 1px dashed var(--arch-loop);
        border-radius: 12px;
        text-align: center;
    }

    .arch-feedback::before { display: none; }

    /* display를 block으로 되돌리면 아이콘과 글자 사이 gap이 사라져 붙어 버린다 */
    .arch-feedback > span {
        position: static;
        transform: none;
        display: flex;
        justify-content: center;
        padding: 0;
        background: none;
        white-space: normal;
    }
}

@media (max-width: 700px) {
    /* 폭을 반으로 접으면 상품 카드가 뭉개져 "다른 상품이 놓인다"가 안 읽힌다 */
    .compare { grid-template-columns: 1fr; gap: 1.75rem; }
}

/* ============================================================
   지면 목업 — 화면 세 장 + 협력 지면 (`ad-formats` 히어로 안)

   갤러리 → 스크롤 캐러셀 → 스크롤 카메라 → 자동 재생 → 정지 화면 → 자리 표시 제거 →
   구역 라벨·화살표 제거 → 화면 분리 + 툴팁 → **툴팁 제거 + 3열 균등**까지 열 번 고쳐 여기까지 왔다.
   기준은 셋이다 — **목업은 도해가 아니라 UI 스크린샷으로 읽혀야 하고**, **지면은 실제로 사는
   페이지끼리 갈라 두고**, **세 지면은 같은 비중으로 나란히 선다**(전부 2026-08-24 사용자).

   목업 위에 얹는 것이 하나도 없다 — 링·번호·구역 라벨·경계 화살표·범례·툴팁 전부 걷어냈다.
   광고 표시는 플랫폼이 실제로 쓰는 `AD` 라벨뿐이고, 어떤 지면을 주는지는 카피와 챕터가 말한다.

   JS가 없다. 이 페이지에서 움직이는 것은 하나도 없다 — 손대는 사람이 다시 붙이지 말 것.
   ============================================================ */

/* 히어로 면(--gray-100) 위에 목업이 그대로 얹힌다.
   히어로가 가운데 정렬이라 목업은 왼쪽 정렬로 되돌려 준다 */
/* 히어로가 가운데 정렬이라 목업만 왼쪽 정렬로 되돌린다.
   `AD 표시가 붙은 자리가…` 안내 줄은 걷어냈다(2026-08-24 사용자) — 지면 캡션과 `AD` 라벨이
   같은 말을 이미 하고 있어 카피와 목업 사이에 한 줄이 더 끼는 값만 했다 */
.fmt-stage { text-align: left; }

/* --- 플랫폼 지면 셋을 같은 폭으로, 협력 지면은 아래 줄에 --- */
/* 세 화면은 높이도 같아야 나란히 선 것으로 읽힌다(2026-08-24 사용자).
   내용 길이는 화면마다 다르므로 행을 늘리고(stretch) 화면이 그 높이를 채우게 한다 —
   남는 자리는 각 화면의 마지막 블록 아래로 간다 */
/* 네 지면은 폭이 모자라도 접히거나 줄지 않는다 — **가로 캐러셀로 넘어간다**
   (2026-08-24 사용자: "넘어가면 말줄임이 아니라 캐러셀로 전환하게 해줘").
   카드 폭을 366px 로 고정해 두면 어느 화면에서도 목업 안이 깨지지 않고,
   대신 담을 수 없는 만큼이 스크롤이 된다. JS 는 없다 — 스냅도 스크롤바도 CSS 다 */
.fmt-stage {
    display: flex;
    align-items: stretch;
    gap: 1.2rem;
    margin-top: 3rem;
    /* 컨테이너(1136px)로는 넉 장이 못 들어간다 — 스테이지만 밖으로 넓힌다.
       `100vw` 는 스크롤바를 포함하므로 5rem 여유를 뒀다 */
    /* 상한은 계산값이다 — 카드 4장(366×4) + 간격 3칸(1.2rem) + 좌우 패딩(1rem×2) */
    width: min(1554px, 100vw - 5rem);
    margin-left: 50%;
    transform: translateX(-50%);
    /* `overflow-x: auto` 는 `overflow-y` 까지 `auto` 로 만들어 **네 면을 다 자른다**.
       카드 그림자가 번질 자리(좌우 16px·아래 20px)를 패딩으로 확보하지 않으면
       그림자가 컨테이너 가장자리에서 세로로 뚝 끊긴다(2026-08-25 사용자) */
    padding: 0.75rem 1rem 1rem;
    /* 스냅도 그 패딩을 기준으로 — 안 그러면 첫 카드가 쉬는 자리와 스냅 자리가 어긋난다 */
    scroll-padding-inline: 1rem;
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x proximity;
    scrollbar-width: thin;
    scrollbar-color: var(--gray-300) transparent;
}

/* 스크롤바가 곧 "더 있다"는 표시다 — macOS 오버레이 스크롤바는 멈추면 사라지므로 직접 그린다 */
.fmt-stage::-webkit-scrollbar { height: 6px; }
.fmt-stage::-webkit-scrollbar-track { background: transparent; }

.fmt-stage::-webkit-scrollbar-thumb {
    border-radius: var(--radius-pill);
    background: var(--gray-300);
}

.fmt-zone {
    position: relative;
    flex: 0 0 366px;
    scroll-snap-align: start;
    padding: 0.7rem 0.7rem 0.8rem;
    border-radius: 20px;
}

/* 늘어난 행 높이를 화면까지 흘려 보낸다 — 협력 지면(is-out)은 fit-content 라 제외한다 */
.fmt-zone { display: flex; flex-direction: column; }

/* 지면 이름은 프레임 **밖**에 둔다. 목업 위에 얹으면 스크린샷이 아니라 도해로 읽힌다는
   교훈(번호·범례·툴팁을 세 번 걷어냈다)은 화면 안에만 해당한다 */
.fmt-cap {
    display: flex;
    align-items: center;
    gap: 6px;
    margin: 0 0 9px 2px;
    font-size: 12px;
    color: var(--gray-500);
}

.fmt-cap b { font-weight: 700; color: var(--gray-700); }
.fmt-cap em { font-style: normal; }

/* 우리 지면이 아니라는 표시 — 라벨 대신 점선 상자 하나로만 갈라 둔다.
   히어로 면이 --gray-100 이므로 트레이는 한 단계 밝은 --gray-50 이다.
   세 화면과 나란히 세우면 비중이 같아져 버리므로 아래 줄에 내용만큼만 두고 가운데로 모은다 */
.fmt-zone.is-out { align-items: center; }

/* 점선은 "우리 지면이 아니다"라는 표시다. 캡션은 화면 셋과 마찬가지로 프레임 **밖**에 서야 하므로
   테두리를 존이 아니라 폰 묶음에 두른다 */
.fmt-offsite {
    display: flex;
    align-items: stretch;
    justify-content: center;
    gap: 9px;
    /* 카드가 늘어나도 점선 상자는 내용만큼만 — 위아래 auto 마진으로 가운데에 놓인다 */
    margin: auto 0;
    width: 100%;
    padding: 0.5rem;
    border: 1px dashed var(--gray-300);
    border-radius: 20px;
    background: var(--gray-50);
}

/* ============================================================
   화면 한 장 — 상태 표시줄(주소줄)과 `SHOP` 로고는 걷어냈다.
   둘 다 정보가 없는 줄이고, 셋으로 늘어난 화면마다 반복되면 그만큼 시선이 샌다(2026-08-24 사용자).
   ============================================================ */
.shot-screen {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--m-border);
    border-radius: 14px;
    background: var(--m-surface);
    /* 그림자는 사이트 카드 관례인 `--shadow-1` 이다. 세 판을 거쳐 여기까지 왔다(2026-08-25 사용자:
       `--shadow-3` "너무 길다" → 두 겹 "끊겨 보인다" → "그림자 자체가 너무 크다").
       **이 카드는 1px 테두리가 이미 가장자리를 만든다** — 그림자가 형태를 맡을 필요가 없다.
       실측: `--shadow-1,2` 두 겹은 카드 밑이 배경보다 21/255 어둡고 16px 번졌다 → 15/255 · 4px */
    box-shadow: var(--shadow-1);
    overflow: hidden;
}

.shot-page {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 15px;
    padding: 16px;
}

.shot-top { display: flex; align-items: center; gap: 11px; }
.shot-top .mock-search { flex: 1; min-width: 0; margin: 0; }

.shot-acct { display: flex; flex: none; gap: 6px; }
.shot-acct i { width: 17px; height: 17px; border-radius: 50%; background: var(--m-track); }

/* 사이드바 필터는 세 화면을 나란히 세우면 목록 폭을 너무 먹는다 — 가로 칩 줄로 눕혔다 */
.shot-chips { display: flex; gap: 6px; }

.shot-chips i {
    height: 16px;
    border-radius: var(--radius-pill);
    background: var(--m-track);
}

.shot-chips i:nth-of-type(1) { width: 46px; }
.shot-chips i:nth-of-type(2) { width: 34px; }
.shot-chips i:nth-of-type(3) { width: 52px; }
.shot-chips i:nth-of-type(4) { width: 30px; }

.shot-h {
    display: flex;
    align-items: baseline;
    gap: 4px;
    font-size: 11px;
    font-weight: 700;
    color: var(--m-text);
}

.shot-h b { font-family: var(--font-number); font-weight: 700; color: var(--m-accent); }

.shot-results .mock-list { padding: 8px 0 0; gap: 5px; }

/* 상품명과 별점·가격을 한 줄에 붙이면 행이 넓어야 한다 — 두 줄로 쌓아 좌우 폭을 줄인다 */
.shot-results .mock-row-body > span { display: block; }
.shot-results .mock-row { padding: 0.42rem 0.5rem; }
.shot-results .mock-thumb { width: 36px; height: 48px; }

/* ============================================================
   홈 화면 — "인기 상품 지면"이 아니라 쇼핑몰 메인 한 장으로 읽혀야 한다(2026-08-24 사용자).
   검색창은 검색 결과 화면에만 두므로(같은 지시) 첫 줄은 카테고리 헤더가 대신한다.
   ============================================================ */
.shot-gnb {
    display: flex;
    align-items: flex-end;
    gap: 11px;
    /* 헤더는 화면 폭을 끝까지 쓴다 — .shot-page 의 16px 패딩을 되돌린다 */
    margin: -16px -16px 0;
    padding: 16px 16px 0;
    border-bottom: 1px solid var(--m-border);
}

.shot-gnb .mock-tabs {
    flex: 1;
    min-width: 0;
    gap: 13px;
    padding: 0;
    border-bottom: 0;
}

.shot-gnb .mock-tab { font-size: 11px; padding-bottom: 8px; }
.shot-gnb .shot-acct { margin-bottom: 8px; }

/* 메인 배너는 지면 폭을 그대로 쓴다 — 스킨 기본 여백(0.55rem)이 남으면 진열과 좌우가 어긋난다 */
.shot-main { display: flex; flex-direction: column; gap: 7px; }
.shot-main > .mock-banner { margin: 0; }
.shot-main .mock-banner-art { width: 58px; height: 58px; }

/* 배너가 한 장이 아니라 구좌라는 표시 — 6px 짜리 줄이라 시선을 뺏지 않는다 */
.shot-dots { display: flex; justify-content: center; gap: 4px; }

.shot-dots i {
    width: 4px;
    height: 4px;
    border-radius: 50%;
    background: var(--m-border);
}

.shot-dots i.is-on { width: 10px; border-radius: var(--radius-pill); background: var(--m-sub); }

.shot-quick { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 6px; }

.shot-quick > span {
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 5px;
}

.shot-quick i {
    display: grid;
    place-items: center;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    background: var(--m-track);
    color: var(--m-sub);
}

/* 빈 원은 로딩 스켈레톤으로 읽힌다 — 사이트 공통 라인 아이콘 규격을 그대로 쓴다 */
.shot-quick svg { width: 17px; height: 17px; }
.shot-quick em { font-style: normal; font-size: 10px; color: var(--m-sub); white-space: nowrap; }

/* ============================================================
   상품 상세 화면 — 상세 페이지답게 정보를 더 넣는다(2026-08-24 사용자).
   경로 · 브랜드 · 할인가 · 배송 · 옵션 · 구매 버튼 · 탭까지 있어야 "함께 본 상품"이
   상세 페이지 맨 아래 추천 구좌로 읽힌다.
   ============================================================ */
.shot-crumb { display: flex; align-items: center; gap: 4px; font-size: 10px; color: var(--m-sub); }
.shot-crumb i { font-style: normal; opacity: 0.55; }
.shot-crumb b { font-weight: 600; color: var(--m-text); }


/* 스킨 폰트가 소수점 rem 이라 9~10px 대에서 글리프가 뭉갠다 — 이 페이지에서는 정수 px 로 덮는다 */
.shot-page .mock-detail-info { justify-content: flex-start; gap: 4px; }
.shot-page .mock-detail-info i { font-size: 10px; }
.shot-page .mock-detail-info b { font-size: 13px; }
.shot-page .mock-detail-info em { display: flex; align-items: baseline; gap: 5px; font-size: 14px; }
.shot-page .mock-detail-info em b { font-size: 13px; color: var(--m-accent); }

.shot-was {
    font-family: var(--font-number);
    font-size: 11px;
    color: var(--m-sub);
    text-decoration: line-through;
}

.shot-buy { display: flex; flex-direction: column; gap: 9px; }

/* 라벨 열은 두 줄이 나눠 쓴다 — 열을 30px 로 고정하면 EN 라벨(Delivery)이 열 안에서 접힌다 */
.shot-pdp-meta {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 3px 8px;
    font-size: 10px;
}
.shot-pdp-meta b { font-weight: 600; color: var(--m-sub); }
.shot-pdp-meta em { font-style: normal; color: var(--m-text); }

.shot-pdp-opt {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    padding: 7px 9px;
    border: 1px solid var(--m-border);
    border-radius: 7px;
    font-size: 11px;
    color: var(--m-sub);
}

.shot-pdp-opt svg { width: 11px; height: 11px; flex: none; opacity: 0.55; }

.shot-pdp-cta { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }

/* 구매 버튼은 파랗게 칠하지 않는다 — 이 화면에서 액센트는 AD 표시 몫이다 */
.shot-btn {
    padding: 8px 0;
    border: 1px solid var(--m-border);
    border-radius: 7px;
    text-align: center;
    font-size: 11px;
    font-weight: 700;
    color: var(--m-text);
    background: var(--m-surface);
}

.shot-btn.is-primary { border-color: var(--m-text); background: var(--m-text); color: var(--m-surface); }

.shot-page > .mock-tabs { gap: 13px; padding: 0; }
.shot-page > .mock-tabs .mock-tab { font-size: 11px; padding-bottom: 8px; }

.shot-shelf { padding-top: 4px; border-top: 1px solid var(--m-border); }

/* 스킨은 상품명 2줄을 가정해 자리를 비워 두지만(가격 줄 정렬용) 여기 넣은 네 상품은
   전부 한 줄이라 카드 밑이 통째로 빈다 — 상품을 바꿀 때 두 줄이 생기면 되돌릴 것 */
.fmt-stage .mock-card-title { min-height: 0; }
.shot-shelf .mock-carousel { padding: 12px 0 0; }
/* 상품 카드는 커머스 기본인 3:4 로 둔다 — 1:1 로 눌러 놨던 건 화면 한 장이 길어지는 걸
   막으려던 것인데, 세 화면 높이를 맞추면서 그 제약이 사라졌다 */
.shot-shelf .mock-card-img { aspect-ratio: 3 / 4; }

/* --- 폰 두 대 (협력 지면) — 브라우저 한 장보다 확실히 작아야 주종이 읽힌다 --- */
/* `min(164px, 100%)` 로 두면 `.fmt-zone.is-out` 의 `fit-content` 가 계산되지 않는다
   (백분율이 미정 폭에 걸려 max-content 가 부풀어 점선 상자가 열 폭을 다 먹는다) */
.shot-phone {
    position: relative;
    flex: 1;
    min-width: 0;
    max-width: 164px;
    padding: 6px;
    border: 1px solid var(--m-border);
    border-radius: 22px;
    background: var(--m-surface);
    /* 화면 카드와 같은 단계로 — 작은 폰이 더 떠 보이면 위계가 뒤집힌다 */
    box-shadow: var(--shadow-1);
}

.shot-phone-in { border-radius: 17px; overflow: hidden; background: var(--m-surface); }

/* 4:5 세로 이미지는 폰 한 대를 지나치게 길게 만든다 */
.shot-phone .mock-social-img { aspect-ratio: 1 / 1; }

/* --- 인스타그램 피드 광고 ---
   스킨은 헤더·사진·CTA 까지만 준다. 그것만으로는 "어느 지면인지 모르겠다"(2026-08-24 사용자) —
   피드 광고를 인스타로 읽히게 하는 건 사진이 아니라 **액션 줄과 좋아요 수, 캡션**이다 */
.shot-ig-actions {
    display: flex;
    align-items: center;
    gap: 9px;
    padding: 7px 8px 3px;
    color: var(--m-text);
}

.shot-ig-actions svg { width: 13px; height: 13px; flex: none; }
.shot-ig-actions i { flex: 1; }

.shot-ig-likes {
    padding: 0 8px;
    font-size: 9px;
    font-weight: 700;
    color: var(--m-text);
}

/* 상품명이 두 줄로 접혔다(2026-08-24 사용자) — 폰 폭이 152px 라 스킨 기본(0.66rem)이 안 들어간다 */
.shot-phone .mock-social-cap {
    padding: 3px 8px 8px;
    font-size: 9px;
    gap: 6px;
}

.shot-phone .mock-social-cap span { min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.shot-phone .mock-social-cap b { flex: none; }
.shot-phone .mock-social-cta { padding: 6px 8px; font-size: 10px; }

/* --- 카카오톡 채팅 목록 ---
   회색 막대만 여섯 줄 있으면 로딩 화면으로 읽힌다(같은 지시). 이름과 마지막 메시지가 있어야
   비즈보드가 "채팅탭 맨 위 구좌"라는 게 보인다 */
.shot-kk { display: flex; flex-direction: column; gap: 7px; padding: 7px 7px 8px; }
.shot-kk-row { display: flex; align-items: center; gap: 7px; }

.shot-kk-av {
    width: 22px;
    height: 22px;
    flex: none;
    border-radius: 7px;
    background: var(--m-track);
}

.shot-kk-body { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }

.shot-kk-body b {
    font-size: 9px;
    font-weight: 700;
    color: var(--m-text);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.shot-kk-body em {
    font-style: normal;
    font-size: 8px;
    color: var(--m-sub);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.shot-kk-badge {
    flex: none;
    min-width: 13px;
    height: 13px;
    border-radius: var(--radius-pill);
    background: #FA5252;
    color: var(--white);
    font-size: 8px;
    font-weight: 700;
    line-height: 13px;
    text-align: center;
}

/* 비즈보드 상품명도 폰 폭에 맞춰 내린다. 그래도 EN(`Running sneakers`)은 안 들어가서
   썸네일을 깎고 `AD` 를 구좌 **아래쪽** 모서리로 뺀다 — 위쪽에 두면 상품명 줄과 부딪친다 */
.shot-phone .mock-biz-board { position: relative; padding: 0.35rem; gap: 0.35rem; }
.shot-phone .mock-biz-board .mock-thumb { width: 24px; height: 30px; }
.shot-phone .mock-biz-board .mock-row-title { font-size: 10px; }
.shot-phone .mock-biz-board .mock-row-meta { font-size: 9px; }

.shot-phone .mock-biz-board .mock-ad-badge {
    position: absolute;
    right: 5px;
    bottom: 5px;
}

/* --- 상품 상세 (기존 `.mock-detail-*` 스킨 재사용) ---
   스킨은 독립 패널용이라 자체 여백을 갖는다. `.shot-page` 가 이미 여백·간격을 잡으므로 벗긴다 */
.shot-page > .mock-detail-top { padding: 0; gap: 0.7rem; }
.shot-page > .mock-detail-top img { width: 90px; height: 112px; }
.shot-page > .mock-detail-rec { padding: 6px 0 0; }

/* 스킨은 4칸이 기본이다 — 세 화면을 나란히 세우려면 3칸이어야 좌우 폭이 맞는다 */
.shot-page .mock-detail-strip { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.shot-page .mock-detail-strip > span { aspect-ratio: 1 / 1; }

/* ============================================================
   광고 표시 — 광고 자리에 **더하지 않고 주변을 물러나게 한다**
   화면 안에 칠한 색은 무엇이든 플랫폼 UI 로 읽힌다. 파란 판을 깔았더니
   "광고가 들어가면 파란 박스가 생긴다"로 읽혀 이 페이지의 주장과 부딪쳤다
   (2026-08-24 사용자: "파란색 하이라이팅은 화면에도 그렇게 보이는 것 같고 눈에 띄지도 않는다").
   그래서 광고 자리는 원래 모습 그대로 두고 **같은 줄의 오가닉 이웃만 낮춘다** —
   대비는 광고에 칠한 색이 아니라 주변이 물러난 결과다.
   ============================================================ */
.fmt-stage .mock-row.is-ad,
.fmt-stage .mock-card.is-ad .mock-card-img,
.fmt-stage .mock-detail-strip > span.is-ad { box-shadow: none; }

/* 스킨이 광고 칸에 깔아 두는 액센트 배경도 같은 이유로 벗긴다 */
.fmt-stage .mock-row.is-ad { background: transparent; }
.fmt-stage .mock-banner,
.fmt-stage .mock-biz-board { background: var(--m-surface); }

/* 말줄임은 인라인 요소에서 동작하지 않는다. 스킨의 `.mock-row-title` 은 `<span>` 이라
   `text-overflow: ellipsis` 가 먹지 않고 EN 상품명(`Running sneakers`)이 `AD` 라벨 밑으로
   22px 파고들었다(ko 는 짧아서 안 드러난다). 검색 목록은 이미 같은 이유로 블록으로 눕혀 뒀다 */
.fmt-stage .mock-biz-board .mock-row-body > span { display: block; }
.fmt-stage .mock-ad-badge { flex: none; }

/* 낮추는 건 **같은 줄 안의 이웃**뿐이다 — 화면 전체를 낮추면 비활성 화면처럼 보인다 */
.fmt-stage .mock-cards > .mock-card:not(.is-ad),
.fmt-stage .mock-list > .mock-row:not(.is-ad),
.fmt-stage .mock-detail-strip > span:not(.is-ad) { opacity: 0.42; }

/* 배너·비즈보드는 그 자체가 하나의 구좌라 테두리는 남기되 액센트만 뺀다 */
.fmt-stage .mock-banner,
.fmt-stage .mock-biz-board { box-shadow: inset 0 0 0 1px var(--m-border); }

/* 라벨은 검정 알약이다. 회색으로 눌러 놨더니 상품 사진 위에서 아예 안 읽혔다 —
   쿠팡·네이버가 쓰는 표기 형태 그대로라 화면을 왜곡하지도 않는다 */
.fmt-stage .mock-ad-badge {
    background: rgba(25, 31, 40, 0.82);
    color: var(--white);
    border-color: transparent;
    font-weight: 700;
}

/* ============================================================
   광고에 쓰이는 값 (챕터 ②)
   **"우리가 소재를 만들어 준다"로 읽히면 안 된다**(2026-08-24 사용자) — 그래서 조립 과정을
   그리지 않고 **광고주가 보는 화면(고르는 목록)** 과 **그 상품에서 그대로 실리는 값** 두 층만 둔다.
   고른 줄만 흰 면 + 액센트 테두리로 켜고 나머지는 회색으로 남겨 "고를 수 있는 것"으로 읽히게 한다.
   ============================================================ */
.creo { max-width: 600px; margin-inline: auto; }

/* 지면을 좌우로 나누면 "왼쪽에서 들어와 오른쪽으로 나간다"는 흐름으로 읽힌다(2026-08-25 사용자).
   콘솔을 가운데 두고 **위아래로** 퍼뜨려야 방향이 아니라 확산으로 읽힌다 */
.creo-fan { display: grid; grid-template-columns: minmax(0, 1fr); }

.creo-side {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
    justify-items: center;
}

.creo-node {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 7px;
    min-width: 0;
}

/* 라벨은 바깥쪽에 둔다 — 그래야 가지가 라벨을 지나치지 않고 타일에 바로 꽂힌다 */
.creo-side.is-t .creo-node { flex-direction: column-reverse; }

/* 촉은 챕터 ③ `.ofs-arrow` 와 같은 모양이다(채워진 삼각). SVG 안에 그리면
   `preserveAspectRatio: none` 때문에 가로로 늘어나므로 CSS 로 붙인다 */
.creo-node::after {
    content: '';
    position: absolute;
    left: 50%;
    width: 0;
    height: 0;
    margin-left: -4px;
    border: 4px solid transparent;
    opacity: 0.34;
}

/* 촉은 **밑동을 축으로** 돌린다 — 가운데를 축으로 돌리면 꼭짓점이 휙 돌아
   선 끝과 어긋난다(2026-08-25 사용자: "선과 화살촉이 제대로 연결 안 되어 있는 걸로 보여") */
.creo-side.is-t .creo-node::after { transform-origin: 50% 100%; }
.creo-side.is-b .creo-node::after { transform-origin: 50% 0; }

.creo-side.is-t .creo-node::after {
    bottom: -16px;
    border-top: 0;
    border-bottom-color: var(--m-accent);
}

.creo-side.is-t .creo-node:first-child::after { transform: rotate(-57deg); }
.creo-side.is-t .creo-node:last-child::after { transform: rotate(57deg); }

.creo-side.is-b .creo-node::after {
    top: -16px;
    border-bottom: 0;
    border-top-color: var(--m-accent);
}

.creo-side.is-b .creo-node:first-child::after { transform: rotate(57deg); }
.creo-side.is-b .creo-node:last-child::after { transform: rotate(-57deg); }

.creo-node em {
    max-width: 100%;
    font-style: normal;
    font-size: 11px;
    font-weight: 700;
    color: var(--m-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* 지면 타일 — 작지만 화면이다. 도형만 남기면 무슨 화면인지 사라진다(2026-08-25 사용자, 두 번).
   광고 자리에만 실제 상품 사진이 들어가고 나머지 칸은 회색 자리표시다 — 사진이 어디 있느냐가
   곧 "그 지면 어디에 이 상품이"다. 조각 어휘(`.ca-*`)를 공유하고 타일별로 배치만 바꾼다 */
.creo-art {
    display: flex;
    flex-direction: column;
    gap: 4px;
    width: 116px;
    height: 80px;
    padding: 6px;
    border-radius: 8px;
    background: var(--m-surface);
    box-shadow: inset 0 0 0 1px var(--m-border);
}

/* 슬롯 비율에 맞춘 파생 이미지를 쓰므로 `cover` 여도 잘리지 않는다 —
   잘린 상품 사진은 "지면별 최적화가 안 된다"로 읽힌다(2026-08-25 사용자) */
.ca-shot { overflow: hidden; border-radius: 3px; background: var(--m-track); }
.ca-shot img { display: block; width: 100%; height: 100%; object-fit: cover; }

.ca-ph { border-radius: 3px; background: var(--m-track); }
.ca-ln { height: 3px; border-radius: 2px; background: var(--m-track); }
.ca-ln.is-s { width: 62%; }
.ca-ln.is-title { width: 38%; }
.ca-dot { flex: none; width: 13px; height: 13px; border-radius: 50%; background: var(--m-track); }

.ca-tx { display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 0; }
.ca-tx > i { height: 3px; border-radius: 2px; background: var(--m-track); }
.ca-tx > i.is-s { width: 55%; }

.ca-row { display: flex; align-items: center; gap: 5px; }
.ca-3 { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 4px; }
.ca-card { display: flex; flex-direction: column; gap: 3px; min-width: 0; }

/* 홈 — 띠 배너 한 칸 아래로 진열이 이어진다 */
.creo-art.is-banner .ca-row.is-band {
    flex: none;
    height: 27px;
    padding: 3px;
    border-radius: 5px;
    background: var(--m-surface-2);
}

.creo-art.is-banner .ca-shot { flex: none; width: 21px; height: 21px; }
.creo-art.is-banner .ca-3 { flex: 1; }
.creo-art.is-banner .ca-card > .ca-ph { flex: 1; }

/* 진열 — 카드 여럿 중 첫 칸. 카드 이미지는 3:4 라 원본을 그대로 쓴다 */
.creo-art.is-grid .ca-3 { flex: 1; }
.creo-art.is-grid .ca-card > .ca-shot,
.creo-art.is-grid .ca-card > .ca-ph { aspect-ratio: 3 / 4; }

/* 검색 결과 — 오가닉 사이에 끼는 한 줄 */
.creo-art.is-rows .ca-row { flex: 1; padding: 0 3px; border-radius: 4px; }
.creo-art.is-rows .ca-row.is-ad { background: var(--m-surface-2); }
.creo-art.is-rows .ca-shot,
.creo-art.is-rows .ca-ph { flex: none; width: 17px; height: 17px; }

/* 상품 추천 — 보고 있는 상품(위 큰 칸)은 광고가 아니라 회색이다 */
.creo-art.is-rec > .ca-ph.is-hero { flex: none; height: 24px; }
.creo-art.is-rec .ca-3 { flex: 1; }
.creo-art.is-rec .ca-card > * { flex: 1; }

/* SNS 피드 — 소재 한 장이 화면을 거의 다 쓴다(2:1 파생 이미지) */
.creo-art.is-feed .ca-row.is-head { flex: none; }
.creo-art.is-feed > .ca-shot { flex: 1; }

/* 외부 DA 광고 — 남의 콘텐츠 사이에 끼는 배너라 위아래로 본문 글줄이 있어야 그 지면으로 읽힌다 */
.creo-art.is-da { gap: 3px; }
.creo-art.is-da > .ca-shot { flex: 1; margin: 2px 0; }

/* 선은 **같은 페이지 챕터 ③ 의 `.ofs-arrow` 와 같은 언어**로 그린다(2026-08-25 사용자:
   "지금까지 안 쓰던 느낌이라 통일감이 떨어진다") — 단색 액센트 + 둥근 끝 + 채워진 삼각 촉.
   그라디언트·번짐은 이 사이트가 안 쓰는 표현이라 걷어냈다. 거미줄로 안 보이게 하는 것은
   세기가 아니라 **굵기(1.6px)와 여유(띠 48px)** 다 — 진하기는 `.arch` 의 층 사이 화살표와 같은
   **액센트 45%** 로 눌러 둔다(단색 액센트 100% 는 타일보다 선이 세다).
   **선은 상자에 닿지 않는다** — 양 끝을 12px 씩 들여쓴다(`--arch-inset` 과 같은 이유이되 그보다
   넉넉하게: 2026-08-25 사용자 "화살표와 컨테이너 사이 마진을 더 두고"). 촉은 그 자리에서 시작한다.
   선 자체도 **점선**이다(랜딩 `.coop-link` 의 점선 트랙과 같은 계열) — 실선보다 한 단계 물러난다.
   **경로는 타일 쪽에서 그리기 시작한다** — 점선 패턴이 시작점부터 깔리므로, 콘솔 쪽에서 시작하면
   촉 앞에 빈칸이 오는 경우가 생긴다.
   가지는 **콘솔 네 구석(viewBox x 96 · 204)에서 출발하는 최단 경로**다 — 테두리 가운데서 출발하면
   바깥 타일까지 가로로 길게 눕는다. 바깥 넷은 **좌우 대칭으로 고르게 휜 활**이고(제어점을 현 위
   0.35 지점에 두고 수직으로 같은 크기만큼 밀어낸다), **가운데 둘은 직선**이다 — 짧은 세로 가지를
   흔들면 장난처럼 보인다(2026-08-25 사용자: 물결 → 꺾은 직선 → 직선 → 살짝 웨이브 → 대칭 활).
   촉이 SVG 안에 있으면 `preserveAspectRatio: none` 때문에 가로로 늘어나므로 CSS 로 붙이고,
   바깥 가지 넷은 `rotate(±57deg)` — 눈대중 말고 **`getPointAtLength` + `getScreenCTM` 으로 끝
   접선을 실측한 값**이다(뷰포트별 50~57°, 대부분 57°). 곡선을 손보면 다시 잴 것.
   `preserveAspectRatio: none` 으로 가로를 늘려 쓰므로 굵기는 `non-scaling-stroke` 로 지킨다 */
.creo-rays { width: 100%; height: 64px; }

.creo-rays path {
    fill: none;
    stroke: var(--m-accent);
    stroke-width: 1.5;
    stroke-linecap: round;
    stroke-linejoin: round;
    stroke-dasharray: 2 5;
    opacity: 0.34;
    vector-effect: non-scaling-stroke;
}

.creo-hub {
    justify-self: center;
    width: 236px;
    max-width: 100%;
    border: 1px solid var(--m-border);
    border-radius: 12px;
    background: var(--m-surface);
    box-shadow: var(--shadow-1);
    overflow: hidden;
}

/* 콘솔이라는 표시는 우리 심볼이 박힌 머리 바 하나면 된다(랜딩 ⑤ 의 `.coop-console` 과 같은 방식) */
.creo-bar {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 7px 9px;
    border-bottom: 1px solid var(--m-border);
    background: var(--m-accent-soft);
    font-size: 11px;
    font-weight: 700;
    color: var(--m-accent);
}

.creo-mark {
    flex: none;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 16px;
    height: 16px;
    border-radius: 5px;
    background: var(--m-surface);
}

.creo-mark img { width: 11px; height: 11px; object-fit: contain; }

.creo .mock-form { padding: 0.6rem 0.7rem 0.7rem; }
.creo .mock-pick { gap: 0.45rem; padding-top: 0.4rem; }
.creo .mock-pick .mock-thumb { width: 22px; height: 28px; border-radius: 5px; }
.creo .mock-pick-name { min-width: 0; font-size: 12px; font-weight: 700; color: var(--m-text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

.creo-drop { display: none; }

/* ── 한 바퀴: 검색 → 선택 → 여섯 지면 ─────────────────────────────────────────
   **완성 상태가 기본값이다** — 위의 규칙들이 그대로 정지 화면이고, JS 가 `.is-anim` 을
   붙였을 때만 단계가 생긴다(랜딩 ⑤ · 실시간 리포팅 히어로와 같은 방식). JS 가 없거나
   `prefers-reduced-motion` 이면 아무것도 달라지지 않는다.
   단계는 셋뿐이다 — `.is-found`(검색 결과가 뜬다) · `.is-picked`(고른다) · `.is-spread`(퍼진다).
   퍼지는 순서는 **가운데에서 바깥으로** 다(선 → 촉 → 사진). 여섯이 한꺼번에 켜지면
   "원래 그런 그림"으로 읽혀서 확산이 안 남는다.
   **자리를 흔드는 값은 쓰지 않는다** — 사라지는 것들은 자리를 남긴 채 투명해질 뿐이다.
   콘솔 폭이 236px 뿐이라 한 칸만 밀려도 그림 전체가 흔들린다. */
.creo { position: relative; }

/* 고른 줄에 여백을 주되 **높이는 그대로 둔다** — 늘어난 만큼 음수 마진으로 되돌린다.
   위아래로 커지면 콘솔이 자라 그림 전체가 흔들리고, 가로로만 벌리면 띠가 입력창에 붙는다 */
.creo.is-anim .mock-pick {
    opacity: 0;
    transform: translateY(5px);
    margin: 3px -6px -3px;
    padding: calc(0.4rem - 3px) 6px 3px;
    border-radius: 7px;
    transition: opacity 300ms var(--ease-out), transform 300ms var(--ease-out),
                background-color 260ms ease;
}

.creo.is-anim.is-found .mock-pick { opacity: 1; transform: none; }
.creo.is-anim.is-picked .mock-pick { background: var(--m-accent-soft); }

.creo.is-anim .mock-input { transition: border-color 200ms ease, background-color 200ms ease; }
.creo.is-anim .mock-input.is-typing { border-color: var(--m-accent); background: var(--m-surface); }

/* 타이핑 커서 — 랜딩 히어로와 같다(깜빡이지 않는다).
   `inline-block` 이라 글자가 아직 한 자도 없어도 줄 높이가 유지된다 */
.creo .mock-input.is-typing::after {
    content: '';
    display: inline-block;
    width: 1.5px;
    height: 0.85em;
    margin-left: 1px;
    vertical-align: -0.08em;
    background: var(--m-accent);
}

.creo.is-anim .mock-check { transition: background-color 200ms ease, border-color 200ms ease; }
.creo.is-anim .mock-check.is-on::after { animation: creoTick 260ms var(--ease-out); }

@keyframes creoTick {
    from { opacity: 0; transform: translate(-50%, -50%) rotate(45deg) scale(0.4); }
}

/* 선·촉·사진은 고른 **뒤에야** 켜진다 — 이 순서가 곧 "고르면 여기까지 나간다"다 */
.creo.is-anim .creo-rays path { opacity: 0; transition: opacity 360ms var(--ease-out); }

.creo.is-anim.is-spread .creo-rays path {
    opacity: 0.34;
    animation: creoFlow 620ms linear 2;
}

/* 점은 콘솔에서 타일 쪽으로 흐른다 — 경로가 타일에서 시작하므로 `dashoffset` 을 키우면
   패턴이 시작점(=타일) 쪽으로 밀린다. 한 주기(2+5=7)의 정수배만 돌려 원래 위상으로 끝낸다 */
@keyframes creoFlow { to { stroke-dashoffset: 7; } }

.creo.is-anim .creo-node::after { opacity: 0; transition: opacity 280ms var(--ease-out); }
.creo.is-anim.is-spread .creo-node::after { opacity: 0.34; }

/* 광고 자리는 원래 회색 자리표시다 — 거기에 사진이 내려앉는 게 "이 지면에 실렸다"다 */
.creo.is-anim .ca-shot img {
    opacity: 0;
    transform: scale(1.07);
    transition: opacity 340ms var(--ease-out), transform 480ms var(--ease-out);
}

.creo.is-anim.is-spread .ca-shot img { opacity: 1; transform: none; }

/* 가운데 가지가 먼저 서고 바깥 둘이 뒤따른다(되감을 때는 지연 없이 한꺼번에 빠진다) */
.creo.is-anim.is-spread .creo-rays path:nth-child(1),
.creo.is-anim.is-spread .creo-rays path:nth-child(3) { transition-delay: 120ms; animation-delay: 120ms; }

.creo.is-anim.is-spread .creo-node:nth-child(2)::after { transition-delay: 300ms; }
.creo.is-anim.is-spread .creo-node:nth-child(1)::after,
.creo.is-anim.is-spread .creo-node:nth-child(3)::after { transition-delay: 430ms; }

/* 사진은 선이 닿은 **뒤에** 들어온다 — 선보다 먼저 뜨면 인과가 뒤집힌다 */
.creo.is-anim.is-spread .creo-node:nth-child(2) .ca-shot img { transition-delay: 340ms; }
.creo.is-anim.is-spread .creo-node:nth-child(1) .ca-shot img,
.creo.is-anim.is-spread .creo-node:nth-child(3) .ca-shot img { transition-delay: 500ms; }

/* 커서·탭 링 — 챕터 ②(상품 선택)와 ③(광고 클릭·구매)이 함께 쓴다.
   랜딩 애니메이션 전용인 공용 `.coop-*` 와는 섞지 않는다 */
.fp-cursor,
.fp-tap { position: absolute; opacity: 0; pointer-events: none; }

.fp-cursor {
    z-index: 3;
    width: 17px;
    height: 17px;
    margin: -2px 0 0 -2px;
    filter: drop-shadow(0 3px 6px rgba(16, 22, 35, 0.32));
}

.fp-cursor svg { display: block; width: 100%; height: 100%; }

.fp-tap {
    z-index: 2;
    width: 24px;
    height: 24px;
    margin: -12px 0 0 -12px;
    border-radius: 50%;
    border: 2px solid var(--m-accent);
    background: rgba(127, 178, 255, 0.28);
}

/* 되감을 때는 트랜지션 없이 스냅한다 — 안 그러면 지우는 과정이 한 번 더 보인다 */
.creo.no-anim .mock-pick,
.creo.no-anim .mock-input,
.creo.no-anim .mock-check,
.creo.no-anim .mock-check.is-on::after,
.creo.no-anim .creo-rays path,
.creo.no-anim .creo-node::after,
.creo.no-anim .ca-shot img { transition: none; animation: none; }


/* 좁으면 부채를 접는다 — 선을 지우고 콘솔 아래에 지면을 늘어놓는다.
   두 묶음을 `display: contents` 로 풀어야 여섯 개가 한 격자에 고르게 선다 */
@media (max-width: 620px) {
    .creo-fan {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 0.7rem 0.5rem;
    }

    .creo-rays { display: none; }
    .creo-node::after { display: none; }
    .creo-side.is-t .creo-node { flex-direction: column; }
    .creo-hub { order: 1; grid-column: 1 / -1; }

    .creo-drop {
        order: 2;
        grid-column: 1 / -1;
        display: flex;
        justify-content: center;
        color: var(--m-accent);
    }

    .creo-drop svg { width: 14px; height: 14px; }

    .creo-side { display: contents; }
    .creo-node { order: 3; }
}

/* 세 칸으로는 타일이 안 들어간다 */
@media (max-width: 420px) {
    .creo-fan { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* ============================================================
   협력 지면 (챕터 ③)
구조는 **두 구역 + 화살표 둘**이다 — 실선(플랫폼 내부) 안의 상품 상세가 출발점이자 도착점이고,
   점선(플랫폼 외부)에는 그 상품 정보가 그대로 실린 소재 둘이 놓인다.
   **유입 화살표만 액센트다** — 이 챕터의 주장은 "나간다"가 아니라 "돌아온다"다.
   다만 구조만으로는 "협력 지면이 있다"까지만 읽혀서(2026-08-25 사용자) 그 위에 한 바퀴를
   덧입힌다: 송출(상품이 나간다) → 클릭(밖에서 만난다) → 유입(같은 사람이 들어온다) → 거래.
   **덧입히기만 한다** — 완성 상태가 CSS 기본값이고 JS 는 `.is-anim` 을 붙일 뿐이다.
   `ad-formats` 전용이라 랜딩 애니메이션 전용인 공용 `.coop-*` 와 섞지 않는다.
   ============================================================ */
.ofs {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 100px minmax(0, 1fr);
    align-items: center;
    column-gap: 0.5rem;
    /* 폭을 다 쓰면 상품 사진이 패널을 잡아먹어 도식이 아니라 사진첩으로 읽힌다 */
    max-width: 560px;
    margin-inline: auto;
}

.ofs-cap {
    grid-column: 1;
    grid-row: 1;
    display: flex;
    align-items: center;
    gap: 5px;
    margin-bottom: 0.4rem;
    font-size: 11px;
    font-weight: 700;
    color: var(--m-sub);
}

.ofs-cap.is-out { grid-column: 3; }

.ofs-cap::before {
    content: '';
    width: 6px;
    height: 6px;
    border-radius: 2px;
    background: var(--m-accent);
}

.ofs-cap.is-out::before { background: var(--m-sub); }

.ofs-zone {
    grid-column: 1;
    grid-row: 2;
    display: grid;
    gap: 0.5rem;
    padding: 0.55rem;
    border: 1px solid var(--m-border);
    border-radius: 12px;
    background: var(--m-surface-2);
}

/* 우리 지면이 아니라는 뜻으로 점선 — 히어로의 `.fmt-offsite` 와 같은 표기다 */
.ofs-zone.is-out { grid-column: 3; border-style: dashed; }

.ofs-links {
    grid-column: 2;
    grid-row: 2;
    display: flex;
    flex-direction: column;
    gap: 1.1rem;
}

.ofs-arrow { display: flex; flex-direction: column; align-items: center; gap: 9px; }
.ofs-arrow em { font-style: normal; font-size: 11px; font-weight: 700; color: var(--m-sub); }

/* 선과 촉이 항상 같은 색이어야 하므로 색은 `color` 한 곳에서만 정하고 둘 다 `currentColor`
   를 쓴다 — 유입 화살표가 켜질 때 한 속성만 트랜지션하면 촉까지 같이 따라온다 */
.ofs-arrow i {
    position: relative;
    display: block;
    width: 100%;
    height: 2px;
    border-radius: 1px;
    color: var(--m-border);
    background: currentColor;
}

.ofs-arrow i::after {
    content: '';
    position: absolute;
    top: 50%;
    right: -1px;
    transform: translateY(-50%);
    border: 4px solid transparent;
    border-right: 0;
    border-left-color: currentColor;
}

.ofs-arrow.is-back em { color: var(--m-accent); }
.ofs-arrow.is-back i { color: var(--m-accent); }

.ofs-arrow.is-back i::after {
    right: auto;
    left: -1px;
    border: 4px solid transparent;
    border-left: 0;
    border-right-color: currentColor;
}

/* --- 플랫폼 내부 — 광고할 상품의 상세 페이지가 곧 도착지다 --- */
.ofs-pdp {
    border: 1px solid var(--m-border);
    border-radius: 10px;
    background: var(--m-surface);
    overflow: hidden;
}

.ofs-pdp-bar {
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 7px 9px;
    border-bottom: 1px solid var(--m-border);
    font-size: 11px;
    font-weight: 700;
    color: var(--m-text);
}

.ofs-pdp-bar svg { flex: none; width: 11px; height: 11px; }

.ofs-shot { position: relative; aspect-ratio: 4 / 3; background: var(--m-track); }
.ofs-shot img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* 같은 사진이라도 지면이 다르다 — 피드 소재는 정사각, 상품 페이지 대표 이미지는 4:3 가로 */
.ofs-shot.is-feed { aspect-ratio: 1 / 1; }
.ofs-shot .mock-ad-badge { position: absolute; top: 5px; left: 5px; }

.ofs-pdp-body { display: grid; gap: 2px; padding: 8px 9px 0; }
.ofs-pdp-body b { font-size: 12px; font-weight: 700; color: var(--m-text); }
.ofs-pdp-body span { font-size: 10px; color: var(--m-sub); }
.ofs-pdp-body em { font-style: normal; font-size: 13px; font-weight: 700; color: var(--m-text); font-family: var(--font-number); }

.ofs-buy {
    margin: 8px 9px 9px;
    padding: 6px 0;
    border-radius: 7px;
    background: var(--m-text);
    color: var(--white);
    font-size: 11px;
    font-weight: 700;
    text-align: center;
}

/* --- 플랫폼 외부 — 소재는 등록된 상품 정보 그대로다 --- */
.ofs-feed {
    border: 1px solid var(--m-border);
    border-radius: 10px;
    background: var(--m-surface);
    overflow: hidden;
}

.ofs-feed-head { display: flex; align-items: center; gap: 6px; padding: 6px 8px; }
.ofs-feed-head .mock-avatar { flex: none; width: 18px; height: 18px; }
.ofs-feed-head .mock-brand { margin-left: auto; }
.ofs-feed-head .mock-brand svg { width: 14px; height: 14px; }

.ofs-feed-name { display: grid; min-width: 0; }
.ofs-feed-name b { font-size: 10px; font-weight: 700; color: var(--m-text); }
.ofs-feed-name em { font-style: normal; font-size: 9px; color: var(--m-sub); }

.ofs-feed-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 6px;
    padding: 7px 9px;
    border-top: 1px solid var(--m-border);
    font-size: 11px;
    font-weight: 700;
    color: var(--m-text);
}

.ofs-feed-foot svg { flex: none; width: 11px; height: 11px; color: var(--m-sub); }

.ofs-biz {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 6px 7px;
    border: 1px solid var(--m-border);
    border-radius: 10px;
    background: var(--m-surface);
}

.ofs-biz .mock-brand svg { display: block; width: 14px; height: 14px; }
.ofs-biz .mock-thumb { flex: none; width: 22px; height: 28px; border-radius: 5px; }

.ofs-biz-body { display: grid; gap: 1px; min-width: 0; }

.ofs-biz-body b {
    font-size: 10px;
    font-weight: 700;
    color: var(--m-text);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.ofs-biz-body em { font-style: normal; font-size: 9px; color: var(--m-sub); font-family: var(--font-number); }
.ofs-biz .mock-ad-badge { flex: none; margin-left: auto; }

/* --- 한 바퀴: 송출 → 클릭 → 유입 → 거래 ------------------------------------ */
.ofs { position: relative; }

/* 송출 전에는 밖에 아무것도 없다 — 소재가 처음부터 있으면 "실린다"가 사라진다.
   자리는 그대로 두고 투명도·이동만 건드려서 도식이 흔들리지 않게 한다 */
.ofs.is-anim .ofs-feed,
.ofs.is-anim .ofs-biz {
    opacity: 0;
    transform: translateX(-10px);
    transition: opacity 380ms var(--ease-out), transform 460ms var(--ease-out);
}

.ofs.is-anim.is-sent .ofs-feed { opacity: 1; transform: none; }

/* 카톡은 **클릭 뒤에** 조용히 든다(2026-08-25 사용자: "클릭하면 카톡 내용도 잔잔하게 등장").
   인스타처럼 툭 들어오면 "또 한 군데"가 아니라 새 사건으로 읽혀서 더 느리고 더 옅게 뜬다 */
.ofs.is-anim .ofs-biz { transition: opacity 640ms var(--ease-out), transform 760ms var(--ease-out); }
.ofs.is-anim.is-kk .ofs-biz { opacity: 1; transform: none; }

/* 화살표를 타는 칩 둘. **나가는 것은 상품이고 들어오는 것은 사람**이라 안에 든 것이 다르다 —
   들어오는 쪽까지 커서로 그리면 마우스가 남의 화면으로 날아가는 그림이 된다(2026-08-25 사용자) */
.ofs-chip {
    position: absolute;
    z-index: 2;
    width: 16px;
    height: 16px;
    margin: -8px 0 0 -8px;
    border-radius: 5px;
    overflow: hidden;
    opacity: 0;
    pointer-events: none;
    background: var(--m-surface);
    box-shadow: 0 0 0 2px var(--m-accent), 0 4px 10px rgba(16, 22, 35, 0.22);
}

.ofs-chip img { display: block; width: 100%; height: 100%; object-fit: cover; }

.ofs-chip.is-user { display: flex; align-items: center; justify-content: center; }
.ofs-chip.is-user svg { width: 12px; height: 12px; fill: var(--m-accent); }

/* 유입 화살표는 정지 화면에서 유일한 액센트다. 한 바퀴 도는 동안에는 **아직 아무도 안 왔으므로**
   눌러 뒀다가 돌아오는 순간 켠다 — 켜지는 것 자체가 이 챕터의 결론이다 */
.ofs.is-anim .ofs-arrow.is-back em,
.ofs.is-anim .ofs-arrow.is-back i { transition: color 300ms ease; }
.ofs.is-anim .ofs-arrow.is-back em { color: var(--m-sub); }
.ofs.is-anim .ofs-arrow.is-back i { color: var(--m-border); }
.ofs.is-anim.is-back .ofs-arrow.is-back em,
.ofs.is-anim.is-back .ofs-arrow.is-back i { color: var(--m-accent); }

/* 도착한 자리가 한 번 번쩍해야 "데려왔다"가 된다. 커서가 화살표를 다 건넌 뒤에 터지도록
   늦춰 두고, 남는 상태가 아니라 **지나가는 애니메이션**이라 정지 화면을 흐리지 않는다 */
.ofs.is-anim.is-land .ofs-pdp { animation: ofsLand 900ms var(--ease-out); }

@keyframes ofsLand {
    30%, 55% { box-shadow: 0 0 0 2px var(--m-accent); }
}

.ofs.is-anim.is-bought .ofs-buy { animation: ofsPress 320ms var(--ease-out); }

@keyframes ofsPress {
    35% { transform: scale(0.96); }
}

/* 눌렀다는 표시는 글자만으로는 약하다 — 체크는 줄 높이 안에 들어가는 크기라 버튼이 안 커진다 */
.ofs.is-anim.is-bought .ofs-buy::before {
    content: '';
    display: inline-block;
    width: 4px;
    height: 8px;
    margin: 0 5px 2px 0;
    border: solid var(--white);
    border-width: 0 2px 2px 0;
    transform: rotate(45deg);
    vertical-align: middle;
}

/* 되감을 때는 트랜지션 없이 스냅한다 — 안 그러면 지우는 과정이 한 번 더 보인다 */
.ofs.no-anim .ofs-feed,
.ofs.no-anim .ofs-biz,
.ofs.no-anim .ofs-arrow.is-back em,
.ofs.no-anim .ofs-arrow.is-back i,
.ofs.no-anim .ofs-pdp,
.ofs.no-anim .ofs-buy { transition: none; animation: none; }

/* 좁아지면 두 구역을 위아래로 세운다 — 폭을 나눠 가지면 소재가 못 알아볼 만큼 작아진다.
   전부 1열로 내리므로 순서는 `order` 가 정한다(캡션 둘이 붙어 버리지 않게) */
@media (max-width: 620px) {
    /* 1열로 서면 구역이 화면 폭을 다 먹어 상품 사진이 폰만 해진다 — 폭을 다시 묶는다 */
    .ofs { grid-template-columns: minmax(0, 1fr); max-width: 320px; }

    .ofs-cap,
    .ofs-cap.is-out,
    .ofs-zone,
    .ofs-zone.is-out,
    .ofs-links { grid-column: 1; grid-row: auto; }

    .ofs-cap { order: 1; }
    .ofs-zone { order: 2; }

    /* 밖이 오른쪽이 아니라 아래라, 소재도 옆이 아니라 위에서 내려와야 화살표와 방향이 맞는다 */
    .ofs.is-anim .ofs-feed,
    .ofs.is-anim .ofs-biz { transform: translateY(-10px); }
    .ofs.is-anim.is-sent .ofs-feed,
    .ofs.is-anim.is-sent .ofs-biz { transform: none; }

    .ofs-links { order: 3; flex-direction: row; justify-content: center; gap: 2.4rem; margin: 0.9rem 0; }
    .ofs-cap.is-out { order: 4; }
    .ofs-zone.is-out { order: 5; }

    /* 구역이 위아래로 서면 화살표도 위아래여야 한다 — 가로 화살표는 가리키는 데가 없다 */
    .ofs-arrow { flex-direction: row; align-items: center; gap: 12px; }
    .ofs-arrow i { width: 2px; height: 34px; }

    .ofs-arrow i::after {
        top: auto;
        right: auto;
        bottom: -1px;
        left: 50%;
        transform: translateX(-50%);
        border: 4px solid transparent;
        border-bottom: 0;
        border-top-color: currentColor;
    }

    .ofs-arrow.is-back i::after {
        top: -1px;
        bottom: auto;
        border: 4px solid transparent;
        border-top: 0;
        border-bottom-color: currentColor;
    }
}

/* 좁은 화면에서는 카드 한 장이 화면에 꽉 차도록 좌우 여백을 줄인다 — 카드를 줄이면
   다시 말줄임이 생기므로 줄이는 건 여백 쪽이다 */
@media (max-width: 760px) {
    .fmt-stage {
        width: calc(100vw - 12px);
        padding-inline: 6px;
        scroll-padding-inline: 6px;
    }
}

/* [RT-BLOCK] */
/* ============================================================
   광고주 대시보드 (solution/features/performance-reporting)
   히어로 = 광고주가 로그인해서 쓰는 대시보드 **두 화면을 나란히**.
   `ad-formats` 와 같은 이유로 .arch 를 쓰지 않는다 — 이 페이지의 질문은
   *요청이 어떻게 도는가*가 아니라 *광고주가 어떤 화면을 받는가*다.

   한 번 눌러서 바꾸는 탭으로 만들었다가 걷어냈다(2026-08-24 사용자):
   두 화면이 각각 무엇을 답하는지가 이 페이지의 요점인데, 탭이면 **한 번에 하나만**
   보이고 방문자가 눌러야만 나머지를 안다. 나란히 두면 비교가 곧 설명이 된다.

   면은 3층이다 — [히어로 gray-50] > [흰 화면] > [회색 내부 카드].
   ============================================================ */
.perf-screens {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    align-items: stretch;
    gap: 1.4rem;
    margin: 2.6rem 0 0;
    text-align: left;
}

/* 라벨 + 화면만 세로로 쌓는다 — 화면을 카드 껍데기로 또 감싸지 않는다 */
.perf-screen { display: flex; flex-direction: column; min-width: 0; }

.perf-screen-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 0.6rem;
    font-size: 13px;
    font-weight: 700;
    color: var(--gray-900);
}

.perf-screen-label svg { width: 15px; height: 15px; flex: none; color: var(--blue-1); }

/* 두 화면의 내용 길이가 달라도 프레임 높이는 맞춘다 — 어긋나면 비교가 아니라 흐트러짐이다 */
.perf-console {
    flex: 1 1 auto;
    padding: 0.85rem 0.9rem 0.95rem;
}

.perf-head {
    display: flex;
    flex-wrap: wrap;
    gap: 5px;
    margin-bottom: 0.65rem;
}

.perf-sel {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border: 1px solid var(--m-border);
    border-radius: 6px;
    background: var(--m-surface);
    font-size: 11px;
    line-height: 1.7;
    color: var(--m-text);
    white-space: nowrap;
}

.perf-sel svg { width: 9px; height: 9px; flex: none; color: var(--m-sub); }

/* --- 요약 — 실제 화면의 "최근 14일 성과". 다섯 지표가 한 줄에 선다 --- */
.perf-sum {
    display: grid;
    grid-template-columns: repeat(5, minmax(0, 1fr));
    gap: 0.4rem;
    padding: 9px 11px 10px;
    border: 1px solid var(--m-border);
    border-radius: 9px;
    background: var(--m-surface-2);
    margin-bottom: 0.65rem;
}

.perf-sum-m { min-width: 0; }
.perf-sum-m > span { display: block; font-size: 10px; color: var(--m-sub); white-space: nowrap; }

.perf-sum-m > b {
    display: block;
    font-family: var(--font-number);
    font-size: 14px;
    font-weight: 700;
    line-height: 1.4;
    letter-spacing: -0.02em;
    color: var(--m-text);
}

/* --- 기간 단위 탭 (전체 / 일별 / 주별 / 월별) --- */
.perf-tabs {
    display: inline-flex;
    margin-bottom: 0.55rem;
    border: 1px solid var(--m-border);
    border-radius: 6px;
    overflow: hidden;
    background: var(--m-surface);
}

.perf-tab {
    padding: 3px 12px;
    font-size: 11px;
    line-height: 1.7;
    color: var(--m-sub);
    white-space: nowrap;
}

.perf-tab + .perf-tab { border-left: 1px solid var(--m-border); }
.perf-tab.is-on { background: var(--m-accent-soft); color: var(--m-accent); font-weight: 600; }

/* --- 캠페인별 ROAS 추이 --------------------------------------------------
   히스토리: ① 처음엔 [노출 수 좌축 + ROAS 우축] 이중축 영역 차트였다. 그건 실제
   화면에서 **`전체`(group='advertiser')** 일 때 나오는 그림이고, 위 필터가 `캠페인별`
   이면 제품은 `CampaignProductBarChart` 를 그린다 — 목업이 필터와 어긋나 있었다.
   ② 그래서 제품대로 그룹 막대로 바꿨더니 **"바 차트 2개로 하니까 이상해 보인다"**
   (2026-08-24 사용자). 맞는 감이었다 — 14일 × 2계열이면 막대 28개가 촘촘히 서고,
   막대는 0 에서 자라야 하는데 ROAS 가 226~318% 라 위쪽이 통째로 비고 아래는 고원이 된다.
   ③ 지금은 **선 차트**다. 선은 0 기준선 의무가 없어 축을 200~350% 로 좁힐 수 있고,
   그제야 두 캠페인의 오르내림이 보인다.

   **⚠️ 이 그림은 제품에 아직 없다** — 제품의 캠페인별은 그룹 막대다. 데이터(캠페인×일자
   ROAS)는 같고 표현만 다르다. 화면을 다시 손댈 일이 생기면 이 갈림을 먼저 확인할 것.

   축 200~350% / 격자 350·300·250 + 바닥 200. **y = (350 − 값) ÷ 150 × 100** 이므로
   축을 바꾸면 28개 좌표와 눈금 라벨 `top` 을 같이 옮겨야 한다. 오른쪽 끝 두 값은
   아래 성과 표의 08.24 ROAS 와 같은 수여야 한다(318 · 264). */
.perf-chart { margin-bottom: 0.7rem; }

/* 좌우로 눈금과 끝값이 앉을 자리를 비워 둔다 — 격자 위에 얹으면 선과 겹친다 */
.perf-chart-box { position: relative; padding: 10px 38px 0 44px; }
.perf-plot { position: relative; height: 100px; }
.perf-plot svg { display: block; width: 100%; height: 100px; }

.perf-ytick {
    position: absolute;
    transform: translateY(-50%);
    font-size: 9px;
    line-height: 1;
    color: var(--m-sub);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.perf-ytick.is-l { left: -44px; }

/* 격자는 실선 헤어라인이다 — 파선은 "임계치"로 읽혀 없는 뜻을 만든다 */
.perf-grid path { fill: none; stroke: var(--m-track); stroke-width: 1; }
.perf-grid path.is-base { stroke: var(--m-border); }

.perf-cline {
    fill: none;
    stroke: var(--c);
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
}

/* 점 — 길이 0 + round cap. 폭이 늘어나도 원이다 */
.perf-cpt path { fill: none; stroke: var(--c); stroke-width: 3.6; stroke-linecap: round; }

.perf-cend { fill: none; stroke: var(--c); stroke-width: 7; stroke-linecap: round; }

/* 끝점은 면 색 링을 깔아 두 선이 겹쳐도 서로를 먹지 않게 한다 —
   마크 둘레에 테두리를 그리는 것이 아니라 면이 갈라 준다 */
.perf-cend.is-ring { stroke: var(--m-surface); stroke-width: 11; }

/* 끝값만 직접 단다. **글자는 계열 색을 입지 않는다** — 주황(#E4701D)은 흰 바탕에서
   본문 대비 3.1:1 이라 마크로는 되지만 글자로는 못 읽는다. 정체는 옆에 붙은 선이 나른다 */
.perf-endlab {
    position: absolute;
    right: -38px;
    transform: translateY(-50%);
    font-size: 10px;
    font-weight: 600;
    color: var(--m-text);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.perf-chart-x {
    display: flex;
    justify-content: space-between;
    margin: 5px 38px 0 44px;
    font-size: 10px;
    color: var(--m-sub);
    font-variant-numeric: tabular-nums;
}

/* --- 범례 — 색만으로 정체를 말하지 않는다 --- */
.perf-legend {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.25rem 0.8rem;
    margin: 0 0 4px 44px;
}

.perf-lg {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-size: 10px;
    color: var(--m-sub);
}

.perf-lg > i { width: 8px; height: 8px; border-radius: 2px; flex: none; background: var(--c); }

.perf-lg-note {
    margin-left: auto;
    font-style: normal;
    font-size: 9px;
    color: var(--m-sub);
    white-space: nowrap;
}

/* 표의 캠페인 이름 앞 색점 — 차트 범례와 표를 같은 색으로 묶는다 */
.perf-cdot {
    display: inline-block;
    width: 6px;
    height: 6px;
    margin-right: 5px;
    border-radius: 2px;
    background: var(--c);
    vertical-align: middle;
}

/* --- 성과 표 — mockups.css 의 .mock-table 을 쓰고 열 폭만 다시 잡는다.
       캠페인 이름이 들어가면서 첫 열(날짜)은 좁고 둘째 열이 넓어야 한다 --- */
.perf-table th,
.perf-table td { padding: 0.3rem 0.2rem; font-size: 10px; }
.perf-table td { font-size: 11px; }
.perf-table th:first-child,
.perf-table td:first-child { width: 13%; }
.perf-table th:nth-child(2),
.perf-table td:nth-child(2) { width: 30%; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.perf-table td:first-child { font-weight: 600; color: var(--m-sub); }
.perf-table td:nth-child(2) { font-weight: 600; }

/* 표가 끝나는 자리에 선이 남으면 잘린 것처럼 보인다 */
.perf-table tbody tr:last-child td { border-bottom: 0; }

/* 360px 대에서는 tabular figure 폭 때문에 CTR(`3.24%`)이 2px 넘친다 — 셀 여백으로 되돌린다 */
@media (max-width: 400px) {
    .perf-table th,
    .perf-table td { padding-left: 0.1rem; padding-right: 0.1rem; }
}

/* --- 인사이트 카드 ------------------------------------------------------
   실제 인사이트 화면은 검색어 기준 실시간 노출 표 하나였다. 그건 **검색 광고 전용**이라
   커머스·여행·티켓 어디에나 붙는 축으로 바꿨다(2026-08-24 사용자) — 지면 / 시간대 / 구매자.
   **셋 다 아직 대시보드에 없는 화면이다**(데이터는 있다): 지면 단위 분해, 시간대별 성과,
   광고주에게 노출하는 구매자 인구통계. 넣기 전에 제공 범위를 확인할 것. */
.perf-card {
    padding: 9px 11px 11px;
    border: 1px solid var(--m-border);
    border-radius: 9px;
    background: var(--m-surface-2);
}

.perf-card + .perf-card { margin-top: 0.55rem; }

.perf-card-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
    margin-bottom: 8px;
}

.perf-card-head > b { font-size: 12px; color: var(--m-text); white-space: nowrap; }

.perf-card-head > em {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-style: normal;
    font-size: 10px;
    color: var(--m-sub);
}

/* --- 데이터 색 — 실제 대시보드에서 가져온다 -----------------------------
   목업이 온통 한 가지 파랑이라 **실제 대시보드와 동떨어져 보였다**(2026-08-24 사용자).
   맞는 지적이었다 — `rmp-ads-dashboard` 의 `PERFORMANCE_CHART_COLORS` 는 이미
   [주황 #fb7e2a · 초록 #16a34a · 핑크 #f44d78 · 파랑 #0971ce · 보라 #8979ff] 5색이다.
   목업은 *화면*이므로 지면 조각을 라이트로 그린 것과 같은 이유로 여기서도 제품을 따른다.

   다만 색은 **일이 있을 때만** 준다 — 아무 막대나 물들이면 막대 길이가 이미 말한 것을
   색으로 한 번 더 말하는 셈이다. 이 화면의 세 카드는 색이 하는 일이 각각 다르다:
     ① 지면별  = 부분-전체(계열 넷)     → 카테고리컬 4색
     ② 시간대별 = 피크 하나가 요점       → 강조(회색 + 액센트)
     ③ 성별    = 부분-전체(둘)         → 액센트 + 중립
        연령    = 순서가 있는 축         → 한 색 램프(옅음→짙음)

   값은 전부 검증기(dataviz `validate_palette.js`)를 통과한 것이다.
   **바꾸려면 눈으로 고르지 말고 다시 돌릴 것** — 회색 카드(#F9FAFB) 기준.
     · 카테고리컬 4색: 명도대·채도·CVD 분리·상시 시야 하한·대비 전부 PASS.
       **초록과 주황을 이웃에 두면 protan 에서 ΔE 2.8 로 붙는다** — 지금 순서(파랑·주황·
       보라·초록)가 그걸 피한 배치다. 제품의 주황 #fb7e2a 은 회색 면 대비 2.47:1 이라
       한 단계 내린 #e4701d 을 쓴다(3:1 통과)
     · 연령 램프: 단일 색상·단조 명도·인접 ΔL·옅은 끝 대비 전부 PASS.
       옅은 끝을 --blue-3(#A0C4FD) 로 두면 대비 1.70 으로 떨어진다 */
.perf-console {
    --dv-1: #0552CC;
    --dv-2: #E4701D;
    --dv-3: #8979FF;
    --dv-4: #16A34A;
    /* 강조 차트의 배경 계열 · 부분-전체의 나머지 쪽 */
    --dv-mute: #8B95A1;
    --dv-ctx: #A3ADB8;
    /* 연령 램프 */
    --dv-r1: #8CB2F7;
    --dv-r2: #5A90F2;
    --dv-r3: #2864DC;
    --dv-r4: #0B3F97;
}

/* --- 부분-전체 가로 스택 (지면 구성 / 성별) ---
   마디를 테두리로 가르지 않는다 — 면 색 2px 틈이 가른다 */
.perf-stack {
    display: flex;
    gap: 2px;
    height: 12px;
}

.perf-stack.is-sm { height: 9px; }

.perf-stack > span {
    width: var(--w);
    background: var(--c);
}

.perf-stack > span:first-child { border-radius: 4px 0 0 4px; }
.perf-stack > span:last-child { border-radius: 0 4px 4px 0; }

/* --- 스택의 범례 겸 표 — 색만으로 정체를 말하지 않는다 --- */
.perf-keys {
    display: flex;
    flex-direction: column;
    gap: 3px;
    margin-top: 9px;
}

.perf-key {
    display: grid;
    grid-template-columns: 7px 1fr auto auto auto;
    align-items: center;
    gap: 7px;
    font-size: 11px;
}

.perf-key > i {
    width: 7px;
    height: 7px;
    border-radius: 2px;
    background: var(--c);
}

.perf-key > span { color: var(--m-sub); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.perf-key > b {
    font-weight: 600;
    color: var(--m-text);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

.perf-key > u {
    text-decoration: none;
    color: var(--m-sub);
    text-align: right;
    font-variant-numeric: tabular-nums;
    min-width: 26px;
}

.perf-key > em {
    font-style: normal;
    font-size: 10px;
    color: var(--m-sub);
    text-align: right;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

/* 성별은 두 쪽뿐이라 목록이 아니라 **수치 한 쌍**으로 세운다 — 왼쪽 열이 짧아
   카드 아래가 비는 것을 막고, 숫자가 커져 대시보드의 요약 타일처럼 읽힌다 */
.perf-keys.is-inline {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 10px;
    margin-top: 11px;
}

.perf-keys.is-inline .perf-key {
    grid-template-columns: 7px auto;
    grid-template-rows: auto auto;
    row-gap: 3px;
    align-items: center;
}

.perf-keys.is-inline .perf-key > b {
    grid-column: 1 / -1;
    text-align: left;
    font-size: 15px;
    letter-spacing: -0.01em;
    /* 큰 숫자에는 tabular 을 쓰지 않는다 — 자간이 벌어져 헐렁해 보인다 */
    font-variant-numeric: normal;
}

/* --- 가로 막대 목록 (연령대) — 색은 --c 로 행마다 받는다 --- */
.perf-bars { display: flex; flex-direction: column; gap: 5px; }
.perf-bars.is-tight { gap: 4px; }

.perf-bar-row {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr) 34px;
    align-items: center;
    gap: 7px;
    font-size: 11px;
}

.perf-bar-row > span { color: var(--m-sub); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.perf-bar-row > i {
    height: 7px;
    border-radius: 4px;
    background: var(--gray-200);
    position: relative;
}

.perf-bar-row > i::after {
    content: '';
    position: absolute;
    inset: 0 auto 0 0;
    width: var(--w);
    border-radius: 4px;
    background: var(--c, var(--m-accent));
}

.perf-bar-row > b {
    font-weight: 600;
    color: var(--m-text);
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* --- 시간대 24칸 — 격자·바닥선이 있어야 도형이 아니라 차트로 읽힌다 ---
   **`.perf-plot` / `.perf-grid` 는 히어로 ROAS 차트가 이미 쓰는 이름이다.**
   그대로 썼다가 뒤에 온 선언이 이겨 히어로 플롯 높이가 100px → 52px 로 줄고
   x축·범례가 그래프 위로 올라탔다. 이 카드 것은 전부 `h` 접두사를 붙인다 */
.perf-hplot { position: relative; height: 52px; }

/* 격자는 실선 헤어라인이다. 파선은 "임계치"로 읽혀 없는 뜻을 만든다 */
.perf-hgrid {
    position: absolute;
    left: 0;
    right: 0;
    bottom: var(--y);
    height: 1px;
    background: var(--m-border);
}

/* 피크 구간을 면으로 한 번 더 말한다 — 막대 색만으로 두면 어디부터가 피크인지 흐리다 */
.perf-hband {
    position: absolute;
    top: 0;
    bottom: 1px;
    left: var(--from);
    right: calc(100% - var(--to));
    background: var(--m-accent-soft);
    border-radius: 3px 3px 0 0;
}

.perf-hours {
    position: absolute;
    inset: 0 0 1px;
    display: flex;
    align-items: flex-end;
    gap: 2px;
}

.perf-hours > i {
    flex: 1 1 0;
    min-width: 0;
    height: var(--h);
    border-radius: 3px 3px 0 0;
    /* 하루 곡선은 맥락이고 피크가 요점이다 — 맥락은 회색으로 내리고 피크만 켠다.
       종전엔 액센트를 opacity 0.22 로 눌러 24칸이 전부 파랑이었다.
       --gray-200 로는 회색 카드 위에서 곡선이 통째로 사라진다(대비 1.18) */
    background: var(--dv-ctx);
}

.perf-hours > i.is-peak { background: var(--m-accent); }

.perf-hours-x {
    display: flex;
    justify-content: space-between;
    margin-top: 5px;
    font-size: 9px;
    color: var(--m-sub);
    font-variant-numeric: tabular-nums;
}

/* --- 구매자 프로필 — 성별 / 연령 두 열 --- */
.perf-prof {
    display: grid;
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1fr);
    gap: 1rem;
    align-items: start;
}

.perf-sub {
    display: block;
    margin-bottom: 7px;
    font-size: 10px;
    font-weight: 600;
    color: var(--m-sub);
}

/* --- 반응형 — 나란히가 안 되는 폭에서는 위아래로 쌓는다 --- */
@media (max-width: 900px) {
    .perf-screens { grid-template-columns: minmax(0, 1fr); gap: 2rem; }
    .perf-console { flex: 0 0 auto; }
}

@media (max-width: 620px) {
    .perf-sum { grid-template-columns: repeat(2, minmax(0, 1fr)); row-gap: 0.55rem; }
    .perf-tabs { width: 100%; }
    .perf-tab { flex: 1 1 0; text-align: center; padding: 3px 0; }
    .perf-chart-box { padding: 10px 34px 0 38px; }
    .perf-ytick.is-l { left: -38px; }
    .perf-chart-x { margin: 5px 34px 0 38px; }
    .perf-endlab { right: -34px; }
    .perf-legend { margin-left: 38px; }
    .perf-lg-note { display: none; }
    .perf-table th:first-child,
    .perf-table td:first-child { width: 15%; }
    .perf-table th { white-space: normal; }
    .perf-prof { grid-template-columns: minmax(0, 1fr); gap: 0.9rem; }
    .perf-key { grid-template-columns: 7px 1fr auto auto; }
    .perf-key > em { display: none; }
}

/* [/RT-BLOCK] */
