Antigravity로 국어 문법 연습 웹페이지 만들기

소개

모두들 열심히 연습하고 올리시는 게시글에 자극받아 저도 연습했습니다.
국어 문법 - 피동표현 웹페이지 만들기입니다.

진행 방법

1.gemini에게 Antigravity에 넣을 프롬프트 만들어 달라고 했습니다 .

피동표현과 인용표현 단원을 공부하기 위한 웹페이지 만들고 싶어.

안티그래비티에 넣을 프롬프트 작성해줘.

PDF내용 참고해줘.

대상 : 중학생(문법 지식이 매우 부족하고, 사고력도 안 좋은 학생)

내용 : 피동 개념, 피동 만드는 방법, 피동 표현의 의도와 효과, 올바르지 않은 피동 표현

세부사항 : 각 설명마다 다음 PDF에 나오는 예를 활용해 사례를 들 것

퀴즈로 피동표현 만들기, 피동 표현의 의도와 효과, 올바르지 않은 피동표현을 문제로 내줘. 10개 정도.

학생들이 쉽고 재미 있게 내용을 따라 가며 익힐 수 있게 해줘.



2. 프롬프트 만들어 주었습니다.

안티그래비티에서 더 완벽한 웹페이지를 만드실 수 있도록, PDF의 구체적인 예시들을 녹여낸 '최종 프롬프트'를 다시 정리해 드릴게요. 이 내용을 복사해서 사용하세요.


📋 안티그래비티 입력용 최종 프롬프트

[설정]

  • 역할: 중학생 눈높이에 맞춘 친절한 국어 선생님

  • 대상: 문법 기초가 부족하고 사고력이 낮은 중학교 2학년 학생

  • 목적: PDF 내용을 바탕으로 '피동 표현'을 쉽고 재미있게 학습하는 웹페이지 제작

[웹페이지 구성 내용]

1. 도입: 피동이 뭐야? (당하는 주인공!)

  • 주어가 제 힘으로 하는 '능동'과 남에게 당하는 '피동'의 차이를 이미지와 함께 설명해줘.

  • PDF 예시 활용:

    • "벌이 동생을 쏘았어(능동)" vs "동생이 벌에 쏘였어(피동)"

    • "사냥꾼이 토끼를 잡았다(능동)" vs "토끼가 사냥꾼에게 잡혔다(피동)"

2. 변신 공식: 피동 표현 만드는 법

  • 학생들이 이해하기 쉽게 '동사에 마법의 글자 넣기'로 설명해줘.

  • 공식 1: '이, 히, 리, 기' 붙이기 (예: 보이다, 닫히다, 물리다, 안기다)

  • 공식 2: '-아지다/-어지다' 붙이기 (예: 나누어지다, 끊어지다)

  • 공식 3: '-되다' 붙이기 (예: 사용되다, 형성되다)

3. 왜 쓸까?: 피동 표현의 의도와 효과

  • 강조: 당하는 대상을 주인공으로 만들고 싶을 때

  • 책임 회피: 누가 했는지 모르거나 숨기고 싶을 때 (예: "컵이 깨졌어요")

  • 객관성: 뉴스나 일보 예보처럼 사실만 전달할 때

4. 주의보!: 올바르지 않은 피동 표현

  • 이중 피동(두 번 당하기)의 어색함을 지적해줘.

  • 수정 사례: '보여지다' → '보이다', '잊혀지다' → '잊히다', '나뉘어지다' → '나뉘다'

5. 실전 퀴즈: 10문제 (정답/해설 포함)

  • 다음 중 피동문인 것은?

  • 능동문을 피동문으로 바꾸기 (예: "경찰이 도둑을 잡았다")

  • 다음 대화에서 피동 표현을 쓴 이유는?

  • 어색한 이중 피동 표현 고쳐 쓰기 (예: "문이 열려졌다")

[디자인 요청]

  • 글자 크기를 크게 하고, 중요한 단어는 굵게 표시해줘.

  • 중학생들이 좋아할 만한 귀여운 이모지를 많이 사용해줘.

  • 단계별로 버튼을 눌러 다음 내용으로 넘어가게 구성해줘.


💡 팁

안티그래비티에 PDF를 올리실 때, 제가 위 프롬프트에 적어드린 PDF 예시(벌, 동생, 사냥꾼 등)가 실제 파일 내용과 일치하므로 안티그래비티가 내용을 훨씬 더 잘 이해하고 페이지를 풍성하게 만들어줄 거예요! 도움이 더 필요하시면 언제든 말씀해 주세요.

  1. 5분도 안 되어 만들어 주었습니다.

    한국어 vs 중국 한국어 vs 중국 한국어 vs


  2. 추가 요청
    -마우스 대면 박스가 활성화 되도록 해달라고 했습니다.
    -개념 설명 부분에 바로 테스트 할 수 있도록 예시를 만들어 달라고 했습니다.
    -문제 맞추면 폭죽 터트리고 축하 벨소리도 넣어달라고 했습니다.

  3. Netlify에 가서 폴더 끌어다 넣어 바로 베포했습니다. 10초도 안 걸리네요^^

  4. 학생에게 링크 보냈습니다. 연락 오면 후기 달게요~

결과와 배운 점

결과물입니다.

https://pidongpidong.netlify.app/

이제 이 정도의 웹페이지는 진짜 '딸깍'하는 느낌입니다.
지난주만 해도 뭔가 시간이 오래 걸렸는데
뭐 때문에 그랬는지 제가 이해 안 가네요. ㅋㅋㅋ
개구리 올챙이적 생각하는 건 참 어렵다는.....

기획과 아이디어가 중요한 시대라는 생각이 점점 듭니다.
저희 학원에선 학생들에게 기획 훈련을 많이 시키는데요~
국영수 모두 만점 받는 학생도 이상하게 기획을 정말 못해요.
자기가 만들고 싶은 주제도 잘 떠올리지 못하는 거에요.
스스로 주제를 떠올리지 못하고
수동적 학습에만 익숙한 아이들의 모습을 보면
속상할 때가 많습니다.
어떻게 수업에서 자기 생각을 만들고 그것을 표현해 낼 수 있게 할까..
고민이 많아지네요.
이렇게 '딸깍' 만들 수 있는 바이브 코딩을 우리 학생들에게 얼른 알려주고 싶어요~


도움 받은 글 (옵션)

항상 공대언니 게시글에 자극 받아요. ㅋㅋㅋ
정말 열정이 넘치십니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>말랑말랑 국어교실 - 피동 표현 완전 정복! 🐝</title>
    <link rel="stylesheet" href="style.css">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Gowun+Dodum&family=Nanum+Pen+Script&family=Outfit:wght@400;700&display=swap" rel="stylesheet">
    <script src="https://unpkg.com/lucide@latest"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/confetti.browser.min.js"></script>
</head>
<body>
    <div class="app-container">
        <!-- Progress Bar -->
        <div class="progress-container">
            <div class="progress-bar" id="progress-bar"></div>
        </div>

        <header class="header">
            <h1 id="main-title">말랑말랑 국어교실 📖</h1>
            <p class="subtitle">친절한 국어 샘과 함께 '피동 표현' 뿌시기!</p>
        </header>

        <main id="content-area">
            <!-- Content will be dynamically inserted here -->
        </main>
    </div>

    <script src="script.js"></script>
    <script>
        lucide.createIcons();
    </script>
</body>
</html>
const steps = [
    {
        id: "intro",
        title: "🐝 피동이 뭐야? (당하는 주인공!)",
        subtitle: "능동 vs 피동",
        emoji: "🐝 vs 👦",
        content: `
            <p class="teacher-speech">"안녕 친구들! 오늘은 <strong>'당하는 것'</strong>에 대해 배워볼 거야. <br>주인공이 직접 하는 건 <strong>'능동'</strong>, <br>남에게 당하는 건 <strong>'피동'</strong>이라고 해!"</p>
            <div class="card-body">
                <div class="example-box">
                    <div class="example active-ex">
                        <span class="label active-label">능동 (직접 함)</span>
                        <p>🐝 "벌이 동생을 <strong>쏘았어</strong>."</p>
                        <span class="subtext">벌이 주인공! 자기가 쏜 거야!</span>
                    </div>
                    <div class="vs">VS</div>
                    <div class="example passive-ex">
                        <span class="label passive-label">피동 (당함)</span>
                        <p>👦 "동생이 벌에 <strong>쏘였어</strong>."</p>
                        <span class="subtext">동생이 주인공! 쏘임을 당했어! 😭</span>
                    </div>
                </div>
                <div class="example-box">
                    <div class="example active-ex">
                        <span class="label active-label">능동</span>
                        <p>🏹 "사냥꾼이 토끼를 <strong>잡았다</strong>."</p>
                    </div>
                    <div class="vs">VS</div>
                    <div class="example passive-ex">
                        <span class="label passive-label">피동</span>
                        <p>🐰 "토끼가 사냥꾼에게 <strong>잡혔다</strong>."</p>
                    </div>
                </div>
            </div>
            <button class="next-btn" onclick="nextStep()">다음으로! 변신 공식 배우기 ✨</button>
        `
    },
    {
        id: "formula",
        title: "🪄 변신 마법 연구소",
        subtitle: "피동 표현 만드는 법 연습",
        emoji: "🎩",
        content: `
            <p class="teacher-speech">"여기는 <strong>마법 연구소</strong>야! 동사에 마법의 글자를 쏙~ 넣어서 피동사로 변신시켜보자!"</p>
            <div class="card-body">
                <div class="magic-lab">
                    
                    <div class="lab-row">
                        <span class="base-vb">👀 보-</span> + 
                        <button class="magic-btn" onclick="magicCombine(this, '이', '보이다')"></button> = 
                        <span class="result-vb" id="res-1">? ? ?</span>
                    </div>

                    <div class="lab-row">
                        <span class="base-vb">🚪 닫-</span> + 
                        <button class="magic-btn" onclick="magicCombine(this, '히', '닫히다')"></button> = 
                        <span class="result-vb" id="res-2">? ? ?</span>
                    </div>

                    <div class="lab-row">
                        <span class="base-vb">🐕 물-</span> + 
                        <button class="magic-btn" onclick="magicCombine(this, '리', '물리다')"></button> = 
                        <span class="result-vb" id="res-3">? ? ?</span>
                    </div>

                    <div class="lab-row">
                        <span class="base-vb">👶 안-</span> + 
                        <button class="magic-btn" onclick="magicCombine(this, '기', '안기다')"></button> = 
                        <span class="result-vb" id="res-4">? ? ?</span>
                    </div>

                    <div class="lab-row" style="border-top:1px solid #eee; padding-top:15px; margin-top:15px">
                        <span class="base-vb">🍰 나누-</span> + 
                        <button class="magic-btn" style="background:#FEB47B" onclick="magicCombine(this, '어지다', '나누어지다')">어지다</button> = 
                        <span class="result-vb" id="res-5">? ? ? ? ?</span>
                    </div>

                    <div class="lab-row">
                        <span class="base-vb">📱 사용</span> + 
                        <button class="magic-btn" style="background:#FFD200" onclick="magicCombine(this, '되다', '사용되다')">되다</button> = 
                        <span class="result-vb" id="res-6">? ? ? ?</span>
                    </div>

                </div>
                <div id="lab-success" style="display:none; text-align:center; color:var(--success); font-weight:bold; margin-top:15px">
                    ✨ 대단해! 모든 마법을 성공시켰어! ✨
                </div>
            </div>
            <button class="next-btn" id="lab-next-btn" style="display:none" onclick="nextStep()">왜 피동을 쓸까? 🤔</button>
            <p id="lab-hint" style="text-align:center; color:#999; font-size:0.9rem; margin-top:10px">버튼을 눌러 마법을 부려줘!</p>
        `
    },
    {
        id: "why",
        title: "🤔 왜 쓸까? 피동의 대결!",
        subtitle: "능동 vs 피동, 상황에 따라 골라 써요!",
        emoji: "💡",
        content: `
            <p class="teacher-speech">"똑같은 상황이라도 <strong>누구를 주인공</strong>으로 하느냐에 따라 맛이 달라져! <br>능동과 피동이 붙으면 어떤 느낌일까?"</p>
            <div class="card-body">
                
                <!-- 대결 1: 강조 -->
                <div class="why-battle">
                    <div class="battle-title">🚀 1. 강조: "누가 더 중요해?"</div>
                    <div class="battle-box">
                        <div class="side active-side">
                            <strong>능동:</strong> "경찰이 도둑을 잡았어!" <br>
                            <span class="subtext">(경찰의 활약이 중요할 때!)</span>
                        </div>
                        <div class="side vs-side">VS</div>
                        <div class="side passive-side">
                            <strong>피동:</strong> "도둑이 잡혔어!" <br>
                            <span class="subtext">(도둑이 잡힌 사실 자체를 강조할 때!)</span>
                        </div>
                    </div>
                </div>

                <!-- 대결 2: 책임 회피 -->
                <div class="why-battle">
                    <div class="battle-title">🙈 2. 책임 회피: "슬쩍 숨기고 싶을 때"</div>
                    <div class="battle-box">
                        <div class="side active-side">
                            <strong>능동:</strong> "내가 꽃병을 깼어." <br>
                            <span class="subtext">(잘못을 인정하는 솔직한 마음!)</span>
                        </div>
                        <div class="side vs-side">VS</div>
                        <div class="side passive-side">
                            <strong>피동:</strong> "꽃병이 깨졌어." <br>
                            <span class="subtext">(은근슬쩍 내 책임을 숨기고 싶을 때! 😉)</span>
                        </div>
                    </div>
                </div>

                <!-- 대결 3: 객관성 -->
                <div class="why-battle">
                    <div class="battle-title">📝 3. 객관성: "사실만 딱딱하게!"</div>
                    <div class="battle-box">
                        <div class="side active-side">
                            <strong>능동:</strong> "우리가 산 정상을 보았어." <br>
                            <span class="subtext">(개인적인 경험을 말할 때!)</span>
                        </div>
                        <div class="side vs-side">VS</div>
                        <div class="side passive-side">
                            <strong>피동:</strong> "산 정상이 보입니다." <br>
                            <span class="subtext">(지도나 뉴스처럼 사실만 전달할 때!)</span>
                        </div>
                    </div>
                </div>

            </div>
            <button class="next-btn" onclick="nextStep()">이건 조심해! 주의보 발령 ⚠️</button>
        `
    },
    {
        id: "caution",
        title: "⚠️ 이중 피동 수리 센터",
        subtitle: "어색한 두 번 피동 고쳐주기!",
        emoji: "🔧",
        content: `
            <p class="teacher-speech">"한국어는 <strong>피동을 두 번</strong> 쓰는 걸 아주 싫어해! <br>어색하고 뚱뚱해진 단어들을 날씬하게 고쳐보자!"</p>
            <div class="card-body">
                
                <div class="repair-item">
                    <div class="bad-text">❌ 보여지다</div>
                    <button class="magic-btn" onclick="repairPassive(this, '✅ 보이다')">날씬하게 고치기! ✨</button>
                </div>

                <div class="repair-item">
                    <div class="bad-text">❌ 잊혀지다</div>
                    <button class="magic-btn" onclick="repairPassive(this, '✅ 잊히다')">날씬하게 고치기! ✨</button>
                </div>

                <div class="repair-item">
                    <div class="bad-text">❌ 나뉘어지다</div>
                    <button class="magic-btn" onclick="repairPassive(this, '✅ 나뉘다')">날씬하게 고치기! ✨</button>
                </div>

                <div class="repair-item">
                    <div class="bad-text">❌ 믿겨지다</div>
                    <button class="magic-btn" onclick="repairPassive(this, '✅ 믿기다')">날씬하게 고치기! ✨</button>
                </div>

                <div id="repair-success" style="display:none; text-align:center; color:var(--success); font-weight:bold; margin-top:15px">
                    ✨ 대단해! 모든 단어를 예쁘게 수리했어! ✨
                </div>
            </div>
            <button class="next-btn" id="repair-next-btn" style="display:none" onclick="startQuiz()">실전 퀴즈로 고고! ✍️</button>
        `
    }
];

const quizQuestions = [
    {
        question: "다음 중 '피동문'인 것은?",
        options: ["철수가 사과를 먹었다.", "꽃이 나비에게 보였다.", "영희가 책을 읽는다.", "선생님이 칭찬을 하셨다."],
        correct: 1,
        hint: "'주인공이 당하는 모습'이 들어간 문장을 찾아봐! 👀",
        explanation: "'보였다'는 '보이다'의 과거형으로 피동 표현이에요!"
    },
    {
        question: "능동문 '경찰이 도둑을 잡았다.'를 피동문으로 바꾸면?",
        options: ["도둑이 경찰을 잡았다.", "도둑이 경찰에게 잡혔다.", "경찰이 도둑에게 잡혔다.", "경찰이 도둑을 잡히다."],
        correct: 1,
        hint: "도둑을 주인공으로 만들고, '잡다'에 '히'를 넣어볼래? 👮‍♂️",
        explanation: "도둑(주어)이 잡힘을 당하는 '잡혔다'가 맞아요!"
    },
    {
        question: "'컵이 깨졌어요'라고 말할 때 피동 표현을 쓴 이유는?",
        options: ["컵을 강조하기 위해", "누가 깼는지 숨기기 위해", "컵이 직접 깨졌기 때문에", "사실만 전달하기 위해"],
        correct: 1,
        hint: "내가 깼다고 말하기 쪼금 부끄러울 때 쓰는 방법이야! 🙈",
        explanation: "책임을 회피하거나 주체를 숨기고 싶을 때 주로 사용해요."
    },
    {
        question: "다음 중 이중 피동으로 어색한 표현은?",
        options: ["들리다", "열리다", "믿겨지다", "안기다"],
        correct: 2,
        hint: "마법은 한 번만! '기'와 '-어지다'가 둘 다 들어갔네? 🪄",
        explanation: "'믿기다' 하나면 충분해요. '-어지다'를 또 붙이면 어색해요!"
    },
    {
        question: "'-되다'를 사용한 피동 표현이 아닌 것은?",
        options: ["사용되다", "건강되다", "형성되다", "파괴되다"],
        correct: 1,
        hint: "'건강하다'는 이미 그 자체로 기분 좋은 상태잖아! 😊",
        explanation: "'건강하다'는 상태를 나타내는 형용사라 피동이 어색해요."
    },
    {
        question: "'문이 바람에 (   ).' 빈칸에 알맞은 피동사는?",
        options: ["닫혔다", "닫았다", "닫으셨다", "닫아지다"],
        correct: 0,
        hint: "바람이 문을 닫았으니, 문은 닫음을 당했겠지? 🚪",
        explanation: "문이 닫음을 당했으므로 '닫히다'의 과거형 '닫혔다'가 적절해요."
    },
    {
        question: "'잊혀지다'를 올바르게 고친 것은?",
        options: ["잊히다", "잊다", "잊어지다", "잊게 되다"],
        correct: 0,
        hint: "'히'만 써도 충분히 잘 잊혀질(?) 거야! 잊다+히! 🧼",
        explanation: "'잊다 + 히'만 써서 '잊히다'가 올바른 표현이에요!"
    },
    {
        question: "능동: '내가 창문을 열었다.' -> 피동: '창문이 나에 의해 (   ).'",
        options: ["열렸다", "열다", "열어졌다", "열리게 하다"],
        correct: 0,
        hint: "창문이 '리' 마법에 걸렸어! ✨",
        explanation: "'열다 + 리'가 붙어 '열리다'가 됩니다."
    },
    {
        question: "다음 중 피동 표현의 효과가 아닌 것은?",
        options: ["행위의 대상을 강조한다.", "자신의 행위를 뽐낸다.", "객관적으로 전달한다.", "행위의 주체를 숨긴다."],
        correct: 1,
        hint: "남에게 당하는 표현으로 어떻게 뽐낼 수 있겠어? 🤷‍♂️",
        explanation: "자신을 뽐내고 싶을 땐 보통 능동문을 사용해요!"
    },
    {
        question: "'불길이 잡혀졌다'의 올바른 수정형은?",
        options: ["잡히다", "잡혔다", "잡고 싶다", "잡아졌다"],
        correct: 1,
        hint: "과거에 일어난 일이니까 '히' 마법을 쓰고 과거형으로! 🕯️",
        explanation: "'잡히다' 하나만 쓰면 충분합니다. '잡혔다'가 자연스러워요."
    }
];

let firstAttempt = true;
const funnyFails = [
    "아이쿠! 마법의 방향이 쪼금 빗나갔네! 🧙‍♂️",
    "오잉? 정답이 요리조리 피하고 있어! 🏃‍♂️💨",
    "까비까비! 이번 건 쪼금 어려웠나? 😅",
    "쉿! 정답이 저기서 손을 흔들고 있어! 👋",
    "음~ 다시 한번 마법의 지팡이를 휘둘러볼까? 🪄"
];

function playFanfare() {
    const context = new (window.AudioContext || window.webkitAudioContext)();
    
    function playNote(freq, startTime, duration) {
        const osc = context.createOscillator();
        const gain = context.createGain();
        osc.connect(gain);
        gain.connect(context.destination);
        osc.frequency.value = freq;
        gain.gain.setValueAtTime(0.1, startTime);
        gain.gain.exponentialRampToValueAtTime(0.01, startTime + duration);
        osc.start(startTime);
        osc.stop(startTime + duration);
    }

    const now = context.currentTime;
    playNote(523.25, now, 0.2);     // C5
    playNote(659.25, now + 0.2, 0.2); // E5
    playNote(783.99, now + 0.4, 0.2); // G5
    playNote(1046.50, now + 0.6, 0.5); // C6
}

let labSuccessCount = 0;
function magicCombine(btn, suffix, result) {
    const row = btn.parentElement;
    const resSpan = row.querySelector('.result-vb');
    
    if (resSpan.innerText === result) return; // Already combined

    resSpan.innerText = result;
    resSpan.classList.add('active-result');
    btn.style.background = '#ccc';
    btn.disabled = true;

    // Small pop effect for each combine
    confetti({
        particleCount: 20,
        spread: 30,
        origin: { x: btn.getBoundingClientRect().x / window.innerWidth, y: btn.getBoundingClientRect().y / window.innerHeight }
    });

    labSuccessCount++;
    if (labSuccessCount === 6) {
        document.getElementById('lab-success').style.display = 'block';
        document.getElementById('lab-next-btn').style.display = 'inline-block';
        document.getElementById('lab-hint').style.display = 'none';
        playFanfare();
    }
}

let repairSuccessCount = 0;
function repairPassive(btn, result) {
    const row = btn.parentElement;
    const badText = row.querySelector('.bad-text');
    
    if (badText.innerText === result) return;

    badText.innerText = result;
    badText.classList.add('good-text');
    btn.style.display = 'none';

    confetti({
        particleCount: 30,
        colors: ['#27AE60']
    });

    repairSuccessCount++;
    if (repairSuccessCount === 4) {
        document.getElementById('repair-success').style.display = 'block';
        document.getElementById('repair-next-btn').style.display = 'inline-block';
        playFanfare();
    }
}

let currentStep = 0;
let quizIndex = 0;
let score = 0;
let isQuizMode = false;

function render() {
    const contentArea = document.getElementById('content-area');
    const progressBar = document.getElementById('progress-bar');
    
    if (!isQuizMode) {
        const step = steps[currentStep];
        progressBar.style.width = ((currentStep + 1) / (steps.length + 1)) * 100 + "%";
        
        if (step.id === "formula") labSuccessCount = 0;
        if (step.id === "caution") repairSuccessCount = 0;

        contentArea.innerHTML = `
            <section class="lesson-card active">
                <div class="emoji-hero">${step.emoji}</div>
                <h2>${step.title}</h2>
                <div class="card-body">
                    ${step.content}
                </div>
            </section>
        `;
    } else {
        renderQuiz();
    }
}

function nextStep() {
    if (currentStep < steps.length - 1) {
        currentStep++;
        render();
    }
}

function startQuiz() {
    isQuizMode = true;
    quizIndex = 0;
    score = 0;
    render();
}

function renderQuiz() {
    const contentArea = document.getElementById('content-area');
    const progressBar = document.getElementById('progress-bar');
    
    if (quizIndex < quizQuestions.length) {
        const q = quizQuestions[quizIndex];
        progressBar.style.width = ((steps.length + quizIndex + 1) / (steps.length + quizQuestions.length)) * 100 + "%";
        
        contentArea.innerHTML = `
            <section class="lesson-card active">
                <span style="color:#888">퀴즈 ${quizIndex + 1} / ${quizQuestions.length}</span>
                <h2 style="margin-top:10px">${q.question}</h2>
                <div class="quiz-options" id="options-container">
                    ${q.options.map((opt, i) => `
                        <div class="quiz-option" onclick="checkAnswer(${i})">${i + 1}. ${opt}</div>
                    `).join('')}
                </div>
                <div id="quiz-feedback"></div>
            </section>
        `;
        firstAttempt = true;
    } else {
        renderResult();
    }
}

function checkAnswer(index) {
    const q = quizQuestions[quizIndex];
    const options = document.querySelectorAll('.quiz-option');
    const feedbackArea = document.getElementById('quiz-feedback');
    
    if (index === q.correct) {
        if (firstAttempt) score++;
        options[index].classList.add('correct');
        
        // Effects
        playFanfare();
        confetti({
            particleCount: 150,
            spread: 70,
            origin: { y: 0.6 },
            colors: ['#FF7E5F', '#FEB47B', '#FFD200']
        });

        // Hide other options
        options.forEach((opt, idx) => {
            if (idx !== q.correct) opt.style.opacity = '0.3';
            opt.onclick = null;
        });

        feedbackArea.innerHTML = `
            <div class="feedback correct">
                따란~! 정답의 요정이 윙크를 보냈어! 😉 <br>
                <span style="font-size:0.9rem; margin-top:5px; display:block">${q.explanation}</span>
            </div>
        `;
        
        const nextBtn = document.createElement('button');
        nextBtn.className = 'next-btn';
        nextBtn.innerText = (quizIndex === quizQuestions.length - 1) ? "결과 보기 📊" : "다음 문제 ➡️";
        nextBtn.onclick = () => {
            quizIndex++;
            renderQuiz();
        };
        feedbackArea.appendChild(nextBtn);

    } else {
        firstAttempt = false;
        options[index].classList.add('wrong');
        const randomFail = funnyFails[Math.floor(Math.random() * funnyFails.length)];
        
        feedbackArea.innerHTML = `
            <div class="feedback wrong">
                ${randomFail} <br>
                <strong style="color:var(--primary)">💡 힌트: ${q.hint}</strong>
            </div>
        `;
        
        // Remove wrong class after a while to allow retry
        setTimeout(() => {
            options[index].classList.remove('wrong');
        }, 1500);
    }
}

function renderResult() {
    const contentArea = document.getElementById('content-area');
    const progressBar = document.getElementById('progress-bar');
    progressBar.style.width = "100%";
    
    let message = "";
    let emoji = "";
    if (score === 10) { emoji = "👑"; message = "축하해요! 당신은 완벽한 국어 천재!"; }
    else if (score >= 7) { emoji = "👏"; message = "와우! 피동 표현을 아주 잘 이해했군요!"; }
    else if (score >= 4) { emoji = "📚"; message = "조금만 더 복습하면 완벽해질 거예요!"; }
    else { emoji = "💪"; message = "괜찮아요! 다시 한번 천천히 읽어볼까요?"; }

    contentArea.innerHTML = `
        <section class="lesson-card active">
            <div class="emoji-hero">${emoji}</div>
            <h2>참 잘했어요!</h2>
            <div class="card-body" style="text-align:center">
                <p style="font-size:1.5rem">나의 점수: <strong>${score} / ${quizQuestions.length}</strong></p>
                <p class="teacher-speech" style="border:none; background:rgba(0,0,0,0.05); margin-top:20px">${message}</p>
                <button class="next-btn" onclick="location.reload()">처음부터 다시 하기 🔄</button>
            </div>
        </section>
    `;
}

// Initial render
render();
:root {
    --primary: #FF7E5F;
    --secondary: #FEB47B;
    --accent: #FFD200;
    --background: linear-gradient(135deg, #fdfcfb 0%, #e2d1c3 100%);
    --card-bg: rgba(255, 255, 255, 0.85);
    --text: #2C3E50;
    --success: #27AE60;
    --error: #E74C3C;
    --radius: 24px;
    --shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}

* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

body {
    font-family: 'Gowun Dodum', sans-serif;
    background: var(--background);
    min-height: 100vh;
    color: var(--text);
    display: flex;
    justify-content: center;
    align-items: center;
    padding: 20px;
    line-height: 1.6;
}

.app-container {
    max-width: 800px;
    width: 100%;
    position: relative;
}

/* Progress bar style */
.progress-container {
    width: 100%;
    height: 12px;
    background: rgba(0, 0, 0, 0.05);
    border-radius: 6px;
    margin-bottom: 20px;
    overflow: hidden;
}

.progress-bar {
    width: 20%;
    height: 100%;
    background: linear-gradient(to right, var(--primary), var(--secondary));
    transition: width 0.5s ease;
}

.header {
    text-align: center;
    margin-bottom: 30px;
}

h1 {
    font-size: 2.5rem;
    color: #4A4A4A;
    margin-bottom: 5px;
}

.subtitle {
    font-size: 1.2rem;
    color: #777;
}

/* Card systems */
.lesson-card {
    background: var(--card-bg);
    backdrop-filter: blur(15px);
    border-radius: var(--radius);
    padding: 40px;
    box-shadow: var(--shadow);
    border: 1px solid rgba(255, 255, 255, 0.3);
    text-align: center;
    transition: all 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    display: none;
    opacity: 0;
    transform: translateY(20px);
}

.lesson-card.active {
    display: block;
    opacity: 1;
    transform: translateY(0);
}

.emoji-hero {
    font-size: 4rem;
    margin-bottom: 15px;
}

h2 {
    font-size: 2rem;
    margin-bottom: 25px;
    color: var(--primary);
}

.teacher-speech {
    font-size: 1.3rem;
    background: rgba(255, 126, 95, 0.1);
    padding: 20px;
    border-radius: 15px;
    margin-bottom: 30px;
    border-left: 5px solid var(--primary);
    transition: all 0.3s ease;
}

.teacher-speech:hover {
    background: rgba(255, 126, 95, 0.15);
    transform: scale(1.01);
    box-shadow: 0 5px 15px rgba(255, 126, 95, 0.1);
}

.teacher-speech strong {
    color: var(--primary);
}

.card-body {
    text-align: left;
}

.example-box {
    display: flex;
    justify-content: space-around;
    align-items: center;
    background: white;
    padding: 25px;
    border-radius: 20px;
    margin-bottom: 20px;
    gap: 15px;
    box-shadow: 0 4px 10px rgba(0,0,0,0.05);
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    cursor: pointer;
}

.example-box:hover {
    transform: translateY(-5px) scale(1.02);
    box-shadow: 0 15px 35px rgba(0,0,0,0.1);
    border: 2px solid var(--primary);
}

.example {
    flex: 1;
    text-align: center;
}

.vs {
    font-weight: bold;
    color: #999;
}

.label {
    display: inline-block;
    padding: 5px 12px;
    border-radius: 20px;
    font-size: 0.9rem;
    font-weight: bold;
    margin-bottom: 10px;
}

.active-label { background: #E1F5FE; color: #0288D1; }
.passive-label { background: #FFF9C4; color: #FBC02D; }

.example p {
    font-size: 1.2rem;
    margin-bottom: 5px;
}

.subtext {
    font-size: 0.9rem;
    color: #888;
}

strong {
    color: var(--primary);
    font-weight: 700;
}

/* Formula styles */
.formula-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 20px;
    margin-top: 20px;
}

.magic-card {
    background: #fff;
    padding: 20px;
    border-radius: 20px;
    border: 2px dashed #EBC;
    text-align: center;
    transition: all 0.3s ease;
    cursor: pointer;
}

.magic-card:hover {
    transform: translateY(-5px);
    background: #fffdf9;
    border-style: solid;
    border-color: var(--primary);
    box-shadow: 0 10px 20px rgba(255, 126, 95, 0.15);
}

.magic-word {
    font-size: 1.8rem;
    color: #FF5E62;
    display: block;
    margin-bottom: 10px;
}

/* Navigation button */
.next-btn {
    margin-top: 40px;
    padding: 15px 40px;
    background: var(--primary);
    color: white;
    border: none;
    border-radius: 50px;
    font-size: 1.3rem;
    font-weight: bold;
    cursor: pointer;
    box-shadow: 0 5px 15px rgba(255, 126, 95, 0.4);
    transition: all 0.3s;
}

.next-btn:hover {
    transform: scale(1.05);
    background: #FF6A46;
}

/* Quiz system */
.quiz-options {
    display: grid;
    gap: 15px;
    margin-top:30px;
}

.quiz-option {
    padding: 18px;
    background: #f8f9fa;
    border: 2px solid #edeff0;
    border-radius: 15px;
    cursor: pointer;
    text-align: left;
    transition: all 0.2s;
    font-size: 1.15rem;
}

.quiz-option:hover {
    background: #fff;
    border-color: var(--primary);
}

.quiz-option.correct {
    background: #ebfaf0;
    border-color: var(--success);
}

.quiz-option.wrong {
    background: #fef0f0;
    border-color: var(--error);
}

.feedback {
    margin-top: 20px;
    padding: 15px;
    border-radius: 15px;
    font-size: 1.1rem;
}

.feedback.correct { background: #d4edda; color: #155724; }
.feedback.wrong { background: #f8d7da; color: #721c24; }

/* Magic Lab Styles */
.magic-lab {
    display: flex;
    flex-direction: column;
    gap: 12px;
    background: #fdfdfd;
    padding: 20px;
    border-radius: 20px;
    border: 1px solid #eee;
}

.lab-row {
    font-size: 1.4rem;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 15px;
}

.magic-btn {
    padding: 5px 15px;
    background: var(--primary);
    color: white;
    border: none;
    border-radius: 10px;
    font-weight: bold;
    cursor: pointer;
    transition: transform 0.2s;
}

.magic-btn:hover {
    transform: scale(1.1);
}

.result-vb {
    font-weight: bold;
    color: #ccc;
    min-width: 100px;
}

.result-vb.active-result {
    color: var(--primary);
    animation: pop 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

@keyframes pop {
    0% { transform: scale(0.5); }
    100% { transform: scale(1); }
}

/* Repair Lab Styles */
.repair-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    background: #FFF9F9;
    padding: 15px 20px;
    border-radius: 15px;
    margin-bottom: 15px;
    border: 1px solid #FFE4E4;
}

.bad-text {
    font-size: 1.3rem;
    font-weight: bold;
    color: #E74C3C;
    transition: all 0.4s ease;
}

.good-text {
    color: #27AE60 !important;
    transform: scale(1.1);
}

/* Why Battle Styles */
.why-battle {
    margin-bottom: 25px;
}

.battle-title {
    font-weight: bold;
    font-size: 1.2rem;
    margin-bottom: 10px;
    color: var(--text);
}

.battle-box {
    display: flex;
    background: white;
    border-radius: 15px;
    overflow: hidden;
    box-shadow: 0 3px 10px rgba(0,0,0,0.05);
    border: 1px solid #eee;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    cursor: pointer;
}

.battle-box:hover {
    transform: translateY(-5px) scale(1.02);
    box-shadow: 0 12px 25px rgba(0,0,0,0.1);
    border-color: var(--primary);
}

.side {
    flex: 1;
    padding: 15px;
    font-size: 1.1rem;
    display: flex;
    flex-direction: column;
    justify-content: center;
}

.active-side { background: #E3F2FD; }
.passive-side { background: #FFF3E0; }

.vs-side {
    flex: 0 0 40px;
    background: #eee;
    font-weight: bold;
    color: #999;
    align-items: center;
    padding: 15px 0;
}

.side strong { color: #333; margin-bottom: 5px; }

@media (max-width: 600px) {
    .example-box {
        flex-direction: column;
    }
    h1 { font-size: 1.8rem; }
    h2 { font-size: 1.5rem; }
}

/* 추가된 인터랙티브 효과 */
.info-card, .bad-good-box > div {
    transition: all 0.3s ease;
    cursor: pointer;
    border: 2px solid transparent;
}

.info-card:hover, .bad-good-box > div:hover {
    transform: translateX(10px) scale(1.01);
    background-color: #fff !important;
    border-color: var(--primary);
    box-shadow: 0 5px 15px rgba(0,0,0,0.08);
}
1

뉴스레터 무료 구독

👉 이 게시글도 읽어보세요