<template>
  <div class="consumer-behavior-page student-training-shell">
    <main class="training-core">
      <section class="task-header">
        <div class="task-badge">市场洞察与需求分析</div>
        <h1 class="task-title">{{ taskTitle }}</h1>
      </section>

      <TrainingTaskBrief
        :background="taskBackground"
        :goals="taskGoals"
        :requirements="taskRequirement"
        :show-material="false"
      />

      <section class="task-card">
      <div class="workbench-head workbench-head--actions-only">
          <div class="workbench-actions">
            <TrainingMaterialButton :material-name="taskConfig?.materialName" :material-url="taskConfig?.materialUrl" />
            <button type="button" class="outline-action" @click="exportOutcome">
              <el-icon><Download /></el-icon>
              导出实训成果
            </button>
          </div>
        </div>

        <nav v-if="flowSteps.length" class="step-indicator" aria-label="消费者需求与行为步骤">
          <template v-for="(step, index) in flowSteps" :key="step">
            <button
              type="button"
              :class="['step-tab', { active: form.activeStep === index, complete: form.activeStep > index }]"
              :aria-label="`第${index + 1}步：${step}`"
              @click="setActiveStep(index)"
            >
              <span class="step-marker">{{ String(index + 1).padStart(2, '0') }}</span>
              <span class="step-copy">
                <strong class="step-name" :title="step">{{ step }}</strong>
                <span class="step-action">{{ form.activeStep === index ? "当前步骤" : "点击切换" }} <span aria-hidden="true">→</span></span>
              </span>
            </button>
            <span v-if="index < flowSteps.length - 1" class="step-connector" aria-hidden="true"></span>
          </template>
        </nav>

        <input
          ref="fileInputRef"
          type="file"
          class="file-input"
          :accept="uploadAccept"
          @change="handleFileChange"
        />
        <input
          ref="questionnaireImportInputRef"
          type="file"
          class="file-input"
          accept=".docx"
          @change="handleQuestionnaireImport"
        />

        <section class="step-card consumer-behavior-step-card">
        <div v-if="activeStepName" class="step-title-row">
          <div>
            <p class="section-eyebrow">Step {{ String(form.activeStep + 1).padStart(2, '0') }}</p>
            <h3>{{ activeStepName }}</h3>
          </div>
        </div>
        <section v-if="form.activeStep === 0" class="step-panel">
          <div class="hypothesis-head">
            <p class="task-desc hypothesis-desc">
              基于实训 8 的用户画像结论，明确本次问卷调查的目标人群与核心假设，填写下表。
            </p>
            <div class="hypothesis-actions">
              <el-button class="hypothesis-action" @click="addTargetHypothesis">增加一行</el-button>
              <el-button class="hypothesis-action hypothesis-action--quiet" :disabled="form.targetHypotheses.length <= 1" @click="removeTargetHypothesis">删除一行</el-button>
            </div>
            <el-button class="training-eight-action" @click="viewTargetUserProfile">查看实训8</el-button>
          </div>
          <div class="target-hypothesis-table-wrap">
            <table class="target-hypothesis-table">
              <thead>
                <tr>
                  <th>目标人群</th>
                  <th>实训8关键发现</th>
                  <th>本次问卷需验证的核心假设</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(hypothesis, index) in form.targetHypotheses" :key="index">
                  <td><input v-model="hypothesis.targetGroup" class="hypothesis-input" placeholder="例如：职场白领（25-35岁）" /></td>
                  <td><textarea v-model="hypothesis.keyFinding" class="hypothesis-textarea" placeholder="例如：高压工作、入睡困难、看重效率" /></td>
                  <td><textarea v-model="hypothesis.coreHypothesis" class="hypothesis-textarea" placeholder="例如：是否更关注白噪声质量与智能场景联动？对价格的敏感度如何？" /></td>
                </tr>
              </tbody>
            </table>
          </div>
          <p class="hypothesis-tip">可编辑表格内容；请基于实训 8 的结论明确每类目标人群的问卷验证方向。</p>
        </section>

        <section v-else-if="form.activeStep === 1" class="step-panel">
          <div class="kano-head">
            <p class="task-desc kano-desc">
              在正式设计问卷之前，需要理解消费者需求的层次结构。不同类型的需求对购买决策的影响方式截然不同。结合案例资料，通过 KANO 模型进行用户需求分类，填写下表。
            </p>
            <div class="kano-actions">
              <el-button class="hypothesis-action" :disabled="form.kanoNeeds.length >= KANO_NEED_LIMIT" @click="addKanoNeed">增加一行</el-button>
              <el-button class="hypothesis-action hypothesis-action--quiet" :disabled="form.kanoNeeds.length <= 1" @click="removeKanoNeed">删除一行</el-button>
            </div>
          </div>
          <div class="kano-table-wrap">
            <table class="kano-table">
              <thead>
                <tr>
                  <th>编号</th>
                  <th>功能</th>
                  <th>对应KANO类型</th>
                  <th>对应功能方向</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(need, index) in form.kanoNeeds" :key="index">
                  <td class="kano-index">{{ index + 1 }}</td>
                  <td><textarea v-model="need.feature" class="hypothesis-textarea kano-textarea" placeholder="示例：灯光亮度可无级调节" aria-label="功能" /></td>
                  <td class="kano-select-cell">
                    <el-select v-model="need.kanoType" class="kano-select" placeholder="请选择类型" aria-label="对应KANO类型">
                      <el-option v-for="option in kanoTypeOptions" :key="option" :label="option" :value="option" />
                    </el-select>
                  </td>
                  <td><textarea v-model="need.featureDirection" class="hypothesis-textarea kano-textarea" placeholder="示例：照明系统" aria-label="对应功能方向" /></td>
                </tr>
              </tbody>
            </table>
          </div>
          <p class="hypothesis-tip">功能与功能方向均可填写；KANO 类型请从下拉菜单选择。最多可填写 {{ KANO_NEED_LIMIT }} 行。</p>
        </section>

        <section v-else-if="form.activeStep === 2" class="step-panel">
          <div class="questionnaire-design-head">
            <p class="task-desc questionnaire-design-desc">
              结合前面的实训分析，设计一份完整的消费者需求调研问卷，包含基本信息、购买行为、需求偏好和开放建议四部分。需求偏好部分请用 Likert 五级量表评价第 2 步归类的功能。
            </p>
            <el-button class="questionnaire-import-action" :loading="questionnaireImporting" @click="triggerQuestionnaireImport">
              <el-icon><Upload /></el-icon>
              导入问卷（Word 文档）
            </el-button>
          </div>

          <div v-if="form.questionnaireImport?.name" class="questionnaire-imported-file">
            <el-icon><Document /></el-icon>
            <span>{{ form.questionnaireImport.name }}</span>
            <button type="button" @click="showQuestionnairePreview = true">预览问卷</button>
          </div>

          <div class="questionnaire-editor-launcher">
            <div class="questionnaire-editor-launcher__copy">
              <span class="section-eyebrow">Questionnaire Studio</span>
              <h4>在线编写消费者需求调研问卷</h4>
              <p>通过分区、题型与选项设置，快速完成可执行的问卷结构。</p>
            </div>
            <el-button class="questionnaire-editor-launcher__action" @click="questionnaireEditorVisible = true">进入问卷编辑器</el-button>
          </div>

          <p class="questionnaire-editor-summary">
            已编辑 {{ form.questionnaireQuestions.length }} 题；{{ form.questionnaireImport?.name ? "已导入 1 份 Word 问卷，可随时预览。" : "也可导入已完成的 .docx 问卷。" }}
          </p>

          <el-dialog v-model="questionnaireEditorVisible" title="消费者需求调研问卷编辑器" width="min(1120px, 94vw)" class="questionnaire-editor-dialog" append-to-body>
            <div class="questionnaire-editor-dialog__intro">
              <p>请覆盖基本信息、购买行为、需求偏好和开放建议四部分；需求偏好至少设置一题 Likert 五级量表。</p>
              <el-button class="questionnaire-editor-add" @click="addQuestionnaireQuestion">新增题目</el-button>
            </div>
            <div class="questionnaire-question-list">
              <article v-for="(question, index) in form.questionnaireQuestions" :key="question.id" class="questionnaire-question-card">
                <span class="questionnaire-question-card__number">{{ String(index + 1).padStart(2, "0") }}</span>
                <div class="questionnaire-question-card__fields">
                  <el-select v-model="question.section" aria-label="问卷分区">
                    <el-option v-for="section in questionnaireSections" :key="section.value" :label="section.label" :value="section.value" />
                  </el-select>
                  <el-select v-model="question.type" aria-label="题目类型">
                    <el-option v-for="type in questionnaireQuestionTypes" :key="type.value" :label="type.label" :value="type.value" />
                  </el-select>
                  <el-input v-model="question.title" :placeholder="questionPlaceholder(question.section)" aria-label="题目内容" />
                  <el-input v-if="question.type === 'SINGLE' || question.type === 'MULTIPLE'" v-model="question.options" placeholder="选项以中文逗号或换行分隔" aria-label="题目选项" />
                  <p v-else-if="question.type === 'LIKERT'" class="likert-tip">量表固定为：非常不重要、较不重要、一般、较重要、非常重要</p>
                </div>
                <button type="button" class="questionnaire-question-card__remove" :disabled="form.questionnaireQuestions.length <= 4" @click="removeQuestionnaireQuestion(index)">删除</button>
              </article>
            </div>
          </el-dialog>

          <el-dialog v-model="showQuestionnairePreview" title="导入问卷预览" width="min(900px, 94vw)" class="questionnaire-preview-dialog" append-to-body>
            <div v-if="form.questionnaireImport?.previewContent" class="questionnaire-word-preview">{{ form.questionnaireImport.previewContent }}</div>
            <p v-else class="questionnaire-preview-empty">暂未解析到可预览内容。</p>
          </el-dialog>
        </section>

        <section v-else class="step-panel">
          <p class="task-desc survey-report-desc">
            将步骤三设计的调查问卷导入问卷星等在线问卷调查平台，开展问卷调查。基于收集到的数据，填写问卷调查报告。
          </p>
          <div class="survey-report-table-wrap">
            <table class="survey-report-table">
              <thead>
                <tr>
                  <th>报告模块标题</th>
                  <th>内容</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="(row, index) in form.surveyReportRows" :key="index">
                  <td>
                    <input v-model="row.title" class="survey-report-title-input" :placeholder="surveyReportTitlePlaceholder(index)" :aria-label="`第${index + 1}个报告模块标题`" />
                  </td>
                  <td>
                    <textarea v-model="row.content" class="survey-report-content-input" :placeholder="surveyReportContentPlaceholder(index)" :aria-label="`第${index + 1}个报告模块内容`" />
                  </td>
                </tr>
              </tbody>
            </table>
          </div>
          <div class="survey-report-guide">
            <div>
              <h5>可参考以下方法</h5>
              <p>1. 根据报告模板，自行分析撰写问卷调查报告。</p>
              <p>2. 使用通用 AI 大模型辅助完成报告：请根据用户调研数据，从用户购买核心决策因素、不同群体决策因素差异、未购买用户的顾虑与市场机会、信息获取渠道与购买场景等方面撰写报告。</p>
              <p>3. 如问卷调查收集的数据不理想，可使用本实训提供的数据进行分析，生成调查报告。</p>
            </div>
            <el-button class="survey-report-template-action" @click="downloadSurveyReportTemplate">
              <el-icon><Download /></el-icon>
              下载报告模板
            </el-button>
          </div>
        </section>

        <div class="step-actions">
          <el-button class="nav-action nav-action--previous" :disabled="form.activeStep === 0" @click="goPrev">
            <el-icon><ArrowLeft /></el-icon>
            上一步
          </el-button>
          <el-button class="nav-action nav-action--save" :loading="saving" @click="saveCurrentProgress">
            <el-icon><CircleCheck /></el-icon>
            保存当前进度
          </el-button>
          <el-button class="nav-action nav-action--next" :disabled="form.activeStep === flowSteps.length - 1" @click="goNext">
            下一步
            <el-icon><ArrowRight /></el-icon>
          </el-button>
        </div>

        <div class="training-actions">
          <el-button class="training-action training-action--submit" :loading="saving" @click="submitTask">
            提交任务
          </el-button>
          <el-button class="training-action training-action--reset" @click="resetTraining">
            重新实训
          </el-button>
        </div>
        </section>
      </section>
    </main>

    <TrainingAiSidebar
      study-tip="当前步骤建议：先确认问卷能覆盖用户基本信息、购买行为、决策因素和未购买顾虑，再用数据分析支撑结论。"
      reference-title="消费者行为分析参考"
      reference-text="· 需求类型：功能需求、价格需求、服务需求、隐私安全需求<br />· 决策因素：价格、品牌、功能、质量、便捷性、售后<br />· 分析方法：分群对比、渠道分析、购买场景分析、未购买原因归因"
      assist-text="报告中尽量把数据结论写成“现象 + 人群差异 + 产品启示”的结构，避免只罗列比例。"
      :progress-items="progressItems"
    />
  </div>
</template>

<script setup>
import { computed, getCurrentInstance, nextTick, onMounted, ref } from "vue";
import { ArrowLeft, ArrowRight, CircleCheck, Document, Download, Upload } from "@element-plus/icons-vue";
import TrainingAiSidebar from "@/views/components/TrainingAiSidebar.vue";
import TrainingMaterialButton from "@/views/components/TrainingMaterialButton.vue";
import TrainingTaskBrief from "@/views/components/TrainingTaskBrief.vue";
import { getTrainingTaskByKey } from "@/api/trainingTask";
import { checkConsumerBehaviorStepOne, checkConsumerBehaviorStepTwo, checkConsumerBehaviorStepThree, checkConsumerBehaviorStepFour, getStudentTrainingAnswer, previewConsumerBehaviorQuestionnaireWord, saveStudentTrainingAnswer, uploadStudentTrainingFile } from "@/api/studentTrainingAnswer";

const TASK_KEY = "consumer-behavior";
const KANO_NEED_LIMIT = 20;
let questionnaireQuestionSequence = 0;
const { proxy } = getCurrentInstance();

const defaultRequirement = "消费者需求与行为分析用于识别目标用户的购买动机、决策因素、渠道偏好和使用场景，为智能产品功能设计与市场切入提供依据。";
const defaultBackground =
  "SX是一家专注于智能健康生活产品的科技公司。公司产品开发团队经过市场分析，发现光线及噪音对睡眠具有较大影响，市场上针对助眠产品主要集中在保健品及药物，较少产品是通过优化睡眠环境来达成助眠效果，因此，初步判断开发一款智能声光伴眠吸顶灯具有市场机会。\n产品开发前，团队进行了目标用户画像，进行了初步的用户分析，现在需要通过问卷调查，收集足够多的数据，分析用户购买智能产品的决策因素，为后续的产品关键功能开发提供市场需求数据支撑与决策依据。";
const defaultGoals = [
  "掌握消费者需求类型划分及特征。",
  "熟悉消费者行为理论与决策机制。",
  "挖掘影响消费者需求及行为的关键因素。",
];

const questionnaireTemplate = `<h4>智能产品购买决策因素调查问卷</h4>
<p><strong>（一）基本信息</strong></p>
<p>1.您的性别： A. 男 B. 女</p>
<p>2.您的年龄： A. 18岁及以下 B. 19-25岁 C. 26-35岁 D. 36-45岁 E. 46岁及以上</p>
<p>3.您的月收入： A. 3000元及以下 B. 3001-5000元 C. 5001-8000元 D. 8001-12000元 E. 12001元及以上</p>
<p>4.您居住的城市级别： A. 一线城市 B. 新一线城市 C. 二线城市 D. 三线及以下城市</p>
<p><strong>（二）购买行为与决策因素</strong></p>
<p>5.您是否购买过智能产品？ A. 是 B. 否（若选B，跳转至第12题）</p>
<p>6.您购买过的智能产品类型可多选： A. 智能手机 B. 智能家电（如扫地机器人、智能冰箱等） C. 智能穿戴设备（如智能手表、手环等） D. 智能玩具 E. 智能健身设备（如智能健身镜） F. 其他（请注明____）</p>
<p>7.在购买智能产品时，您优先考虑的因素可多选： A. 价格 B. 品牌知名度 C. 功能实用性 D. 产品质量与稳定性 E. 操作便捷性 F. 数据安全与隐私保护 G. 外观设计 H. 售后服务 I. 生态兼容性（如能否与其他智能设备联动） J. 其他（请注明____）</p>
<p>8.请您根据实际感受，评价以下因素对您购买智能产品的重要程度，请在对应选项中打“√”</p>
<table>
  <thead>
    <tr>
      <th>因素</th>
      <th>非常不重要</th>
      <th>不重要</th>
      <th>一般</th>
      <th>重要</th>
      <th>非常重要</th>
    </tr>
  </thead>
  <tbody>
    <tr><td>价格</td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td>品牌知名度</td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td>功能实用性</td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td>产品质量与稳定性</td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td>操作便捷性</td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td>数据安全与隐私保护</td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td>外观设计</td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td>售后服务</td><td></td><td></td><td></td><td></td><td></td></tr>
    <tr><td>生态兼容性</td><td></td><td></td><td></td><td></td><td></td></tr>
  </tbody>
</table>
<p>9.您是否会因为智能产品具备独特创新功能而愿意支付更高价格？ A. 一定会 B. 可能会 C. 不确定 D. 可能不会 E. 一定不会</p>
<p>10.您获取智能产品信息的主要渠道可多选： A. 电商平台（如淘宝、京东等） B. 社交媒体（如抖音、小红书等） C. 朋友、家人推荐 D. 线下实体店体验 E. 科技媒体评测 F. 其他（请注明____）</p>
<p>11.您购买智能产品的主要场景是： A. 自己使用 B. 赠送家人 C. 赠送朋友 D. 商务礼品 E. 其他（请注明____）</p>
<p><strong>（三）未购买情况与顾虑</strong></p>
<p>12.您未购买智能产品的主要原因可多选： A. 价格过高 B. 对智能产品功能不了解 C. 担心产品质量与稳定性 D. 担心数据安全与隐私泄露 E. 觉得操作复杂，难以上手 F. 没有合适的产品满足需求 G. 其他（请注明____）</p>
<p>13.如果您计划购买智能产品，您最期待的功能是： A. 更强大的智能化功能 B. 更便捷的操作方式 C. 更好的数据安全与隐私保护 D. 更丰富的生态兼容性 E. 其他（请注明____）</p>
<p><strong>（四）开放性问题</strong></p>
<p>14.对于智能产品的发展，您有哪些建议或期望？</p>`;

const surveyStats = `（一）基本信息
1.性别：男235人（47%），女265人（53%）
2.年龄：18岁及以下30人（6%），19-25岁120人（24%），26-35岁180人（36%），36-45岁100人（20%），46岁及以上70人（14%）
3.月收入：3000元及以下80人（16%），3001-5000元120人（24%），5001-8000元150人（30%），8001-12000元100人（20%），12001元及以上50人（10%）
4.城市级别：一线城市100人（20%），新一线城市150人（30%），二线城市120人（24%），三线及以下城市130人（26%）

（二）购买行为与决策因素
5.是否购买过智能产品：是420人（84%），否80人（16%）
6.购买过的智能产品类型：智能手机380人（76%），智能家电220人（44%），智能穿戴设备180人（36%），智能玩具60人（12%），智能健身设备40人（8%），其他20人（4%）
7.优先考虑的因素：价格250人（50%），品牌知名度180人（36%），功能实用性320人（64%），产品质量与稳定性280人（56%），操作便捷性220人（44%），数据安全与隐私保护150人（30%），外观设计120人（24%），售后服务100人（20%），生态兼容性80人（16%），其他30人（6%）
8.各因素影响程度统计：价格65%，品牌知名度50%，功能实用性80%，产品质量与稳定性75%，操作便捷性60%，数据安全与隐私保护45%，外观设计35%，售后服务40%，生态兼容性30%
9.是否为创新功能支付更高价格：一定会80人（16%），可能会220人（44%），不确定100人（20%），可能不会70人（14%），一定不会30人（6%）
10.获取信息渠道：电商平台300人（60%），社交媒体250人（50%），朋友、家人推荐200人（40%），线下实体店体验150人（30%），科技媒体评测120人（24%），其他30人（6%）
11.购买场景：自己使用350人（70%），赠送家人80人（16%），赠送朋友40人（8%），商务礼品20人（4%），其他10人（2%）

（三）未购买情况与顾虑
12.未购买原因：价格过高35人（43.75%），对功能不了解20人（25%），担心质量与稳定性15人（18.75%），担心数据安全与隐私泄露8人（10%），觉得操作复杂5人（6.25%），没有合适产品3人（3.75%），其他2人（2.5%）
13.期待的功能：更强大智能化功能25人（31.25%），更便捷操作方式20人（25%），更好数据安全与隐私保护15人（18.75%），更丰富生态兼容性12人（15%），其他8人（10%）

（四）开放性问题
部分用户建议：希望智能产品价格更加亲民；简化操作流程，适合各年龄段人群；加强数据安全保护；丰富产品功能，满足多样化需求；提升售后服务质量等。`;

const visualGroups = [
  {
    title: "1.基本信息",
    items: [
      { key: "gender", label: "性别" },
      { key: "age", label: "年龄" },
      { key: "income", label: "月收入" },
      { key: "city", label: "城市级别" },
    ],
  },
  {
    title: "2.购买行为与决策因素",
    items: [
      { key: "hasPurchased", label: "是否购买过智能产品" },
      { key: "productTypes", label: "购买过的智能产品类型" },
      { key: "priorityFactors", label: "优先考虑的因素" },
      { key: "factorImportance", label: "各因素影响程度统计" },
      { key: "innovationPremium", label: "是否为创新功能支付更高价格" },
      { key: "infoChannels", label: "获取信息渠道" },
      { key: "purchaseScenario", label: "购买场景" },
    ],
  },
  {
    title: "3.未购买情况与顾虑",
    items: [
      { key: "nonPurchaseReasons", label: "未购买原因" },
      { key: "expectedFunctions", label: "期待的功能" },
    ],
  },
];

const taskConfig = ref(null);
const saving = ref(false);
const uploading = ref(false);
const questionnaireImporting = ref(false);
const fileInputRef = ref(null);
const questionnaireImportInputRef = ref(null);
const questionnaireEditorRef = ref(null);
const uploadContext = ref({ type: "", key: "" });
const questionnaireEditorVisible = ref(false);
const showQuestionnairePreview = ref(false);

const uploadAccept = computed(() => {
  if (uploadContext.value.type === "questionnaire") return ".pdf";
  if (uploadContext.value.type === "dataExcel") return ".xls,.xlsx";
  if (uploadContext.value.type === "chart") return ".png,.jpg,.jpeg,.webp";
  return ".png,.jpg,.jpeg,.webp,.pdf,.doc,.docx";
});

function createForm() {
  return {
    activeStep: 0,
    targetHypotheses: createTargetHypotheses(),
    kanoNeeds: createKanoNeeds(),
    questionnaireQuestions: createQuestionnaireQuestions(),
    questionnaireImport: null,
    surveyReportRows: createSurveyReportRows(),
    questionnaireText: questionnaireTemplate,
    questionnaireFileName: "",
    questionnaireFileUrl: "",
    dataExcelFileName: "",
    dataExcelFileUrl: "",
    chartFiles: {},
  };
}

function createTargetHypotheses() {
  return [
    { targetGroup: "职场白领（25-35岁）", keyFinding: "", coreHypothesis: "" },
    { targetGroup: "精致妈妈（28-38岁）", keyFinding: "", coreHypothesis: "" },
    { targetGroup: "银发人群（50-65岁）", keyFinding: "", coreHypothesis: "" },
  ];
}

function createEmptyTargetHypothesis() {
  return { targetGroup: "", keyFinding: "", coreHypothesis: "" };
}

const kanoTypeOptions = ["基本型", "期望型", "兴奋型", "无差异型", "反向型"];
const questionnaireSections = [
  { value: "基本信息", label: "基本信息" },
  { value: "购买行为", label: "购买行为" },
  { value: "需求偏好", label: "需求偏好" },
  { value: "开放建议", label: "开放建议" },
];
const questionnaireQuestionTypes = [
  { value: "SINGLE", label: "单选题" },
  { value: "MULTIPLE", label: "多选题" },
  { value: "LIKERT", label: "Likert 五级量表" },
  { value: "TEXT", label: "开放题" },
];

function createKanoNeeds() {
  return Array.from({ length: 3 }, createEmptyKanoNeed);
}

function createEmptyKanoNeed() {
  return { feature: "", kanoType: "", featureDirection: "" };
}

function createQuestionnaireQuestions() {
  return [
    createQuestionnaireQuestion("基本信息", "SINGLE"),
    createQuestionnaireQuestion("购买行为", "SINGLE"),
    createQuestionnaireQuestion("需求偏好", "LIKERT"),
    createQuestionnaireQuestion("开放建议", "TEXT"),
  ];
}

function createQuestionnaireQuestion(section = "基本信息", type = "SINGLE") {
  questionnaireQuestionSequence += 1;
  return { id: `question-${Date.now()}-${questionnaireQuestionSequence}`, section, type, title: "", options: "" };
}

function createSurveyReportRows() {
  return Array.from({ length: 5 }, () => ({ title: "", content: "" }));
}

const form = ref(createForm());

const taskTitle = computed(() => taskConfig.value?.taskName || "消费者需求与行为");
const taskBackground = computed(() => taskConfig.value?.background || defaultBackground);
const taskGoals = computed(() => parseArray(taskConfig.value?.objectives, defaultGoals));
const taskRequirement = computed(() => taskConfig.value?.requirements || defaultRequirement);
const flowSteps = computed(() => parseArray(taskConfig.value?.steps, []).slice(0, 4));
const activeStepName = computed(() => flowSteps.value[form.value.activeStep] || "");

const progressItems = computed(() => [
  { text: hasQuestionnaireDesign() ? "已完成：问卷设计" : "待完成：问卷设计", status: hasQuestionnaireDesign() ? "done" : "" },
  { text: form.value.dataExcelFileName ? "已完成：数据整理上传" : "待完成：整理并上传Excel", status: form.value.dataExcelFileName ? "done" : "" },
  { text: Object.keys(form.value.chartFiles).length ? "进行中：数据可视化截图" : "待完成：数据可视化截图", status: Object.keys(form.value.chartFiles).length ? "done" : "" },
  { text: hasSurveyReport() ? "已完成：问卷调研报告" : "待完成：问卷调研报告", status: hasSurveyReport() ? "done" : "" },
]);

onMounted(async () => {
  await loadTaskConfig();
  await loadSavedAnswer();
  await nextTick();
  renderQuestionnaireEditor();
});

async function loadTaskConfig() {
  try {
    const res = await getTrainingTaskByKey(TASK_KEY);
    taskConfig.value = res?.data || null;
  } catch (error) {
    taskConfig.value = null;
  }
}

async function loadSavedAnswer() {
  try {
    const res = await getStudentTrainingAnswer(TASK_KEY);
    const answer = res?.data;
    if (answer?.step1Answer) {
      applySavedAnswer(answer.step1Answer);
    }
  } catch (error) {
    // 回显失败不阻断页面填写。
  }
}

function parseArray(value, fallback) {
  if (Array.isArray(value)) return value.length ? value : fallback;
  if (!value) return fallback;
  try {
    const parsed = JSON.parse(value);
    return Array.isArray(parsed) && parsed.length ? parsed : fallback;
  } catch (error) {
    const list = String(value)
      .split(/[;；|,，\n]/)
      .map((item) => item.trim())
      .filter(Boolean);
    return list.length ? list : fallback;
  }
}

function applySavedAnswer(value) {
  try {
    const parsed = JSON.parse(value);
    if (!parsed || typeof parsed !== "object") return;
    form.value = {
      ...createForm(),
      ...parsed,
      activeStep: Number.isInteger(parsed.activeStep) ? parsed.activeStep : 0,
      questionnaireText: normalizeQuestionnaireContent(parsed.questionnaireText || questionnaireTemplate),
      targetHypotheses: normalizeTargetHypotheses(parsed.targetHypotheses),
      kanoNeeds: normalizeKanoNeeds(parsed.kanoNeeds),
      questionnaireQuestions: normalizeQuestionnaireQuestions(parsed.questionnaireQuestions),
      questionnaireImport: normalizeQuestionnaireImport(parsed.questionnaireImport),
      surveyReportRows: normalizeSurveyReportRows(parsed.surveyReportRows),
      chartFiles: parsed.chartFiles || {},
    };
    nextTick(renderQuestionnaireEditor);
  } catch (error) {
    // 忽略历史异常数据。
  }
}

function normalizeTargetHypotheses(rows) {
  if (!Array.isArray(rows) || !rows.length) return createTargetHypotheses();
  return rows.map((row) => ({
    targetGroup: String(row?.targetGroup || ""),
    keyFinding: String(row?.keyFinding || ""),
    coreHypothesis: String(row?.coreHypothesis || ""),
  }));
}

function normalizeKanoNeeds(rows) {
  if (!Array.isArray(rows) || !rows.length) return createKanoNeeds();
  return rows.slice(0, KANO_NEED_LIMIT).map((row) => ({
    feature: String(row?.feature || ""),
    kanoType: kanoTypeOptions.includes(row?.kanoType) ? row.kanoType : "",
    featureDirection: String(row?.featureDirection || ""),
  }));
}

function normalizeQuestionnaireQuestions(rows) {
  if (!Array.isArray(rows) || !rows.length) return createQuestionnaireQuestions();
  return rows.map((row, index) => ({
    id: String(row?.id || `question-restored-${index}`),
    section: questionnaireSections.some((item) => item.value === row?.section) ? row.section : "基本信息",
    type: questionnaireQuestionTypes.some((item) => item.value === row?.type) ? row.type : "SINGLE",
    title: String(row?.title || ""),
    options: String(row?.options || ""),
  }));
}

function normalizeQuestionnaireImport(value) {
  if (!value || typeof value !== "object" || !value.name) return null;
  return {
    name: String(value.name),
    url: String(value.url || ""),
    previewContent: String(value.previewContent || ""),
  };
}

function normalizeSurveyReportRows(rows) {
  if (!Array.isArray(rows) || !rows.length) return createSurveyReportRows();
  return Array.from({ length: 5 }, (_, index) => ({
    title: String(rows[index]?.title || ""),
    content: String(rows[index]?.content || ""),
  }));
}

function syncQuestionnaireText() {
  if (!questionnaireEditorRef.value) return;
  form.value.questionnaireText = questionnaireEditorRef.value.innerHTML;
}

function renderQuestionnaireEditor() {
  if (!questionnaireEditorRef.value) return;
  if (questionnaireEditorRef.value.innerHTML !== form.value.questionnaireText) {
    questionnaireEditorRef.value.innerHTML = form.value.questionnaireText;
  }
}

function normalizeQuestionnaireContent(value) {
  const content = String(value || "").trim();
  if (!content) return questionnaireTemplate;
  return /<\/?[a-z][\s\S]*>/i.test(content) ? content : textToHtml(content);
}

function textToHtml(value) {
  return String(value)
    .split(/\n{2,}/)
    .map((block) => `<p>${escapeHtml(block).replace(/\n/g, "<br>")}</p>`)
    .join("");
}

function escapeHtml(value) {
  return String(value)
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#39;");
}

function questionnaireTextForExport() {
  syncQuestionnaireText();
  const wrapper = document.createElement("div");
  wrapper.innerHTML = form.value.questionnaireText || "";
  return wrapper.innerText.trim();
}

function triggerFileSelect(type, key = "") {
  uploadContext.value = { type, key };
  fileInputRef.value?.click();
}

function setActiveStep(index) {
  form.value.activeStep = index;
  if (index === 0) {
    nextTick(renderQuestionnaireEditor);
  }
}

function addTargetHypothesis() {
  form.value.targetHypotheses.push(createEmptyTargetHypothesis());
}

function removeTargetHypothesis() {
  if (form.value.targetHypotheses.length <= 1) return;
  form.value.targetHypotheses.pop();
}

function addKanoNeed() {
  if (form.value.kanoNeeds.length >= KANO_NEED_LIMIT) {
    proxy?.$modal?.msgWarning(`最多可填写 ${KANO_NEED_LIMIT} 行`);
    return;
  }
  form.value.kanoNeeds.push(createEmptyKanoNeed());
}

function removeKanoNeed() {
  if (form.value.kanoNeeds.length <= 1) return;
  form.value.kanoNeeds.pop();
}

function questionPlaceholder(section) {
  const placeholders = {
    基本信息: "例如：您的年龄处于以下哪个区间？",
    购买行为: "例如：您通常通过什么渠道购买智能助眠产品？",
    需求偏好: "例如：白噪声可定时关闭对您有多重要？",
    开放建议: "例如：您希望智能助眠产品增加哪些功能？",
  };
  return placeholders[section] || "请输入题目内容";
}

function addQuestionnaireQuestion() {
  form.value.questionnaireQuestions.push(createQuestionnaireQuestion());
}

function removeQuestionnaireQuestion(index) {
  if (form.value.questionnaireQuestions.length <= 4) return;
  form.value.questionnaireQuestions.splice(index, 1);
}

function triggerQuestionnaireImport() {
  questionnaireImportInputRef.value?.click();
}

function viewTargetUserProfile() {
  window.open("/demand/people", "_blank", "noopener");
}

async function handleFileChange(event) {
  const file = event.target.files?.[0];
  if (!file) return;
  const data = new FormData();
  data.append("file", file);
  uploading.value = true;
  try {
    const res = await uploadStudentTrainingFile(data);
    const url = res?.url || res?.fileName || res?.data?.url || res?.data?.fileName || "";
    const { type, key } = uploadContext.value;
    if (type === "questionnaire") {
      form.value.questionnaireFileName = file.name;
      form.value.questionnaireFileUrl = url;
    } else if (type === "dataExcel") {
      form.value.dataExcelFileName = file.name;
      form.value.dataExcelFileUrl = url;
    } else if (type === "chart" && key) {
      form.value.chartFiles = {
        ...form.value.chartFiles,
        [key]: { name: file.name, url },
      };
    }
    proxy?.$modal?.msgSuccess("上传成功");
  } finally {
    uploading.value = false;
    event.target.value = "";
  }
}

async function handleQuestionnaireImport(event) {
  const file = event.target.files?.[0];
  if (!file) return;
  if (!/\.docx$/i.test(file.name)) {
    proxy?.$modal?.msgWarning("请导入 .docx 格式的 Word 问卷，以便在线预览");
    event.target.value = "";
    return;
  }
  const data = new FormData();
  data.append("file", file);
  questionnaireImporting.value = true;
  try {
    const previewRes = await previewConsumerBehaviorQuestionnaireWord(data);
    const uploadRes = await uploadStudentTrainingFile(data);
    const url = uploadRes?.url || uploadRes?.fileName || uploadRes?.data?.url || uploadRes?.data?.fileName || "";
    form.value.questionnaireImport = {
      name: file.name,
      url,
      previewContent: String(previewRes?.data?.content || ""),
    };
    showQuestionnairePreview.value = true;
    proxy?.$modal?.msgSuccess("问卷导入成功");
  } finally {
    questionnaireImporting.value = false;
    event.target.value = "";
  }
}

function goPrev() {
  if (form.value.activeStep > 0) setActiveStep(form.value.activeStep - 1);
}

async function goNext() {
  if (form.value.activeStep <= 2) await persist("IN_PROGRESS");
  if (form.value.activeStep < flowSteps.value.length - 1) setActiveStep(form.value.activeStep + 1);
}

function hasSurveyReport() {
  return form.value.surveyReportRows.every((item) => String(item?.title || "").trim() && String(item?.content || "").trim());
}

function hasQuestionnaireDesign() {
  return Boolean(form.value.questionnaireImport?.name)
    || form.value.questionnaireQuestions.some((item) => String(item?.title || "").trim());
}

function buildAnswerPayload(status) {
  syncQuestionnaireText();
  const saveAction = status === "SUBMITTED" ? "SUBMIT" : status === "RESET" ? "RESET" : "SAVE";
  return {
    saveAction,
    currentStep: form.value.activeStep + 1,
    step1Answer: JSON.stringify({
      ...form.value,
      taskKey: TASK_KEY,
      taskId: taskConfig.value?.id || "",
      taskName: taskTitle.value,
      flowSteps: flowSteps.value,
      updatedAt: new Date().toISOString(),
    }),
  };
}

async function persist(status = "IN_PROGRESS") {
  saving.value = true;
  try {
    if (status !== "RESET" && (form.value.activeStep === 0 || status === "SUBMITTED")) {
      await checkConsumerBehaviorStepOne({ hypotheses: form.value.targetHypotheses });
    }
    if (status !== "RESET" && (form.value.activeStep === 1 || status === "SUBMITTED")) {
      await checkConsumerBehaviorStepTwo({ needs: form.value.kanoNeeds });
    }
    if (status !== "RESET" && (form.value.activeStep === 2 || status === "SUBMITTED")) {
      await checkConsumerBehaviorStepThree({
        questions: form.value.questionnaireQuestions,
        importedDocumentUrl: form.value.questionnaireImport?.url || "",
      });
    }
    if (status !== "RESET" && (form.value.activeStep === 3 || status === "SUBMITTED")) {
      await checkConsumerBehaviorStepFour({ rows: form.value.surveyReportRows });
    }
    await saveStudentTrainingAnswer(TASK_KEY, buildAnswerPayload(status));
    proxy?.$modal?.msgSuccess(status === "SUBMITTED" ? "提交成功" : "保存成功");
  } finally {
    saving.value = false;
  }
}

function saveCurrentProgress() {
  return persist("IN_PROGRESS");
}

function submitTask() {
  return persist("SUBMITTED");
}

async function resetTraining() {
  form.value = createForm();
  await nextTick();
  renderQuestionnaireEditor();
  await persist("RESET");
}

function exportOutcome() {
  syncQuestionnaireText();
  const lines = [
    `任务：${taskTitle.value}`,
    "",
    `当前步骤：${flowSteps.value[form.value.activeStep] || ""}`,
    "",
    "问卷调查目标人群与核心假设：",
    ...form.value.targetHypotheses.map((item, index) => `${index + 1}. 目标人群：${item.targetGroup || ""}\n实训8关键发现：${item.keyFinding || ""}\n核心假设：${item.coreHypothesis || ""}`),
    "",
    "KANO 用户需求分类：",
    ...form.value.kanoNeeds.map((item, index) => `${index + 1}. 功能：${item.feature || ""}\nKANO类型：${item.kanoType || ""}\n功能方向：${item.featureDirection || ""}`),
    "",
    "消费者需求调研问卷：",
    form.value.questionnaireImport?.name ? `导入问卷：${form.value.questionnaireImport.name}` : "",
    ...form.value.questionnaireQuestions.map((item, index) => `${index + 1}. [${item.section}] ${item.title || ""}（${questionnaireQuestionTypes.find((type) => type.value === item.type)?.label || ""}）`),
    "",
    "问卷设计：",
    questionnaireTextForExport(),
    "",
    "问卷PDF文件：",
    form.value.questionnaireFileName || "未上传",
    "",
    "数据收集文件：",
    form.value.dataExcelFileName || "未上传",
    "",
    "问卷调研报告：",
    ...form.value.surveyReportRows.map((item, index) => `${index + 1}. ${item.title || "未命名模块"}\n${item.content || ""}`),
  ];
  const blob = new Blob([lines.join("\n")], { type: "text/plain;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = `${taskTitle.value}-实训结果.txt`;
  link.click();
  URL.revokeObjectURL(url);
}

function surveyReportTitlePlaceholder(index) {
  return ["例如：调研背景与目的", "例如：样本与调研方法", "例如：用户购买决策因素", "例如：不同群体需求差异", "例如：产品建议与结论"][index] || "请输入报告模块标题";
}

function surveyReportContentPlaceholder(index) {
  return ["说明本次问卷调研的背景、目标用户与调研目的。", "说明样本数量、调研时间、调研渠道与数据来源。", "结合问卷数据，分析影响用户购买决策的核心因素。", "比较不同人群在需求、价格、渠道或购买场景上的差异。", "总结调研结论，并提出产品功能、定价或营销建议。"][index] || "请输入报告内容";
}

function downloadSurveyReportTemplate() {
  const rows = Array.from({ length: 5 }, (_, index) => `<tr><td>${surveyReportTitlePlaceholder(index)}</td><td>${surveyReportContentPlaceholder(index)}</td></tr>`).join("");
  const html = `<!doctype html><html><head><meta charset="utf-8"><title>消费者需求调研报告模板</title><style>body{font-family:SimSun,serif;padding:32px;color:#222}h1{font-size:22px;text-align:center}p{line-height:1.75}table{width:100%;border-collapse:collapse;margin-top:24px}th,td{border:1px solid #777;padding:14px;vertical-align:top}th{background:#14a3df;color:#fff}td:first-child{width:22%}</style></head><body><h1>消费者需求调研报告</h1><p>请将步骤三设计的调查问卷导入在线问卷调查平台开展调研，并基于收集到的数据完成本报告。</p><table><thead><tr><th>报告模块标题</th><th>内容</th></tr></thead><tbody>${rows}</tbody></table></body></html>`;
  const blob = new Blob([html], { type: "application/msword;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url;
  link.download = "消费者需求调研报告模板.doc";
  link.click();
  URL.revokeObjectURL(url);
}
</script>

<style scoped lang="scss">
.consumer-behavior-page {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(720px, 1fr) 340px;
  gap: 24px;
  width: 100%;
  max-width: 100%;
  min-height: calc(100vh - 106px);
  margin: 0;
  padding: 24px 24px 32px;
  color: #e8f7ff;
  background: #06111d;
}

.training-core {
  min-width: 0;
  padding: 28px;
  border: 1px solid rgba(0, 180, 255, 0.25);
  border-radius: 36px;
  background: rgba(8, 18, 28, 0.6);
  box-shadow: 0 22px 48px rgba(0, 0, 0, 0.22), inset 0 1px 0 rgba(169, 229, 255, 0.08);
  backdrop-filter: blur(8px);
}

.task-header {
  margin-bottom: 24px;
}

.task-badge {
  display: inline-flex;
  margin-bottom: 12px;
  padding: 4px 14px;
  border: 1px solid rgba(0, 170, 255, 0.5);
  border-radius: 30px;
  color: #d6f6ff;
  background: rgba(0, 170, 255, 0.2);
  font-size: var(--student-fs-caption);
  font-weight: 700;
}

.task-title {
  margin: 0;
  color: #ffffff;
  font-size: var(--student-fs-display);
  line-height: 1.3;
  font-weight: 900;
}

.goal-bg,
.task-card,
.step-card {
  margin-bottom: 28px;
  padding: 18px 22px;
  border: 1px solid rgba(82, 174, 226, 0.42);
  border-radius: 26px;
  background: rgba(0, 25, 42, 0.64);
}

.goal-bg {
  p,
  li {
    color: #d7ecff;
    font-size: var(--student-fs-body);
    line-height: 1.8;
  }

  p,
  ol {
    margin: 0;
  }

  ol {
    padding-left: 18px;
  }
}

.subtitle-icon {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #eafaff;
  font-size: var(--student-fs-h1);
  font-weight: 900;
}

.subtitle-icon--spaced {
  margin-top: 16px;
}

.task-card {
  margin-top: 0;
}

.workbench-head {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 18px;
  margin-bottom: 22px;
  padding-bottom: 18px;
  border-bottom: 1px solid rgba(0, 180, 255, 0.2);
}

.section-eyebrow {
  margin: 0;
  color: #71dfff;
  font-size: var(--student-fs-caption);
  font-weight: 800;
  line-height: 1.4;
}

.workbench-head h3 {
  margin: 4px 0 8px;
  color: #ffffff;
  font-size: var(--student-fs-h1);
  font-weight: 800;
  line-height: 1.3;
}

.workbench-actions {
  display: flex;
  flex: 0 0 auto;
  flex-wrap: wrap;
  justify-content: flex-end;
  margin-left: auto;
  gap: 10px;
}

.workbench-description {
  margin: 0;
  color: #d7ecff;
  font-size: var(--student-fs-body);
  font-weight: 400;
  line-height: 1.8;
}

.outline-action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 40px;
  padding: 0 18px;
  border: 1px solid rgba(99, 217, 255, 0.55);
  border-radius: 999px;
  color: #e9fbff;
  background: rgba(17, 126, 178, 0.36);
  font-size: var(--student-fs-button);
  font-weight: 800;

  &:hover {
    transform: translateY(-1px);
    border-color: rgba(116, 235, 255, 0.85);
    background: rgba(18, 146, 204, 0.5);
  }
}

.step-indicator {
  position: relative;
  display: flex;
  align-items: center;
  gap: 0;
  width: calc(100% + 24px);
  margin: 0 -12px 32px;
  padding: 18px 22px;
  overflow-x: auto;
  border: 1px solid rgba(0, 180, 255, 0.3);
  border-radius: 18px;
  background:
    linear-gradient(90deg, rgba(6, 42, 61, 0.58), rgba(1, 18, 31, 0.42)),
    rgba(0, 0, 0, 0.3);
  box-shadow: inset 0 1px 0 rgba(145, 233, 255, 0.08);
  scrollbar-width: thin;
}

.step-tab {
  display: flex;
  flex: 1 0 145px;
  align-items: center;
  min-width: 0;
  min-height: 66px;
  padding: 8px 10px;
  border: 1px solid rgba(68, 141, 177, 0.35);
  border-radius: 8px;
  color: #9ab3d0;
  background: rgba(3, 27, 43, 0.52);
  box-shadow: inset 0 1px 0 rgba(135, 221, 255, 0.04);
  font-family: inherit;
  font-size: var(--student-fs-body);
  font-weight: 800;
  text-align: left;
  cursor: pointer;
  transition: transform 0.2s ease, color 0.2s ease, border-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;

  &:hover {
    transform: translateY(-2px);
    border-color: rgba(89, 223, 255, 0.82);
    color: #ffffff;
    background: rgba(8, 92, 131, 0.52);
    box-shadow: 0 7px 18px rgba(0, 0, 0, 0.24), inset 0 1px 0 rgba(152, 239, 255, 0.16);

    .step-action {
      color: #9bf4ff;
    }
  }

  &.active {
    border-color: rgba(89, 226, 255, 0.85);
    color: #ffffff;
    background: linear-gradient(115deg, rgba(4, 109, 155, 0.78), rgba(5, 62, 102, 0.64));
    box-shadow: 0 0 18px rgba(24, 183, 235, 0.22), inset 0 1px 0 rgba(176, 246, 255, 0.2);

    .step-marker {
      border-color: #72e8ff;
      color: #ffffff;
      background: linear-gradient(135deg, #08b7e8, #1375d0);
      box-shadow: 0 0 0 5px rgba(25, 179, 237, 0.14), 0 0 18px rgba(46, 208, 255, 0.58);
    }
  }

  &.complete {
    color: #dffbff;

    .step-marker {
      border-color: rgba(84, 230, 221, 0.85);
      color: #062b37;
      background: #6ef0e1;
      box-shadow: 0 0 12px rgba(79, 231, 218, 0.35);
    }
  }
}

.step-marker {
  display: inline-flex;
  flex: 0 0 38px;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border: 1px solid rgba(101, 176, 208, 0.6);
  border-radius: 50%;
  color: #a6c4d9;
  background: rgba(3, 25, 40, 0.8);
  box-shadow: inset 0 0 12px rgba(38, 174, 233, 0.08);
  font-size: var(--student-fs-caption);
  font-weight: 900;
  letter-spacing: 0.04em;
  transition: border-color 0.2s ease, color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease;
}

.step-copy {
  display: grid;
  min-width: 0;
  gap: 4px;
  margin-left: 10px;
}

.step-name {
  display: -webkit-box;
  overflow: hidden;
  color: inherit;
  font-size: var(--student-fs-body);
  font-weight: 800;
  line-height: 1.25;
  text-overflow: ellipsis;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
}

.step-action {
  color: #66b6d4;
  font-size: var(--student-fs-caption);
  font-weight: 800;
  letter-spacing: 0.06em;
  line-height: 1;
  transition: color 0.2s ease;
}

.step-connector {
  position: relative;
  flex: 0 1 40px;
  min-width: 18px;
  height: 2px;
  margin: 0 8px;
  overflow: visible;
  background: rgba(98, 169, 201, 0.34);
}

.step-connector::after {
  position: absolute;
  top: 50%;
  right: -1px;
  width: 6px;
  height: 6px;
  border-top: 1px solid #73b1ce;
  border-right: 1px solid #73b1ce;
  content: "";
  transform: translateY(-50%) rotate(45deg);
}

.step-tab.complete + .step-connector {
  background: linear-gradient(90deg, #6ef0e1, #1cb8e9);
  box-shadow: 0 0 9px rgba(53, 218, 235, 0.46);

  &::after {
    border-color: #63e6f1;
  }
}

.step-panel {
  min-width: 0;
}

.step-card {
  margin-bottom: 0;
}

.step-title-row {
  display: flex;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 14px;

  h3 {
    margin: 4px 0 0;
    color: #ffffff;
    font-size: var(--student-fs-h2);
    font-weight: 900;
    line-height: 1.3;
  }
}

.panel-title {
  padding-bottom: 14px;
  margin-bottom: 18px;
  border-bottom: 1px solid rgba(51, 169, 217, 0.38);
}

.panel-title span {
  color: #6eeaff;
  font-weight: 900;
}

.panel-title h4 {
  margin: 8px 0 0;
  color: #f8fcff;
  font-size: var(--student-fs-h1);
  line-height: 1.2;
}

.task-desc {
  margin: 14px 0 18px;
  color: #c7d8e6;
  font-size: var(--student-fs-body);
  line-height: 1.8;
}

.questionnaire-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 12px;
}

.hypothesis-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 18px 28px;
  margin-bottom: 20px;
}

.hypothesis-desc {
  margin: 0;
  color: #d9eaf4;
  font-size: var(--student-fs-h2);
  font-weight: 600;
}

.hypothesis-actions,
.kano-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
}

.hypothesis-actions :deep(.hypothesis-action),
.kano-actions :deep(.hypothesis-action),
.training-eight-action {
  min-width: 146px;
  height: 42px;
  border: 1px solid rgba(92, 224, 255, 0.7);
  border-radius: 10px;
  color: #ffffff;
  background: linear-gradient(95deg, #0b84bd, #096491);
  font-size: var(--student-fs-button-lg);
  font-weight: 800;
}

.hypothesis-actions :deep(.hypothesis-action--quiet),
.kano-actions :deep(.hypothesis-action--quiet) {
  border-color: rgba(115, 191, 220, 0.58);
  color: #d9f4ff;
  background: rgba(13, 85, 117, 0.72);
}

.training-eight-action {
  grid-column: 2;
  grid-row: 1;
  min-width: 136px;
}

.target-hypothesis-table-wrap {
  overflow-x: auto;
  border: 1px solid rgba(0, 180, 255, 0.24);
  border-radius: 18px;
  background: rgba(1, 14, 26, 0.72);
}

.target-hypothesis-table {
  width: 100%;
  min-width: 920px;
  border-collapse: collapse;
  table-layout: fixed;

  th,
  td {
    padding: 12px;
    border-right: 1px solid rgba(77, 167, 220, 0.26);
    border-bottom: 1px solid rgba(77, 167, 220, 0.26);
    vertical-align: middle;
  }

  th {
    color: #ecfbff;
    background: linear-gradient(100deg, #158fc4, #08739f);
    font-size: var(--student-fs-h2);
    font-weight: 800;
  }

  th:nth-child(1) { width: 28%; }
  th:nth-child(2) { width: 28%; }
  th:nth-child(3) { width: 44%; }

  tr:last-child td { border-bottom: 0; }
  th:last-child,
  td:last-child { border-right: 0; }
}

.hypothesis-input,
.hypothesis-textarea {
  box-sizing: border-box;
  width: 100%;
  border: 1px solid rgba(67, 134, 166, 0.8);
  outline: none;
  color: #eaf7ff;
  background: rgba(7, 29, 43, 0.92);
  font-family: inherit;
  font-size: var(--student-fs-body);
  line-height: 1.65;

  &::placeholder { color: #8da5b2; opacity: 1; }
  &:focus {
    border-color: #5fe7ff;
    box-shadow: 0 0 0 3px rgba(34, 207, 255, 0.14);
  }
}

.hypothesis-input {
  height: 42px;
  padding: 0 12px;
  border-radius: 10px;
}

.hypothesis-textarea {
  min-height: 86px;
  padding: 10px 12px;
  border-radius: 10px;
  resize: vertical;
}

.hypothesis-tip {
  margin: 12px 0 0;
  color: #75dff7;
  font-size: var(--student-fs-body-sm);
}

.kano-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px 28px;
  margin-bottom: 20px;
}

.kano-desc {
  max-width: 780px;
  margin: 0;
  color: #d9eaf4;
  font-size: var(--student-fs-h2);
  font-weight: 600;
}

.kano-table-wrap {
  overflow-x: auto;
  border: 1px solid rgba(0, 180, 255, 0.24);
  border-radius: 18px;
  background: rgba(1, 14, 26, 0.72);
}

.kano-table {
  width: 100%;
  min-width: 980px;
  border-collapse: collapse;
  table-layout: fixed;

  th,
  td {
    padding: 10px 12px;
    border-right: 1px solid rgba(77, 167, 220, 0.26);
    border-bottom: 1px solid rgba(77, 167, 220, 0.26);
    vertical-align: middle;
  }

  th {
    color: #ecfbff;
    background: linear-gradient(100deg, #158fc4, #08739f);
    font-size: var(--student-fs-h2);
    font-weight: 800;
  }

  th:nth-child(1) { width: 9%; }
  th:nth-child(2) { width: 42%; }
  th:nth-child(3) { width: 25%; }
  th:nth-child(4) { width: 24%; }

  tr:last-child td { border-bottom: 0; }
  th:last-child,
  td:last-child { border-right: 0; }
}

.kano-index {
  color: #83e9ff;
  font-weight: 800;
  text-align: center;
}

.kano-textarea {
  min-height: 58px;
}

.kano-select-cell {
  text-align: center;
}

.kano-select {
  width: min(100%, 190px);
}

.kano-select :deep(.el-select__wrapper) {
  min-height: 42px;
  border: 1px solid rgba(67, 134, 166, 0.8);
  border-radius: 10px;
  box-shadow: none;
  color: #eaf7ff;
  background: rgba(7, 29, 43, 0.92);
}

.kano-select :deep(.el-select__placeholder) {
  color: #8da5b2;
}

.questionnaire-design-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 18px 28px;
  margin-bottom: 20px;
}

.questionnaire-design-desc {
  max-width: 820px;
  margin: 0;
  color: #d9eaf4;
  font-size: var(--student-fs-h2);
  font-weight: 600;
}

.questionnaire-import-action,
.questionnaire-editor-launcher__action {
  min-width: 178px;
  height: 44px;
  border: 1px solid rgba(92, 224, 255, 0.7);
  border-radius: 10px;
  color: #ffffff;
  background: linear-gradient(95deg, #0b84bd, #096491);
  font-size: var(--student-fs-button-lg);
  font-weight: 800;
}

.questionnaire-imported-file {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  max-width: 100%;
  min-height: 42px;
  padding: 0 13px;
  margin-bottom: 18px;
  border: 1px solid rgba(87, 215, 255, 0.4);
  border-radius: 12px;
  color: #dff9ff;
  background: rgba(10, 97, 137, 0.28);

  span {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  button {
    flex: 0 0 auto;
    border: 0;
    color: #75e5ff;
    background: transparent;
    cursor: pointer;
    font-weight: 800;
  }
}

.questionnaire-editor-launcher {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  min-height: 190px;
  padding: 32px 40px;
  overflow: hidden;
  border: 1px solid rgba(54, 195, 243, 0.36);
  border-radius: 20px;
  background:
    radial-gradient(circle at 86% 18%, rgba(31, 207, 255, 0.22), transparent 34%),
    linear-gradient(115deg, rgba(7, 59, 87, 0.94), rgba(2, 20, 34, 0.9));
}

.questionnaire-editor-launcher__copy {
  position: relative;
  z-index: 1;

  h4 {
    margin: 7px 0;
    color: #ffffff;
    font-size: 23px;
  }

  p {
    max-width: 600px;
    margin: 0;
    color: #b6d1df;
    line-height: 1.7;
  }
}

.questionnaire-editor-launcher__action {
  flex: 0 0 auto;
  min-width: 170px;
  height: 52px;
}

.questionnaire-editor-summary {
  margin: 13px 0 0;
  color: #72deff;
  font-size: var(--student-fs-body-sm);
}

:deep(.questionnaire-editor-dialog .el-dialog),
:deep(.questionnaire-preview-dialog .el-dialog) {
  overflow: hidden;
  border: 1px solid rgba(70, 200, 247, 0.35);
  border-radius: 18px;
  color: #e7f8ff;
  background: #061724;
}

:deep(.questionnaire-editor-dialog .el-dialog__title),
:deep(.questionnaire-preview-dialog .el-dialog__title) {
  color: #ffffff;
  font-weight: 800;
}

.questionnaire-editor-dialog__intro {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  margin-bottom: 18px;

  p {
    margin: 0;
    color: #b9d3e0;
    line-height: 1.7;
  }
}

.questionnaire-editor-add {
  flex: 0 0 auto;
  border-color: rgba(92, 224, 255, 0.7);
  color: #ffffff;
  background: linear-gradient(95deg, #0b84bd, #096491);
}

.questionnaire-question-list {
  display: grid;
  gap: 12px;
  max-height: min(58vh, 700px);
  padding-right: 5px;
  overflow: auto;
}

.questionnaire-question-card {
  display: grid;
  grid-template-columns: 36px minmax(0, 1fr) auto;
  gap: 12px;
  align-items: start;
  padding: 14px;
  border: 1px solid rgba(67, 144, 184, 0.34);
  border-radius: 14px;
  background: rgba(13, 45, 63, 0.66);
}

.questionnaire-question-card__number {
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border: 1px solid rgba(80, 222, 255, 0.45);
  border-radius: 50%;
  color: #74e5ff;
  font-size: var(--student-fs-caption);
  font-weight: 800;
}

.questionnaire-question-card__fields {
  display: grid;
  grid-template-columns: 180px 180px minmax(0, 1fr);
  gap: 10px;

  :deep(.el-select__wrapper),
  :deep(.el-input__wrapper) {
    min-height: 38px;
    border: 1px solid rgba(67, 134, 166, 0.8);
    box-shadow: none;
    color: #eaf7ff;
    background: rgba(5, 26, 39, 0.9);
  }

  :deep(.el-input__inner) { color: #eaf7ff; }
}

.likert-tip {
  grid-column: 1 / -1;
  margin: 0;
  color: #7ce0f8;
  font-size: var(--student-fs-caption);
}

.questionnaire-question-card__remove {
  padding: 8px 10px;
  border: 1px solid rgba(104, 161, 187, 0.5);
  border-radius: 8px;
  color: #bddfeb;
  background: transparent;
  cursor: pointer;

  &:disabled {
    cursor: not-allowed;
    opacity: 0.45;
  }
}

.questionnaire-word-preview {
  max-height: min(62vh, 760px);
  padding: 20px;
  overflow: auto;
  border: 1px solid rgba(77, 167, 220, 0.28);
  border-radius: 12px;
  color: #e2f3fa;
  background: rgba(3, 25, 38, 0.86);
  white-space: pre-wrap;
  line-height: 1.85;
}

.questionnaire-preview-empty {
  color: #b9d3e0;
}

.survey-report-desc {
  max-width: 1050px;
  margin-bottom: 24px;
}

.survey-report-table-wrap {
  overflow-x: auto;
  border: 1px solid rgba(65, 169, 214, 0.52);
  border-radius: 16px;
  background: rgba(2, 23, 36, 0.56);
}

.survey-report-table {
  width: 100%;
  min-width: 760px;
  border-collapse: collapse;

  th,
  td {
    border: 1px solid rgba(77, 148, 183, 0.5);
  }

  th {
    padding: 14px 18px;
    color: #e9fbff;
    background: rgba(9, 111, 157, 0.68);
    font-size: var(--student-fs-body);
    letter-spacing: 0.04em;
  }

  th:first-child,
  td:first-child {
    width: 22%;
  }

  td {
    padding: 10px;
    background: rgba(5, 31, 47, 0.42);
  }
}

.survey-report-title-input,
.survey-report-content-input {
  display: block;
  width: 100%;
  border: 0;
  outline: 0;
  color: #e7f8ff;
  background: transparent;
  font: inherit;

  &::placeholder {
    color: #668a9b;
  }
}

.survey-report-title-input {
  min-height: 88px;
  padding: 8px;
  text-align: center;
  font-weight: 700;
}

.survey-report-content-input {
  min-height: 88px;
  padding: 8px 12px;
  resize: vertical;
  line-height: 1.75;
}

.survey-report-guide {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 28px;
  margin-top: 26px;
  padding: 20px 22px;
  border: 1px solid rgba(69, 164, 207, 0.27);
  border-radius: 14px;
  color: #b8d2de;
  background: linear-gradient(105deg, rgba(6, 48, 69, 0.75), rgba(5, 24, 38, 0.52));

  h5,
  p {
    margin: 0;
    line-height: 1.85;
  }

  h5 {
    color: #ffffff;
    font-size: var(--student-fs-body);
  }
}

.survey-report-template-action {
  flex: 0 0 auto;
  min-width: 146px;
  min-height: 42px;
}

.questionnaire-desc {
  flex: 1;
  margin: 0;
}

.questionnaire-upload {
  min-width: 0;
}

.questionnaire-file {
  margin-bottom: 10px;
}

.questionnaire-field {
  margin-top: 0;
}

.large-textarea.questionnaire-textarea {
  height: 920px;
  min-height: 920px;
  white-space: pre-wrap;
  overflow: auto;
}

.questionnaire-textarea[contenteditable="true"] {
  resize: none;
  white-space: normal;
}

.questionnaire-textarea[contenteditable="true"]:empty::before {
  color: #8fa8b8;
  content: attr(data-placeholder);
}

.questionnaire-textarea :deep(h4) {
  margin: 0 0 26px;
  color: #f4fbff;
  font-size: var(--student-fs-h1);
  font-weight: 900;
}

.questionnaire-textarea :deep(p) {
  margin: 0 0 10px;
}

.questionnaire-textarea :deep(strong) {
  display: inline-block;
  margin-top: 16px;
  color: #f4fbff;
  font-size: var(--student-fs-h2);
}

.questionnaire-textarea :deep(table) {
  width: min(820px, 100%);
  margin: 10px 0 24px;
  border-collapse: collapse;
  color: #e7f5ff;
  background: rgba(1, 14, 26, 0.72);
  font-size: var(--student-fs-body);
  table-layout: fixed;
}

.questionnaire-textarea :deep(th),
.questionnaire-textarea :deep(td) {
  height: 38px;
  padding: 6px 10px;
  border: 1px solid rgba(0, 180, 255, 0.22);
  text-align: left;
  vertical-align: middle;
}

.questionnaire-textarea :deep(th) {
  color: #dff5ff;
  background: rgba(8, 55, 82, 0.98);
  font-weight: 900;
}

.questionnaire-textarea :deep(th:first-child),
.questionnaire-textarea :deep(td:first-child) {
  width: 180px;
  font-weight: 800;
}

.field-block {
  display: block;
  margin-top: 18px;
}

.field-block > span {
  display: block;
  margin-bottom: 10px;
  color: #f1f8ff;
  font-size: var(--student-fs-body);
  font-weight: 900;
}

.large-textarea {
  width: 100%;
  min-height: 180px;
  padding: 16px 18px;
  border: 1px solid rgba(45, 95, 126, 0.95);
  border-radius: 14px;
  outline: none;
  resize: vertical;
  color: #eef5ff;
  background: #0f1a24;
  font-size: var(--student-fs-body);
  line-height: 1.7;
  transition: box-shadow 0.16s ease, border-color 0.16s ease;
}

.large-textarea::placeholder {
  color: #8fa8b8;
  opacity: 0.9;
}

.large-textarea:focus {
  border-color: rgba(102, 235, 255, 0.9);
  box-shadow: inset 0 0 0 1px rgba(102, 235, 255, 0.42), 0 0 20px rgba(0, 159, 220, 0.16);
}

.file-input {
  display: none;
}

.upload-row {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px;
  margin-top: 18px;
}

.upload-action,
.mini-upload {
  min-height: 40px;
  padding: 0 18px;
  border: 1px solid rgba(92, 224, 255, 0.7);
  border-radius: 999px;
  color: #ffffff;
  background: linear-gradient(95deg, #0b84bd, #096491);
  font-weight: 800;
}

.file-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  max-width: 100%;
  padding: 8px 12px;
  border: 1px solid rgba(95, 232, 255, 0.38);
  border-radius: 999px;
  color: #9fe8ff;
  background: rgba(1, 14, 26, 0.72);
  font-size: var(--student-fs-body-sm);
  font-weight: 700;

  span {
    overflow-wrap: anywhere;
  }
}

.data-board {
  padding: 16px;
  border: 1px solid rgba(0, 180, 255, 0.22);
  border-radius: 22px;
  background: rgba(1, 14, 26, 0.72);
}

.data-board pre {
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  color: #d7ecff;
  font-family: inherit;
  font-size: var(--student-fs-body);
  line-height: 1.78;
}

.visual-group {
  margin-top: 22px;
}

.visual-group h5 {
  margin: 0 0 12px;
  color: #f1f8ff;
  font-size: var(--student-fs-h2);
}

.analysis-heading {
  margin: 28px 0 16px;
  color: #f1f8ff;
  font-size: var(--student-fs-h2);
  font-weight: 900;
  line-height: 1.8;
}

:deep(.report-fields) {
  display: grid;
  gap: 18px;
}

:deep(.report-fields .field-block) {
  display: block;
  width: 100%;
  margin-top: 0;
}

:deep(.report-fields .field-block > span) {
  display: block;
  margin-bottom: 8px;
  color: #f1f8ff;
  font-size: var(--student-fs-body);
  font-weight: 900;
}

:deep(.report-fields .large-textarea) {
  display: block;
  width: 100%;
  min-height: 132px;
  padding: 14px 16px;
  border: 1px solid rgba(45, 95, 126, 0.95);
  border-radius: 14px;
  outline: none;
  resize: vertical;
  color: #eef5ff;
  background: #0f1a24;
  font-family: inherit;
  font-size: var(--student-fs-body);
  line-height: 1.7;
  box-sizing: border-box;
}

:deep(.report-fields .large-textarea:placeholder-shown) {
  color: #cbd4dc;
}

:deep(.report-fields .large-textarea:focus) {
  border-color: rgba(102, 235, 255, 0.9);
  box-shadow: inset 0 0 0 1px rgba(102, 235, 255, 0.42), 0 0 20px rgba(0, 159, 220, 0.16);
}

:deep(.report-fields .large-textarea::placeholder) {
  color: #cbd4dc;
  opacity: 1;
}

.visual-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 14px;
}

.visual-card {
  min-height: 120px;
  padding: 16px;
  border: 1px solid rgba(0, 180, 255, 0.22);
  border-radius: 20px;
  background: rgba(1, 14, 26, 0.72);
}

.visual-card span {
  display: block;
  margin-bottom: 14px;
  color: #e8f8ff;
  font-weight: 900;
}

.visual-card small {
  display: block;
  margin-top: 10px;
  color: #9fdced;
  word-break: break-all;
}

.step-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
  margin-top: 22px;
  margin-bottom: 36px;
}

.nav-action {
  min-height: 40px;
  padding: 0 18px;
  border-color: rgba(99, 217, 255, 0.55);
  border-radius: 999px;
  color: #e9fbff;
  background: rgba(17, 126, 178, 0.36);
  font-size: var(--student-fs-button);
  font-weight: 800;
}

.nav-action--next {
  border-color: rgba(92, 224, 255, 0.7);
  color: #ffffff;
  background: linear-gradient(95deg, #0b84bd, #096491);
}

.nav-action--save {
  border-color: rgba(92, 224, 255, 0.7);
  color: #ffffff;
  background: linear-gradient(95deg, #0b84bd, #096491);
}

.nav-action.is-disabled {
  opacity: 0.45;
}

.training-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 52px;
  margin-top: 36px;
}

.training-actions :deep(.training-action) {
  min-width: 172px;
  height: 64px;
  padding: 0 28px;
  border: 1px solid #2c83aa;
  border-radius: 6px;
  color: #dff7ff;
  background: rgba(13, 64, 88, 0.62);
  box-shadow: none;
  font-size: var(--student-fs-h1);
  font-weight: 900;
  line-height: 1;
  letter-spacing: 0;
  text-shadow: none;
}

.training-actions :deep(.training-action span) {
  display: inline-flex;
  align-items: center;
  color: inherit;
  font-size: inherit;
  line-height: 1;
}

.training-actions :deep(.training-action--submit),
.training-actions :deep(.training-action--reset) {
  border-color: #2c83aa;
  color: #dff7ff;
  background: rgba(13, 64, 88, 0.62);
}

.training-actions :deep(.training-action:hover:not(.is-disabled)) {
  border-color: #46b5e7;
  color: #ffffff;
  background: rgba(18, 85, 116, 0.78);
}

@media (max-width: 1200px) {
  .consumer-behavior-page {
    grid-template-columns: 1fr;
  }

  .visual-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 900px) {
  .consumer-behavior-page {
    padding: 14px 14px 18px;
  }

  .training-core {
    padding: 18px;
    border-radius: 24px;
  }

  .workbench-head,
  .workbench-actions,
  .step-title-row,
  .step-actions,
  .training-actions {
    flex-direction: column;
    align-items: stretch;
  }

  .workbench-actions :deep(.material-download),
  .workbench-actions .outline-action {
    width: 100%;
  }

  .hypothesis-head {
    grid-template-columns: 1fr;
  }

  .training-eight-action {
    grid-column: auto;
    grid-row: auto;
    width: 100%;
  }

  .hypothesis-actions,
  .kano-actions {
    justify-content: stretch;
  }

  .hypothesis-actions :deep(.hypothesis-action),
  .kano-actions :deep(.hypothesis-action) {
    flex: 1;
  }

  .kano-head {
    align-items: stretch;
    flex-direction: column;
  }

  .questionnaire-design-head,
  .questionnaire-editor-launcher,
  .questionnaire-editor-dialog__intro {
    align-items: stretch;
    flex-direction: column;
  }

  .questionnaire-import-action,
  .questionnaire-editor-launcher__action {
    width: 100%;
  }

  .questionnaire-editor-launcher {
    padding: 26px;
  }

  .questionnaire-question-card {
    grid-template-columns: 32px minmax(0, 1fr);
  }

  .questionnaire-question-card__fields {
    grid-template-columns: 1fr;
  }

  .questionnaire-question-card__remove {
    grid-column: 2;
    justify-self: end;
  }

  .survey-report-guide {
    flex-direction: column;
  }

  .survey-report-template-action {
    width: 100%;
  }

  .step-indicator {
    align-items: stretch;
    flex-direction: column;
    width: 100%;
    margin-right: 0;
    margin-left: 0;
    overflow: visible;
    border-radius: 20px;
  }

  .step-tab {
    flex: 0 0 auto;
    width: 100%;
  }

  .step-connector {
    flex: 0 0 22px;
    width: 2px;
    height: 22px;
    margin-left: 29px;
    text-align: center;
    writing-mode: vertical-rl;
  }

  .step-actions :deep(.nav-action),
  .training-actions :deep(.training-action) {
    width: 100%;
  }
}

@media (max-width: 760px) {
  .training-core,
  .task-card,
  .step-card {
    padding: 18px;
  }

  .questionnaire-head {
    flex-direction: column;
  }

  .questionnaire-upload {
    width: 100%;
  }

  .training-actions {
    gap: 14px;
  }

  .training-actions :deep(.training-action) {
    width: 100%;
  }

  .visual-grid {
    grid-template-columns: 1fr;
  }
}
.workbench-head--actions-only {
  justify-content: flex-end;
  margin-bottom: 18px;
  padding-bottom: 0;
  border-bottom: 0;
}
</style>

