// 이 파일이 하는 일: "Git 깊이 보기" 코스 — 커밋을 스냅샷으로 이해하는 것에서 출발해
// 브랜치·머지·충돌 해결·되돌리기·PR 리뷰 매너까지 8개 섹션으로 안내하는 정적 학습 페이지.
// (스냅샷 커밋 → 브랜치 → 머지 vs 리베이스 → 충돌 실전 → .gitignore → log/diff/stash → 되돌리기 3형제 → PR 매너 + 실습)
// 학습 포인트: API 호출이 없는 '내용 고정' 페이지다. 스타일은 global.css의
// 가이드 전용 클래스(step-card, code-block, tip 등)를 재사용한다 — 색을 여기서 하드코딩하지 않는다.
// 텍스트 다이어그램은 JSX 중괄호/백틱 충돌을 피하려고 파일 상단의 백틱 문자열 상수로 정의한다.

import { Link } from 'react-router-dom';

// ── 텍스트 다이어그램 · 예시 상수들 ──

const CODE_SNAPSHOT = `커밋 = 프로젝트 전체를 찍은 '사진' 한 장

시간 →
[사진1]────[사진2]────[사진3]────[사진4]
로그인    회원가입   버그 수정   디자인 개선
페이지    폼 추가              (지금 여기, HEAD)

- 커밋마다 "그 순간 프로젝트 전체의 모습"이 통째로 기록돼요.
  (변경된 부분만 저장하는 게 아니라, 스냅샷을 찍되 안 바뀐 파일은
   이전 사진 것을 재활용 — 그래서 빠르고 용량도 작아요.)
- 각 사진에는 고유 번호(해시)가 붙어요: a3f9c21 처럼.
- HEAD = "내가 지금 보고 있는 사진"을 가리키는 손가락.`;

const CODE_THREE_ZONES = `Git의 3단계 — 사진을 찍기까지

[작업 폴더]  →  git add  →  [스테이지]  →  git commit  →  [저장소]
 코드를 고침       "이 파일들     찰칵 준비 완료      사진첩에
                  사진에 넣자"                      정식 보관

비유: 단체 사진을 찍을 때
  작업 폴더 = 교실에서 각자 놀고 있는 상태
  스테이지  = "사진 찍을 사람 이리 모여!" 하고 줄 세운 상태
  커밋      = 찰칵! 사진첩에 붙이고 날짜·설명 기록

git add를 왜 따로 하냐면 — 고친 것 중 '일부만' 골라서
사진에 담을 수 있게 하려는 거예요. 관련 없는 수정을
한 커밋에 뒤섞지 않는 게 좋은 습관의 시작입니다.`;

const CODE_BRANCH = `브랜치 = 평행우주 분기점

            ┌──[C4]──[C5]   feature/login-page (실험 우주)
[C1]──[C2]──[C3]
            └──[C6]         main (원래 우주, 항상 안정)

- 브랜치를 만드는 건 "여기서부터 평행우주 하나 열게"라는 선언.
- 실험 우주에서 아무리 코드를 부숴도 main 우주는 멀쩡해요.
- 브랜치는 사실 커밋 하나를 가리키는 '이름표'일 뿐이라
  만드는 데 0.1초, 용량도 거의 0. 마음껏 만들어도 됩니다.

git switch -c feature/login-page   # 평행우주 열고 이동
git switch main                    # 원래 우주로 복귀`;

const CODE_MERGE_REBASE = `머지 vs 리베이스 — 평행우주를 합치는 두 가지 방법

① merge: 두 우주를 '합류'시키고 합류 지점을 기록
            ┌──[C4]──[C5]──┐
[C1]──[C2]──[C3]           [M]  ← 머지 커밋(합류 기념 사진)
            └──[C6]────────┘
   장점: 역사가 있는 그대로 남음 (누가 언제 갈라졌는지 다 보임)
   단점: 합류가 많아지면 그래프가 지하철 노선도처럼 복잡해짐

② rebase: 내 우주의 커밋들을 '들어 올려' 최신 지점 뒤로 옮겨 심기
[C1]──[C2]──[C3]──[C6]──[C4']──[C5']
   장점: 역사가 한 줄로 깔끔해짐
   단점: 커밋을 '다시 쓰는' 것이라, 이미 팀원과 공유한
         커밋에 하면 대혼란 (같은 사진이 두 장 생김)

우리 팀 기본 규칙: 잘 모르겠으면 merge.
rebase는 '아직 나 혼자만 가진 커밋'에만 쓰세요.`;

const CODE_CONFLICT = `충돌이 났을 때 파일에 나타나는 것 — 외계어 아님!

<<<<<<< HEAD
  const title = "어썸데브 학습 센터";
=======
  const title = "AWESOMEDEV 학습 플랫폼";
>>>>>>> feature/rename

읽는 법:
  <<<<<<< HEAD  부터 =======  까지 → 내 우주(현재 브랜치)의 내용
  =======  부터 >>>>>>>  까지     → 상대 우주(합치려는 브랜치)의 내용

Git이 하는 말은 딱 하나예요:
"같은 줄을 두 우주에서 다르게 고쳤는데, 어느 쪽이 맞는지
 나는 판단 못 하겠어. 사람이 골라 줘."

해결 절차 (3단계):
1) 두 내용을 읽고 → 하나를 고르거나, 둘을 합쳐 새로 씀
2) <<<<<<< ======= >>>>>>> 마커 줄들을 전부 지움
3) git add 해당파일 → git commit  (해결 완료 선언!)`;

const CODE_GITIGNORE = `.gitignore — "이건 사진에 찍지 마" 명단

# mirim-app 프론트엔드의 실제 .gitignore와 비슷한 예:
node_modules/     # 라이브러리 창고 — npm install로 언제든 재생성
dist/             # 빌드 결과물 — 소스에서 다시 만들 수 있음
.env              # 비밀번호·API 키 — 절대 저장소에 올리면 안 됨!
*.log             # 로그 파일 — 내 PC에서만 의미 있음

원리: git은 커밋할 때 이 명단의 파일들을 '아예 없는 셈' 쳐요.
기준은 간단합니다 — "다시 만들 수 있거나, 비밀이거나, 나만의 것"
이면 ignore. 손으로 쓴 소스 코드면 커밋.

주의: 이미 한 번 커밋된 파일은 나중에 .gitignore에 추가해도
계속 추적돼요. (사진첩에 이미 붙은 사진은 명단으로 못 빼요 —
git rm --cached 파일명 으로 추적을 먼저 끊어야 합니다.)`;

const CODE_LOG_DIFF_STASH = `사진첩을 탐험하는 세 가지 도구

# log — 사진첩 넘겨 보기
git log --oneline --graph --all
  * a3f9c21 (HEAD -> main) 로그인 버그 수정
  * 7be0d44 회원가입 폼 추가
  * 1c2e9ab 프로젝트 시작

# diff — 두 사진의 '다른 그림 찾기'
git diff                    # 작업 폴더 vs 마지막 커밋
git diff main feature/x     # 두 브랜치 사이 차이
  - const port = 3000;      ← 빨간 줄: 지워진 내용
  + const port = 8080;      ← 초록 줄: 새로 생긴 내용

# stash — 하던 일 '서랍에 임시 보관'
git stash        # 지금 수정 중인 것들을 서랍에 넣고 폴더를 깨끗하게
git stash pop    # 서랍에서 도로 꺼내기
  쓰는 순간: 작업 중인데 "급한 버그부터 고쳐줘!" 요청이 왔을 때.
  커밋하기엔 애매한 미완성 코드를 잠시 치워두는 용도예요.`;

const CODE_UNDO_TRIO = `되돌리기 3형제 — 위험도 순으로 줄 세우기

① checkout(switch/restore) — 위험도 ★☆☆ "구경만"
   git checkout a3f9c21        # 과거 사진 시점으로 '구경' 가기
   git restore 파일명           # 파일 하나를 마지막 커밋 상태로 복원
   → 역사를 바꾸지 않아요. 단, restore는 저장 안 한 수정을 날림!

② revert — 위험도 ★★☆ "반대 사진을 새로 찍기"
   git revert a3f9c21
   → 그 커밋의 정반대 내용을 '새 커밋'으로 추가.
     역사를 지우지 않고 되돌려서, 팀과 공유한 브랜치에서도 안전.
     실무에서 "그 기능 롤백해 주세요"는 대부분 이것.

③ reset — 위험도 ★★★ "사진첩에서 사진을 뜯어냄"
   git reset --hard a3f9c21
   → 그 이후 커밋들이 역사에서 사라짐. --hard는 작업 내용까지 삭제.
     이미 push한 커밋에 쓰면 팀원들의 역사와 어긋나 대참사.

한 줄 요약: 공유 전엔 reset도 OK, 공유 후엔 무조건 revert,
확신이 없으면 일단 멘토에게. (reset --hard는 Ctrl+Z가 없어요!)`;

const CODE_PR_MANNERS = `PR(Pull Request) 리뷰 매너 — 주고받기 양쪽 다

[보내는 사람 (PR 올릴 때)]
- 제목만 봐도 알게: "feat: 출석 체크 페이지 추가" (X: "수정함")
- 설명에 3줄: 뭘 / 왜 / 어떻게 확인하면 되는지
- 작게 쪼개기: 파일 30개짜리 PR은 리뷰가 아니라 고행이에요
- 올리기 전 셀프 리뷰: 내 diff를 내가 먼저 한 번 읽기

[리뷰하는 사람 (댓글 달 때)]
- 코드를 비판하지, 사람을 비판하지 않기
  (X) "이걸 왜 이렇게 짰어요?"
  (O) "이 부분은 map을 쓰면 더 짧아질 것 같아요. 어떻게 생각해요?"
- 좋은 부분도 말하기: "이 변수 이름 정말 알아보기 쉽네요"
- 제안과 필수를 구분: "취향 차이지만~" / "이건 버그라 꼭 수정 필요"

[받는 사람 (리뷰 답할 때)]
- 리뷰는 나에 대한 공격이 아니라 코드를 향한 선물
- 반영했으면 "반영했습니다 + 커밋 링크", 생각이 다르면 근거로 토론
- 이해 안 되면 그냥 물어보기 — 질문은 신입의 특권입니다`;

const CODE_CONFLICT_LAB = `실습: 일부러 충돌을 만들어 해결해 보기 (내 PC, 10분)

# 0) 연습용 새 저장소 만들기 (진짜 프로젝트 아님, 마음껏 부숴도 됨)
mkdir git-lab && cd git-lab
git init
echo 안녕하세요 > hello.txt
git add . && git commit -m "첫 커밋"

# 1) 평행우주를 열고, 같은 줄을 다르게 고치기
git switch -c universe-a
echo 어썸데브 > hello.txt
git commit -am "우주 A: 어썸데브로 변경"

git switch main
echo 미림마이스터고 > hello.txt
git commit -am "main: 미림으로 변경"

# 2) 합치기 → 충돌 발생! (당황 금지, 예정된 이벤트)
git merge universe-a
#   CONFLICT (content): Merge conflict in hello.txt

# 3) hello.txt를 열면 <<<<<<< ======= >>>>>>> 마커가 보여요.
#    섹션 4의 3단계대로: 내용 고르기 → 마커 지우기 → add & commit
git add hello.txt
git commit -m "충돌 해결: 두 문구를 합침"

# 4) 결과 감상
git log --oneline --graph
#    두 우주가 합류한 그래프가 보이면 성공!`;

// ── 이 페이지 안에서만 쓰는 작은 부품들 ──
// 학습 포인트: 같은 모양이 반복되면 컴포넌트로 뽑는다. props만 바꿔 재사용.
function Section({ n, title, sub, children }) {
  return (
    <section className="step-card" id={`sec-${n}`}>
      <div className="step-head">
        <span className="step-num">{n}</span>
        <div>
          <h3>{title}</h3>
          {sub && <span className="step-sub">{sub}</span>}
        </div>
      </div>
      <div className="step-body">{children}</div>
    </section>
  );
}

function Code({ children }) {
  return <pre className="code-block"><code>{children}</code></pre>;
}

const SECTIONS = [
  { n: 1, label: '커밋 = 스냅샷' },
  { n: 2, label: '브랜치 = 평행우주' },
  { n: 3, label: '머지 vs 리베이스' },
  { n: 4, label: '충돌 해결 실전' },
  { n: 5, label: '.gitignore' },
  { n: 6, label: 'log·diff·stash' },
  { n: 7, label: '되돌리기 3형제' },
  { n: 8, label: 'PR 매너 + 실습' },
];

export default function GitDeepPage() {
  return (
    <div>
      {/* 히어로: 이 코스가 어디서 출발해 어디까지 가는지 */}
      <div className="hero">
        <div className="eyebrow">Course · 소프트웨어</div>
        <h1>Git 깊이 보기<br />— 사진첩에서 평행우주까지</h1>
        <p>
          add·commit·push를 외워서 쓰는 단계를 졸업하고, Git이 <strong>속으로 무슨 생각을
          하는지</strong> 이해하는 코스예요. 충돌 마커를 봐도 겁나지 않고, 실수를 해도
          스스로 되돌릴 수 있게 되는 것 — 그게 이 코스의 목표입니다.
        </p>
        <div className="chip-row">
          <span className="chip">예상 소요 90분</span>
          <span className="chip">실습 3개 포함</span>
          <span className="chip">준비물: Git 설치된 내 PC</span>
        </div>
      </div>

      {/* 섹션 바로가기 */}
      <nav className="pill-nav">
        {SECTIONS.map((s) => (
          <a key={s.n} href={`#sec-${s.n}`}>
            <b>{s.n}</b>
            {s.label}
          </a>
        ))}
      </nav>

      <Section n={1} title="커밋 = 프로젝트의 스냅샷" sub="Git은 변경 기록이 아니라 '사진첩'이다">
        <p>
          Git을 처음 배울 때 가장 큰 오해가 "커밋 = 바뀐 부분의 기록"이라는 거예요.
          아닙니다. 커밋은 <strong>그 순간 프로젝트 전체를 통째로 찍은 사진 한 장</strong>이에요.
          여러분의 폰 사진첩과 똑같아요 — 어제 사진과 오늘 사진은 각각 완전한 사진이지,
          "어제와 달라진 픽셀 목록"이 아니잖아요.
        </p>
        <Code>{CODE_SNAPSHOT}</Code>
        <p>
          그리고 사진을 찍기 전에 <strong>줄 세우는 단계</strong>가 하나 있어요.
          이게 처음엔 번거로워 보이지만, Git을 잘 쓰는 사람과 못 쓰는 사람을
          가르는 핵심 개념입니다.
        </p>
        <Code>{CODE_THREE_ZONES}</Code>
        <div className="tip">
          <b>직접 확인해 보기</b> 우리 학습 플랫폼 저장소를 클론받았다면 그 폴더에서{' '}
          <span className="icode">git log --oneline</span>을 쳐 보세요. 지금까지 찍힌
          사진(커밋)들의 목록이 최신순으로 나와요. 맨 위 7자리 코드가 바로 그 사진의
          고유 번호(해시)입니다. Gitea(edu.awesomedevapp.com:3000)에서 같은 저장소의
          커밋 목록을 열어 두 화면이 똑같은지 비교해 보세요.
        </div>
      </Section>

      <Section n={2} title="브랜치 = 평행우주" sub="만드는 데 0.1초, 부숴도 안전한 실험실">
        <p>
          "지금 잘 돌아가는 코드를 건드리기 무서워요" — 모든 개발자의 공통 고민이고,
          Git의 답이 <strong>브랜치</strong>예요. 브랜치를 만드는 순간, 지금 이 지점에서
          <strong> 평행우주</strong>가 하나 열립니다. 그 우주에서 코드를 아무리 부수고
          실험해도 원래 우주(<span className="icode">main</span>)는 1도 안 변해요.
        </p>
        <Code>{CODE_BRANCH}</Code>
        <p>
          더 놀라운 건 비용이에요. 브랜치는 프로젝트를 복사하는 게 아니라
          <strong> 커밋 하나를 가리키는 이름표</strong>일 뿐이라, 파일이 10만 개여도
          브랜치 생성은 즉시 끝납니다. 그래서 실무에서는 <strong>기능 하나 = 브랜치 하나</strong>가
          기본이에요. 우리 회사도 <span className="icode">feature/기능이름</span> 브랜치에서
          작업하고, 완성되면 PR로 <span className="icode">main</span>에 합칩니다.
        </p>
        <svg className="diagram" viewBox="0 0 640 240" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="main 브랜치의 C3 커밋에서 feature 브랜치가 갈라져 나온 그래프">
          <line x1="80" y1="170" x2="430" y2="170" stroke="var(--primary)" strokeWidth="2.5" strokeLinecap="round" />
          <line x1="300" y1="170" x2="380" y2="80" stroke="var(--teal)" strokeWidth="2.5" strokeLinecap="round" />
          <line x1="380" y1="80" x2="470" y2="80" stroke="var(--teal)" strokeWidth="2.5" strokeLinecap="round" />
          <circle cx="80" cy="170" r="15" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="80" y="174" textAnchor="middle" fontSize="12" fill="var(--ink)">C1</text>
          <circle cx="190" cy="170" r="15" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="190" y="174" textAnchor="middle" fontSize="12" fill="var(--ink)">C2</text>
          <circle cx="300" cy="170" r="15" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="300" y="174" textAnchor="middle" fontSize="12" fill="var(--ink)">C3</text>
          <circle cx="430" cy="170" r="15" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="430" y="174" textAnchor="middle" fontSize="12" fill="var(--ink)">C6</text>
          <circle cx="380" cy="80" r="15" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="380" y="84" textAnchor="middle" fontSize="12" fill="var(--ink)">C4</text>
          <circle cx="470" cy="80" r="15" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="470" y="84" textAnchor="middle" fontSize="12" fill="var(--ink)">C5</text>
          <text x="425" y="46" textAnchor="middle" fontSize="13" fontWeight="700" fill="var(--teal)">feature/login-page (실험 우주)</text>
          <text x="460" y="175" fontSize="13" fontWeight="700" fill="var(--primary)">main (원래 우주)</text>
          <text x="300" y="212" textAnchor="middle" fontSize="12" fill="var(--muted)">분기점 — 여기(C3)서 평행우주가 열려요</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: C3에서 feature 브랜치가 갈라져도 main 우주는 그대로 안전하다</p>
        <div className="warn">
          <b>흔한 실수</b> — <span className="icode">main</span>에서 바로 작업하다가
          "아 브랜치 안 만들었다!" 하는 경우. 괜찮아요, 커밋 전이라면{' '}
          <span className="icode">git switch -c feature/새브랜치</span>를 치는 순간
          지금까지의 수정 내용이 새 브랜치로 그대로 따라옵니다.
        </div>
      </Section>

      <Section n={3} title="머지 vs 리베이스" sub="평행우주를 합치는 두 가지 철학 (개념만!)">
        <p>
          평행우주를 열었으면 언젠가 다시 합쳐야죠. 방법이 두 가지인데,
          <strong> 결과 코드는 같아도 '역사책'이 다르게 쓰여요.</strong>
        </p>
        <Code>{CODE_MERGE_REBASE}</Code>
        <p>
          비유하면 이래요. <strong>머지</strong>는 "두 반이 따로 수학여행 갔다가 합류했다"고
          역사책에 있는 그대로 쓰는 것. <strong>리베이스</strong>는 "처음부터 한 반이
          쭉 같이 다닌 것처럼" 역사책을 다시 쓰는 것. 다시 쓴 역사책이 읽기엔 깔끔하지만,
          이미 옛 역사책을 <strong>복사해 간 사람(=push된 커밋을 받은 팀원)</strong>이 있다면
          두 역사책이 충돌해 난리가 나요.
        </p>
        <svg className="diagram" viewBox="0 0 640 370" xmlns="http://www.w3.org/2000/svg" role="img" aria-label="머지와 리베이스가 만드는 커밋 그래프 비교">
          <text x="24" y="30" fontSize="14" fontWeight="700" fill="var(--ink)">① merge — 두 우주의 합류를 그대로 기록</text>
          <line x1="70" y1="125" x2="230" y2="125" stroke="var(--primary)" strokeWidth="2.5" strokeLinecap="round" />
          <line x1="230" y1="125" x2="330" y2="80" stroke="var(--teal)" strokeWidth="2.5" strokeLinecap="round" />
          <line x1="330" y1="80" x2="420" y2="80" stroke="var(--teal)" strokeWidth="2.5" strokeLinecap="round" />
          <line x1="420" y1="80" x2="520" y2="125" stroke="var(--teal)" strokeWidth="2.5" strokeLinecap="round" />
          <line x1="230" y1="125" x2="375" y2="170" stroke="var(--primary)" strokeWidth="2.5" strokeLinecap="round" />
          <line x1="375" y1="170" x2="520" y2="125" stroke="var(--primary)" strokeWidth="2.5" strokeLinecap="round" />
          <circle cx="70" cy="125" r="14" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="70" y="129" textAnchor="middle" fontSize="12" fill="var(--ink)">C1</text>
          <circle cx="150" cy="125" r="14" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="150" y="129" textAnchor="middle" fontSize="12" fill="var(--ink)">C2</text>
          <circle cx="230" cy="125" r="14" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="230" y="129" textAnchor="middle" fontSize="12" fill="var(--ink)">C3</text>
          <circle cx="330" cy="80" r="14" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="330" y="84" textAnchor="middle" fontSize="12" fill="var(--ink)">C4</text>
          <circle cx="420" cy="80" r="14" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="420" y="84" textAnchor="middle" fontSize="12" fill="var(--ink)">C5</text>
          <circle cx="375" cy="170" r="14" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="375" y="174" textAnchor="middle" fontSize="12" fill="var(--ink)">C6</text>
          <circle cx="520" cy="125" r="14" fill="var(--card)" stroke="var(--amber)" strokeWidth="2.5" />
          <text x="520" y="129" textAnchor="middle" fontSize="12" fontWeight="700" fill="var(--ink)">M</text>
          <text x="546" y="129" fontSize="12" fill="var(--muted)">머지 커밋</text>
          <line x1="24" y1="212" x2="616" y2="212" stroke="var(--line)" strokeWidth="1" strokeDasharray="4 4" />
          <text x="24" y="248" fontSize="14" fontWeight="700" fill="var(--ink)">② rebase — 커밋을 옮겨 심어 역사를 한 줄로</text>
          <line x1="70" y1="300" x2="310" y2="300" stroke="var(--primary)" strokeWidth="2.5" strokeLinecap="round" />
          <line x1="310" y1="300" x2="490" y2="300" stroke="var(--teal)" strokeWidth="2.5" strokeLinecap="round" />
          <circle cx="70" cy="300" r="14" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="70" y="304" textAnchor="middle" fontSize="12" fill="var(--ink)">C1</text>
          <circle cx="150" cy="300" r="14" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="150" y="304" textAnchor="middle" fontSize="12" fill="var(--ink)">C2</text>
          <circle cx="230" cy="300" r="14" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="230" y="304" textAnchor="middle" fontSize="12" fill="var(--ink)">C3</text>
          <circle cx="310" cy="300" r="14" fill="var(--card)" stroke="var(--primary)" strokeWidth="2" />
          <text x="310" y="304" textAnchor="middle" fontSize="12" fill="var(--ink)">C6</text>
          <circle cx="400" cy="300" r="14" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="400" y="304" textAnchor="middle" fontSize="12" fill="var(--ink)">C4'</text>
          <circle cx="490" cy="300" r="14" fill="var(--card)" stroke="var(--teal)" strokeWidth="2" />
          <text x="490" y="304" textAnchor="middle" fontSize="12" fill="var(--ink)">C5'</text>
          <text x="445" y="345" textAnchor="middle" fontSize="12" fill="var(--muted)">옮겨 심은 커밋 — 해시가 바뀌어요 (C4 → C4')</text>
        </svg>
        <p className="muted" style={{ fontSize: 12.5, textAlign: 'center', marginTop: 2 }}>그림: 같은 작업도 merge는 합류 지점(M)을 남기고, rebase는 역사를 한 줄로 다시 쓴다</p>
        <div className="tip">
          <b>수습 단계 처방전</b> — 지금은 <strong>merge만 써도 충분</strong>해요.
          리베이스는 "이런 게 있다"만 알아 두고, 나중에 혼자만의 로컬 커밋을 정리하고
          싶어질 때 멘토와 함께 처음 해 보세요.
        </div>
      </Section>

      <Section n={4} title="충돌 해결 실전" sub="<<<<<<< 마커는 에러가 아니라 질문이다">
        <p>
          두 우주에서 <strong>같은 파일의 같은 줄</strong>을 다르게 고쳤다면?
          Git은 어느 쪽이 맞는지 판단할 수 없으니 여러분에게 질문을 던져요.
          그 질문지가 바로 악명 높은 충돌 마커입니다. 처음 보면 파일이 깨진 것 같아
          심장이 철렁하지만 — <strong>파일은 안 깨졌고, Git은 화나지 않았어요.</strong>
          그냥 객관식 문제가 하나 출제된 것뿐이에요.
        </p>
        <Code>{CODE_CONFLICT}</Code>
        <p>
          답은 셋 중 하나예요. <strong>내 것을 고르거나, 상대 것을 고르거나,
          둘을 읽고 더 나은 제3의 코드를 새로 쓰거나.</strong> 셋 다 정답이 될 수 있고,
          뭐가 맞는지는 코드의 맥락이 정해 줍니다. VS Code를 쓰면 충돌 구간 위에
          "Accept Current / Accept Incoming / Accept Both" 버튼이 떠서 클릭으로도
          고를 수 있어요 — 하지만 원리(마커 읽기)를 알고 누르는 것과 모르고 누르는 것은
          하늘과 땅 차이입니다.
        </p>
        <div className="warn">
          <b>진짜 사고는 이것</b> — 충돌 자체가 아니라, 마커를 <strong>안 지우고</strong>{' '}
          커밋해 버리는 것. <span className="icode">&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD</span> 같은
          줄이 코드에 남으면 당연히 빌드가 깨져요. 해결 후 커밋 전에 파일을 한 번 더
          훑어보는 습관을 들이세요.
        </div>
      </Section>

      <Section n={5} title=".gitignore의 원리" sub="사진에 찍히면 안 되는 것들의 명단">
        <p>
          프로젝트 폴더의 모든 파일이 사진첩에 들어가야 할까요? 아니에요.{' '}
          <span className="icode">node_modules</span>는 라이브러리 수천 개가 든 창고라
          용량이 수백 MB인데, <span className="icode">npm install</span> 한 방이면 언제든
          다시 만들 수 있어요. <span className="icode">.env</span>에는 DB 비밀번호 같은
          비밀이 들어 있고요. 이런 것들은 <strong>사진에 찍히면 안 되는 명단</strong>,
          즉 <span className="icode">.gitignore</span>에 올립니다.
        </p>
        <Code>{CODE_GITIGNORE}</Code>
        <div className="warn">
          <b>비밀은 한 번 찍히면 끝</b> — <span className="icode">.env</span>를 실수로
          커밋해서 push까지 했다면, 나중에 지워도 <strong>과거 사진(커밋 이력)에는 영원히
          남아요.</strong> 이 경우 파일 삭제가 아니라 <strong>비밀번호·키 자체를 교체</strong>해야
          합니다. 사고가 났다면 숨기지 말고 즉시 멘토에게 알리세요 — 빠른 보고가
          가장 훌륭한 대처예요.
        </div>
        <div className="tip">
          <b>직접 확인해 보기</b> 우리 플랫폼 프론트엔드 폴더에서{' '}
          <span className="icode">.gitignore</span> 파일을 열어 보세요. 그리고{' '}
          <span className="icode">git status</span>를 쳤을 때{' '}
          <span className="icode">node_modules</span>가 목록에 <strong>안 보이는 것</strong>을
          확인하세요. 수천 개 파일이 있는데도 Git이 완벽하게 못 본 척하고 있는 겁니다.
        </div>
      </Section>

      <Section n={6} title="log · diff · stash" sub="사진첩 넘기기, 다른 그림 찾기, 서랍에 넣어두기">
        <p>
          이 셋은 코드를 <strong>바꾸지 않는</strong> 탐험 도구(stash만 살짝 예외)라서
          아무리 써도 안전해요. 그래서 제일 자주, 제일 편하게 쓰게 되는 명령들입니다.
        </p>
        <Code>{CODE_LOG_DIFF_STASH}</Code>
        <p>
          특히 <span className="icode">git diff</span>는 <strong>커밋 버튼을 누르기 전의
          마지막 거울</strong>이에요. "내가 지금 뭘 바꿨더라?"를 눈으로 확인하고 커밋하는
          사람과, 확인 없이 <span className="icode">git add .</span>부터 치는 사람의
          커밋 품질은 시간이 갈수록 벌어집니다.
        </p>
        <div className="tip">
          <b>직접 확인해 보기</b> 아무 저장소에서 파일 하나를 살짝 고친 뒤{' '}
          <span className="icode">git diff</span> → <span className="icode">git stash</span>{' '}
          → 파일이 원래대로 돌아간 것 확인 → <span className="icode">git stash pop</span> →
          수정이 되살아난 것까지 확인해 보세요. "서랍에 넣었다 꺼내기" 한 사이클을
          손으로 돌려 보면 절대 안 잊어버려요.
        </div>
      </Section>

      <Section n={7} title="되돌리기 3형제" sub="checkout · revert · reset — 위험도가 전부 다르다">
        <p>
          실수했을 때 쓰는 명령이 세 개나 되는 이유는, <strong>"되돌린다"의 의미가
          세 가지</strong>이기 때문이에요. 과거를 <strong>구경</strong>만 할지,
          과거의 반대를 <strong>새로 기록</strong>할지, 아예 역사를 <strong>지울지</strong>.
          위험도가 완전히 다르니 꼭 구분해서 기억하세요.
        </p>
        <Code>{CODE_UNDO_TRIO}</Code>
        <p>
          기억법: <strong>checkout은 타임머신 관광</strong>(역사 그대로),{' '}
          <strong>revert는 정정 보도</strong>(틀린 기사를 지우지 않고 정정 기사를 새로 냄),{' '}
          <strong>reset은 신문사 창고 방화</strong>(기사 자체를 없앰 — 혼자 볼 일기장에서만!).
          push한 커밋 앞에서 <span className="icode">reset --hard</span>가 손가락에
          맴돌면, 그건 명령어를 칠 때가 아니라 멘토를 부를 때예요.
        </p>
        <div className="tip">
          <b>안심 포인트</b> — 사실 Git에서 커밋까지 마친 코드는 웬만해선 안 사라져요.{' '}
          <span className="icode">git reflog</span>라는 "HEAD의 블랙박스"가 있어서,
          reset으로 날린 커밋도 대부분 구조할 수 있습니다. 그러니 실수해도 우선 침착하게 —
          단, <strong>커밋 안 한 수정</strong>은 구조 불가이니 작업이 아까우면 자주 커밋!
        </div>
      </Section>

      <Section n={8} title="PR 리뷰 매너 + 실습" sub="코드는 함께 만드는 것 — 그리고 충돌을 직접 겪어 보기">
        <p>
          어썸데브에서 여러분의 코드는 PR을 거쳐 <span className="icode">main</span>에
          들어가요. PR은 시험 제출이 아니라 <strong>대화의 시작</strong>입니다.
          리뷰를 주고받는 매너가 곧 팀 개발 실력이에요.
        </p>
        <Code>{CODE_PR_MANNERS}</Code>
        <p>
          마지막으로, 이 코스의 하이라이트 실습이에요. 충돌은 <strong>피하는 게 아니라
          익숙해지는 것</strong>이고, 익숙해지는 가장 빠른 길은 안전한 곳에서 일부러
          한 번 겪어 보는 겁니다.
        </p>
        <div className="tip">
          <b>직접 확인해 보기 (메인 실습)</b> 아래를 터미널에 한 줄씩 그대로 따라 치세요.
          연습용 폴더라 뭘 해도 안전해요. 3단계에서 충돌 마커를 만나면 —
          이제 여러분은 읽는 법을 압니다.
        </div>
        <Code>{CODE_CONFLICT_LAB}</Code>
        <div className="tip">
          <b>한 걸음 더</b> — 같은 실습을 Gitea(edu.awesomedevapp.com:3000)의 개인 연습
          저장소에 push해서, 브랜치 두 개로 PR을 만들어 보세요. 웹 화면에서
          "충돌이 있어 자동 머지 불가" 표시가 뜨는 것까지 보면, 로컬과 원격의
          충돌 경험이 하나로 이어집니다.
        </div>
      </Section>

      <div className="step-card">
        <div className="step-body">
          <h3 style={{ marginBottom: 6 }}>🌿 여기까지 왔다면</h3>
          <p className="muted">
            이제 커밋은 <strong>사진</strong>, 브랜치는 <strong>평행우주</strong>,
            충돌 마커는 <strong>객관식 질문</strong>으로 보일 거예요. 되돌리기 3형제의
            위험도를 구분할 줄 알고, PR에서 리뷰를 주고받는 매너까지 챙겼다면 팀 개발
            준비 완료입니다. 다음은 여러분이 만든 브랜치가 실제 서버에 올라가는 여정 —{' '}
            <Link to="/learn/network"><strong>네트워크의 이해</strong></Link> 코스에서
            push된 코드가 어떤 길로 배포 서버까지 달려가는지 이어서 배워 보세요.
            그리고 오늘 배운 충돌 해결 실습을 마쳤다면, 멘토에게{' '}
            <span className="icode">git log --oneline --graph</span> 결과를 보여 주며
            과제 체크를 받아 보세요.
          </p>
        </div>
      </div>
    </div>
  );
}
