tea.html 65 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8"/>
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0"/>
  6. <title>茶决决 · VOC 洞察报告 · 产品定位 × 竞品分析 × 机会格局 × 用户需求</title>
  7. <style>
  8. :root {
  9. --bg-0: #0A0A0A; --bg-1: #111111; --bg-2: #1A1A1A; --bg-3: #252525;
  10. --border: rgba(255,255,255,0.08); --border-strong: rgba(255,255,255,0.16);
  11. --text-1: #F5F5F5; --text-2: #A8A8A8; --text-3: #6B6B6B;
  12. --amber: #F5A623; --amber-glow: rgba(245,166,35,0.15);
  13. --green: #00DC82; --purple: #8B5CF6; --rose: #FF4D8D; --blue: #3B82F6; --red: #EF4444; --orange: #FF8C42;
  14. --teal: #14B8A6; --teal-glow: rgba(20,184,166,0.12);
  15. --font-head: 'Inter','Noto Sans SC','PingFang SC','Hiragino Sans GB','Microsoft YaHei','微软雅黑','Source Han Sans CN',system-ui,-apple-system,BlinkMacSystemFont,sans-serif;
  16. --font-body: 'Noto Sans SC','Inter','PingFang SC','Hiragino Sans GB','Microsoft YaHei','微软雅黑','Source Han Sans CN',system-ui,-apple-system,BlinkMacSystemFont,sans-serif;
  17. --font-mono: 'JetBrains Mono','SF Mono','Fira Code','Cascadia Code',Consolas,'Courier New',monospace;
  18. --max-w: 1280px; --radius-sm: 8px; --radius-md: 12px; --radius-lg: 20px;
  19. }
  20. * { margin: 0; padding: 0; box-sizing: border-box; }
  21. html { scroll-behavior: smooth; font-size: 16px; scroll-snap-type: y proximity; }
  22. @media (prefers-reduced-motion: reduce) { html { scroll-snap-type: none; scroll-behavior: auto; } }
  23. body {
  24. font-family: var(--font-body); background: var(--bg-0); color: var(--text-1);
  25. line-height: 1.65; -webkit-font-smoothing: antialiased; overflow-x: hidden; position: relative;
  26. }
  27. body::before {
  28. content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  29. background: radial-gradient(ellipse 900px 700px at var(--amb-x, 20%) var(--amb-y, 25%), rgba(20,184,166,0.10), transparent 60%),
  30. radial-gradient(ellipse 800px 600px at calc(100% - var(--amb-x, 20%)) calc(100% - var(--amb-y, 25%)), rgba(245,166,35,0.06), transparent 60%);
  31. transition: background 1.4s cubic-bezier(.2,.7,.2,1);
  32. }
  33. body::after {
  34. content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 0;
  35. background-image: linear-gradient(rgba(255,255,255,0.015) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.015) 1px, transparent 1px);
  36. background-size: 80px 80px;
  37. mask-image: radial-gradient(ellipse 90% 95% at 50% 50%, black 0%, transparent 85%);
  38. -webkit-mask-image: radial-gradient(ellipse 90% 95% at 50% 50%, black 0%, transparent 85%);
  39. }
  40. main.deck { position: relative; z-index: 1; }
  41. ::selection { background: var(--teal); color: #000; }
  42. a { color: inherit; text-decoration: none; }
  43. img { max-width: 100%; display: block; }
  44. .text-hero { font-family: var(--font-head); font-weight: 900; letter-spacing: -0.04em; line-height: 0.95; font-size: clamp(4rem, 12vw, 10rem); }
  45. .text-poster { font-family: var(--font-head); font-weight: 800; letter-spacing: -0.03em; line-height: 1.05; font-size: clamp(2.5rem, 6vw, 5rem); }
  46. .text-h1 { font-family: var(--font-head); font-weight: 700; letter-spacing: -0.02em; line-height: 1.1; font-size: clamp(2rem, 4vw, 3.5rem); }
  47. .text-h2 { font-family: var(--font-head); font-weight: 700; letter-spacing: -0.015em; line-height: 1.2; font-size: clamp(1.4rem, 2.5vw, 2rem); }
  48. .text-h3 { font-weight: 600; font-size: clamp(1.05rem, 1.6vw, 1.3rem); letter-spacing: -0.01em; }
  49. .text-body { font-size: clamp(0.92rem, 1.1vw, 1rem); line-height: 1.75; color: var(--text-2); }
  50. .text-sm { font-size: 0.85rem; color: var(--text-2); }
  51. .text-xs { font-size: 0.72rem; color: var(--text-3); letter-spacing: 0.02em; }
  52. .text-mono { font-family: var(--font-mono); }
  53. .text-amber { color: var(--amber); } .text-green { color: var(--green); } .text-purple { color: var(--purple); }
  54. .text-rose { color: var(--rose); } .text-blue { color: var(--blue); } .text-red { color: var(--red); } .text-orange { color: var(--orange); } .text-teal { color: var(--teal); }
  55. section.report-section {
  56. min-height: 100vh; padding: clamp(60px, 10vh, 120px) clamp(24px, 6vw, 80px);
  57. position: relative; border-bottom: 1px solid var(--border);
  58. display: flex; flex-direction: column; justify-content: center;
  59. scroll-snap-align: start; scroll-snap-stop: always; overflow: hidden; isolation: isolate;
  60. }
  61. section.report-section::before {
  62. content: attr(data-slide-num); position: absolute; top: clamp(20px, 3vh, 36px); right: clamp(24px, 4vw, 60px);
  63. font-family: var(--font-mono); font-weight: 600; font-size: clamp(0.68rem, 0.75vw, 0.78rem);
  64. letter-spacing: 0.25em; color: var(--text-3); z-index: 4; pointer-events: none;
  65. }
  66. section.report-section::after {
  67. content: ''; position: absolute; inset: 0; pointer-events: none; z-index: -1;
  68. background: radial-gradient(ellipse 70% 60% at 85% 15%, var(--slide-glow-1, rgba(20,184,166,0.06)), transparent 55%),
  69. radial-gradient(ellipse 60% 50% at 15% 85%, var(--slide-glow-2, rgba(245,166,35,0.04)), transparent 55%);
  70. opacity: 0; transition: opacity 1s cubic-bezier(.2,.7,.2,1);
  71. }
  72. section.report-section.in-view::after { opacity: 1; }
  73. section.report-section[data-tone="teal"] { --slide-glow-1: rgba(20,184,166,0.10); --slide-glow-2: rgba(20,184,166,0.04); }
  74. section.report-section[data-tone="amber"] { --slide-glow-1: rgba(245,166,35,0.10); --slide-glow-2: rgba(245,166,35,0.04); }
  75. section.report-section[data-tone="rose"] { --slide-glow-1: rgba(255,77,141,0.09); --slide-glow-2: rgba(255,77,141,0.04); }
  76. section.report-section[data-tone="green"] { --slide-glow-1: rgba(0,220,130,0.08); --slide-glow-2: rgba(0,220,130,0.03); }
  77. section.report-section[data-tone="purple"] { --slide-glow-1: rgba(139,92,246,0.10); --slide-glow-2: rgba(139,92,246,0.04); }
  78. section.report-section[data-tone="blue"] { --slide-glow-1: rgba(59,130,246,0.08); --slide-glow-2: rgba(59,130,246,0.03); }
  79. section.report-section[data-tone="orange"] { --slide-glow-1: rgba(255,140,66,0.10); --slide-glow-2: rgba(255,140,66,0.04); }
  80. .section-inner { width: 100%; max-width: var(--max-w); margin: 0 auto; position: relative; }
  81. .section-head { margin-bottom: clamp(32px, 5vh, 64px); }
  82. .section-eyebrow {
  83. display: inline-flex; align-items: center; gap: 10px;
  84. font-family: var(--font-mono); font-size: 0.72rem; letter-spacing: 0.18em;
  85. text-transform: uppercase; color: var(--teal); font-weight: 500; margin-bottom: 18px;
  86. }
  87. .section-eyebrow::before { content: ''; display: inline-block; width: 24px; height: 1px; background: var(--teal); }
  88. .section-sub { color: var(--text-2); font-size: 1.05rem; max-width: 720px; margin-top: 14px; line-height: 1.8; }
  89. .grid { display: grid; gap: clamp(14px, 1.6vw, 22px); }
  90. .grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
  91. .grid-3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
  92. .grid-4 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
  93. .card { background: linear-gradient(180deg, rgba(255,255,255,0.025) 0%, rgba(255,255,255,0.008) 100%), var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius-md); padding: clamp(20px, 2.2vw, 32px); position: relative; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); transition: transform 0.4s cubic-bezier(.2,.7,.2,1), border-color 0.3s ease, box-shadow 0.4s ease; }
  94. .card:hover { border-color: var(--border-strong); transform: translateY(-3px); box-shadow: 0 12px 40px rgba(0,0,0,0.35), 0 0 0 1px rgba(20,184,166,0.08); }
  95. .card-accent { border-left: 3px solid var(--teal); }
  96. .card-rose { border-left: 3px solid var(--rose); }
  97. .card-green { border-left: 3px solid var(--green); }
  98. .card-blue { border-left: 3px solid var(--blue); }
  99. .card-purple { border-left: 3px solid var(--purple); }
  100. .card-amber { border-left: 3px solid var(--amber); }
  101. .tag { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 4px; font-size: 0.72rem; font-weight: 500; letter-spacing: 0.02em; font-family: var(--font-head); background: rgba(20,184,166,0.1); color: var(--teal); border: 1px solid rgba(20,184,166,0.22); }
  102. .tag.green { background: rgba(0,220,130,0.08); color: var(--green); border-color: rgba(0,220,130,0.2); }
  103. .tag.purple { background: rgba(139,92,246,0.08); color: var(--purple); border-color: rgba(139,92,246,0.2); }
  104. .tag.rose { background: rgba(255,77,141,0.08); color: var(--rose); border-color: rgba(255,77,141,0.2); }
  105. .tag.blue { background: rgba(59,130,246,0.08); color: var(--blue); border-color: rgba(59,130,246,0.2); }
  106. .tag.orange { background: rgba(255,140,66,0.08); color: var(--orange); border-color: rgba(255,140,66,0.2); }
  107. .tag.gray { background: rgba(255,255,255,0.04); color: var(--text-2); border-color: var(--border); }
  108. .cover-hero { position: absolute; inset: 0; display: flex; flex-direction: column; justify-content: center; padding: clamp(40px, 8vh, 100px) clamp(24px, 6vw, 80px); background: radial-gradient(ellipse 60% 80% at 30% 30%, rgba(20,184,166,0.08) 0%, transparent 70%), radial-gradient(ellipse 40% 60% at 80% 70%, rgba(245,166,35,0.05) 0%, transparent 70%), var(--bg-0); }
  109. .cover-grid-bg { position: absolute; inset: 0; background-image: linear-gradient(rgba(255,255,255,0.025) 1px, transparent 1px), linear-gradient(90deg, rgba(255,255,255,0.025) 1px, transparent 1px); background-size: 64px 64px; pointer-events: none; mask-image: radial-gradient(ellipse 80% 90% at 50% 50%, black 0%, transparent 80%); -webkit-mask-image: radial-gradient(ellipse 80% 90% at 50% 50%, black 0%, transparent 80%); }
  110. .cover-content { position: relative; z-index: 2; max-width: var(--max-w); }
  111. .cover-meta { display: flex; align-items: center; gap: 16px; font-family: var(--font-mono); font-size: 0.78rem; color: var(--text-3); letter-spacing: 0.18em; text-transform: uppercase; margin-bottom: 32px; }
  112. .cover-meta::before { content: ''; width: 32px; height: 2px; background: var(--teal); }
  113. .cover-title-stack { display: flex; flex-direction: column; gap: 4px; }
  114. .cover-title { font-family: var(--font-head); font-weight: 900; letter-spacing: -0.04em; line-height: 0.92; font-size: clamp(3.5rem, 11vw, 9rem); color: #fff; background: linear-gradient(135deg, #fff 30%, rgba(20,184,166,0.9) 100%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }
  115. .cover-sub { font-size: clamp(1rem, 1.6vw, 1.4rem); color: var(--text-2); max-width: 780px; margin-top: 32px; line-height: 1.7; }
  116. .cover-stats { display: grid; grid-template-columns: repeat(5, 1fr); gap: clamp(12px, 2vw, 28px); margin-top: clamp(48px, 8vh, 96px); padding-top: clamp(24px, 4vh, 48px); border-top: 1px solid var(--border); max-width: 1050px; }
  117. .cover-stat .num { font-family: var(--font-head); font-weight: 800; font-size: clamp(1.6rem, 2.8vw, 2.4rem); letter-spacing: -0.02em; color: var(--teal); }
  118. .cover-stat .lbl { font-size: 0.78rem; color: var(--text-3); margin-top: 4px; font-family: var(--font-mono); letter-spacing: 0.05em; text-transform: uppercase; }
  119. @media(max-width:720px){ .cover-stats{ grid-template-columns:repeat(2,1fr); } }
  120. .nav-rail { position: fixed; left: clamp(16px,2vw,32px); top: 50%; transform: translateY(-50%); z-index: 100; display: flex; flex-direction: column; gap: 12px; }
  121. .nav-dot { width: 32px; height: 3px; border-radius: 2px; background: rgba(255,255,255,0.14); cursor: pointer; transition: all 0.5s cubic-bezier(.2,.7,.2,1); position: relative; display: flex; align-items: center; }
  122. .nav-dot.active { background: var(--teal); width: 48px; box-shadow: 0 0 12px rgba(20,184,166,0.4); }
  123. .nav-dot:hover { background: rgba(255,255,255,0.3); }
  124. .nav-dot::after { content: attr(data-tip); position: absolute; left: calc(100% + 16px); top: 50%; transform: translateY(-50%) translateX(-6px); background: rgba(20,20,20,0.92); backdrop-filter: blur(8px); border: 1px solid var(--border); padding: 6px 12px; border-radius: 6px; font-size: 0.72rem; color: var(--text-1); white-space: nowrap; opacity: 0; pointer-events: none; transition: opacity 0.25s ease, transform 0.25s ease; font-family: var(--font-mono); letter-spacing: 0.04em; }
  125. .nav-dot:hover::after,.nav-dot.active::after { opacity: 1; transform: translateY(-50%) translateX(0); }
  126. .top-bar { position: fixed; top: 0; left: 0; right: 0; display: flex; justify-content: space-between; align-items: center; padding: 18px clamp(24px,4vw,48px); z-index: 99; pointer-events: none; background: linear-gradient(180deg, rgba(10,10,10,0.85) 0%, transparent 100%); }
  127. .brand-logo { font-family: var(--font-head); font-weight: 900; font-size: 0.88rem; letter-spacing: 0.2em; }
  128. .brand-logo .dot { color: var(--teal); }
  129. .progress-line { position: fixed; top: 0; left: 0; height: 2px; background: linear-gradient(90deg, var(--teal), var(--amber)); z-index: 1000; width: 0%; transition: width 0.3s ease; }
  130. .voice-wall { display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 14px; }
  131. .voice-card { background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius-md); padding: 22px; position: relative; transition: all 0.3s ease; }
  132. .voice-card::before { content: '"'; position: absolute; top: 6px; left: 10px; font-family: Georgia, serif; font-size: 54px; color: var(--teal); opacity: 0.3; line-height: 1; pointer-events: none; }
  133. .voice-card .voice-content { font-size: 0.92rem; line-height: 1.7; color: var(--text-1); margin: 16px 0 14px 20px; font-weight: 400; }
  134. .voice-card .voice-meta { display: flex; justify-content: space-between; align-items: center; padding-top: 10px; border-top: 1px solid var(--border); font-size: 0.73rem; color: var(--text-3); }
  135. .voice-card.hot { border-color: rgba(20,184,166,0.3); }
  136. .voice-card.rose { border-color: rgba(255,77,141,0.25); }
  137. .voice-card.rose::before { color: var(--rose); opacity: 0.25; }
  138. .voice-card.green { border-color: rgba(0,220,130,0.25); }
  139. .voice-card.green::before { color: var(--green); opacity: 0.25; }
  140. .voice-card:hover { border-color: var(--teal); transform: translateY(-2px); }
  141. .insight-banner { min-height: 180px; background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius-md); padding: clamp(22px,3vw,36px); display: flex; flex-direction: column; gap: 16px; position: relative; overflow: hidden; }
  142. .insight-banner::before { content: attr(data-num); position: absolute; top: 14px; right: 22px; font-family: var(--font-head); font-weight: 900; font-size: clamp(3.5rem,7vw,5.5rem); line-height: 1; color: var(--bg-3); letter-spacing: -0.05em; pointer-events: none; }
  143. .insight-banner h3 { font-family: var(--font-head); font-weight: 800; font-size: clamp(1.2rem,2vw,1.6rem); letter-spacing: -0.02em; line-height: 1.25; color: var(--text-1); max-width: 82%; }
  144. .insight-banner h3 strong { color: var(--teal); font-weight: 900; }
  145. .insight-banner .insight-body { color: var(--text-2); font-size: 0.92rem; line-height: 1.75; max-width: 82%; }
  146. .theme-poster { background: var(--bg-1); border: 1px solid var(--border); border-radius: var(--radius-md); padding: 26px; position: relative; overflow: hidden; }
  147. .theme-poster.pain { border-top: 3px solid var(--rose); }
  148. .theme-poster.bright { border-top: 3px solid var(--green); }
  149. .theme-poster.scene { border-top: 3px solid var(--blue); }
  150. .theme-poster.amber { border-top: 3px solid var(--amber); }
  151. .theme-poster.purple { border-top: 3px solid var(--purple); }
  152. .theme-poster.teal { border-top: 3px solid var(--teal); }
  153. .theme-poster h4 { font-family: var(--font-head); font-weight: 700; font-size: 1.15rem; margin-bottom: 8px; }
  154. .theme-poster .count { font-family: var(--font-mono); font-size: 0.76rem; color: var(--text-3); margin-bottom: 12px; }
  155. .theme-poster .count .num { font-size: 1.25rem; font-weight: 700; color: var(--text-1); margin-right: 4px; }
  156. .theme-poster .examples { list-style: none; display: flex; flex-direction: column; gap: 7px; margin-top: 8px; }
  157. .theme-poster .examples li { padding: 9px 13px; background: var(--bg-2); border-left: 2px solid var(--border-strong); border-radius: 4px; font-size: 0.83rem; line-height: 1.55; color: var(--text-2); }
  158. .theme-poster.pain .examples li { border-left-color: var(--rose); }
  159. .theme-poster.bright .examples li { border-left-color: var(--green); }
  160. .theme-poster.scene .examples li { border-left-color: var(--blue); }
  161. .theme-poster.amber .examples li { border-left-color: var(--amber); }
  162. .theme-poster.purple .examples li { border-left-color: var(--purple); }
  163. .theme-poster.teal .examples li { border-left-color: var(--teal); }
  164. .table-wrap { overflow-x: auto; border-radius: var(--radius-md); border: 1px solid var(--border); }
  165. .data-tbl { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
  166. .data-tbl thead th { text-align: left; padding: 11px 13px; background: var(--bg-1); border-bottom: 1px solid var(--border); font-family: var(--font-mono); font-weight: 500; font-size: 0.68rem; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-3); }
  167. .data-tbl tbody td { padding: 11px 13px; border-bottom: 1px solid var(--border); color: var(--text-1); vertical-align: middle; }
  168. .data-tbl tbody tr:last-child td { border-bottom: none; }
  169. .data-tbl tbody tr:hover { background: rgba(255,255,255,0.02); }
  170. .mtx-cell { background:var(--bg-1); border:1px solid var(--border); border-radius:var(--radius-md); padding:22px; position:relative; display:flex; flex-direction:column; transition:all 0.3s ease; }
  171. .mtx-cell:hover { border-color:var(--border-strong); transform:translateY(-2px); }
  172. .mtx-cell .cell-label { font-family:var(--font-mono); font-size:0.68rem; letter-spacing:0.12em; color:var(--text-3); margin-bottom:6px; text-transform:uppercase; }
  173. .mtx-cell.q1 { border-top:3px solid var(--teal); }
  174. .mtx-cell.q2 { border-top:3px solid var(--amber); }
  175. .mtx-cell.q3 { border-top:3px solid var(--purple); }
  176. .mtx-cell.q4 { border-top:3px solid var(--blue); }
  177. .mtx-cell.q5 { border-top:3px solid var(--green); }
  178. .fade-up { opacity:1; transform:none; transition:opacity 0.9s cubic-bezier(.16,.84,.33,1),transform 0.9s cubic-bezier(.16,.84,.33,1); }
  179. html.js .fade-up { opacity:0; transform:translateY(32px); will-change:opacity,transform; }
  180. html.js .fade-up.is-visible { opacity:1; transform:translateY(0); }
  181. .rise-in { opacity:1; transform:none; transition:opacity 1.1s cubic-bezier(.16,.84,.33,1),transform 1.1s cubic-bezier(.16,.84,.33,1); }
  182. html.js .rise-in { opacity:0; transform:translateY(48px) scale(0.97); will-change:opacity,transform; }
  183. html.js .rise-in.is-visible { opacity:1; transform:translateY(0) scale(1); }
  184. .headline-anim { display:inline-block; }
  185. .headline-anim .char { display:inline-block; opacity:1; transform:none; transition:opacity 0.7s cubic-bezier(.16,.84,.33,1),transform 0.7s cubic-bezier(.16,.84,.33,1); }
  186. html.js .headline-anim .char { opacity:0; transform:translateY(0.6em) rotate(6deg); will-change:opacity,transform; }
  187. html.js .headline-anim.is-visible .char { opacity:1; transform:translateY(0) rotate(0); }
  188. .kbd-hint { position:fixed; right:clamp(16px,2vw,28px); bottom:clamp(16px,2vh,28px); z-index:100; display:flex; align-items:center; gap:10px; padding:10px 16px; border-radius:999px; background:rgba(20,20,20,0.85); backdrop-filter:blur(16px); border:1px solid var(--border-strong); font-family:var(--font-mono); font-size:0.72rem; color:var(--text-2); letter-spacing:0.04em; transition:opacity 0.6s ease,transform 0.6s ease; }
  189. .kbd-hint.fade { opacity:0; transform:translateY(12px); pointer-events:none; }
  190. .kbd-hint kbd { display:inline-flex; align-items:center; justify-content:center; min-width:22px; height:22px; padding:0 6px; background:var(--bg-3); border:1px solid var(--border-strong); border-radius:4px; font-size:0.7rem; font-family:var(--font-mono); color:var(--text-1); box-shadow:0 1px 0 rgba(0,0,0,0.4); }
  191. .slide-counter { position:fixed; left:clamp(16px,2vw,28px); bottom:clamp(16px,2vh,28px); z-index:100; display:flex; align-items:center; gap:8px; padding:8px 14px; border-radius:999px; background:rgba(20,20,20,0.85); backdrop-filter:blur(16px); border:1px solid var(--border-strong); font-family:var(--font-mono); font-size:0.74rem; letter-spacing:0.1em; color:var(--text-2); }
  192. .slide-counter .now { color:var(--teal); font-weight:700; }
  193. .slide-counter .bar { width:60px; height:2px; background:rgba(255,255,255,0.1); border-radius:2px; overflow:hidden; }
  194. .cover-hero .aurora { position:absolute; inset:0; pointer-events:none; overflow:hidden; z-index:1; }
  195. .cover-hero .aurora span { position:absolute; border-radius:50%; filter:blur(80px); opacity:0.5; }
  196. .cover-hero .aurora span:nth-child(1){width:500px;height:500px;background:rgba(20,184,166,0.35);top:-10%;left:10%;animation:aurora-drift-1 18s ease-in-out infinite alternate;}
  197. .cover-hero .aurora span:nth-child(2){width:420px;height:420px;background:rgba(245,166,35,0.30);bottom:-8%;right:10%;animation:aurora-drift-2 22s ease-in-out infinite alternate;}
  198. .cover-hero .aurora span:nth-child(3){width:300px;height:300px;background:rgba(139,92,246,0.18);top:40%;left:55%;animation:aurora-drift-3 26s ease-in-out infinite alternate;}
  199. @keyframes aurora-drift-1{from{transform:translate(0,0) scale(1)}to{transform:translate(60px,80px) scale(1.2)}}
  200. @keyframes aurora-drift-2{from{transform:translate(0,0) scale(1)}to{transform:translate(-80px,-60px) scale(1.15)}}
  201. @keyframes aurora-drift-3{from{transform:translate(0,0) scale(1)}to{transform:translate(-100px,40px) scale(1.3)}}
  202. @media(prefers-reduced-motion:reduce){.cover-hero .aurora span{animation:none}}
  203. footer.report-footer { padding:48px clamp(24px,6vw,80px); text-align:center; border-top:1px solid var(--border); color:var(--text-3); font-size:0.8rem; background:var(--bg-0); }
  204. footer.report-footer .meta { font-family:var(--font-mono); letter-spacing:0.12em; text-transform:uppercase; margin-top:8px; font-size:0.7rem; }
  205. @media(max-width:600px){.nav-rail{display:none}.top-bar{padding:14px 18px;font-size:0.72rem}}
  206. .metric-row { display:grid; grid-template-columns:repeat(auto-fit, minmax(160px, 1fr)); gap:12px; }
  207. .metric-card { background:var(--bg-1); border:1px solid var(--border); border-radius:var(--radius-md); padding:20px; position:relative; overflow:hidden; }
  208. .metric-card::before { content:''; position:absolute; top:0; left:0; right:0; height:2px; background:linear-gradient(90deg, var(--teal), transparent); opacity:0.6; }
  209. .metric-card .m-label { font-family:var(--font-mono); font-size:0.66rem; letter-spacing:0.12em; color:var(--text-3); text-transform:uppercase; margin-bottom:6px; }
  210. .metric-card .m-value { font-family:var(--font-head); font-weight:800; font-size:1.8rem; letter-spacing:-0.02em; color:var(--text-1); }
  211. .metric-card .m-sub { font-size:0.73rem; color:var(--text-2); margin-top:5px; }
  212. .divider { border:none; border-top:1px solid var(--border); margin:clamp(20px,3vh,36px) 0; }
  213. .pillar-badge { display:inline-flex; align-items:center; gap:8px; padding:6px 14px; border-radius:99px; font-family:var(--font-mono); font-size:0.7rem; letter-spacing:0.12em; font-weight:600; margin-bottom:10px; }
  214. .pillar-badge.p1 { background:rgba(139,92,246,0.1); color:var(--purple); border:1px solid rgba(139,92,246,0.25); }
  215. .pillar-badge.p2 { background:rgba(59,130,246,0.1); color:var(--blue); border:1px solid rgba(59,130,246,0.25); }
  216. .pillar-badge.p3 { background:rgba(0,220,130,0.08); color:var(--green); border:1px solid rgba(0,220,130,0.25); }
  217. .pillar-badge.p4 { background:rgba(255,77,141,0.08); color:var(--rose); border:1px solid rgba(255,77,141,0.25); }
  218. .chip-group { display:flex; flex-wrap:wrap; gap:6px; }
  219. .chip { display:inline-flex; align-items:center; padding:3px 10px; border-radius:99px; font-size:0.73rem; font-weight:500; background:var(--bg-3); color:var(--text-2); border:1px solid var(--border); }
  220. .dual-engine { display:grid; grid-template-columns:1fr auto 1fr; gap:18px; align-items:center; }
  221. .dual-engine .engine-box { background:var(--bg-1); border:1px solid var(--border); border-radius:var(--radius-md); padding:22px; position:relative; }
  222. .dual-engine .engine-box.tea { border-top:3px solid var(--green); }
  223. .dual-engine .engine-box.porcelain { border-top:3px solid var(--teal); }
  224. .dual-engine .engine-arrow { font-size:2rem; color:var(--text-3); text-align:center; display:flex; flex-direction:column; align-items:center; gap:8px; }
  225. .dual-engine .engine-meter { height:4px; border-radius:2px; background:var(--bg-3); margin-top:10px; overflow:hidden; }
  226. .dual-engine .engine-meter .fill { height:100%; border-radius:2px; }
  227. .dual-engine .engine-meter .fill.strong { background:var(--teal); width:85%; }
  228. .dual-engine .engine-meter .fill.weak { background:var(--amber); width:30%; }
  229. @media(max-width:720px){ .dual-engine{ grid-template-columns:1fr; } .dual-engine .engine-arrow{ flex-direction:row; } }
  230. </style>
  231. </head>
  232. <body>
  233. <nav class="nav-rail" aria-label="章节导航">
  234. <a class="nav-dot active" href="#s0" data-tip="封面" data-idx="0"></a>
  235. <a class="nav-dot" href="#positioning" data-tip="1 产品定位" data-idx="1"></a>
  236. <a class="nav-dot" href="#competitors" data-tip="2 竞品格局" data-idx="2"></a>
  237. <a class="nav-dot" href="#needs" data-tip="3 用户需求" data-idx="3"></a>
  238. <a class="nav-dot" href="#opportunity" data-tip="4 机会方向" data-idx="4"></a>
  239. <a class="nav-dot" href="#structure" data-tip="5 结构性问题" data-idx="5"></a>
  240. <a class="nav-dot" href="#observe" data-tip="6 追踪信号" data-idx="6"></a>
  241. </nav>
  242. <div class="top-bar">
  243. <div class="brand-logo">茶决决<span class="dot">·</span>景德瓷江西茶 / VOC 洞察 v1.0</div>
  244. <div class="text-mono text-xs" style="color:var(--text-3);">产品定位 × 竞品分析 × 机会格局 × 用户需求</div>
  245. </div>
  246. <div class="kbd-hint" id="kbdHint"><span>键盘切换</span><kbd>↑</kbd><kbd>↓</kbd><span>或</span><kbd>PgUp</kbd><kbd>PgDn</kbd></div>
  247. <div class="progress-line" id="progressLine"></div>
  248. <div class="slide-counter" id="slideCounter"><span class="now" id="slideNow">1</span><span>/</span><span id="slideTotal">7</span><div class="bar"><span style="display:block;height:100%;width:0%;background:linear-gradient(90deg,var(--teal),var(--amber));"></span></div></div>
  249. <main class="deck">
  250. <!-- ===== COVER ===== -->
  251. <section class="report-section" id="s0" data-tone="teal" data-slide-num="01/07" style="min-height:100vh;padding:0;">
  252. <div class="cover-hero">
  253. <div class="aurora" aria-hidden="true"><span></span><span></span><span></span></div>
  254. <div class="cover-grid-bg"></div>
  255. <div class="cover-content">
  256. <div class="cover-meta rise-in" style="display:flex;justify-content:space-between;align-items:center;gap:16px;flex-wrap:wrap;">
  257. <span>FMODE / VOC Intelligence / 2026 · 茶决决 · 四大维度洞察</span>
  258. <span style="display:inline-flex;align-items:center;gap:6px;padding:4px 12px;background:rgba(0,220,130,0.08);color:#00DC82;border:1px solid rgba(0,220,130,0.35);border-radius:16px;font-family:var(--font-mono);font-size:0.72rem;letter-spacing:0.12em;font-weight:600;">抖音 LIVE 采集 + 小红书</span>
  259. </div>
  260. <div class="cover-title-stack">
  261. <p class="text-mono text-teal rise-in" style="font-size:0.85rem;letter-spacing:0.2em;margin-bottom:16px;">产品定位 × 竞品分析 × 机会格局 × 用户需求</p>
  262. <h1 class="cover-title rise-in">茶决决<br/><span style="color:var(--amber);-webkit-text-fill-color:var(--amber);background:none;font-size:0.58em;">VOC 洞察报告</span></h1>
  263. <p class="text-poster rise-in" style="margin-top:16px;color:var(--text-2);font-size:1.25rem;">景德瓷江西茶 · 28家门店 · <strong style="color:var(--teal);">定位 → 竞品坐标 → 需求 → 机会方向</strong></p>
  264. </div>
  265. <p class="cover-sub fade-up">
  266. 基于 <strong class="text-teal">抖音 65 条视频 + 1,589 条评论</strong>与<strong class="text-teal">小红书 50 条笔记 + 900 条评论</strong>的真实 VOC。
  267. 四个分析支柱:品牌<strong style="color:var(--purple);">产品定位</strong>是什么 → <strong style="color:var(--blue);">竞品</strong>在用户心中指谁 →
  268. <strong style="color:var(--rose);">用户</strong>真正需要什么 → <strong style="color:var(--green);">机会</strong>可能在哪里。
  269. </p>
  270. <div class="cover-stats fade-up">
  271. <div class="cover-stat"><div class="num">65</div><div class="lbl">抖音视频采集</div></div>
  272. <div class="cover-stat"><div class="num">1,589</div><div class="lbl">抖音评论</div></div>
  273. <div class="cover-stat"><div class="num">10</div><div class="lbl">采集关键词</div></div>
  274. <div class="cover-stat"><div class="num">28</div><div class="lbl">门店(直营+加盟)</div></div>
  275. <div class="cover-stat"><div class="num">4维</div><div class="lbl">分析框架</div></div>
  276. </div>
  277. <p class="text-mono text-xs fade-up" style="margin-top:56px;color:var(--text-3);">↓ SCROLL DOWN / 键盘 ↑↓ PgUp PgDn 切页 · 采集截止 2026-05-29 · 方向性探索</p>
  278. </div>
  279. </div>
  280. </section>
  281. <!-- ===== PILLAR 1: 产品定位 ===== -->
  282. <section class="report-section" id="positioning" data-tone="purple" data-slide-num="02/07">
  283. <div class="section-inner">
  284. <div class="section-head rise-in">
  285. <div class="pillar-badge p1">PILLAR 1 / 4</div>
  286. <div class="section-eyebrow" style="margin-top:4px;">产品定位 · BRAND POSITIONING</div>
  287. <h2 class="text-h1"><span class="headline-anim">"茶+瓷"的双引擎:一个已经点火,一个还在预热</span></h2>
  288. <p class="section-sub">VOC 中浮现的茶决决定位不是品牌方怎么说,而是<strong class="text-purple">用户在用钱投票时感知到的是什么</strong>。</p>
  289. </div>
  290. <div class="grid grid-2 fade-up" style="margin-bottom:22px;">
  291. <div class="card card-purple">
  292. <h4 style="font-weight:700;margin-bottom:8px;">品牌基础信息</h4>
  293. <p style="color:var(--text-2);font-size:0.88rem;line-height:1.7;">
  294. <strong>品牌名:</strong>茶决决·景德瓷江西茶<br/>
  295. <strong>品类:</strong>江西本土茶饮连锁<br/>
  296. <strong>创立:</strong>2021年,4周年<br/>
  297. <strong>门店:</strong>8家直营 + 5家托管 + 15家加盟 = 28家<br/>
  298. <strong>覆盖:</strong>南昌、景德镇、上饶、宜春<br/>
  299. <strong>价格区间:</strong>人均约19元<br/>
  300. <strong>核心差异:</strong>景德镇手工瓷器杯具 + 江西本地茶叶
  301. </p>
  302. </div>
  303. <div class="card">
  304. <h4 style="font-weight:700;margin-bottom:8px;">品牌官方叙事</h4>
  305. <p style="color:var(--text-2);font-size:0.85rem;line-height:1.7;">
  306. <strong style="color:var(--text-3);">茶:</strong>庐山、井冈山、遂川地方代表茶山优良茶叶<br/>
  307. <strong style="color:var(--text-3);">瓷:</strong>千年瓷都景德镇瓷器文化,彩瓷+青花瓷<br/>
  308. <strong style="color:var(--text-3);">文化:</strong>江西赣派文化(南昌、景德镇、上饶)<br/>
  309. <strong style="color:var(--amber);">愿景:</strong>"每一杯茶韵与景德镇手工瓷器都藏创始人对千年窑火传承的茶瓷热爱与追求"
  310. </p>
  311. <p style="color:var(--text-2);font-size:0.82rem;margin-top:10px;line-height:1.6;padding:10px;background:var(--bg-2);border-radius:4px;">
  312. <span style="color:var(--teal);">→ 值得关注:</span>"茶"和"瓷"在品牌名称中各占一半,但在用户实际感知中,两者并不同等响亮。
  313. </p>
  314. </div>
  315. </div>
  316. <!-- Dual engine -->
  317. <div class="section-head fade-up" style="margin-bottom:14px;"><h3 class="text-h3">"茶+瓷"双引擎:评论数据中的信号强度</h3></div>
  318. <div class="dual-engine fade-up" style="margin-bottom:20px;">
  319. <div class="engine-box tea">
  320. <h4 style="color:var(--green);font-weight:700;margin-bottom:6px;">茶的维度</h4>
  321. <p style="color:var(--text-2);font-size:0.8rem;line-height:1.55;">产品复购驱动 · 口碑传播基础 · 品牌护城河</p>
  322. <div style="margin-top:10px;">
  323. <p style="font-size:0.76rem;color:var(--text-3);">正向赞美 <span style="color:var(--green);font-weight:700;">114条</span>(7.2%)</p>
  324. <p style="font-size:0.76rem;color:var(--text-3);">口味不满 <span style="color:var(--rose);font-weight:700;">26条</span>(1.6%)</p>
  325. <p style="font-size:0.76rem;color:var(--text-3);">"好喝"讨论以短句为主,缺乏深度口感描述</p>
  326. </div>
  327. <div class="engine-meter"><div class="fill weak"></div></div>
  328. <p style="font-size:0.7rem;color:var(--amber);margin-top:4px;">信号强度:偏弱 — "好喝"是低频低深度讨论</p>
  329. </div>
  330. <div class="engine-arrow"><span style="font-size:0.68rem;color:var(--text-3);">茶<br/>决<br/>决</span></div>
  331. <div class="engine-box porcelain">
  332. <h4 style="color:var(--teal);font-weight:700;margin-bottom:6px;">瓷的维度</h4>
  333. <p style="color:var(--text-2);font-size:0.8rem;line-height:1.55;">首次尝试驱动 · 社交传播引擎 · 差异化记忆点</p>
  334. <div style="margin-top:10px;">
  335. <p style="font-size:0.76rem;color:var(--text-3);">瓷器关注 <span style="color:var(--teal);font-weight:700;">108条</span>(6.8%)</p>
  336. <p style="font-size:0.76rem;color:var(--text-3);">视觉吸引 <span style="color:var(--teal);font-weight:700;">84条</span>(5.3%)</p>
  337. <p style="font-size:0.76rem;color:var(--text-3);">TOP 1 高赞评论"可爱毁了"389K赞 — 直指瓷杯</p>
  338. </div>
  339. <div class="engine-meter"><div class="fill strong"></div></div>
  340. <p style="font-size:0.7rem;color:var(--teal);margin-top:4px;">信号强度:强 — 最高频的差异化关注点</p>
  341. </div>
  342. </div>
  343. <div class="fade-up" style="padding:18px 22px;background:var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);border-left:3px solid var(--amber);margin-bottom:16px;">
  344. <h4 style="font-weight:700;margin-bottom:8px;font-size:0.88rem;">定价感知区间:19元在三杆秤上</h4>
  345. <div style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:10px;">
  346. <div><p style="color:var(--text-3);font-size:0.68rem;text-transform:uppercase;letter-spacing:0.1em;">对标纪念品/体验</p><p style="color:var(--green);font-size:0.84rem;">19元带瓷杯走 → <strong>划算</strong><br/>"才19一杯" 71K赞</p></div>
  347. <div><p style="color:var(--text-3);font-size:0.68rem;text-transform:uppercase;letter-spacing:0.1em;">对标奶茶</p><p style="color:var(--rose);font-size:0.84rem;">19元一杯奶茶 → <strong>偏贵</strong><br/>"还不如洪都大拇指,还便宜"</p></div>
  348. <div><p style="color:var(--text-3);font-size:0.68rem;text-transform:uppercase;letter-spacing:0.1em;">对标霸王茶姬</p><p style="color:var(--amber);font-size:0.84rem;">19元 → <strong>合理甚至偏低</strong><br/>霸王这个价位茶底更稳定</p></div>
  349. </div>
  350. </div>
  351. <div class="fade-up" style="padding:20px 24px;background:var(--bg-1);border:1px solid rgba(255,77,141,0.2);border-radius:var(--radius-md);border-left:3px solid var(--rose);">
  352. <h4 style="font-weight:700;margin-bottom:6px;font-size:0.92rem;">定位的核心张力</h4>
  353. <p style="color:var(--text-2);font-size:0.86rem;line-height:1.7;">
  354. 茶决决当前最强的记忆点是<strong class="text-teal">"瓷器杯+可爱"</strong>,但这两个锚点都不是"好喝"。
  355. 当用户第一次体验停在"好看但不好喝",<strong class="text-rose">复购的动机从何而来</strong>——这不是需要立刻回答的问题,但值得持续关注。
  356. </p>
  357. </div>
  358. </div>
  359. </section>
  360. <!-- ===== PILLAR 2: 竞品格局 ===== -->
  361. <section class="report-section" id="competitors" data-tone="blue" data-slide-num="03/07">
  362. <div class="section-inner">
  363. <div class="section-head rise-in">
  364. <div class="pillar-badge p2">PILLAR 2 / 4</div>
  365. <div class="section-eyebrow" style="margin-top:4px;">竞品格局 · COMPETITOR LANDSCAPE</div>
  366. <h2 class="text-h1"><span class="headline-anim">用户在选择时,实际在比什么</span></h2>
  367. <p class="section-sub">所有竞品均从 VOC 中提取——用户在评论中<strong class="text-blue">自发提及、对比、推荐</strong>的品牌。</p>
  368. </div>
  369. <div class="grid grid-3 fade-up" style="margin-bottom:22px;">
  370. <div class="theme-poster pain">
  371. <h4>第一圈层 · 江西本土直接对手</h4>
  372. <div class="count"><span class="num">同赛道</span>江西本土茶饮</div>
  373. <ul class="examples">
  374. <li><strong>江西鲲茶</strong>(提及7次)— 万寿宫古筝表演打造"场"的沉浸感。"茶决决跟鲲茶都好喝""鲲茶比茶决决好喝多了"。鲲茶做「场」,茶决决做「物」。</li>
  375. <li><strong>洪都大拇指</strong>(提及8次)— 本地人日常口粮茶。"还不如喝洪都大拇指,还比这个便宜"。在"日常奶茶消费"场景下是直接替代选项。</li>
  376. </ul>
  377. </div>
  378. <div class="theme-poster scene">
  379. <h4>第二圈层 · 全国连锁降维覆盖</h4>
  380. <div class="count"><span class="num">跨区域</span>品类标杆</div>
  381. <ul class="examples">
  382. <li><strong>霸王茶姬</strong>(提及26次,最高)— 江西限定款有独立热度。全国品牌在「区域化」上也在用力——这恰好是茶决决的天然优势领域。</li>
  383. <li><strong>茉莉奶白</strong>(提及10次)— 轻乳茶赛道新锐,口感可能与茶决决产品重叠。</li>
  384. <li><strong>古茗</strong>(提及6次)— 价格更低的日常选项,学生和上班族中有稳固基础。</li>
  385. </ul>
  386. </div>
  387. <div class="theme-poster amber">
  388. <h4>第三圈层 · 用户心中的那杆秤</h4>
  389. <div class="count"><span class="num">心理基准</span>判断"值不值"的标准</div>
  390. <ul class="examples">
  391. <li><strong>"19块的奶茶应该好喝"</strong> — "外观好评,口感差评,买了不会想第二次"。瓷器拉新,口味决定复购。</li>
  392. <li><strong>"霸王茶姬的江西限定"</strong> — 用户已经在做"区域限定"的横向对比。</li>
  393. <li><strong>"本地人都知道的好喝"</strong> — "江西人知道吗?"2.5K赞。本地认知有缺口。</li>
  394. </ul>
  395. </div>
  396. </div>
  397. <div class="section-head fade-up" style="margin-bottom:12px;"><h3 class="text-h3">茶决决 vs 江西鲲茶:"场"与"物"的竞争维度差异</h3></div>
  398. <div class="table-wrap fade-up" style="margin-bottom:16px;">
  399. <table class="data-tbl">
  400. <thead><tr><th>维度</th><th style="color:var(--teal);">茶决决</th><th style="color:var(--blue);">江西鲲茶</th><th>可能含义</th></tr></thead>
  401. <tbody>
  402. <tr><td><strong>核心差异点</strong></td><td style="color:var(--teal);">景德瓷杯子/茶壶(可带走)</td><td style="color:var(--blue);">万寿宫古筝/琵琶现场表演</td><td>一个卖"物",一个卖"场"</td></tr>
  403. <tr><td><strong>用户记忆锚点</strong></td><td style="color:var(--teal);">"那杯有陶瓷小杯子的奶茶"</td><td style="color:var(--blue);">"那个有古筝弹唱的地方"</td><td>物的记忆更持久,场的体验更沉浸</td></tr>
  404. <tr><td><strong>内容传播类型</strong></td><td style="color:var(--teal);">拍杯子/开箱/合照</td><td style="color:var(--blue);">拍氛围/古筝/万寿宫夜景</td><td>茶决决UGC更"静",鲲茶更"动"</td></tr>
  405. <tr><td><strong>复购驱动力</strong></td><td style="color:var(--amber);">杯子换了?新品杯子好看?</td><td style="color:var(--blue);">换曲子了?今天有表演吗?</td><td>茶决决复购靠"新",鲲茶靠"变"</td></tr>
  406. <tr><td><strong>扩张约束</strong></td><td style="color:var(--green);">瓷器供应链可标准化</td><td style="color:var(--amber);">古筝表演依赖场地和人员</td><td>茶决决规模化可能更可控</td></tr>
  407. </tbody>
  408. </table>
  409. </div>
  410. <div class="fade-up" style="padding:18px 22px;background:var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);border-left:3px solid var(--blue);">
  411. <h4 style="font-weight:700;margin-bottom:8px;font-size:0.85rem;">竞品在评论中被提及的频次(1,589条抖音评论中)</h4>
  412. <div class="chip-group">
  413. <span class="chip" style="border-color:rgba(59,130,246,0.4);color:var(--blue);">霸王茶姬 26次</span>
  414. <span class="chip">茉莉奶白 10次</span>
  415. <span class="chip" style="border-color:rgba(255,77,141,0.3);color:var(--rose);">洪都大拇指 8次</span>
  416. <span class="chip" style="border-color:rgba(20,184,166,0.3);color:var(--teal);">江西鲲茶 7次</span>
  417. <span class="chip">古茗 6次</span>
  418. <span class="chip">爷爷不泡茶 3次</span>
  419. <span class="chip">喜茶 2次</span>
  420. <span class="chip">奈雪的茶 2次</span>
  421. </div>
  422. </div>
  423. </div>
  424. </section>
  425. <!-- ===== PILLAR 3: 用户需求 ===== -->
  426. <section class="report-section" id="needs" data-tone="rose" data-slide-num="04/07">
  427. <div class="section-inner">
  428. <div class="section-head rise-in">
  429. <div class="pillar-badge p4">PILLAR 3 / 4</div>
  430. <div class="section-eyebrow" style="margin-top:4px;">用户需求 · USER NEEDS</div>
  431. <h2 class="text-h1"><span class="headline-anim">已满足的需求 vs 未被充分满足的需求</span></h2>
  432. <p class="section-sub">VOC 数据同时显示了<strong class="text-green">用户为什么来</strong>和<strong class="text-rose">用户为什么可能不再来</strong>两条线索。</p>
  433. </div>
  434. <div class="grid grid-2 fade-up" style="margin-bottom:22px;">
  435. <div class="theme-poster bright">
  436. <h4>已满足的需求(用户为什么来)</h4>
  437. <div class="count"><span class="num">3个</span>强信号</div>
  438. <ul class="examples">
  439. <li><strong>拍照出片/社交分享</strong> — "可爱毁了"389K赞,"这个盖子有的很有创意"714赞。瓷杯提供了极强的视觉素材。</li>
  440. <li><strong>旅游仪式感/纪念品</strong> — "来江西旅游的正确打开方式""还能带走""20左右还能带走"。瓷杯=可带走的旅行记忆。</li>
  441. <li><strong>新鲜感/猎奇</strong> — "景德镇尽出这些馋人的怪东西""奶茶界对于杯子的创意已经到了极限"。但新鲜感是一次性的。</li>
  442. </ul>
  443. </div>
  444. <div class="theme-poster pain">
  445. <h4>未被充分满足的需求(为什么可能不再来)</h4>
  446. <div class="count"><span class="num">4个</span>值得关注的信号</div>
  447. <ul class="examples">
  448. <li><strong>好喝</strong> — "好看报喝"8K赞,"外观好评,口感差评""刚喝 真难喝"。要做到"不辜负杯子的颜值"。</li>
  449. <li><strong>值这个价</strong> — "还不如喝洪都大拇指""外地人拍照买一杯,喝奶茶还是要喝大拇指"。19元需要更多价值支撑。</li>
  450. <li><strong>日常消费的理由</strong> — "经常喝""天天喝"的评论几乎没有。当前是"旅游型产品"。</li>
  451. <li><strong>本地人身份认同</strong> — "江西人知道吗?"2.5K赞。本地人不知道一个"江西本土品牌",根基就不扎实。</li>
  452. </ul>
  453. </div>
  454. </div>
  455. <div class="section-head fade-up" style="margin-bottom:12px;"><h3 class="text-h3">从评论中还原的用户面貌</h3></div>
  456. <div class="grid grid-4 fade-up" style="margin-bottom:16px;">
  457. <div class="theme-poster teal" style="padding:18px 20px;">
  458. <h4 style="font-size:1rem;">外地游客 <span class="tag" style="font-size:0.65rem;">当前主力</span></h4>
  459. <ul class="examples"><li>来南昌/景德镇旅游,被种草</li><li><strong>最在意:</strong>拍照好看、能带走纪念品</li><li><strong>"满意"长这样:</strong>"拍出来好看,小杯子带回家"</li></ul>
  460. </div>
  461. <div class="theme-poster scene" style="padding:18px 20px;">
  462. <h4 style="font-size:1rem;">本地偶尔消费</h4>
  463. <ul class="examples"><li>逛街时偶尔买一杯</li><li><strong>最在意:</strong>味道不踩雷、价格合理</li><li><strong>"满意"长这样:</strong>"味道还行,杯子家里已好几个"</li></ul>
  464. </div>
  465. <div class="theme-poster purple" style="padding:18px 20px;">
  466. <h4 style="font-size:1rem;">茶饮爱好者</h4>
  467. <ul class="examples"><li>尝试各品牌,评论区做对比</li><li><strong>最在意:</strong>茶底品质、口感层次</li><li><strong>"满意"长这样:</strong>"茶决决的茶底是什么品种?"</li></ul>
  468. </div>
  469. <div class="theme-poster amber" style="padding:18px 20px;">
  470. <h4 style="font-size:1rem;">送礼/社交需求</h4>
  471. <ul class="examples"><li>给朋友带"江西特产"</li><li><strong>最在意:</strong>包装好看、有江西特色</li><li><strong>"满意"长这样:</strong>"买了几个杯子送同事,都说好看"</li></ul>
  472. </div>
  473. </div>
  474. <div class="section-head fade-up" style="margin-bottom:10px;"><h3 class="text-h3">用户原声抽样</h3></div>
  475. <div class="voice-wall fade-up">
  476. <div class="voice-card hot"><div class="voice-content">可爱毁了</div><div class="voice-meta"><span>抖音·茶决决</span><span class="text-teal">389K赞 · TOP1</span></div></div>
  477. <div class="voice-card hot"><div class="voice-content">去江西旅游,店员特意摆好给我们拍照的</div><div class="voice-meta"><span>抖音·茶决决</span><span class="text-teal">108K赞 · TOP2</span></div></div>
  478. <div class="voice-card hot"><div class="voice-content">嗯。才19一杯</div><div class="voice-meta"><span>抖音·茶决决</span><span class="text-teal">71K赞 · TOP3</span></div></div>
  479. <div class="voice-card rose"><div class="voice-content">好看报喝</div><div class="voice-meta"><span>抖音·茶决决</span><span class="text-rose">8K赞 · 口味负评</span></div></div>
  480. <div class="voice-card rose"><div class="voice-content">外观好评,口感差评,买了一次不会想第二次</div><div class="voice-meta"><span>抖音·茶决决</span><span class="text-rose">一次性消费</span></div></div>
  481. <div class="voice-card"><div class="voice-content">我建议奶茶饮品还是把精力放在怎么提高口味口感上……不是天天带这些花里胡哨的东西回家的</div><div class="voice-meta"><span>抖音·茶决决</span><span class="text-amber">366赞</span></div></div>
  482. <div class="voice-card"><div class="voice-content">江西人知道吗?</div><div class="voice-meta"><span>抖音·茶决决</span><span class="text-amber">2.5K赞</span></div></div>
  483. <div class="voice-card green"><div class="voice-content">51去南昌玩就为了这些小茶壶买了好多杯,都喝不完</div><div class="voice-meta"><span>抖音·茶决决</span><span class="text-green">965赞 · 旅游场景</span></div></div>
  484. <div class="voice-card"><div class="voice-content">早知道这个这么有意思就不选紫砂壶了</div><div class="voice-meta"><span>抖音·茶决决</span><span class="text-teal">660赞 · 瓷器偏好</span></div></div>
  485. <div class="voice-card green"><div class="voice-content">茶决决跟鲲茶都好喝</div><div class="voice-meta"><span>抖音·竞品对比</span><span class="text-green">中立对比</span></div></div>
  486. <div class="voice-card rose"><div class="voice-content">不好喝 尊嘟 还不如喝洪都大拇指 还比这个便宜</div><div class="voice-meta"><span>抖音·竞品对比</span><span class="text-rose">竞品替代</span></div></div>
  487. <div class="voice-card"><div class="voice-content">这个盖子有的很有创意 我一直以为奶茶界对于杯子的创意已经到了极限 看来是市场从未饱和</div><div class="voice-meta"><span>抖音·茶决决</span><span class="text-teal">714赞 · 创新认可</span></div></div>
  488. </div>
  489. </div>
  490. </section>
  491. <!-- ===== PILLAR 4: 机会方向 ===== -->
  492. <section class="report-section" id="opportunity" data-tone="green" data-slide-num="05/07">
  493. <div class="section-inner">
  494. <div class="section-head rise-in">
  495. <div class="pillar-badge p3">PILLAR 4 / 4</div>
  496. <div class="section-eyebrow" style="margin-top:4px;">机会方向 · OPPORTUNITY DIRECTIONS</div>
  497. <h2 class="text-h1"><span class="headline-anim">从数据中浮现的五条可能路径</span></h2>
  498. <p class="section-sub">不是"应该做哪个"的判断,而是<strong class="text-green">有哪些可能性值得探索</strong>。</p>
  499. </div>
  500. <div class="grid grid-2 fade-up" style="margin-bottom:14px;">
  501. <div class="mtx-cell q1">
  502. <div class="cell-label">DIRECTION A</div>
  503. <h3 style="color:var(--teal);font-size:1.1rem;">把"茶"补到和"瓷"一个水准</h3>
  504. <p style="color:var(--text-2);font-size:0.85rem;line-height:1.65;margin-top:6px;">不是做到"惊艳",而是"不辜负杯子的颜值"——及格线以上的口味 + 极致的视觉 = 完整的品牌体验。</p>
  505. <p style="color:var(--text-2);font-size:0.78rem;margin-top:8px;"><strong class="text-green">VOC线索:</strong>"好看报喝"是最高频负向信号 · "买了不会想第二次" · 核心SKU的味型记忆点打造</p>
  506. <p style="color:var(--text-2);font-size:0.78rem;margin-top:4px;"><strong class="text-rose">约束:</strong>口味是主观的。但如果不补口味,品牌就始终在卖杯子而不是卖茶。</p>
  507. </div>
  508. <div class="mtx-cell q2">
  509. <div class="cell-label">DIRECTION B</div>
  510. <h3 style="color:var(--amber);font-size:1.1rem;">从"旅游打卡"走向"本地日常"</h3>
  511. <p style="color:var(--text-2);font-size:0.85rem;line-height:1.65;margin-top:6px;">旅游款(瓷杯)和日常款(同茶底品质)差异化——旅游款做溢价和传播,日常款做复购和口碑。</p>
  512. <p style="color:var(--text-2);font-size:0.78rem;margin-top:8px;"><strong class="text-green">VOC线索:</strong>"江西人知道吗?" · 本地复购信号缺失 · "经常喝""每天都来"几乎为零</p>
  513. <p style="color:var(--text-2);font-size:0.78rem;margin-top:4px;"><strong class="text-rose">约束:</strong>本地日常消费的对手是洪都大拇指、古茗——需要重新思考价格体系。</p>
  514. </div>
  515. <div class="mtx-cell q3">
  516. <div class="cell-label">DIRECTION C</div>
  517. <h3 style="color:var(--purple);font-size:1.1rem;">把"瓷器差异化"做深</h3>
  518. <p style="color:var(--text-2);font-size:0.85rem;line-height:1.65;margin-top:6px;">从"送杯子"升级为"瓷器文化体验":限量款、季节款、城市限定款——让用户有收集的理由。</p>
  519. <p style="color:var(--text-2);font-size:0.78rem;margin-top:8px;"><strong class="text-green">VOC线索:</strong>"杯子的创意到了极限 看来是市场从未饱和" · 已有模仿者出现</p>
  520. <p style="color:var(--text-2);font-size:0.78rem;margin-top:4px;"><strong class="text-rose">约束:</strong>边际新鲜感递减——用户家里放不了太多杯子。</p>
  521. </div>
  522. <div class="mtx-cell q4">
  523. <div class="cell-label">DIRECTION D</div>
  524. <h3 style="color:var(--blue);font-size:1.1rem;">品牌IP化的"江西故事"</h3>
  525. <p style="color:var(--text-2);font-size:0.85rem;line-height:1.65;margin-top:6px;">"景德瓷+江西茶"是有深度的文化叙事——不只是"好看的杯子",而是有历史、有工艺的故事。</p>
  526. <p style="color:var(--text-2);font-size:0.78rem;margin-top:8px;"><strong class="text-green">VOC线索:</strong>品牌故事(千年非遗/窑火)在VOC中未被用户自发提及 · 鲲茶通过古筝成功植入文化感</p>
  527. <p style="color:var(--text-2);font-size:0.78rem;margin-top:4px;"><strong class="text-rose">约束:</strong>文化叙事太重会提高门槛——需要在"轻量化传播"和"文化深度"间找平衡。</p>
  528. </div>
  529. <div class="mtx-cell q5">
  530. <div class="cell-label">DIRECTION E</div>
  531. <h3 style="color:var(--green);font-size:1.1rem;">从"江西限定"到"江西名片"</h3>
  532. <p style="color:var(--text-2);font-size:0.85rem;line-height:1.65;margin-top:6px;">"只有江西有"不是缺点,而是可被放大的稀缺性卖点——就像"只有长沙有茶颜悦色"。</p>
  533. <p style="color:var(--text-2);font-size:0.78rem;margin-top:8px;"><strong class="text-green">VOC线索:</strong>"就唯一的缺点:只有江西有"2.2K赞 · "going我又买不到"42K赞 · 28家店有一定密度</p>
  534. <p style="color:var(--text-2);font-size:0.78rem;margin-top:4px;"><strong class="text-rose">约束:</strong>"只有江西有"限制了TAM。但"先用区域稀缺性做高势能再走出去"是茶颜走过的路。</p>
  535. </div>
  536. </div>
  537. <div class="fade-up" style="padding:18px 22px;background:var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);border-left:3px solid var(--teal);">
  538. <h4 style="font-weight:700;margin-bottom:4px;font-size:0.88rem;">这几个方向之间的内在联系</h4>
  539. <p style="color:var(--text-2);font-size:0.84rem;line-height:1.65;">
  540. A(口味)和 C(瓷器)是产品维度的"两条腿";B(日常消费)和 D(品牌IP)是市场维度的"两条路";E(江西名片)是品牌势能的总目标。
  541. 它们之间存在先后依赖——在 A(口味)还没解决之前,D(品牌IP)传播越成功,反噬可能越快。
  542. </p>
  543. </div>
  544. </div>
  545. </section>
  546. <!-- ===== 结构性问题 ===== -->
  547. <section class="report-section" id="structure" data-tone="orange" data-slide-num="06/07">
  548. <div class="section-inner">
  549. <div class="section-head rise-in">
  550. <div class="section-eyebrow">STRUCTURAL · 结构性问题</div>
  551. <h2 class="text-h1"><span class="headline-anim">需要持续关注的几个张力</span></h2>
  552. <p class="section-sub">不是问题清单,而是<strong class="text-amber">值得在策略制定时被看到的几个结构性话题</strong>。</p>
  553. </div>
  554. <div class="grid grid-3 fade-up" style="margin-bottom:22px;">
  555. <div class="insight-banner" data-num="01" style="border-left:3px solid var(--teal);min-height:auto;">
  556. <h3>"茶"和"瓷"的权重该如何分配</h3>
  557. <div class="insight-body" style="font-size:0.85rem;">品牌名中"茶"在前,但消费者记忆点"瓷"远强于"茶"。如果长期"瓷重茶轻",品牌是否还叫"茶决决"?把"茶"拉回到同等感知水平需要多少投入?</div>
  558. </div>
  559. <div class="insight-banner" data-num="02" style="border-left:3px solid var(--amber);min-height:auto;">
  560. <h3>本地人和游客的"两个茶决决"</h3>
  561. <div class="insight-body" style="font-size:0.85rem;">游客看到的是"打卡神器",本地人看到的是"那个游客买的东西"。同一家店在不同人群眼中有完全不同的品牌形象——是否需要不同的产品和沟通方式?</div>
  562. </div>
  563. <div class="insight-banner" data-num="03" style="border-left:3px solid var(--purple);min-height:auto;">
  564. <h3>从"网红"到"长红"的窗口期</h3>
  565. <div class="insight-body" style="font-size:0.85rem;">"可爱毁了"389K赞说明传播力很强。但网红品牌轨迹:爆火→模仿者出现→新鲜感消退→回归均值。瓷器差异化给了更长的窗口期——但不是无限的。</div>
  566. </div>
  567. </div>
  568. <div class="metric-row fade-up" style="margin-bottom:20px;">
  569. <div class="metric-card"><div class="m-label">正向口味评论</div><div class="m-value">114<span style="font-size:0.7rem;color:var(--text-2);">条</span></div><div class="m-sub">占全部评论 7.2%</div></div>
  570. <div class="metric-card"><div class="m-label">负向口味评论</div><div class="m-value" style="color:var(--rose);">26<span style="font-size:0.7rem;color:var(--text-2);">条</span></div><div class="m-sub">占全部评论 1.6%</div></div>
  571. <div class="metric-card"><div class="m-label">瓷器/周边关注</div><div class="m-value" style="color:var(--teal);">108<span style="font-size:0.7rem;color:var(--text-2);">条</span></div><div class="m-sub">最高频差异化关注点</div></div>
  572. <div class="metric-card"><div class="m-label">竞品提及总量</div><div class="m-value" style="color:var(--blue);">77<span style="font-size:0.7rem;color:var(--text-2);">条</span></div><div class="m-sub">霸王茶姬占比最高 33%</div></div>
  573. <div class="metric-card"><div class="m-label">旅游/地域相关</div><div class="m-value" style="color:var(--green);">99<span style="font-size:0.7rem;color:var(--text-2);">条</span></div><div class="m-sub">核心流量来源</div></div>
  574. <div class="metric-card"><div class="m-label">TOP1 视频点赞</div><div class="m-value" style="color:var(--amber);">1.85M</div><div class="m-sub">"总要为了这个情绪价值来杯奶茶吧"</div></div>
  575. </div>
  576. <div class="fade-up" style="padding:18px 22px;background:var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);border-left:3px solid var(--amber);">
  577. <h4 style="font-weight:700;margin-bottom:8px;font-size:0.85rem;">品牌自述痛点与 VOC 信号的对照</h4>
  578. <div class="table-wrap">
  579. <table class="data-tbl">
  580. <thead><tr><th>品牌自述痛点</th><th>VOC 中的信号</th><th>可能关联</th></tr></thead>
  581. <tbody>
  582. <tr><td>营销活动流于形式,需赋能门店转化</td><td>旅游打卡流量大但本地复购信号弱</td><td>流量质量需分层——打卡流量 ≠ 转化流量</td></tr>
  583. <tr><td>营销需和景德瓷结合但缺乏融合形式</td><td>瓷器是最高频关注点但以"送杯子"为主</td><td>瓷器的故事深度可继续拓展</td></tr>
  584. <tr><td>赛道竞品扎堆,门店增长遇瓶颈</td><td>竞品提及77条,霸王/鲲茶/大拇指各有所长</td><td>差异化的深度决定护城河的宽度</td></tr>
  585. <tr><td>品牌差异化定位模糊,选择优先级不足</td><td>"好看但不好喝"削弱了定位的说服力</td><td>定位不只靠"讲",更要靠"做"</td></tr>
  586. <tr><td>游客认知覆盖面弱,本地粘性不足</td><td>"江西人知道吗?" · 本地复购信号缺失</td><td>游客和本地人可能需要不同的产品策略</td></tr>
  587. </tbody>
  588. </table>
  589. </div>
  590. </div>
  591. </div>
  592. </section>
  593. <!-- ===== OBSERVATION METRICS ===== -->
  594. <section class="report-section" id="observe" data-tone="green" data-slide-num="07/07">
  595. <div class="section-inner">
  596. <div class="section-head rise-in">
  597. <div class="section-eyebrow">OBSERVATION · 观察指标</div>
  598. <h2 class="text-h1"><span class="headline-anim">用来跟踪变化的信号</span></h2>
  599. <p class="section-sub">以下用于<strong class="text-teal">观察变化方向</strong>,不是KPI。定期回看这些信号的变化趋势。</p>
  600. </div>
  601. <div class="table-wrap fade-up" style="margin-bottom:24px;">
  602. <table class="data-tbl">
  603. <thead><tr><th>观察维度</th><th>当前快照</th><th>关注变化</th><th>为什么有意义</th></tr></thead>
  604. <tbody>
  605. <tr><td><strong>"好看报喝"类评论的占比变化</strong></td><td>高赞评论 TOP 10 中出现 2 次口味负面</td><td><span class="tag green">↓ 是否减少</span></td><td>最核心的产品口碑信号</td></tr>
  606. <tr><td><strong>本地消费者自发提及的比例</strong></td><td>几乎全部是旅游/打卡场景</td><td><span class="tag green">↑ "经常喝""每次都来"</span></td><td>从旅游型到日常型品牌的标志</td></tr>
  607. <tr><td><strong>鲲茶 vs 茶决决的用户对比讨论</strong></td><td>用户自发做对比,各有偏好</td><td><span class="tag green">→ 倾向性变化</span></td><td>本地赛道相对位置的晴雨表</td></tr>
  608. <tr><td><strong>瓷器/杯子的边际新鲜感</strong></td><td>处于高位,仍有惊喜感</td><td><span class="tag rose">↓ "又来了/又是杯子"</span></td><td>差异化是否在衰减</td></tr>
  609. <tr><td><strong>"只有江西有"的情感基调</strong></td><td>以遗憾/向往为主(正面)</td><td><span class="tag green">→ 是否转抱怨</span></td><td>稀缺性叙事是否可持续</td></tr>
  610. <tr><td><strong>霸王茶姬江西限定的挤压</strong></td><td>霸王江西限定有独立热度</td><td><span class="tag rose">↑ 是否被直接对比并倾向霸王</span></td><td>全国品牌区域化对本土的冲击</td></tr>
  611. <tr><td><strong>好喝类评论的深度</strong></td><td>以"好喝""好绝"短句为主</td><td><span class="tag green">↑ 出现具体口感描述</span></td><td>产品口碑从"感觉"升级为"认知"</td></tr>
  612. <tr><td><strong>竞品模仿/类似评论</strong></td><td>"去潮州旅游的时候见过类似"</td><td><span class="tag rose">↑ 模仿者声音增多</span></td><td>差异化护城河的宽度</td></tr>
  613. </tbody>
  614. </table>
  615. </div>
  616. <div class="grid grid-2 fade-up">
  617. <div style="padding:18px;background:var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);">
  618. <h4 style="font-weight:700;margin-bottom:6px;font-size:0.85rem;">数据采集说明</h4>
  619. <p style="color:var(--text-2);font-size:0.78rem;line-height:1.65;">抖音:10组关键词 → 65条视频+1,589条评论(LIVE模式)<br/>小红书:50条笔记+900条评论(SAMPLE模式)<br/>采集时间:2026-05-29 · 局限:公开内容快照,未含美团/点评/外卖/线下问卷</p>
  620. </div>
  621. <div style="padding:18px;background:var(--bg-1);border:1px solid var(--border);border-radius:var(--radius-md);">
  622. <h4 style="font-weight:700;margin-bottom:6px;font-size:0.85rem;">方法论说明</h4>
  623. <p style="color:var(--text-2);font-size:0.78rem;line-height:1.65;">竞品均来自用户自发提及 · 需求推断基于用户实际表达 · 报告定位为方向性探索 · 下一步:小红书LIVE采集→内部交叉验证→竞品实地对标→方向收敛</p>
  624. </div>
  625. </div>
  626. <div class="fade-up" style="margin-top:40px;text-align:center;">
  627. <p class="text-mono text-xs" style="color:var(--text-3);letter-spacing:0.12em;margin-bottom:6px;">END OF REPORT · 茶决决 VOC 洞察 v1.0</p>
  628. <p style="color:var(--text-3);font-size:0.74rem;">产品定位 × 竞品分析 × 机会格局 × 用户需求 · 方向性探索 · 2026-05-30</p>
  629. </div>
  630. </div>
  631. </section>
  632. </main>
  633. <footer class="report-footer">
  634. <div>茶决决 · 景德瓷江西茶 · VOC 洞察报告 v1.0</div>
  635. <div class="meta">FMODE / VOC Intelligence / 产品定位 × 竞品分析 × 机会格局 × 用户需求 / 2026-05-30</div>
  636. </footer>
  637. <script>
  638. (function(){
  639. 'use strict';
  640. document.documentElement.classList.add('js');
  641. const sections=document.querySelectorAll('section.report-section');
  642. const navDots=document.querySelectorAll('.nav-dot');
  643. const progressLine=document.getElementById('progressLine');
  644. const slideNow=document.getElementById('slideNow');
  645. const slideCounter=document.getElementById('slideCounter');
  646. const kbdHint=document.getElementById('kbdHint');
  647. let activeIdx=0,scrollTicking=false;
  648. function updateActive(){
  649. let best=-1;const vh=window.innerHeight;
  650. sections.forEach(function(sec,i){const r=sec.getBoundingClientRect();if(r.top<=vh*0.5&&r.bottom>=vh*0.2)best=i;});
  651. if(best<0)best=0;
  652. if(best!==activeIdx){activeIdx=best;navDots.forEach(function(d){d.classList.remove('active');});if(navDots[activeIdx])navDots[activeIdx].classList.add('active');sections.forEach(function(s,i){if(i===activeIdx)s.classList.add('in-view');});if(slideNow)slideNow.textContent=activeIdx+1;}
  653. const totalH=document.body.scrollHeight-window.innerHeight;
  654. const pct=totalH>0?Math.min(100,Math.round((window.scrollY/totalH)*100)):0;
  655. if(progressLine)progressLine.style.width=pct+'%';
  656. if(slideCounter){const barEl=slideCounter.querySelector('.bar span');if(barEl)barEl.style.width=pct+'%';}
  657. }
  658. window.addEventListener('scroll',function(){if(!scrollTicking){requestAnimationFrame(function(){updateActive();scrollTicking=false;});scrollTicking=true;}},{passive:true});
  659. window.addEventListener('keydown',function(e){const key=e.key||e.keyCode;let dir=0;if(key==='ArrowDown'||key==='ArrowRight'||key==='PageDown'||key==='j'||key==='J')dir=1;if(key==='ArrowUp'||key==='ArrowLeft'||key==='PageUp'||key==='k'||key==='K')dir=-1;if(dir===0)return;e.preventDefault();const next=Math.max(0,Math.min(sections.length-1,activeIdx+dir));if(sections[next]){sections[next].scrollIntoView({behavior:'smooth',block:'center'});activeIdx=next;}});
  660. navDots.forEach(function(dot){dot.addEventListener('click',function(e){e.preventDefault();const target=document.querySelector(dot.getAttribute('href'));if(target)target.scrollIntoView({behavior:'smooth',block:'center'});});});
  661. const observer=new IntersectionObserver(function(entries){entries.forEach(function(entry){if(entry.isIntersecting)entry.target.classList.add('is-visible');});},{threshold:0.15,rootMargin:'0px 0px -40px 0px'});
  662. document.querySelectorAll('.fade-up,.rise-in').forEach(function(el){observer.observe(el);});
  663. document.querySelectorAll('.headline-anim').forEach(function(el){const text=el.textContent||'';el.textContent='';el.innerHTML=text.split('').map(function(c){return '<span class="char">'+(c===' '?'&nbsp;':c)+'</span>';}).join('');const chars=el.querySelectorAll('.char');chars.forEach(function(ch,i){ch.style.transitionDelay=(i*0.025)+'s';});const hObs=new IntersectionObserver(function(entries){entries.forEach(function(entry){if(entry.isIntersecting){el.classList.add('is-visible');hObs.unobserve(el);}});},{threshold:0.5});hObs.observe(el);});
  664. let mx=0.5,my=0.5;
  665. document.addEventListener('mousemove',function(e){mx=e.clientX/window.innerWidth;my=e.clientY/window.innerHeight;document.body.style.setProperty('--amb-x',(mx*100).toFixed(1)+'%');document.body.style.setProperty('--amb-y',(my*100).toFixed(1)+'%');},{passive:true});
  666. setTimeout(function(){if(kbdHint)kbdHint.classList.add('fade');},8000);
  667. updateActive();
  668. if(sections[0])sections[0].classList.add('in-view');
  669. })();
  670. </script>
  671. </body>
  672. </html>