// AI-Men · Mentor App Prototype
// One component, themed via prop. Three screens: list → detail → chat.
// Mentor avatars use clean 2D gradient tiles as placeholders for the
// original character art (the original files were inaccessible due to
// filename encoding — drop them into /assets/ with English names to swap).

// Standalone-bundle resource resolver: maps an asset path to an inlined blob
// URL when bundled (window.__resources), otherwise returns the path as-is.
if (typeof window !== 'undefined' && !window.__res) {
  window.__res = function (p) { return (window.__resources && window.__resources[p]) || p; };
}

const { useState, useEffect, useRef, useMemo } = React;

const MENTORS = [
  {
    id: "abraham", kr: "아브라함", initial: "아", en: "Abraham",
    image: "assets/abraham_all.png", avatarPos: "center 6%",
    imageFull: "assets/abraham_all.png",
    tagline: "믿음의 조상",
    sub: "믿음으로 고향을 떠난\n이스라엘의 조상",
    expertise: "믿음·순종·언약",
    story: "75세에 하나님의 부르심을 받아 고향 갈대아 우르를 떠났다. 자손이 하늘의 별 같으리라는 약속을 기도로 붙들며 25년을 기다렸다. 100세에 이삭을 얻은 후에도 번제로 드리라는 명령에 순종했다. 하나님은 그를 믿음의 아버지라 칭하셨다.",
    verse: "믿음은 바라는 것들의 실상이요 보이지 않는 것들의 증거니라.",
    verseRef: "히브리서 11:1",
    method: "언약 기도 + 하나님 말씀 붙들기",
    lesson: "응답이 늦어도 하나님의 약속을 기도로 기록하고 붙들면 반드시 이루어진다.",
    tags: ["믿음","순종","언약","인내"],
    tone: { from: "#FFE5C7", to: "#F5BD7C", ink: "#7A4214" },
    cta: "AI 아브라함과 대화하기",
    intro: "안녕하세요. 저는 당신과 함께하는 아브라함입니다. 오늘은 마음이 어떠신가요?",
  },
  {
    id: "david", kr: "다윗", initial: "다", en: "David",
    image: "assets/david_all.png", avatarPos: "center 6%",
    imageFull: "assets/david_all.png",
    tagline: "마음에 합한 왕",
    sub: "하나님의 마음에 합한\n이스라엘의 왕",
    expertise: "예배·임재·찬양",
    story: "골리앗과 싸울 때도, 사울에게 쫓길 때도, 죄를 범한 후에도 다윗은 끊임없이 기도를 글로 기록했다. 양을 치던 목동 시절부터 만군의 여호와의 이름을 신뢰했으며, 평생 동안 찬양과 예배를 멈추지 않아 하나님 마음에 합한 자라는 인정을 받았다.",
    verse: "너는 칼과 창과 단창으로 내게 나아오거니와 나는 만군의 여호와의 이름 곧 네가 모욕하는 이스라엘 군대의 하나님의 이름으로 네게 나아가노라.",
    verseRef: "사무엘상 17:45",
    method: "여호와의 이름 선포 + 전심의 찬양",
    lesson: "세상의 무기가 아닌 하나님의 이름을 신뢰할 때 위기가 무너지고, 주님을 향한 중심이 왕의 자리를 지킨다.",
    tags: ["예배","합한자","임재","찬양"],
    tone: { from: "#D9EAF8", to: "#86B7E0", ink: "#1F4A78" },
    cta: "AI 다윗과 대화하기",
    intro: "평안하세요. 시인이자 왕, 다윗입니다. 무엇을 노래하고 싶으신가요?",
  },
  {
    id: "moses", kr: "모세", initial: "모", en: "Moses",
    image: "assets/moses_all.png", avatarPos: "center 5%",
    imageFull: "assets/moses_all.png",
    tagline: "출애굽과 이끎",
    sub: "이스라엘을 애굽에서 이끈\n율법의 중보자",
    expertise: "사명·권능·중보",
    story: "40년간 광야에서 양 치다가 80세에 부르심을 받았다. 내가 누구이기에 바로에게 가겠냐고 고개 숙였으나, 하나님의 권능을 의지하여 열 가지 재앙과 홍해를 가르는 기적을 행했다. 광야 길 동안 백성들의 원망 속에서도 온유함으로 중보의 자리를 지켰다.",
    verse: "믿음으로 모세는 장성하여 바로의 공주의 아들이라 칭함 받기를 거절하고 도리어 하나님의 백성과 함께 고난 받기를 잠시 죄악의 낙을 누리는 것보다 더 좋아하고.",
    verseRef: "히브리서 11:24-25",
    method: "대면 기도 + 지팡이의 권능 의지",
    lesson: "자신의 연약함을 내려놓고 하나님의 손에 붙들릴 때, 광야 같은 인생길을 통과하는 사명의 리더십이 나타난다.",
    tags: ["사명","권능","온유","중보"],
    tone: { from: "#E8DFF3", to: "#B49ED0", ink: "#3F2B5C" },
    cta: "AI 모세와 대화하기",
    intro: "제가 모세입니다. 당신의 광야 한복판에서 함께 걷고 싶어요.",
  },
  {
    id: "nehemiah", kr: "느헤미야", initial: "느", en: "Nehemiah",
    image: "assets/nehemiah_all.png", avatarPos: "center 5%",
    imageFull: "assets/nehemiah_all.png",
    tagline: "예루살렘 성벽",
    sub: "52일 만에 예루살렘 성벽을\n재건한 기도의 리더",
    expertise: "재건·통곡·리더십",
    story: "페르시아 왕의 술관원이었던 느헤미야는 예루살렘 성벽이 무너졌다는 소식에 수일간 금식하며 기도했다. 안락함을 버리고 총독으로 부임하여 대적들의 조롱과 방해 속에서도 한 손에는 병기를 잡고 한 손으로 일을 하며 52일 만에 성벽을 완공했다.",
    verse: "내가 하늘의 하나님 앞에 울고 슬퍼하며 금식하며 기도하여 이르되 하늘의 하나님 여호와 크고 두려우신 하나님이여 주를 사랑하고 주의 계명을 지키는 자에게 언약을 지키시며 긍휼을 베푸시는 주여 간구하나이다.",
    verseRef: "느헤미야 1:4-5",
    method: "눈물의 금식 중보 + 현장 방비",
    lesson: "무너진 공동체의 아픔을 내 아픔으로 안고 기도하며, 한 손에 말씀의 병기를 들고 행동할 때 재건의 역사가 일어난다.",
    tags: ["재건","통곡","리더십","방비"],
    tone: { from: "#DEEFD6", to: "#90BC78", ink: "#2E5B1F" },
    cta: "AI 느헤미야와 대화하기",
    intro: "느헤미야입니다. 무너진 마음의 성벽도 다시 쌓을 수 있어요. 시작해볼까요?",
  },
  {
    id: "daniel", kr: "다니엘", initial: "다", en: "Daniel",
    image: "assets/daniel_all.png", avatarPos: "center 5%",
    imageFull: "assets/daniel_all.png",
    tagline: "뜻을 정한 기도",
    sub: "사자굴에서도 기도를 멈추지 않은\n하나님의 사람",
    expertise: "지조·정시기도·감사",
    story: "바벨론 포로로 끌려가서도 하루 세 번 예루살렘을 향해 무릎 꿇고 기도했다. 기도 금지령이 내려지고 왕의 조서에 도장이 찍힌 것을 알고도 전에 하던 대로 감사 기도를 드렸으며, 타협하지 않는 신앙을 지켜 사자굴 속에서도 하나님의 보호하심을 입었다.",
    verse: "다니엘이 이 조서에 왕의 도장이 찍힌 것을 알고도 자기 집에 돌아가서는 윗방에 올라가 예루살렘으로 향한 창문을 열고 전에 하던 대로 하루 세 번씩 무릎을 꿇고 기도하며 그의 하나님께 감사하였더라.",
    verseRef: "다니엘 6:10",
    method: "뜻을 정함 + 감사 정시 기도",
    lesson: "세상의 위협 앞에서도 타협하지 않고 기도의 자리를 지키는 자를 하나님은 위기 속에서 반드시 건지신다.",
    tags: ["지조","정시기도","탁월","감사"],
    tone: { from: "#FBDDD7", to: "#E69084", ink: "#7A2E22" },
    cta: "AI 다니엘과 대화하기",
    intro: "다니엘입니다. 당신이 마주한 분별의 자리에 함께 있겠습니다.",
  },
  {
    id: "esther", kr: "에스더", initial: "에", en: "Esther",
    image: "assets/esther_all.png", avatarPos: "center 6%",
    imageFull: "assets/esther_all.png",
    tagline: "죽으면 죽으리이다",
    sub: "민족을 구하기 위해\n목숨을 건 금식 기도자",
    expertise: "금식·결단·역전",
    story: "유대인 학살 명령이 내려졌을 때 에스더는 죽으면 죽으리라는 결단을 하고 3일 금식 기도를 선포했다. 왕의 부름 없이 나아가면 죽는 규례를 깨뜨리고 목숨을 걸고 왕 앞에 나아갔으며, 그 결단을 통해 민족을 전멸의 위기에서 구하고 역전의 부림절을 만들어냈다.",
    verse: "나도 나의 시녀와 더불어 이렇게 금식한 후에 규례를 어기고 왕에게 나아가리니 죽으면 죽으리이다 하니라.",
    verseRef: "에스더 4:16",
    method: "합심 금식 기도 + 생명 건 결단",
    lesson: "위기의 순간에 생명을 걸고 하나님의 도우심을 구하며 결단할 때, 대적의 계략이 도리어 역전되는 기적이 일어난다.",
    tags: ["금식","결단","역전","사명"],
    tone: { from: "#ECDDF4", to: "#C39BD8", ink: "#5B3A75" },
    cta: "AI 에스더와 대화하기",
    intro: "에스더입니다. 두려운 결단 앞에 서 있나요? 함께 기도하며 용기를 내봐요.",
  },
  {
    id: "hannah", kr: "한나", initial: "한", en: "Hannah",
    image: "assets/hannah_all.png", avatarPos: "center 7%",
    imageFull: "assets/hannah_all.png",
    tagline: "마음을 쏟은 기도",
    sub: "간절한 기도로 사무엘을 얻은\n믿음의 어머니",
    expertise: "심정·통곡·서원",
    story: "자녀가 없어 매년 성전에서 통곡하며 기도했다. 주의 여종에게 아들을 주시면 그를 평생 여호와께 드리겠다고 서원하며 여호와 앞에 심정을 통하는 기도를 드렸다. 인간적인 원망을 기도로 승화시켜 응답을 받았고 이스라엘의 영적 지도자 사무엘을 낳았다.",
    verse: "한나가 대답하여 이르되 내 주여 그렇지 아니하니이다 나는 마음이 슬픈 여자라 포도주나 독주를 마신 것이 아니요 여호와 앞에 내 심정을 통하는 것뿐이오니.",
    verseRef: "사무엘상 1:15",
    method: "통곡의 심정 통하기 + 서원 기도",
    lesson: "사람과 다투지 않고 오직 하나님 앞에 나아가 마음을 쏟아놓을 때, 막힌 문이 열리고 영적 리더가 세워진다.",
    tags: ["심정통함","통곡","서원","응답"],
    tone: { from: "#F3E7D6", to: "#D9BC92", ink: "#6B4E28" },
    cta: "AI 한나와 대화하기",
    intro: "한나예요. 말로 다 못 할 마음이 있나요? 하나님은 그 침묵의 기도도 들으세요.",
  },
  {
    id: "elijah", kr: "엘리야", initial: "엘", en: "Elijah",
    image: "assets/elijah_all.png", avatarPos: "center 5%",
    imageFull: "assets/elijah_all.png",
    tagline: "갈멜산의 불",
    sub: "갈멜산에서 850명과 맞선\n기도의 용사",
    expertise: "능력·기도·회복",
    story: "3년 6개월의 가뭄 후 갈멜산에서 바알 선지자 450명, 아세라 선지자 400명과 대결했다. 무릎을 땅에 꿇고 얼굴을 두 무릎 사이에 넣으며 간절히 부르짖어 제단에 하늘의 불이 내려오게 했고, 여호와만이 참 하나님이심을 온 백성 앞에 선포했다.",
    verse: "여호와여 내게 응답하옵소서 내게 응답하옵소서 이 백성에게 주 여호와는 하나님이신 것과 주는 그들의 마음을 되돌이키심을 알게 하옵소서 하매.",
    verseRef: "열왕기상 18:37",
    method: "간절한 부르짖음 + 무너진 제단 수축",
    lesson: "영적 어두움 속에서도 무너진 제단을 수축하고 불을 구하는 간절한 기도는 반드시 하나님의 응답을 가져온다.",
    tags: ["능력","불의기도","대결","회복"],
    tone: { from: "#FBDCC2", to: "#EE9A52", ink: "#7E3B12" },
    cta: "AI 엘리야와 대화하기",
    intro: "엘리야입니다. 지쳐 쓰러지고 싶은 날인가요? 다시 불을 구하는 기도, 함께해요.",
  },
  {
    id: "joseph", kr: "요셉", initial: "요", en: "Joseph",
    image: "assets/joseph_all.png", avatarPos: "center 6%",
    imageFull: "assets/joseph_all.png",
    tagline: "꿈과 섭리",
    sub: "노예와 죄수에서\n애굽의 총리가 된 믿음의 사람",
    expertise: "비전·형통·동행",
    story: "형들에게 팔려 노예가 되고 억울하게 감옥에 갇혔지만 하나님을 원망하지 않았다. 어릴 때 하나님이 주신 비전의 꿈을 마음 깊이 품었으며, 하나님이 늘 함께하심으로 어디서나 형통함을 입어 결국 애굽의 총리가 되어 기근에서 민족을 구원했다.",
    verse: "당신들은 나를 해하려 하였으나 하나님은 그것을 선으로 바꾸사 오늘과 같이 많은 백성의 생명을 구원하게 하시려 하셨나니.",
    verseRef: "창세기 50:20",
    method: "섭리 인정 + 하나님과의 동행",
    lesson: "인생의 가장 어두운 순간과 고난마저도 하나님은 결국 선으로 바꾸시며 약속을 성취하신다.",
    tags: ["비전","형통","동행","용서"],
    tone: { from: "#FBEFD3", to: "#E6C474", ink: "#7A5A18" },
    cta: "AI 요셉과 대화하기",
    intro: "요셉입니다. 억울하고 아픈 시간을 지나고 있나요? 그 이야기를 들려주세요.",
  },
  {
    id: "paul", kr: "바울", initial: "바", en: "Paul",
    image: "assets/paul_all.png", avatarPos: "center 10%",
    imageFull: "assets/paul_all.png",
    tagline: "이방인의 사도",
    sub: "감옥에서 기도 편지로\n교회를 세운 사도",
    expertise: "사명·전도·푯대",
    story: "감옥에 갇혔을 때도 기뻐하라, 항상 기뻐하라며 눈물과 기도로 편지를 썼다. 신약 13권의 서신서에 기도의 내용을 담아 초대교회들을 든든히 세웠으며, 예수 그리스도의 복음을 증언하는 사명을 완성하기 위해 자신의 생명조차 조금도 귀한 것으로 여기지 않았다.",
    verse: "내가 달려갈 길과 주 예수께 받은 사명 곧 하나님의 은혜의 복음을 증언하는 일을 마치려 함에는 나의 생명조차 조금도 귀한 것으로 여기지 아니하노라.",
    verseRef: "사도행전 20:24",
    method: "푯대를 향한 달음질 + 자족의 비결",
    lesson: "예수님을 만나 사명을 발견한 사람은 어떤 환경과 핍박 속에서도 복음 전진을 멈추지 않는다.",
    tags: ["사명","이방인","전도","푯대"],
    tone: { from: "#F3D9D3", to: "#D89685", ink: "#6E2E20" },
    cta: "AI 바울과 대화하기",
    intro: "바울입니다. 지금 어떤 형편에 있든, 그 자리에서 감사를 함께 찾아봐요.",
  },
  {
    id: "peter", kr: "베드로", initial: "베", en: "Peter",
    image: "assets/peter_all.png", avatarPos: "center 6%",
    imageFull: "assets/peter_all.png",
    tagline: "반석과 초대교회",
    sub: "어부에서 초대 교회의\n반석이 된 사도",
    expertise: "회복·반석·성령",
    story: "주님을 세 번 부인했던 베드로는 통곡의 회개 눈물로 변화되었다. 부활하신 주님이 찾아오셔서 사랑을 확인시켜 주셨을 때 무너진 중심을 회복했으며, 오순절 성령 강림 후 담대히 복음을 전하여 한 번의 설교로 삼천 명을 주께 돌아오게 했다.",
    verse: "말씀하시되 나를 따라오라 내가 너희를 사람을 낚는 어부가 되게 하리라 하시니.",
    verseRef: "마태복음 4:19",
    method: "사랑의 고백 회복 + 성령 충만",
    lesson: "뼈아픈 실패와 연약함이 있을지라도, 주님의 자비 안에서 복음의 성령을 받으면 신실한 반석으로 다시 선다.",
    tags: ["회복","반석","성령","어부"],
    tone: { from: "#DCE3EC", to: "#A0AEC2", ink: "#37445A" },
    cta: "AI 베드로와 대화하기",
    intro: "베드로입니다. 넘어진 적 있나요? 저도 그랬어요. 다시 일어서는 이야기, 함께해요.",
  },
  {
    id: "ruth", kr: "룻", initial: "룻", en: "Ruth",
    image: "assets/ruth_all.png", avatarPos: "center 7%",
    imageFull: "assets/ruth_all.png",
    tagline: "약속의 상속",
    sub: "이방 여인에서 다윗 왕의\n증조할머니가 된 믿음의 여인",
    expertise: "선택·효행·신실",
    story: "남편을 잃고 이방 여인으로 베들레헴에 왔지만 하나님을 온전히 신뢰했다. 어머니의 하나님이 나의 하나님이 되시리라는 신앙 고백을 따라 시어머니 나오미를 정성껏 공경했고, 보아스를 만나 다윗 왕과 예수 그리스도의 계보에 오르는 복을 받았다.",
    verse: "룻이 이르되 내게 어머니를 떠나며 어머니를 따르지 말고 돌아가라 강권하지 마옵소서 어머니께서 가시는 곳에 나도 가고 어머니께서 머무시는 곳에서 나도 머물겠나이다.",
    verseRef: "룻기 1:16",
    method: "일편단심의 고백 + 신실한 헌신",
    lesson: "깨어진 환경 속에서도 하나님을 선택하고 신실하게 자리를 지킬 때, 삶의 계보가 바뀌는 축복이 임한다.",
    tags: ["선택","효행","신실","회복"],
    tone: { from: "#F7E8CC", to: "#E0BE7E", ink: "#6E5020" },
    cta: "AI 룻과 대화하기",
    intro: "룻이에요. 묵묵히 걷는 길이 외롭게 느껴지나요? 그 길을 함께 걸어요.",
  },
  {
    id: "jeremiah", kr: "예레미야", initial: "예", en: "Jeremiah",
    image: "assets/jeremiah_all.png", avatarPos: "center 6%",
    imageFull: "assets/jeremiah_all.png",
    tagline: "눈물의 선포",
    sub: "40년간 핍박받으면서도\n하나님의 말씀을 기록한 선지자",
    expertise: "눈물·사명·기록",
    story: "내가 다시는 여호와를 선포하지 아니하리라 했다가도 내 마음이 불붙는 것 같아 견딜 수 없다고 고백하며 눈물로 사명을 지켰다. 백성들의 거역과 조롱 속에서도 유다의 멸망과 회복을 눈물로 선포하며 하나님의 언약의 말씀을 묵묵히 두루마리에 기록했다.",
    verse: "내가 다시는 여호와를 선포하지 아니하며 그의 이름으로 말하지 아니하리라 하면 나의 마음이 불붙는 것 같아서 골수에 사무치니 답답하여 견딜 수 없나이다.",
    verseRef: "예레미야 20:9",
    method: "중보의 눈물 + 심중에 사무치는 말씀 선포",
    lesson: "환경이 거부하고 외로울지라도 심령에 불붙는 하나님의 말씀을 끝까지 붙들고 전하는 자가 참된 사명자다.",
    tags: ["눈물","사명","불붙는중심","기록"],
    tone: { from: "#DCE0E8", to: "#9AA4B8", ink: "#353E52" },
    cta: "AI 예레미야와 대화하기",
    intro: "예레미야입니다. 눈물이 많은 날인가요? 그 눈물 속에서 소망을 함께 찾아봐요.",
  },
  {
    id: "job", kr: "욥", initial: "욥", en: "Job",
    image: "assets/job_all.png", avatarPos: "center 8%",
    imageFull: "assets/job_all.png",
    tagline: "순금 같은 신뢰",
    sub: "모든 것을 잃고도\n하나님을 찬양한 의인",
    expertise: "인내·고난·신뢰",
    story: "하루아침에 재산, 자녀, 건강을 모두 잃었다. 친구들의 정죄와 아내의 포기 속에서도 주신 이도 여호와시요 거두신 이도 여호와시니 여호와의 이름이 찬송을 받으실지니라 고백했다. 입술로 범죄하지 않고 단련의 과정을 수용하여 순금 같은 믿음을 증명했다.",
    verse: "그러나 내가 가는 길을 그가 아시나니 그가 나를 단련하신 후에는 내가 순금 같이 되어 나오리라.",
    verseRef: "욥기 23:10",
    method: "입술의 파수꾼 + 단련 수용",
    lesson: "이해할 수 없는 고난의 터널 속에서도 원망을 멈추고 주님을 신뢰하면, 순금 같은 신앙으로 정제되어 복을 얻는다.",
    tags: ["인내","순금","고난","신뢰"],
    tone: { from: "#E8E4DC", to: "#BFB6A6", ink: "#4E463A" },
    cta: "AI 욥과 대화하기",
    intro: "욥입니다. 답이 보이지 않는 고난 중에 있나요? 그 마음을 함께 나눠요.",
  },
  {
    id: "isaiah", kr: "이사야", initial: "이", en: "Isaiah",
    image: "assets/isaiah_all.png", avatarPos: "center 6%",
    imageFull: "assets/isaiah_all.png",
    tagline: "메시아 예언",
    sub: "메시아를 700년 앞서\n예언한 선지자",
    expertise: "임재·회개·자원",
    story: "성전에서 하나님의 영광을 보았을 때 화로다 나여라며 회개했고, 내가 여기 있나이다 나를 보내소서라며 자원하여 제단 숯불로 입술을 정결하게 하셨다. 그 후 고난받는 메시아의 도래와 거룩한 구원의 소식을 구체적이고 명확하게 대언했다.",
    verse: "내가 또 주의 목소리를 들으니 주께서 이르시되 내가 누구를 보내며 누가 우리를 위하여 갈꼬 하시니 그 때에 내가 이르되 내가 여기 있나이다 나를 보내소서 하였더니.",
    verseRef: "이사야 6:8",
    method: "거룩한 임재 직면 + 사명의 자원",
    lesson: "주님의 거룩한 영광 앞에 철저히 깨어지고 자원하여 순종하는 자를 통해, 시대를 앞서는 위대한 계시의 통로가 열린다.",
    tags: ["임재","회개","자원","메시아"],
    tone: { from: "#F2ECDF", to: "#D6C7A4", ink: "#5E5232" },
    cta: "AI 이사야와 대화하기",
    intro: "이사야입니다. 부르심 앞에 망설이고 있나요? 그 마음을 함께 들여다봐요.",
  },
  {
    id: "joshua", kr: "여호수아", initial: "여", en: "Joshua",
    image: "assets/joshua_all.png", avatarPos: "center 5%",
    imageFull: "assets/joshua_all.png",
    tagline: "가나안 정복",
    sub: "가나안을 정복한\n이스라엘의 지도자",
    expertise: "담대·정복·결단",
    story: "모세의 뒤를 이어 이스라엘을 이끌 때 두려웠지만 하나님이 강하고 담대하라며 명령하셨다. 이 율법책을 네 입에서 떠나지 말게 하며 주야로 그것을 묵상하라는 약속을 붙잡았고, 요단강을 건너고 여리고를 도는 철저한 순종으로 가나안 정복의 승리를 이끌었다.",
    verse: "내가 네게 명령한 것이 아니냐 강하고 담대하라 두려워하지 말며 놀라지 말라 네가 어디로 가든지 네 하나님 여호와가 너와 함께 하느니라 하시니라.",
    verseRef: "여호수아 1:9",
    method: "말씀 주야 묵상 + 담대한 전진",
    lesson: "하나님이 주신 약속의 말씀을 주야로 묵상하며 좌우로 치우치지 않을 때, 담대한 정복의 문이 열린다.",
    tags: ["담대","정복","임재","결단"],
    tone: { from: "#DCE7F0", to: "#9CB4CE", ink: "#2E4660" },
    cta: "AI 여호수아와 대화하기",
    intro: "여호수아입니다. 무너뜨려야 할 벽 앞에 서 있나요? 강하고 담대하게, 함께 가요.",
  },
  {
    id: "mary", kr: "마리아", initial: "마", en: "Mary",
    image: "assets/mary_all.png", avatarPos: "center 7%",
    imageFull: "assets/mary_all.png",
    tagline: "순종의 수용",
    sub: "예수님의 어머니,\n마니피캇의 기도자",
    expertise: "순종·수용·겸손",
    story: "천사로부터 예수님을 잉태할 것이라는 소식을 들었을 때 주의 여종이오니 말씀대로 내게 이루어지이다라며 자신의 삶을 온전히 내어드렸다. 처녀의 몸으로 임신하는 위험 속에서도 구세주의 길을 예비하며 찬가(마니피캇)를 불러 주님을 높였다.",
    verse: "마리아가 이르되 주의 여종이오니 말씀대로 내게 이루어지이다 하매 천사가 떠나가니라.",
    verseRef: "누가복음 1:38",
    method: "말씀의 전적 수용 + 영혼의 찬가",
    lesson: "인간적인 계산과 두려움을 내려놓고 주의 말씀이 삶에 이루어지도록 수용할 때, 구원의 통로로 귀하게 쓰임받는다.",
    tags: ["순종","수용","겸손","예비"],
    tone: { from: "#DCE6F2", to: "#A6BBD6", ink: "#33486A" },
    cta: "AI 마리아와 대화하기",
    intro: "마리아예요. 이해되지 않는 부르심 앞에 있나요? 함께 내어 맡기는 법을 나눠요.",
  },
  {
    id: "ezra", kr: "에스라", initial: "에", en: "Ezra",
    image: "assets/ezra_all.png", avatarPos: "center 5%",
    imageFull: "assets/ezra_all.png",
    tagline: "말씀 회복",
    sub: "바벨론 포로 귀환 후 말씀으로\n민족을 회복시킨 제사장",
    expertise: "말씀·연구·가르침",
    story: "에스라는 포로에서 돌아온 백성들에게 새벽부터 정오까지 말씀을 낭독했다. 백성들이 말씀을 듣고 울며 회개할 때 여호와를 기뻐하는 것이 너희의 힘이라며 격려했고, 여호와의 율법을 연구하여 준행하며 율례와 규례를 이스라엘에게 가르치기로 결심했다.",
    verse: "에스라가 여호와의 율법을 연구하여 준행하며 율례와 규례를 이스라엘에게 가르치기로 결심하였었더라.",
    verseRef: "에스라 7:10",
    method: "율법의 심화 연구 + 준행 및 전수 결단",
    lesson: "공동체의 진정한 회복은 하나님의 말씀을 온전히 연구하고 준행하며, 그 원칙을 삶의 기초로 가르칠 때 일어난다.",
    tags: ["말씀회복","연구","가르침","개혁"],
    tone: { from: "#F3E6C8", to: "#D8B85E", ink: "#6E5418" },
    cta: "AI 에스라와 대화하기",
    intro: "에스라입니다. 다시 말씀 앞에 서고 싶은가요? 함께 그 말씀을 펴봐요.",
  },
  {
    id: "stephen", kr: "스데반", initial: "스", en: "Stephen",
    image: "assets/stephen_all.png", avatarPos: "center 6%",
    imageFull: "assets/stephen_all.png",
    tagline: "첫 순교의 영광",
    sub: "돌에 맞으면서도 원수를 위해\n기도한 첫 순교자",
    expertise: "순교·성령충만·용서",
    story: "성령과 지혜가 충만하여 복음을 전하다가 공회의 논쟁 속에서도 천사의 얼굴과 같이 빛났다. 돌에 맞아 죽어가면서도 주 예수여 내 영혼을 받으시옵소서라고 기도하고, 무릎을 꿇고 크게 불러 주여 이 죄를 그들에게 돌리지 마옵소서라며 원수를 용서했다.",
    verse: "그들이 돌로 스데반을 치니 스데반이 부르짖어 이르되 주 예수여 내 영혼을 받으시옵소서 하고 무릎을 꿇고 크게 불러 이르되 주여 이 죄를 그들에게 돌리지 마옵소서 이 말을 하고 자니라.",
    verseRef: "사도행전 7:59-60",
    method: "용서의 중보 기도 + 영안을 열어 주님 바라보기",
    lesson: "성령이 충만하여 하늘 문이 열린 사람은, 죽음의 위기 속에서도 원수를 용서하며 주님의 성품을 온전히 나타낸다.",
    tags: ["순교","성령충만","용서","천사의얼굴"],
    tone: { from: "#E8E4DC", to: "#BDB4A4", ink: "#4A4236" },
    cta: "AI 스데반과 대화하기",
    intro: "스데반입니다. 용서가 도무지 안 되는 사람이 있나요? 그 마음을 함께 기도해요.",
  },
  {
    id: "john", kr: "사도요한", initial: "요", en: "John",
    image: "assets/john_all.png", avatarPos: "center 10%",
    imageFull: "assets/john_all.png",
    tagline: "사랑과 계시",
    sub: "사랑의 사도, 요한복음과\n계시록을 기록한 사도",
    expertise: "사랑·계시·소망",
    story: "예수님이 십자가에서 가장 사랑하는 제자에게 어머니를 부탁하셨다. 밧모 섬에 유배되어서도 성령에 감동하여 하늘의 계시를 보았으며, 끝까지 사랑의 계명을 외치며 요한복음, 요한일이삼서, 요한계시록을 기록하여 교회의 소망이 되었다.",
    verse: "사랑하는 자들아 우리가 서로 사랑하자 사랑은 하나님께 속한 것이니 사랑하는 자마다 하나님으로부터 나서 하나님을 알고.",
    verseRef: "요한일서 4:7",
    method: "사랑의 계명 묵상 + 성령 감동의 기록",
    lesson: "주님의 사랑 안에 거하며 성령에 감동된 사람은, 고립된 유배지에서도 하늘의 새 예루살렘을 바라보는 소망의 통로가 된다.",
    tags: ["사랑","계시","소망","동행"],
    tone: { from: "#E7E8DC", to: "#BCBE9E", ink: "#4C4E30" },
    cta: "AI 사도요한과 대화하기",
    intro: "사도요한입니다. 사랑하기 어려운 마음이 드나요? 그 이야기를 함께 나눠요.",
  },
];

// ----- Tiny icon set (no external libs) -----
function Icon({ name, size = 20, stroke = 1.8 }) {
  const s = size;
  const sw = stroke;
  const common = {
    width: s, height: s, viewBox: '0 0 24 24',
    fill: 'none', stroke: 'currentColor',
    strokeWidth: sw, strokeLinecap: 'round', strokeLinejoin: 'round',
  };
  switch (name) {
    case 'chev-left':
      return <svg {...common}><polyline points="14 6 8 12 14 18"/></svg>;
    case 'chev-right':
      return <svg {...common}><polyline points="9 6 15 12 9 18"/></svg>;
    case 'send':
      return <svg {...common}><path d="M5 12l14-7-5 16-3-7-6-2z"/></svg>;
    case 'star':
      return <svg width={s} height={s} viewBox="0 0 24 24" fill="currentColor"><path d="M12 2.5l2.9 6 6.6.95-4.78 4.66 1.13 6.57L12 17.6 6.15 20.68l1.13-6.57L2.5 9.45l6.6-.95L12 2.5z"/></svg>;
    case 'star-o':
      return <svg {...common}><polygon points="12 2.5 14.9 8.5 21.5 9.45 16.72 14.1 17.85 20.68 12 17.6 6.15 20.68 7.28 14.1 2.5 9.45 9.1 8.5"/></svg>;
    case 'book':
      return <svg {...common}><path d="M4 5a2 2 0 0 1 2-2h12v16H6a2 2 0 0 0-2 2V5z"/><path d="M4 19a2 2 0 0 1 2-2h12"/></svg>;
    case 'hands':
      return <svg {...common}><path d="M7 12V5a1.5 1.5 0 0 1 3 0v6"/><path d="M10 12V3.5a1.5 1.5 0 0 1 3 0V12"/><path d="M13 11V5a1.5 1.5 0 0 1 3 0v8"/><path d="M16 9a1.5 1.5 0 0 1 3 0v6a6 6 0 0 1-12 0v-2"/></svg>;
    case 'leaf':
      return <svg {...common}><path d="M4 20s2-12 16-16c0 10-6 16-12 16-2 0-4 0-4 0z"/><path d="M4 20c4-4 8-7 12-9"/></svg>;
    case 'pencil':
      return <svg {...common}><path d="M14 4l6 6-10 10H4v-6L14 4z"/><path d="M13 5l6 6"/></svg>;
    case 'user':
      return <svg {...common}><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></svg>;
    case 'chat':
      return <svg {...common}><path d="M21 12a8 8 0 0 1-11.4 7.2L4 21l1.8-5.6A8 8 0 1 1 21 12z"/></svg>;
    case 'bolt':
      return <svg width={s} height={s} viewBox="0 0 24 24" fill="currentColor"><path d="M13 2L4 14h7l-1 8 9-12h-7l1-8z"/></svg>;
    case 'sparkle':
      return <svg {...common}><path d="M12 4v6"/><path d="M12 14v6"/><path d="M4 12h6"/><path d="M14 12h6"/></svg>;
    case 'plus':
      return <svg {...common}><path d="M12 5v14"/><path d="M5 12h14"/></svg>;
    case 'bell':
      return <svg {...common}><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></svg>;
    case 'search':
      return <svg {...common}><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>;
    case 'dots':
      return <svg {...common} strokeWidth="2.5"><circle cx="5" cy="12" r="1"/><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/></svg>;
    case 'link':
      return <svg {...common}><path d="M10 13a5 5 0 0 0 7 0l3-3a5 5 0 0 0-7-7l-1 1"/><path d="M14 11a5 5 0 0 0-7 0l-3 3a5 5 0 0 0 7 7l1-1"/></svg>;
    case 'eye-off':
      return <svg {...common}><path d="M9.9 5.1A9.8 9.8 0 0 1 12 5c5 0 9 5 9 7a11 11 0 0 1-2.2 3.1M6.5 6.5C3.9 8 2 11 2 12c0 2 4 7 10 7a9.5 9.5 0 0 0 5.5-1.6"/><path d="M3 3l18 18"/><path d="M9.9 9.9a3 3 0 0 0 4.2 4.2"/></svg>;
    case 'flag':
      return <svg {...common}><path d="M5 21V4"/><path d="M5 4h11l-1.5 3.5L16 11H5"/></svg>;
    case 'sort':
      return <svg {...common}><path d="M7 4v16"/><path d="M4 8l3-4 3 4"/><path d="M17 20V4"/><path d="M14 16l3 4 3-4"/></svg>;
    case 'download':
      return <svg {...common}><path d="M12 3v12"/><path d="M7 11l5 5 5-5"/><path d="M5 21h14"/></svg>;
    case 'cloud':
      return <svg {...common}><path d="M6.5 18a4 4 0 0 1-.3-7.98 5.5 5.5 0 0 1 10.6-1.02A3.75 3.75 0 0 1 17 18H6.5z"/></svg>;
    case 'copy':
      return <svg {...common}><rect x="9" y="9" width="11" height="11" rx="2"/><path d="M5 15V5a2 2 0 0 1 2-2h8"/></svg>;
    case 'pin':
      return <svg {...common}><path d="M12 17v5"/><path d="M9 3h6l-1 6 3 3H7l3-3-1-6z"/></svg>;
    case 'trash':
      return <svg {...common}><path d="M4 7h16"/><path d="M9 7V4h6v3"/><path d="M6 7l1 13h10l1-13"/></svg>;
    case 'x':
      return <svg {...common}><path d="M6 6l12 12"/><path d="M18 6l-12 12"/></svg>;
    case 'heart':
      return <svg {...common}><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>;
    case 'heart-fill':
      return <svg width={s} height={s} viewBox="0 0 24 24" fill="currentColor"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg>;
    case 'comment':
      return <svg {...common}><path d="M21 11.5a8.38 8.38 0 0 1-8.5 8.5 8.5 8.5 0 0 1-3.7-.84L3 21l1.84-5.8a8.38 8.38 0 0 1-.84-3.7 8.5 8.5 0 0 1 8.5-8.5 8.38 8.38 0 0 1 8.5 8.5z"/></svg>;
    case 'home':
      return <svg {...common}><path d="M3 11l9-7 9 7"/><path d="M5 10v10h14V10"/></svg>;
    case 'people':
      return <svg {...common}><circle cx="9" cy="9" r="3"/><path d="M3 20a6 6 0 0 1 12 0"/><circle cx="17" cy="7" r="2.5"/><path d="M21 18a4 4 0 0 0-5-3.87"/></svg>;
    case 'wifi':
      return <svg width={s} height={s} viewBox="0 0 16 12" fill="currentColor"><path d="M8 11.5a1.2 1.2 0 1 0 0-2.4 1.2 1.2 0 0 0 0 2.4zM3.5 6.7a6.5 6.5 0 0 1 9 0l.9-.9a7.75 7.75 0 0 0-10.8 0l.9.9zM5.7 8.9a3.5 3.5 0 0 1 4.6 0l.9-.9a4.75 4.75 0 0 0-6.4 0l.9.9zM.7 3.7a10.5 10.5 0 0 1 14.6 0l.7-.9a11.75 11.75 0 0 0-16 0l.7.9z"/></svg>;
    case 'battery':
      return <svg width={26} height={s} viewBox="0 0 26 12" fill="currentColor"><rect x="1" y="2" width="20" height="8" rx="2" fill="none" stroke="currentColor" strokeWidth="1"/><rect x="22.5" y="4.5" width="2" height="3" rx="1"/><rect x="3" y="4" width="16" height="4" rx="1"/></svg>;
    case 'cellular':
      return <svg width={18} height={s} viewBox="0 0 18 12" fill="currentColor"><rect x="0" y="8" width="3" height="4" rx="0.5"/><rect x="5" y="5" width="3" height="7" rx="0.5"/><rect x="10" y="2" width="3" height="10" rx="0.5"/><rect x="15" y="0" width="3" height="12" rx="0.5" opacity="0.35"/></svg>;
    default: return null;
  }
}

// ----- Mentor avatar tile (uses real image when available, falls back to
//       gradient + initial when /assets/{id}.png isn't there yet) -----
function MentorAvatar({ mentor, size = 60 }) {
  const { from, to, ink } = mentor.tone;
  const [imgFailed, setImgFailed] = useState(!mentor.image);

  return (
    <div className="avatar-tile" style={{
      width: size, height: size, borderRadius: '50%',
      background: `radial-gradient(circle at 30% 28%, ${from}, ${to} 75%)`,
      fontSize: Math.round(size * 0.46),
      color: ink,
      overflow: 'hidden',
    }}>
      {imgFailed && <span style={{ position: 'relative', zIndex: 1 }}>{mentor.initial}</span>}
      {!imgFailed && mentor.image && (
        <img
          src={window.__res(mentor.image)}
          alt={mentor.kr}
          onError={() => setImgFailed(true)}
          style={{
            width: '100%', height: '100%',
            objectFit: 'cover', objectPosition: mentor.avatarPos || 'center 8%',
            position: 'absolute', inset: 0, zIndex: 2,
            display: 'block',
          }}
        />
      )}
    </div>
  );
}

// ----- Status bar -----
function StatusBar({ theme }) {
  return (
    <div className="statusbar">
      <span>9:41</span>
      <div className="icons">
        <Icon name="cellular" size={12} />
        <Icon name="wifi" size={12} />
        <Icon name="battery" size={12} />
      </div>
    </div>
  );
}

// ----- App brand -----
function Brand() {
  return (
    <div className="brand">
      <span className="cross" />
      <span>AI-Men</span>
    </div>
  );
}

// ===== Screen: Mentor List =====
function ListScreen({ onPick, themeKey, onTab, onHistory }) {
  const recent = ChatStore.list().slice(0, 3);
  return (
    <>
      <div className="appbar">
        <button className="iconbtn" aria-label="Back" onClick={() => onTab && onTab('home')}><Icon name="chev-left" /></button>
        <Brand />
        <button className="iconbtn" aria-label="대화 기록" onClick={onHistory}><Icon name="chat" /></button>
      </div>
      <div className="content">
        {recent.length > 0 && (
          <button className="conv-resume" onClick={onHistory}>
            <span className="cr-avs">
              {recent.map(c => {
                const mm = MENTORS.find(m => m.id === c.mentorId);
                return mm ? <span key={c.mentorId} className="cr-av"><MentorAvatar mentor={mm} size={34} /></span> : null;
              })}
            </span>
            <span className="cr-text">
              <span className="cr-title">지난 대화 이어가기</span>
              <span className="cr-sub">{recent.length}명의 멘토와 나눈 대화</span>
            </span>
            <Icon name="chev-right" size={18} stroke={2} />
          </button>
        )}
        {themeKey === 'sky' && (
          <div className="daily-banner">
            <div className="db-emoji">🔥</div>
            <div className="db-text">
              <div className="db-title">연속 7일 기도 출석</div>
              <div className="db-sub">오늘의 멘토를 만나 +25 XP</div>
            </div>
            <div className="db-xp">+25 XP</div>
          </div>
        )}
        <div className="page-title">신앙 멘토 선택</div>
        <div className="page-sub">
          {themeKey === 'sky' ? '한 분과 깊이 대화하며 신앙을 자라게 해요' : '오늘 마음을 나눌 한 사람을 골라보세요'}
        </div>
        <div className="mentor-list">
          {MENTORS.map((m, idx) => (
            <button
              key={m.id}
              className="mentor-card"
              onClick={() => onPick(m)}
            >
              <div className="avatar"><MentorAvatar mentor={m} size={themeKey === 'sky' ? 64 : 52} /></div>
              <div className="body">
                <div className="name">
                  <strong>{m.kr}</strong>
                  <span>{m.en}</span>
                </div>
                <div className="tagline">{m.tagline}</div>
              </div>
              <div className="chev"><Icon name="chev-right" size={20} stroke={2} /></div>
            </button>
          ))}
        </div>
      </div>
      <BottomTabs active="mentor" themeKey={themeKey} onTab={onTab} />
    </>
  );
}

// ===== Screen: Mentor Detail =====
function DetailScreen({ mentor, onBack, onChat, themeKey }) {
  // B theme: show full-body character as a hero illustration.
  // A theme: keep a clean compact hero.
  const useFullHero = themeKey === 'sky' && mentor.imageFull;
  const [saved, setSaved] = useState(false);
  const [toast, setToast] = useState('');
  function toggleSave() {
    const next = !saved;
    setSaved(next);
    setToast(next ? '멘토를 저장했어요' : '저장을 해제했어요');
    setTimeout(() => setToast(''), 1600);
  }

  return (
    <>
      <div className="appbar">
        <button className="iconbtn" aria-label="Back" onClick={onBack}><Icon name="chev-left" /></button>
        <Brand />
        <button className={`iconbtn ${saved ? 'saved' : ''}`} aria-label="Bookmark" aria-pressed={saved} onClick={toggleSave}>
          <Icon name={saved ? 'star' : 'star-o'} size={20} stroke={2} />
        </button>
      </div>

      <div className="content" style={{ paddingBottom: 110 }}>
        {useFullHero ? (
          <div className="detail-hero hero-full">
            <div className="hero-bg" />
            <div className="hero-text">
              <div className="kr">{mentor.kr}</div>
              <div className="en">{mentor.en}</div>
              <div className="pill">
                <span className="tag-pill">
                  <Icon name="hands" size={11} stroke={2.2} />
                  {mentor.tagline}
                </span>
              </div>
              <div className="xp-row">
                <div className="xp-bar"><div className="xp-fill" style={{ width: '62%' }} /></div>
                <span className="xp-num">Lv.5 · 62%</span>
              </div>
            </div>
            <img className="hero-figure" src={window.__res(mentor.imageFull)} alt={mentor.kr} />
          </div>
        ) : (
          <div className="detail-hero">
            <div className="avatar"><MentorAvatar mentor={mentor} size={themeKey === 'sky' ? 88 : 80} /></div>
            <div className="meta">
              <div className="kr">{mentor.kr}</div>
              <div className="en">{mentor.en}</div>
              <div className="pill">
                <span className="tag-pill">
                  <Icon name="hands" size={11} stroke={2.2} />
                  {mentor.tagline}
                </span>
              </div>
              {themeKey === 'sky' && (
                <div className="xp-row">
                  <div className="xp-bar"><div className="xp-fill" style={{ width: '62%' }} /></div>
                  <span className="xp-num">Lv.5 · 62%</span>
                </div>
              )}
            </div>
          </div>
        )}

        <div className="info-card tone-blue">
          <div className="ic-header">
            <span className="ic-dot"><Icon name="book" size={13} stroke={2.2} /></span>
            신앙 스토리
          </div>
          <div className="ic-body">{mentor.story || mentor.sub}</div>
        </div>

        <div className="info-card tone-accent">
          <div className="ic-header">
            <span className="ic-dot"><Icon name="star" size={13} /></span>
            핵심 명언
          </div>
          <div className="ic-body quote">
            "{mentor.verse || '믿음으로 행하라.'}"
            <span className="verse-ref">{mentor.verseRef || '히브리서 11:1'}</span>
          </div>
        </div>

        <div className="info-card tone-gold">
          <div className="ic-header">
            <span className="ic-dot"><Icon name="hands" size={13} stroke={2.2} /></span>
            사용 기법
          </div>
          <div className="ic-body">{mentor.method || '말씀 묵상 + 기도'}</div>
        </div>

        <div className="info-card tone-leaf">
          <div className="ic-header">
            <span className="ic-dot"><Icon name="leaf" size={13} stroke={2.2} /></span>
            핵심 교훈
          </div>
          <div className="ic-body">{mentor.lesson || '하나님의 약속을 붙들면 반드시 이루어진다.'}</div>
        </div>

        {mentor.tags && mentor.tags.length > 0 && (
          <div className="mentor-tags">
            {mentor.tags.map(t => <span key={t} className="mtag">#{t}</span>)}
          </div>
        )}
      </div>

      <button className="cta" onClick={onChat}>
        <Icon name="chat" size={18} stroke={2.2} />
        {mentor.cta}
      </button>
      {toast && <div className="cm-toast">{toast}</div>}
    </>
  );
}

// ===== Conversation persistence (local only — no server / DB) =====
const CHAT_KEY = 'aimen_chats_v1';
const ChatStore = {
  _read() {
    try { return JSON.parse(localStorage.getItem(CHAT_KEY)) || {}; }
    catch (e) { return {}; }
  },
  _write(obj) {
    try { localStorage.setItem(CHAT_KEY, JSON.stringify(obj)); } catch (e) {}
  },
  load(mentorId) {
    return this._read()[mentorId] || null;
  },
  save(mentorId, messages) {
    const all = this._read();
    all[mentorId] = { messages, updatedAt: Date.now() };
    this._write(all);
  },
  remove(mentorId) {
    const all = this._read();
    delete all[mentorId];
    this._write(all);
  },
  list() {
    const all = this._read();
    return Object.keys(all)
      .map(id => ({ mentorId: id, ...all[id] }))
      .filter(c => c.messages && c.messages.some(m => m.from === 'me'))
      .sort((a, b) => (b.updatedAt || 0) - (a.updatedAt || 0));
  },
};

function relTime(ts) {
  if (!ts) return '';
  const min = Math.floor((Date.now() - ts) / 60000);
  if (min < 1) return '방금 전';
  if (min < 60) return `${min}분 전`;
  const hr = Math.floor(min / 60);
  if (hr < 24) return `${hr}시간 전`;
  const day = Math.floor(hr / 24);
  if (day < 7) return `${day}일 전`;
  const d = new Date(ts);
  return `${d.getMonth() + 1}월 ${d.getDate()}일`;
}

// ===== Screen: Conversation History (멘토 대화 기록) =====
function ConvHistoryScreen({ onBack, onOpen, onTab, activeTab = 'mentor' }) {
  const [items, setItems] = useState(() => ChatStore.list());

  function del(e, mentorId) {
    e.preventDefault();
    e.stopPropagation();
    ChatStore.remove(mentorId);
    setItems(ChatStore.list());
  }

  function lastPreview(msgs) {
    for (let i = msgs.length - 1; i >= 0; i--) {
      if (msgs[i] && msgs[i].text) return msgs[i];
    }
    return null;
  }

  return (
    <>
      <div className="appbar">
        <button className="iconbtn" aria-label="Back" onClick={onBack}><Icon name="chev-left" /></button>
        <Brand />
        <span style={{ width: 38 }} />
      </div>
      <div className="content">
        <div className="page-title">멘토 대화 기록</div>
        <div className="page-sub">지난 대화를 이어서 나눌 수 있어요</div>

        {items.length === 0 ? (
          <div className="conv-empty">
            <div className="ce-art" aria-hidden="true">💬</div>
            <div className="ce-title">아직 나눈 대화가 없어요</div>
            <div className="ce-desc">신앙 멘토를 골라 첫 대화를 시작해 보세요.<br/>나눈 이야기가 이곳에 모입니다.</div>
          </div>
        ) : (
          <div className="conv-list">
            {items.map(c => {
              const mentor = MENTORS.find(m => m.id === c.mentorId);
              if (!mentor) return null;
              const prev = lastPreview(c.messages);
              const cnt = c.messages.filter(m => m.from === 'me').length;
              return (
                <button key={c.mentorId} className="conv-card" onClick={() => onOpen(mentor)}>
                  <div className="avatar"><MentorAvatar mentor={mentor} size={56} /></div>
                  <div className="conv-body">
                    <div className="conv-top">
                      <span className="conv-name">AI {mentor.kr} 멘토</span>
                      <span className="conv-time">{relTime(c.updatedAt)}</span>
                    </div>
                    <div className="conv-snippet">{prev ? prev.text.replace(/\n/g, ' ') : ''}</div>
                    <div className="conv-meta">💬 {cnt}개의 메시지 · 이어서 대화하기</div>
                  </div>
                  <span className="conv-del" onClick={(e) => del(e, c.mentorId)} role="button" aria-label="대화 삭제">✕</span>
                </button>
              );
            })}
          </div>
        )}
      </div>
      <BottomTabs active={activeTab} themeKey="sky" onTab={onTab} />
    </>
  );
}

// ===== Screen: Chat =====
function ChatScreen({ mentor, onBack, themeKey }) {
  const freshMessages = [
    { from: 'mentor', text: mentor.intro, quick: ['요즘 기도가 응답이 없어요', '말씀 묵상이 어려워요', '감사 제목을 나누고 싶어요'] },
  ];
  const [messages, setMessages] = useState(() => {
    const saved = ChatStore.load(mentor.id);
    return saved && saved.messages && saved.messages.length ? saved.messages : freshMessages;
  });
  const [draft, setDraft] = useState('');
  const [isTyping, setIsTyping] = useState(false);
  const [saved, setSaved] = useState(false);
  const [bmToast, setBmToast] = useState('');
  const feedRef = useRef(null);

  function toggleSave() {
    const next = !saved;
    setSaved(next);
    setBmToast(next ? '멘토를 저장했어요' : '저장을 해제했어요');
    setTimeout(() => setBmToast(''), 1600);
  }

  useEffect(() => {
    if (feedRef.current) {
      feedRef.current.scrollTop = feedRef.current.scrollHeight;
    }
  }, [messages, isTyping]);

  // Persist the conversation locally so 대화 기록 can show & resume it
  useEffect(() => {
    if (messages.some(m => m.from === 'me')) {
      ChatStore.save(mentor.id, messages);
    }
  }, [messages, mentor.id]);

  function resetChat() {
    ChatStore.remove(mentor.id);
    setMessages(freshMessages);
    setIsTyping(false);
  }

  // Canned reply for prototype
  const cannedReply = useMemo(() => ({
    text: "저도 광야에서 그런 시간이 있었습니다.\n로뎀나무 아래 누워 포기하고 싶었지요. (열왕기상 19:4)\n\n하지만 하나님은 그때 천사를 보내셨어요. 당신의 기도는 결코 헛되지 않습니다.",
    verseTag: '열왕기상 19:4 연결됨',
  }), []);

  const followUp = useMemo(() => ({
    text: '좋아요! 하나님은 당신의 기도를 들으시고 가장 선한 때에 응답하실 거예요. 언제든지 함께 기도해요. 🌿',
  }), []);

  function sendText(text) {
    if (!text.trim()) return;
    const myMsg = { from: 'me', text };
    setMessages(prev => [...prev, myMsg]);
    setDraft('');
    setIsTyping(true);
    setTimeout(() => {
      setIsTyping(false);
      const isFirstReply = messages.filter(m => m.from === 'me').length === 0;
      const reply = isFirstReply
        ? { from: 'mentor', text: cannedReply.text, verseTag: cannedReply.verseTag, quick: ['감사합니다. 기도 제목을 적어볼게요', '다른 말씀도 알려주세요'] }
        : { from: 'mentor', text: followUp.text };
      setMessages(prev => [...prev, reply]);
    }, 900);
  }

  return (
    <>
      <div className="appbar">
        <button className="iconbtn" aria-label="Back" onClick={onBack}><Icon name="chev-left" /></button>
        <Brand />
        <button className={`iconbtn ${saved ? 'saved' : ''}`} aria-label="Bookmark" aria-pressed={saved} onClick={toggleSave}>
          <Icon name={saved ? 'star' : 'star-o'} size={20} />
        </button>
      </div>

      <div className="chat-header">
        <div className="av"><MentorAvatar mentor={mentor} size={46} /></div>
        <div className="who">
          <div className="nm">AI {mentor.kr} 멘토</div>
          <div className="exp">
            <Icon name="bolt" size={11} />
            {mentor.expertise}
          </div>
        </div>
        {themeKey === 'sky' && (
          <div className="streak">🔥 7일</div>
        )}
        <button className="chat-reset" onClick={resetChat} aria-label="새 대화 시작">새로 시작</button>
      </div>

      <div className="chat-feed" ref={feedRef}>
        {messages.map((m, i) => (
          <React.Fragment key={i}>
            <div className={`msg-row ${m.from}`}>
              {m.from === 'mentor' && <div className="av-sm"><MentorAvatar mentor={mentor} size={30} /></div>}
              <div className="bubble">
                {m.text}
                {m.verseTag && (
                  <span className="verse-tag">
                    <Icon name="book" size={11} stroke={2.2} />
                    {m.verseTag}
                  </span>
                )}
              </div>
            </div>
            {m.quick && i === messages.length - 1 && !isTyping && (
              <div className="quick-row">
                {m.quick.map((q, j) => (
                  <button key={j} className="quick-chip" onClick={() => sendText(q)}>{q}</button>
                ))}
              </div>
            )}
          </React.Fragment>
        ))}
        {isTyping && (
          <div className="msg-row mentor">
            <div className="av-sm"><MentorAvatar mentor={mentor} size={30} /></div>
            <div className="bubble">
              <span className="typing">
                <span className="dot" /><span className="dot" /><span className="dot" />
              </span>
            </div>
          </div>
        )}
      </div>

      <div className="composer">
        <input
          className="input"
          placeholder="메시지 입력…"
          value={draft}
          onChange={e => setDraft(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') sendText(draft); }}
        />
        <button
          className={`send ${draft.trim() ? '' : 'disabled'}`}
          onClick={() => sendText(draft)}
          aria-label="Send"
        >
          <Icon name="send" size={20} stroke={2.2} />
        </button>
      </div>
      {bmToast && <div className="cm-toast">{bmToast}</div>}
    </>
  );
}

// ===== Bottom tabs =====
function BottomTabs({ active, themeKey, onTab }) {
  // 5-tab structure: 홈 · 기도기록 · 멘토 · 커뮤니티 · 내정보
  const tabs = [
    { id: 'home',      icon: 'home',   label: '홈' },
    { id: 'log',       icon: 'pencil', label: '기록' },
    { id: 'mentor',    icon: 'star',   label: '멘토' },
    { id: 'community', icon: 'people', label: '커뮤니티' },
    { id: 'me',        icon: 'user',   label: '내정보' },
  ];
  return (
    <div className="tabbar">
      {tabs.map(t => (
        <button
          key={t.id}
          className={`tab ${active === t.id ? 'active' : ''}`}
          onClick={() => onTab && onTab(t.id)}
        >
          <span className="ico">
            <Icon name={t.icon} size={22} stroke={2} />
          </span>
          <span className="label">{t.label}</span>
        </button>
      ))}
    </div>
  );
}

// ===== Root app =====
// initialScreen + initialMentorId let each artboard preview a distinct screen
// while remaining fully clickable (back/forward still works inside the frame).
function MentorApp({ theme = 'sky', initialScreen = 'list', initialMentorId = null }) {
  const NIGHT_SCREENS = ['welcome', 'home-night', 'growth-tree', 'about', 'login', 'signup', 'micro', 'profile', 'notifications', 'notifications-empty', 'settings-notif', 'settings-theme', 'settings-backup', 'settings-help', 'donation', 'ai-coaching', 'life-verse', 'board', 'board-detail', 'letter'];
  const initialMentor = initialMentorId
    ? MENTORS.find(m => m.id === initialMentorId)
    : null;
  const [screen, setScreen] = useState(initialScreen);
  const [selected, setSelected] = useState(initialMentor);
  const [communitySub, setCommunitySub] = useState(
    initialScreen === 'community-encouragement' ? 'encouragement' : 'feed'
  );
  // When the canvas previews start directly on post-detail, prime openPost with
  // the first community post so the screen isn't blank.
  const [openPost, setOpenPost] = useState(
    initialScreen === 'post-detail' && window.COMMUNITY_POSTS
      ? window.COMMUNITY_POSTS[0]
      : null
  );
  const [openLog, setOpenLog] = useState(
    initialScreen === 'log-detail' && window.SAMPLE_LOGS
      ? window.SAMPLE_LOGS[0]
      : null
  );

  const [chatFrom, setChatFrom] = useState('detail');
  const [histFrom, setHistFrom] = useState('list');
  const [lvFrom, setLvFrom] = useState('home-night');
  const [boardId, setBoardId] = useState('b01');

  function pick(m) { setSelected(m); setScreen('detail'); }
  function chat() { setChatFrom('detail'); setScreen('chat'); }
  function openHistory(from) { setHistFrom(from || 'list'); setScreen('history'); }
  function openChatWith(m) { setSelected(m); setChatFrom('history'); setScreen('chat'); }
  function back() {
    if (screen === 'chat') setScreen(chatFrom);
    else if (screen === 'history') setScreen(histFrom);
    else if (screen === 'detail') { setScreen('list'); }
    else if (screen === 'post-detail') setScreen('community');
    else if (screen === 'compose') setScreen('community');
  }

  function onTab(tabId) {
    if (tabId === 'home') setScreen('home-night');
    else if (tabId === 'log') setScreen('log');
    else if (tabId === 'mentor') setScreen('list');
    else if (tabId === 'community') {
      setCommunitySub('feed');
      setScreen('community');
    }
    else if (tabId === 'me') setScreen('profile');
  }

  function openPostDetail(p) { setOpenPost(p); setScreen('post-detail'); }
  function goCompose() { setScreen('compose'); }
  function submitPost() { setScreen('community'); }
  const [notifFrom, setNotifFrom] = useState('profile');
  function openNotifications(from) { setNotifFrom(from || 'profile'); setScreen('notifications'); }

  // If a screen needs a mentor and none is selected, fall back to list.
  const needsMentor = screen === 'detail' || screen === 'chat';
  const effectiveScreen = needsMentor && !selected ? 'list' : screen;

  // Map alias starts to the right screen
  const screenToRender = effectiveScreen === 'community-encouragement' ? 'community' : effectiveScreen === 'community-ranking' ? 'community' : effectiveScreen;
  const subToShow = effectiveScreen === 'community-encouragement' ? 'encouragement' : effectiveScreen === 'community-ranking' ? 'ranking' : communitySub;

  // Recompute theme on every render — when user taps a tab and screen
  // switches from a night screen (home) into a light screen (mentor list),
  // the wrapping .phone class flips so the right CSS variables apply.
  const effectiveTheme = NIGHT_SCREENS.includes(screenToRender) ? 'night' : theme;

  return (
    <div className={`phone theme-${effectiveTheme}`}>
      <StatusBar theme={effectiveTheme} />
      {screenToRender === 'list' && <ListScreen onPick={pick} themeKey={theme} onTab={onTab} onHistory={() => openHistory('list')} />}
      {screenToRender === 'history' && (
        <ConvHistoryScreen
          onBack={back}
          onOpen={openChatWith}
          onTab={onTab}
          activeTab={histFrom === 'profile' ? 'me' : 'mentor'}
        />
      )}
      {screenToRender === 'welcome' && (
        <window.WelcomeScreen
          onStart={() => setScreen('signup')}
          onLogin={() => setScreen('login')}
        />
      )}
      {screenToRender === 'home-night' && (
        <>
          <window.HomeNightScreen onTab={(t) => t === 'growth' ? setScreen('growth-tree') : t === 'donation' ? setScreen('donation') : t === 'coaching' ? setScreen('ai-coaching') : t === 'life-verse' ? (setLvFrom('home-night'), setScreen('life-verse')) : t === 'board' ? setScreen('board') : onTab(t)} />
          <BottomTabs active="home" themeKey={effectiveTheme} onTab={onTab} />
        </>
      )}
      {screenToRender === 'ai-coaching' && (
        <window.AICoachingScreen onBack={() => setScreen('home-night')} />
      )}
      {screenToRender === 'life-verse' && (
        <window.LifeVerseScreen onBack={() => setScreen(lvFrom)} />
      )}
      {screenToRender === 'board' && (
        <window.NoticeBoardScreen onBack={() => setScreen('home-night')} onOpen={(id) => { setBoardId(id); setScreen('board-detail'); }} />
      )}
      {screenToRender === 'board-detail' && (
        <window.NoticeDetailScreen postId={boardId} onBack={() => setScreen('board')} />
      )}
      {screenToRender === 'growth-tree' && (
        <window.GrowthTreeScreen onBack={() => setScreen('home-night')} />
      )}
      {screenToRender === 'about' && (
        <window.AboutScreen onBack={() => setScreen('home-night')} />
      )}
      {screenToRender === 'donation' && (
        <window.DonationScreen onBack={() => setScreen('home-night')} />
      )}
      {screenToRender === 'micro' && (
        <window.MicroInteractionsScreen onBack={() => setScreen('home-night')} />
      )}
      {screenToRender === 'login' && (
        <window.LoginScreen
          onBack={() => setScreen('welcome')}
          onLogin={() => setScreen('home-night')}
          onGoSignup={() => setScreen('signup')}
        />
      )}
      {screenToRender === 'signup' && (
        <window.SignupScreen
          onBack={() => setScreen('welcome')}
          onDone={() => setScreen('home-night')}
        />
      )}
      {screenToRender === 'log' && (
        <window.PrayerLogListScreen
          onCompose={() => setScreen('log-compose')}
          onOpenLog={(l) => { setOpenLog(l); setScreen('log-detail'); }}
          onTab={onTab}
        />
      )}
      {screenToRender === 'log-empty' && (
        <window.PrayerLogListScreen
          empty
          onCompose={() => setScreen('log-compose')}
          onTab={onTab}
        />
      )}
      {screenToRender === 'log-compose' && (
        <window.PrayerLogComposeScreen
          onBack={() => setScreen('log')}
          onSubmit={() => setScreen('log')}
        />
      )}
      {screenToRender === 'log-detail' && (
        <window.PrayerLogDetailScreen
          log={openLog}
          onBack={() => setScreen('log')}
        />
      )}
      {screenToRender === 'profile' && (
        <window.ProfileScreen
          onTab={onTab}
          onAbout={() => setScreen('about')}
          onGrowth={() => setScreen('growth-tree')}
          onHistory={() => openHistory('profile')}
          onLifeVerse={() => { setLvFrom('profile'); setScreen('life-verse'); }}
          onNotifications={() => openNotifications('profile')}
          onSettings={(id) => setScreen('settings-' + id)}
          onLogout={() => setScreen('welcome')}
        />
      )}
      {(screenToRender === 'settings-notif' || screenToRender === 'settings-theme' || screenToRender === 'settings-backup' || screenToRender === 'settings-help') && (
        <window.SettingsScreen
          section={screenToRender.replace('settings-', '')}
          onBack={() => setScreen('profile')}
        />
      )}
      {screenToRender === 'notifications' && (
        <window.NotificationsScreen onBack={() => setScreen(notifFrom)} />
      )}
      {screenToRender === 'notifications-empty' && (
        <window.NotificationsScreen empty onBack={() => setScreen('profile')} />
      )}
      {screenToRender === 'detail' && selected && <DetailScreen mentor={selected} onBack={back} onChat={chat} themeKey={theme} />}
      {screenToRender === 'chat' && selected && <ChatScreen mentor={selected} onBack={back} themeKey={theme} />}
      {screenToRender === 'community' && subToShow === 'feed' && (
        <window.FeedScreen
          onOpenPost={openPostDetail}
          onCompose={goCompose}
          onSwitch={setCommunitySub}
          onNotifications={() => openNotifications('community')}
          sub={subToShow}
          onTab={onTab}
        />
      )}
      {screenToRender === 'community' && subToShow === 'encouragement' && (
        <window.EncouragementScreen
          onSwitch={setCommunitySub}
          onNotifications={() => openNotifications('community')}
          sub={subToShow}
          onTab={(t) => t === 'letter' ? setScreen('letter') : onTab(t)}
        />
      )}
      {screenToRender === 'letter' && (
        <window.LetterScreen onBack={() => { setCommunitySub('encouragement'); setScreen('community'); }} />
      )}
      {screenToRender === 'community' && subToShow === 'ranking' && (
        <>
          <window.RankingScreen
            onSwitch={setCommunitySub}
            onNotifications={() => openNotifications('community')}
            sub={subToShow}
            onTab={onTab}
          />
          <BottomTabs active="community" themeKey={effectiveTheme} onTab={onTab} />
        </>
      )}
      {screenToRender === 'post-detail' && openPost && (
        <window.PostDetailScreen post={openPost} onBack={back} />
      )}
      {screenToRender === 'compose' && (
        <window.ComposeScreen onBack={back} onSubmit={submitPost} />
      )}
    </div>
  );
}

// Export to window so other Babel scripts can use it
window.MentorApp = MentorApp;
window.MENTORS = MENTORS;
