SurveyVista/Web/Areas/Admin/Views/SurveyAnalysis/AnalyzeQuestionnaire.cshtml
2026-03-07 02:37:33 +01:00

550 lines
39 KiB
Text

@* Views/Admin/SurveyAnalysis/AnalyzeQuestionnaire.cshtml *@
@model Services.AIViewModel.QuestionnaireAnalysisOverview
@{
ViewData["Title"] = $"AI Analysis — {Model.QuestionnaireTitle}";
}
@section Styles {
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" />
<style>
@@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Space+Grotesk:wght@300;400;500;600;700&display=swap');
:root {
--neon-blue:#60a5fa;--neon-purple:#c084fc;--neon-green:#34d399;--neon-pink:#f472b6;
--neon-yellow:#fbbf24;--neon-red:#f87171;--neon-cyan:#22d3ee;--neon-indigo:#818cf8;
--neon-teal:#33b3ae;--neon-amber:#f59e0b;
--dark-900:#0f172a;--dark-800:#1e293b;--dark-700:#334155;--dark-600:#475569;
--dark-500:#64748b;--dark-400:#94a3b8;--dark-300:#cbd5e1;--dark-200:#e2e8f0;
--glass-bg:rgba(255,255,255,0.04);--glass-border:rgba(255,255,255,0.08);
--font-main:'Space Grotesk',sans-serif;--font-mono:'JetBrains Mono',monospace;
}
*{margin:0;padding:0;box-sizing:border-box}
body{font-family:var(--font-main);background:var(--dark-900);color:#e2e8f0;overflow-x:hidden}
/* ===== ANIMATED BG ===== */
.nex-bg{position:fixed;inset:0;z-index:-1;overflow:hidden}
.nex-bg .grid{position:absolute;inset:0;background-image:linear-gradient(rgba(96,165,250,0.04) 1px,transparent 1px),linear-gradient(90deg,rgba(96,165,250,0.04) 1px,transparent 1px);background-size:60px 60px;animation:gridDrift 25s linear infinite}
.nex-bg .mesh{position:absolute;inset:0;background:radial-gradient(ellipse at 25% 20%,rgba(96,165,250,0.06) 0%,transparent 55%),radial-gradient(ellipse at 75% 60%,rgba(192,132,252,0.05) 0%,transparent 55%),radial-gradient(ellipse at 50% 90%,rgba(52,211,153,0.04) 0%,transparent 55%);animation:meshFloat 18s ease-in-out infinite}
@@keyframes gridDrift{0%{transform:translate(0,0)}100%{transform:translate(60px,60px)}}
@@keyframes meshFloat{0%,100%{filter:hue-rotate(0deg);transform:scale(1)}50%{filter:hue-rotate(15deg);transform:scale(1.02)}}
@@keyframes pulse{0%,100%{opacity:1;transform:scale(1)}50%{opacity:.6;transform:scale(1.12)}}
@@keyframes fadeInUp{from{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}
@@keyframes shimmer{0%{transform:translateX(-100%)}100%{transform:translateX(100%)}}
@@keyframes barGrow{from{width:0}to{width:var(--w)}}
.container{max-width:1400px;margin:0 auto;padding:0 2rem}
/* ===== HEADER ===== */
.page-header{position:relative;z-index:10;padding:2rem 0 1.5rem;border-bottom:1px solid rgba(129,140,248,0.1)}
.breadcrumb-nex{display:flex;align-items:center;gap:.8rem;margin-bottom:1.8rem;font-family:var(--font-mono);font-size:.7rem;letter-spacing:.08em}
.breadcrumb-nex a{color:var(--dark-400);text-decoration:none;display:flex;align-items:center;gap:.5rem;transition:color .2s}
.breadcrumb-nex a:hover{color:var(--neon-indigo)}
.breadcrumb-nex .sep{color:var(--dark-600);font-size:.55rem}
.breadcrumb-nex .current{color:var(--neon-indigo);font-weight:600}
.header-row{display:flex;justify-content:space-between;align-items:flex-start;gap:2rem}
.header-left{flex:1}
.header-badge{display:inline-flex;align-items:center;gap:.5rem;padding:.4rem 1rem;background:rgba(129,140,248,0.08);border:1px solid rgba(129,140,248,0.2);border-radius:50px;margin-bottom:1.5rem;font-family:var(--font-mono);font-size:.6rem;font-weight:600;letter-spacing:.1em;color:var(--neon-indigo)}
.header-badge .dot{width:6px;height:6px;background:var(--neon-green);border-radius:50%;animation:pulse 2s infinite}
.header-title{font-size:2.8rem;font-weight:700;line-height:1.1;margin-bottom:.8rem;color:#fff}
.header-title .grad{background:linear-gradient(135deg,var(--neon-blue),var(--neon-purple),var(--neon-pink));-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}
.header-sub{font-size:1rem;color:var(--dark-300);line-height:1.6;max-width:550px}
.header-sub .q-name{color:var(--neon-indigo);font-weight:600}
.header-actions{display:flex;flex-wrap:wrap;gap:.7rem;align-items:flex-start;padding-top:.5rem}
.h-btn{display:flex;align-items:center;gap:.6rem;padding:.65rem 1.2rem;border-radius:10px;text-decoration:none;font-family:var(--font-mono);font-size:.68rem;font-weight:600;letter-spacing:.04em;transition:all .25s;border:1px solid}
.h-btn:hover{transform:translateY(-2px);text-decoration:none}
.h-btn.pri{background:linear-gradient(135deg,var(--neon-indigo),var(--neon-purple));border-color:transparent;color:#fff}
.h-btn.pri:hover{box-shadow:0 12px 28px rgba(129,140,248,0.25);color:#fff}
.h-btn.sec{background:rgba(255,255,255,0.04);border-color:rgba(255,255,255,0.1);color:var(--dark-300)}
.h-btn.sec:hover{background:rgba(129,140,248,0.08);border-color:rgba(129,140,248,0.25);color:var(--neon-indigo)}
.h-btn.danger{background:rgba(248,113,113,0.08);border-color:rgba(248,113,113,0.25);color:var(--neon-red)}
.h-btn.danger:hover{background:rgba(248,113,113,0.15);color:var(--neon-red)}
.h-btn i{font-size:.8rem}
/* ===== METRICS ===== */
.metrics-section{position:relative;z-index:10;padding:2.5rem 0}
.metrics-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1.2rem}
.m-card{background:rgba(30,41,59,0.45);backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.07);border-radius:16px;padding:1.8rem;position:relative;overflow:hidden;transition:all .3s;animation:fadeInUp .5s ease both}
.m-card:nth-child(2){animation-delay:.1s}.m-card:nth-child(3){animation-delay:.2s}.m-card:nth-child(4){animation-delay:.3s}
.m-card:hover{transform:translateY(-4px);border-color:rgba(129,140,248,0.3)}
.m-card .glow{position:absolute;top:0;left:0;right:0;height:2px;opacity:0;transition:opacity .3s}
.m-card:hover .glow{opacity:1}
.m-card.c1 .glow{background:linear-gradient(90deg,var(--neon-indigo),var(--neon-cyan))}
.m-card.c2 .glow{background:linear-gradient(90deg,var(--neon-purple),var(--neon-pink))}
.m-card.c3 .glow{background:linear-gradient(90deg,var(--neon-green),var(--neon-teal))}
.m-card.c4 .glow{background:linear-gradient(90deg,var(--neon-red),var(--neon-amber))}
.m-icon{width:48px;height:48px;border-radius:12px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:1.2rem;margin-bottom:1.2rem}
.m-card.c1 .m-icon{background:linear-gradient(135deg,var(--neon-indigo),var(--neon-blue))}
.m-card.c2 .m-icon{background:linear-gradient(135deg,var(--neon-purple),var(--neon-pink))}
.m-card.c3 .m-icon{background:linear-gradient(135deg,var(--neon-green),var(--neon-teal))}
.m-card.c4 .m-icon{background:linear-gradient(135deg,var(--neon-red),var(--neon-amber))}
.m-val{font-size:2.2rem;font-weight:700;color:#fff;line-height:1;margin-bottom:.4rem}
.m-lbl{font-family:var(--font-mono);font-size:.6rem;font-weight:600;letter-spacing:.1em;color:var(--dark-400);text-transform:uppercase}
.m-card .pulse-dot{position:absolute;top:1.2rem;right:1.2rem;width:10px;height:10px;background:var(--neon-red);border-radius:50%;animation:pulse 1.5s infinite}
.m-card .orb{position:absolute;bottom:-15px;right:-15px;width:60px;height:60px;border-radius:50%;opacity:.08}
.m-card.c1 .orb{background:var(--neon-indigo)}.m-card.c2 .orb{background:var(--neon-purple)}
.m-card.c3 .orb{background:var(--neon-green)}.m-card.c4 .orb{background:var(--neon-red)}
/* ===== CARDS ===== */
.dash-section{position:relative;z-index:10;padding:1.5rem 0}
.dash-grid{display:grid;grid-template-columns:1fr 1fr;gap:1.5rem}
.nex-card{background:rgba(30,41,59,0.45);backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.07);border-radius:18px;overflow:hidden;position:relative;transition:all .3s}
.nex-card:hover{border-color:rgba(129,140,248,0.25)}
.nex-card .top-glow{position:absolute;top:0;left:0;right:0;height:2px;background:linear-gradient(90deg,var(--neon-indigo),var(--neon-purple));opacity:0;transition:opacity .3s}
.nex-card:hover .top-glow{opacity:1}
.c-head{padding:1.8rem 1.8rem 1rem;display:flex;align-items:center;gap:1.2rem}
.c-icon{width:44px;height:44px;border-radius:12px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:1.1rem;flex-shrink:0}
.c-icon.risk{background:linear-gradient(135deg,var(--neon-red),var(--neon-amber))}
.c-icon.sent{background:linear-gradient(135deg,var(--neon-green),var(--neon-teal))}
.c-icon.issue{background:linear-gradient(135deg,var(--neon-indigo),var(--neon-purple))}
.c-icon.theme{background:linear-gradient(135deg,var(--neon-amber),var(--neon-yellow))}
.c-head h3{font-size:1.1rem;font-weight:700;color:#fff;margin-bottom:.2rem}
.c-head p{color:var(--dark-400);font-size:.78rem}
.c-body{padding:0 1.8rem 1.8rem}
/* ===== RISK BARS ===== */
.risk-row{background:rgba(255,255,255,0.025);border:1px solid rgba(255,255,255,0.06);border-radius:12px;padding:1.1rem 1.2rem;margin-bottom:.8rem;transition:all .2s}
.risk-row:last-child{margin-bottom:0}
.risk-row:hover{background:rgba(255,255,255,0.04);transform:translateX(4px)}
.risk-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:.7rem}
.risk-left{display:flex;align-items:center;gap:.8rem}
.risk-dot{width:10px;height:10px;border-radius:50%;flex-shrink:0}
.risk-dot.low{background:var(--neon-green);box-shadow:0 0 8px rgba(52,211,153,0.4)}
.risk-dot.mod{background:var(--neon-yellow);box-shadow:0 0 8px rgba(251,191,36,0.4)}
.risk-dot.high{background:var(--neon-red);box-shadow:0 0 8px rgba(248,113,113,0.4)}
.risk-dot.crit{background:#dc2626;box-shadow:0 0 8px rgba(220,38,38,0.5)}
.risk-name{font-weight:600;color:#fff;font-size:.9rem}
.risk-cnt{font-family:var(--font-mono);font-weight:700;color:var(--dark-300);background:rgba(255,255,255,0.05);padding:.2rem .7rem;border-radius:6px;font-size:.75rem;min-width:32px;text-align:center}
.risk-bar{height:8px;background:rgba(255,255,255,0.06);border-radius:4px;overflow:hidden;margin-bottom:.4rem}
.risk-fill{height:100%;border-radius:4px;position:relative;overflow:hidden;animation:barGrow .8s ease both}
.risk-fill::after{content:'';position:absolute;inset:0;background:linear-gradient(90deg,transparent,rgba(255,255,255,0.15),transparent);animation:shimmer 2.5s infinite}
.risk-fill.low{background:linear-gradient(90deg,var(--neon-green),var(--neon-cyan))}
.risk-fill.mod{background:linear-gradient(90deg,var(--neon-yellow),#fb923c)}
.risk-fill.high{background:linear-gradient(90deg,var(--neon-red),var(--neon-amber))}
.risk-fill.crit{background:linear-gradient(90deg,#dc2626,#991b1b)}
.risk-pct{font-family:var(--font-mono);font-size:.65rem;font-weight:600;color:var(--dark-400);text-align:right}
.risk-alert{display:flex;align-items:center;gap:1rem;padding:.9rem 1.2rem;background:rgba(248,113,113,0.06);border:1px solid rgba(248,113,113,0.2);border-radius:10px;margin-top:1rem;position:relative;overflow:hidden}
.risk-alert::before{content:'';position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--neon-red)}
.risk-alert-icon{color:var(--neon-red);font-size:1rem;margin-left:.5rem}
.risk-alert-lbl{font-family:var(--font-mono);font-size:.55rem;font-weight:700;letter-spacing:.1em;color:var(--neon-red);margin-bottom:.15rem}
.risk-alert-txt{font-size:.78rem;color:var(--dark-300)}
.risk-alert-txt a{color:var(--neon-indigo);text-decoration:none;font-weight:600}
.risk-alert-txt a:hover{text-decoration:underline}
/* ===== SENTIMENT ===== */
.sent-row{background:rgba(255,255,255,0.025);border:1px solid rgba(255,255,255,0.06);border-radius:12px;padding:1.1rem 1.2rem;margin-bottom:.8rem;transition:all .2s}
.sent-row:last-child{margin-bottom:0}
.sent-row:hover{background:rgba(255,255,255,0.04)}
.sent-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:.7rem}
.sent-left{display:flex;align-items:center;gap:.8rem}
.sent-icon{font-size:1rem}
.sent-icon.pos{color:var(--neon-green)}.sent-icon.neu{color:var(--dark-400)}.sent-icon.neg{color:var(--neon-red)}
.sent-name{font-weight:600;color:#fff;font-size:.9rem}
.sent-pct{font-family:var(--font-mono);font-weight:700;color:var(--dark-300);font-size:.85rem}
.sent-bar{height:8px;background:rgba(255,255,255,0.06);border-radius:4px;overflow:hidden}
.sent-fill{height:100%;border-radius:4px;animation:barGrow .8s ease both}
.sent-fill.pos{background:linear-gradient(90deg,var(--neon-green),var(--neon-cyan))}
.sent-fill.neu{background:linear-gradient(90deg,var(--dark-500),var(--dark-400))}
.sent-fill.neg{background:linear-gradient(90deg,var(--neon-red),var(--neon-amber))}
.sent-verdict{display:flex;align-items:center;gap:1rem;padding:1rem 1.2rem;border-radius:10px;border:1px solid;margin-top:1rem}
.sent-verdict.good{background:rgba(52,211,153,0.06);border-color:rgba(52,211,153,0.2)}
.sent-verdict.ok{background:rgba(251,191,36,0.06);border-color:rgba(251,191,36,0.2)}
.sent-verdict.bad{background:rgba(248,113,113,0.06);border-color:rgba(248,113,113,0.2)}
.verdict-icon{font-size:1.1rem}
.sent-verdict.good .verdict-icon{color:var(--neon-green)}
.sent-verdict.ok .verdict-icon{color:var(--neon-yellow)}
.sent-verdict.bad .verdict-icon{color:var(--neon-red)}
.verdict-txt{font-weight:600;color:#fff;font-size:.85rem}
/* ===== EXECUTIVE SUMMARY ===== */
.summary-section{position:relative;z-index:10;padding:1.5rem 0}
.summary-card{background:rgba(30,41,59,0.45);backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.07);border-radius:18px;overflow:hidden}
.summary-head{background:linear-gradient(135deg,rgba(30,41,59,0.95),rgba(51,65,85,0.95));padding:1.5rem 2rem;display:flex;align-items:center;gap:1.2rem;border-bottom:1px solid rgba(129,140,248,0.15);position:relative}
.summary-head::before{content:'';position:absolute;inset:0;background:linear-gradient(135deg,rgba(129,140,248,0.08) 0%,transparent 60%)}
.summary-head-icon{width:44px;height:44px;background:linear-gradient(135deg,var(--neon-indigo),var(--neon-purple));border-radius:10px;display:flex;align-items:center;justify-content:center;color:#fff;font-size:1.1rem;position:relative;z-index:2;flex-shrink:0}
.summary-head h3{font-family:var(--font-mono);font-size:.95rem;font-weight:700;letter-spacing:.05em;color:#e2e8f0;position:relative;z-index:2}
.summary-head p{font-size:.75rem;color:var(--dark-400);position:relative;z-index:2}
.summary-body{padding:2rem}
/* Rendered markdown styles */
.md-content{font-size:.92rem;line-height:1.8;color:var(--dark-200)}
.md-content h1,.md-content h2{font-family:var(--font-mono);font-weight:700;letter-spacing:.05em;color:var(--neon-indigo);margin:2rem 0 1rem;padding-bottom:.6rem;border-bottom:1px solid rgba(129,140,248,0.15);font-size:1rem}
.md-content h1:first-child,.md-content h2:first-child{margin-top:0}
.md-content h3{font-family:var(--font-mono);font-weight:700;letter-spacing:.04em;color:#fff;margin:1.5rem 0 .8rem;font-size:.9rem}
.md-content p{margin-bottom:1rem;color:var(--dark-200)}
.md-content strong{color:#fff;font-weight:700}
.md-content ul,.md-content ol{margin:0 0 1rem 0;padding-left:0;list-style:none}
.md-content li{position:relative;padding:.5rem 0 .5rem 1.8rem;color:var(--dark-200);border-bottom:1px solid rgba(255,255,255,0.03)}
.md-content li:last-child{border-bottom:none}
.md-content li::before{content:'';position:absolute;left:0;top:.85rem;width:8px;height:8px;background:linear-gradient(135deg,var(--neon-indigo),var(--neon-purple));border-radius:2px;transform:rotate(45deg)}
.md-content hr{border:none;height:1px;background:linear-gradient(90deg,transparent,rgba(129,140,248,0.2),transparent);margin:1.5rem 0}
.md-content code{background:rgba(129,140,248,0.1);border:1px solid rgba(129,140,248,0.2);padding:.15rem .5rem;border-radius:4px;font-family:var(--font-mono);font-size:.8rem;color:var(--neon-indigo)}
/* ===== ISSUES ===== */
.insights-section{position:relative;z-index:10;padding:1.5rem 0}
.insights-grid{display:grid;grid-template-columns:2fr 1fr;gap:1.5rem}
.issue-item{background:rgba(255,255,255,0.025);border:1px solid rgba(255,255,255,0.06);border-radius:14px;padding:1.5rem;margin-bottom:1rem;border-left:3px solid;transition:all .2s}
.issue-item:last-child{margin-bottom:0}
.issue-item:hover{background:rgba(255,255,255,0.04);transform:translateX(4px)}
.issue-item.p1{border-left-color:var(--neon-red)}.issue-item.p2{border-left-color:var(--neon-amber)}
.issue-item.p3{border-left-color:var(--neon-indigo)}.issue-item.p4{border-left-color:var(--neon-cyan)}
.issue-item.p5{border-left-color:var(--dark-500)}
.issue-top{display:flex;align-items:center;gap:1rem;margin-bottom:1rem}
.pri-badge{width:36px;height:36px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-family:var(--font-mono);font-size:.65rem;font-weight:700;color:#fff;flex-shrink:0}
.issue-item.p1 .pri-badge{background:var(--neon-red)}.issue-item.p2 .pri-badge{background:var(--neon-amber);color:var(--dark-900)}
.issue-item.p3 .pri-badge{background:var(--neon-indigo)}.issue-item.p4 .pri-badge{background:var(--neon-cyan);color:var(--dark-900)}
.issue-item.p5 .pri-badge{background:var(--dark-500)}
.issue-cat{font-weight:700;color:#fff;font-size:1rem;flex:1}
.pri-chip{font-family:var(--font-mono);font-size:.55rem;font-weight:600;letter-spacing:.08em;padding:.25rem .7rem;border-radius:20px;border:1px solid}
.issue-item.p1 .pri-chip{background:rgba(248,113,113,0.15);border-color:rgba(248,113,113,0.3);color:var(--neon-red)}
.issue-item.p2 .pri-chip{background:rgba(245,158,11,0.15);border-color:rgba(245,158,11,0.3);color:var(--neon-amber)}
.issue-item.p3 .pri-chip{background:rgba(129,140,248,0.15);border-color:rgba(129,140,248,0.3);color:var(--neon-indigo)}
.issue-item.p4 .pri-chip{background:rgba(34,211,238,0.15);border-color:rgba(34,211,238,0.3);color:var(--neon-cyan)}
.issue-item.p5 .pri-chip{background:rgba(100,116,139,0.15);border-color:rgba(100,116,139,0.3);color:var(--dark-400)}
.issue-desc{color:var(--dark-300);font-size:.85rem;line-height:1.6;margin-bottom:1rem}
.intervention{background:rgba(129,140,248,0.04);border:1px solid rgba(129,140,248,0.1);border-radius:8px;padding:1rem;margin-bottom:.8rem}
.intervention-head{display:flex;align-items:center;gap:.5rem;font-family:var(--font-mono);font-size:.6rem;font-weight:600;letter-spacing:.1em;color:var(--neon-indigo);margin-bottom:.6rem}
.intervention-txt{color:var(--dark-200);font-size:.82rem;line-height:1.6}
.area-tags{display:flex;flex-wrap:wrap;gap:.4rem}
.area-tag{padding:.2rem .6rem;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);border-radius:5px;font-size:.65rem;color:var(--dark-300)}
/* ===== THEMES ===== */
.theme-group{background:rgba(255,255,255,0.025);border:1px solid rgba(255,255,255,0.06);border-radius:12px;padding:1.3rem;margin-bottom:1rem}
.theme-group:last-child{margin-bottom:0}
.theme-head{display:flex;align-items:center;gap:.7rem;font-family:var(--font-mono);font-size:.6rem;font-weight:600;letter-spacing:.1em;color:var(--dark-300);margin-bottom:1rem}
.theme-head i{font-size:.7rem;color:var(--neon-indigo)}
.tag-list{display:flex;flex-wrap:wrap;gap:.5rem}
.tag-phrase{padding:.35rem .8rem;background:rgba(96,165,250,0.12);border:1px solid rgba(96,165,250,0.25);border-radius:6px;font-size:.72rem;color:var(--neon-blue);font-weight:500}
.tag-cat{padding:.35rem .8rem;background:rgba(251,191,36,0.12);border:1px solid rgba(251,191,36,0.25);border-radius:6px;font-size:.72rem;color:var(--neon-yellow);font-weight:500}
/* ===== FOOTER META ===== */
.meta-section{position:relative;z-index:10;padding:1.5rem 0 4rem}
.meta-bar{background:rgba(30,41,59,0.45);backdrop-filter:blur(20px);border:1px solid rgba(255,255,255,0.07);border-radius:14px;padding:1.2rem 1.8rem;display:flex;align-items:center;justify-content:space-between;gap:1.5rem;flex-wrap:wrap}
.meta-info{display:flex;align-items:center;gap:.8rem;flex:1}
.meta-info i{color:var(--neon-indigo);font-size:.9rem}
.meta-txt{font-family:var(--font-mono);font-size:.68rem;color:var(--dark-400);display:flex;align-items:center;gap:.6rem;flex-wrap:wrap}
.meta-txt .sep{color:var(--dark-600)}
.meta-actions{display:flex;gap:.7rem}
.meta-btn{display:flex;align-items:center;gap:.5rem;padding:.55rem 1rem;background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.08);border-radius:8px;color:var(--dark-300);text-decoration:none;font-family:var(--font-mono);font-size:.62rem;font-weight:600;letter-spacing:.04em;transition:all .2s}
.meta-btn:hover{background:rgba(129,140,248,0.08);border-color:rgba(129,140,248,0.25);color:var(--neon-indigo);text-decoration:none}
/* ===== EMPTY STATE ===== */
.empty{text-align:center;padding:2.5rem;color:var(--dark-500)}
.empty i{font-size:1.5rem;margin-bottom:.8rem;opacity:.5;display:block}
/* ===== RESPONSIVE ===== */
@@media(max-width:1200px){.metrics-grid{grid-template-columns:repeat(2,1fr)}.dash-grid,.insights-grid{grid-template-columns:1fr}}
@@media(max-width:768px){
.header-row{flex-direction:column}.header-actions{width:100%}
.metrics-grid{grid-template-columns:1fr}
.header-title{font-size:2rem}
.meta-bar{flex-direction:column;text-align:center}
.meta-actions{justify-content:center}
}
@@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}
</style>
}
<div class="nex-bg"><div class="grid"></div><div class="mesh"></div></div>
<!-- Header -->
<section class="page-header">
<div class="container">
<div class="breadcrumb-nex">
<a href="@Url.Action("Index")"><i class="fa-solid fa-brain"></i> Analysis Dashboard</a>
<i class="fa-solid fa-chevron-right sep"></i>
<span class="current">@Model.QuestionnaireTitle</span>
</div>
<div class="header-row">
<div class="header-left">
<div class="header-badge"><span class="dot"></span> CLAUDE AI ANALYSIS</div>
<h1 class="header-title">Mental Health <span class="grad">Analysis</span></h1>
<p class="header-sub">Comprehensive AI-powered analysis for <span class="q-name">@Model.QuestionnaireTitle</span> — sentiment, risk assessment, and workplace insights.</p>
</div>
<div class="header-actions">
<a href="@Url.Action("Dashboard", new { id = Model.QuestionnaireId })" class="h-btn pri"><i class="fa-solid fa-gauge-high"></i> Executive Dashboard</a>
<a href="@Url.Action("GenerateReport", new { id = Model.QuestionnaireId })" class="h-btn sec"><i class="fa-solid fa-file-lines"></i> Report</a>
<a href="@Url.Action("ExportAnalysis", new { id = Model.QuestionnaireId })" class="h-btn sec"><i class="fa-solid fa-download"></i> Export</a>
<a href="@Url.Action("HighRiskResponses", new { id = Model.QuestionnaireId })" class="h-btn danger"><i class="fa-solid fa-triangle-exclamation"></i> High Risk</a>
</div>
</div>
</div>
</section>
<!-- Metrics -->
<section class="metrics-section">
<div class="container">
<div class="metrics-grid">
<div class="m-card c1">
<div class="glow"></div>
<div class="m-icon"><i class="fa-solid fa-users"></i></div>
<div class="m-val">@Model.TotalResponses</div>
<div class="m-lbl">Total Responses</div>
<div class="orb"></div>
</div>
<div class="m-card c2">
<div class="glow"></div>
<div class="m-icon"><i class="fa-solid fa-sparkles"></i></div>
<div class="m-val">@Model.AnalyzedResponses</div>
<div class="m-lbl">AI Analyzed</div>
<div class="orb"></div>
</div>
<div class="m-card c3">
<div class="glow"></div>
<div class="m-icon"><i class="fa-solid fa-face-smile"></i></div>
<div class="m-val">@Math.Round(Model.OverallPositiveSentiment * 100, 1)%</div>
<div class="m-lbl">Positive Sentiment</div>
<div class="orb"></div>
</div>
<div class="m-card c4">
<div class="glow"></div>
<div class="m-icon"><i class="fa-solid fa-shield-halved"></i></div>
<div class="m-val">@(Model.HighRiskResponses + Model.CriticalRiskResponses)</div>
<div class="m-lbl">High / Critical Risk</div>
@if (Model.HighRiskResponses + Model.CriticalRiskResponses > 0) { <div class="pulse-dot"></div> }
<div class="orb"></div>
</div>
</div>
</div>
</section>
<!-- Risk + Sentiment -->
<section class="dash-section">
<div class="container">
<div class="dash-grid">
<!-- Risk Distribution -->
<div class="nex-card">
<div class="top-glow"></div>
<div class="c-head">
<div class="c-icon risk"><i class="fa-solid fa-shield-halved"></i></div>
<div><h3>Risk Distribution</h3><p>Mental health risk assessment across all responses</p></div>
</div>
<div class="c-body">
@if (Model.AnalyzedResponses > 0)
{
var total = (double)Model.AnalyzedResponses;
<div class="risk-row">
<div class="risk-top"><div class="risk-left"><div class="risk-dot low"></div><span class="risk-name">Low Risk</span></div><div class="risk-cnt">@Model.LowRiskResponses</div></div>
<div class="risk-bar"><div class="risk-fill low" style="--w:@(Math.Round(Model.LowRiskResponses / total * 100, 1))%;width:var(--w)"></div></div>
<div class="risk-pct">@Math.Round(Model.LowRiskResponses / total * 100, 1)%</div>
</div>
<div class="risk-row">
<div class="risk-top"><div class="risk-left"><div class="risk-dot mod"></div><span class="risk-name">Moderate Risk</span></div><div class="risk-cnt">@Model.ModerateRiskResponses</div></div>
<div class="risk-bar"><div class="risk-fill mod" style="--w:@(Math.Round(Model.ModerateRiskResponses / total * 100, 1))%;width:var(--w)"></div></div>
<div class="risk-pct">@Math.Round(Model.ModerateRiskResponses / total * 100, 1)%</div>
</div>
<div class="risk-row">
<div class="risk-top"><div class="risk-left"><div class="risk-dot high"></div><span class="risk-name">High Risk</span></div><div class="risk-cnt">@Model.HighRiskResponses</div></div>
<div class="risk-bar"><div class="risk-fill high" style="--w:@(Math.Round(Model.HighRiskResponses / total * 100, 1))%;width:var(--w)"></div></div>
<div class="risk-pct">@Math.Round(Model.HighRiskResponses / total * 100, 1)%</div>
</div>
<div class="risk-row">
<div class="risk-top"><div class="risk-left"><div class="risk-dot crit"></div><span class="risk-name">Critical Risk</span></div><div class="risk-cnt">@Model.CriticalRiskResponses</div></div>
<div class="risk-bar"><div class="risk-fill crit" style="--w:@(Math.Round(Model.CriticalRiskResponses / total * 100, 1))%;width:var(--w)"></div></div>
<div class="risk-pct">@Math.Round(Model.CriticalRiskResponses / total * 100, 1)%</div>
</div>
@if (Model.HighRiskResponses > 0 || Model.CriticalRiskResponses > 0)
{
<div class="risk-alert">
<div class="risk-alert-icon"><i class="fa-solid fa-triangle-exclamation"></i></div>
<div>
<div class="risk-alert-lbl">ATTENTION REQUIRED</div>
<div class="risk-alert-txt"><strong>@(Model.HighRiskResponses + Model.CriticalRiskResponses) responses</strong> flagged for immediate review. <a href="@Url.Action("HighRiskResponses", new { id = Model.QuestionnaireId })">View details →</a></div>
</div>
</div>
}
}
else { <div class="empty"><i class="fa-solid fa-circle-info"></i><p>No risk data available</p></div> }
</div>
</div>
<!-- Sentiment -->
<div class="nex-card">
<div class="top-glow"></div>
<div class="c-head">
<div class="c-icon sent"><i class="fa-solid fa-heart-pulse"></i></div>
<div><h3>Sentiment Analysis</h3><p>Emotional tone assessment across responses</p></div>
</div>
<div class="c-body">
@if (Model.AnalyzedResponses > 0)
{
<div class="sent-row">
<div class="sent-top"><div class="sent-left"><i class="fa-solid fa-face-smile sent-icon pos"></i><span class="sent-name">Positive</span></div><span class="sent-pct">@Math.Round(Model.OverallPositiveSentiment * 100, 1)%</span></div>
<div class="sent-bar"><div class="sent-fill pos" style="--w:@(Model.OverallPositiveSentiment * 100)%;width:var(--w)"></div></div>
</div>
<div class="sent-row">
<div class="sent-top"><div class="sent-left"><i class="fa-solid fa-face-meh sent-icon neu"></i><span class="sent-name">Neutral</span></div><span class="sent-pct">@Math.Round(Model.OverallNeutralSentiment * 100, 1)%</span></div>
<div class="sent-bar"><div class="sent-fill neu" style="--w:@(Model.OverallNeutralSentiment * 100)%;width:var(--w)"></div></div>
</div>
<div class="sent-row">
<div class="sent-top"><div class="sent-left"><i class="fa-solid fa-face-frown sent-icon neg"></i><span class="sent-name">Negative</span></div><span class="sent-pct">@Math.Round(Model.OverallNegativeSentiment * 100, 1)%</span></div>
<div class="sent-bar"><div class="sent-fill neg" style="--w:@(Model.OverallNegativeSentiment * 100)%;width:var(--w)"></div></div>
</div>
var vClass = ""; var vIcon = ""; var vText = "";
if (Model.OverallPositiveSentiment >= 0.6) { vClass = "good"; vIcon = "fa-thumbs-up"; vText = "Excellent mental health climate"; }
else if (Model.OverallPositiveSentiment >= 0.4) { vClass = "ok"; vIcon = "fa-scale-balanced"; vText = "Moderate mental health climate"; }
else { vClass = "bad"; vIcon = "fa-triangle-exclamation"; vText = "Concerning mental health climate"; }
<div class="sent-verdict @vClass">
<i class="fa-solid @vIcon verdict-icon"></i>
<span class="verdict-txt">@vText</span>
</div>
}
else { <div class="empty"><i class="fa-solid fa-circle-info"></i><p>No sentiment data available</p></div> }
</div>
</div>
</div>
</div>
</section>
<!-- Executive Summary -->
@if (!string.IsNullOrEmpty(Model.ExecutiveSummary))
{
<section class="summary-section">
<div class="container">
<div class="summary-card">
<div class="summary-head">
<div class="summary-head-icon"><i class="fa-solid fa-clipboard-list"></i></div>
<div><h3>EXECUTIVE SUMMARY</h3><p>Comprehensive analysis overview powered by Claude AI</p></div>
</div>
<div class="summary-body">
<div class="md-content" id="executiveSummary"></div>
</div>
</div>
</div>
</section>
}
<!-- Insights: Issues + Themes -->
<section class="insights-section">
<div class="container">
<div class="insights-grid">
<!-- Workplace Issues -->
<div class="nex-card">
<div class="top-glow"></div>
<div class="c-head">
<div class="c-icon issue"><i class="fa-solid fa-magnifying-glass-chart"></i></div>
<div><h3>Workplace Issues & Interventions</h3><p>Priority-ranked issues with recommended actions</p></div>
</div>
<div class="c-body">
@if (Model.TopWorkplaceIssues != null && Model.TopWorkplaceIssues.Any())
{
@foreach (var issue in Model.TopWorkplaceIssues.Take(5))
{
<div class="issue-item p@issue.Priority">
<div class="issue-top">
<div class="pri-badge">P@issue.Priority</div>
<span class="issue-cat">@issue.Category</span>
<span class="pri-chip">PRIORITY @issue.Priority</span>
</div>
<div class="issue-desc">@issue.Issue</div>
<div class="intervention">
<div class="intervention-head"><i class="fa-solid fa-lightbulb"></i> RECOMMENDED INTERVENTION</div>
<div class="intervention-txt">@issue.RecommendedIntervention</div>
</div>
@if (issue.AffectedAreas.Any())
{
<div class="area-tags">
@foreach (var area in issue.AffectedAreas) { <span class="area-tag">@area</span> }
</div>
}
</div>
}
}
else { <div class="empty"><i class="fa-solid fa-circle-info"></i><p>No workplace issues identified</p></div> }
</div>
</div>
<!-- Themes -->
<div class="nex-card">
<div class="top-glow"></div>
<div class="c-head">
<div class="c-icon theme"><i class="fa-solid fa-tags"></i></div>
<div><h3>Common Themes</h3><p>Key patterns and categories</p></div>
</div>
<div class="c-body">
@if (Model.MostCommonKeyPhrases != null && Model.MostCommonKeyPhrases.Any())
{
<div class="theme-group">
<div class="theme-head"><i class="fa-solid fa-quote-left"></i> MOST MENTIONED PHRASES</div>
<div class="tag-list">
@foreach (var phrase in Model.MostCommonKeyPhrases.Take(10)) { <span class="tag-phrase">@phrase</span> }
</div>
</div>
@if (Model.TopWorkplaceIssues.Any())
{
<div class="theme-group">
<div class="theme-head"><i class="fa-solid fa-layer-group"></i> ISSUE CATEGORIES</div>
<div class="tag-list">
@foreach (var cat in Model.TopWorkplaceIssues.Select(i => i.Category).Distinct().Take(6)) { <span class="tag-cat">@cat</span> }
</div>
</div>
}
}
else { <div class="empty"><i class="fa-solid fa-circle-info"></i><p>No themes identified</p></div> }
</div>
</div>
</div>
</div>
</section>
<!-- Footer Meta -->
<section class="meta-section">
<div class="container">
<div class="meta-bar">
<div class="meta-info">
<i class="fa-solid fa-circle-info"></i>
<div class="meta-txt">
<span>Analyzed @Model.LastAnalyzedAt.ToString("MMMM dd, yyyy 'at' HH:mm")</span>
<span class="sep">|</span>
<span>@Model.AnalyzedResponses responses processed</span>
<span class="sep">|</span>
<span>Powered by Claude AI (Anthropic)</span>
</div>
</div>
<div class="meta-actions">
<a href="@Url.Action("BatchAnalyze", new { id = Model.QuestionnaireId })" class="meta-btn"><i class="fa-solid fa-rotate"></i> Refresh</a>
<a href="@Url.Action("AnalyzeTrends", new { id = Model.QuestionnaireId })" class="meta-btn"><i class="fa-solid fa-chart-line"></i> Trends</a>
</div>
</div>
</div>
</section>
@section Scripts {
<!-- Markdown parser (lightweight) -->
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', function () {
// Parse and render executive summary as proper HTML from markdown
var raw = @Html.Raw(System.Text.Json.JsonSerializer.Serialize(Model.ExecutiveSummary ?? ""));
var container = document.getElementById('executiveSummary');
if (container && raw) {
// Configure marked for clean output
marked.setOptions({
breaks: true,
gfm: true,
headerIds: false,
mangle: false
});
container.innerHTML = marked.parse(raw);
}
});
</script>
}