<% var x = bh || {}; var bd = x.breakdown || {};

  var LABEL = {};
  ['visibility','authority','citationQuality','sentiment','entityStrength','shareOfVoice'].forEach(function (k) { LABEL[k] = h.sigName(k); });

  var HELP = {
    visibility: {
      t: 'The share of AI answers that named you.',
      s: 'Engines that returned no answers are left out.'
    },
    authority: {
      t: 'How often your own pages were cited as a source in those answers.',
      s: 'Counted from the citation links in each answer. 50 citations is a full score.'
    },
    citationQuality: {
      t: 'The same citation count on a narrower scale.',
      s: 'From the same citation links as Citation score.'
    },
    sentiment: {
      t: 'When AI describes you, how favourable that description is.',
      s: 'One verdict per answer, read from the sentences around your name.'
    },
    entityStrength: {
      t: 'How many times your brand was named across the tracked questions.',
      s: 'A count of mentions, scaled to 100.'
    },
    shareOfVoice: {
      t: 'Your share of all brand mentions in the answers, yours plus every competitor named alongside you.',
      s: 'From the Competitors table, updated on each run.'
    }
  };

  var known = Object.keys(LABEL).filter(function(k){ return bd[k] != null; });
  var lowest = known.length ? known.reduce(function(a,k){ return bd[k] < bd[a] ? k : a; }, known[0]) : null;
  var verdict = x.score==null ? 'Not measured yet'
              : (x.score>=75?'Strong':(x.score>=50?'Developing':'Needs work'));

  var hasScore = x.score != null;

  var measured = (x.measured != null) ? x.measured : known.length;

  var kn = typeof knowledge !== 'undefined' ? (knowledge || []) : [];
  var isAgencyUser = locals.showStaff;
  var wrongN = typeof wrongCount !== 'undefined' ? wrongCount : 0;
  var uncheckedN = typeof uncheckedCount !== 'undefined' ? uncheckedCount : 0;

  function disagree(list){
    var ok = list.some(function (f) { return f.verdict === 'correct'; });
    var no = list.some(function (f) { return f.verdict === 'wrong'; });
    return ok && no;
  }
%>
<div class="pg-head" style="margin-bottom:0">
  <div>
    <div class="eyebrow">Overview / Brand Health</div>
  </div>
  <div class="ph-right" style="display:flex;gap:10px;align-items:center">
    <%- include('../partials/range-picker') %>
    <% if(x.createdAt){ var _ck = new Date(x.createdAt), _today = _ck.toDateString() === new Date().toDateString(); %><span class="rr-meta">Updated <%= _today ? 'today, ' + _ck.toLocaleTimeString('en-GB', { hour: '2-digit', minute: '2-digit' }) : h.stamp(_ck) %></span><% } %>

  </div>
</div>

<h1 class="claim"><%= title %></h1>
<% if (hasScore && x.score > 0) { %>
  <p class="claim-lede">Across <%= measured %> measured signal<%= measured === 1 ? '' : 's' %>, your brand scores <em><%= x.score %></em> out of 100.</p>
<% } else if (x.score === 0) { %>
  <p class="claim-lede">Every signal we could measure came back at zero.</p>
<% } else { %>
  <p class="claim-lede">Nothing about your brand has been measured yet.</p>
<% } %>
<p class="claim-sub"><%
  if (hasScore) { %>Average of <%= measured %> signal<%= measured === 1 ? '' : 's' %><% if (measured < 6) { %> (<%= 6 - measured %> with no reading yet)<% } %>.<% if (lowest) { %> <b><%= LABEL[lowest] %></b> is the lowest.<% } %><%
  } else { %>Six signals from your AI Visibility answers. The score appears after the first run.<%
  } %> <%- h.ihelp('What this page is',
      'Six signals about your brand from the AI engines\' answers, combined into one score'
      + (x.createdAt ? ', from the run on <b>' + h.date(x.createdAt) + '</b>.' : '.')) %></p>

<%

  var _answers = kn.reduce(function (t, g) { return t + g.answers.length; }, 0);
  var _shelf = [], _off = [];
  function _cell(l, v, xt) { _shelf.push({ l: l, v: v, x: xt || '' }); }
  function _blank(n, cta, href) { _off.push({ n: n, cta: cta, href: href || '' }); }

  if (x.score != null || known.length) {  }
  else if (kn.length) _cell('Questions tracked', (locals.questions || []).length);
  else _blank('Brand Health score', 'Brand Health has not been calculated for this client yet');

  if (kn.length) {
    _cell('Answers stored', _answers);
    _cell('Confirmed wrong', wrongN);
    _cell('Not checked yet', uncheckedN);
  } else {
    _blank('What AI knows about you', 'No engine has been asked about you yet');
  }
%>

<div class="bento" style="margin-top:22px">

  <div class="vdark vd-cut bh-score b5">
    <span class="vn-fillet"></span>

    <% if (locals.showStaff) { %>
      <form class="inline-form" method="POST" action="/api/brand-health/recompute" style="position:absolute;top:0;right:0">
        <button class="vn-cut" type="submit">Recompute
          <svg viewBox="0 0 12 12" fill="none" width="13" height="13" aria-hidden="true"><path d="M10 6a4 4 0 11-1.2-2.85M10 1.6V4H7.6" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg>
        </button>
      </form>
    <% } else { %>
      <a class="vn-cut" href="/ai-visibility">See the answers
        <svg viewBox="0 0 12 12" fill="none" width="13" height="13" aria-hidden="true"><path d="M3 9L9 3M9 3H4.2M9 3v4.8" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"/></svg>
      </a>
    <% } %>
    <div class="score-hero">

      <div class="sh-left">
        <div class="sh-fig">

        <div class="eyebrow">Brand Health Score <%- h.ihelp('Brand Health Score',
          'The average of the signals on the right that have a reading. Updated after each AI Visibility run.') %>
        </div>

        <div class="score-num tnum"><% if (hasScore) { %><%= x.score %><small>/100</small><% } else { %><span class="noval">—</span><% } %></div>

        <% if (hasScore) { %>
          <div class="score-meter" role="img" aria-label="<%= x.score %> out of 100"><span style="width:<%= x.score %>%"></span></div>
        <% } %>
        <% if(x.delta){ %><div class="chip <%= x.delta>=0?'pos':'neg' %>" style="margin-top:12px"><%= x.delta>=0?'▲':'▼' %> <%= Math.abs(x.delta) %> vs the last update</div><% } %>
        </div>

        <div class="sh-say">
          <div class="rr-meta">
            <%= verdict %>.<% if(lowest && x.score!=null){ %> Biggest lever: <b><%= LABEL[lowest] %></b>.<% } %>
            <% if(x.measured){ %><br><span style="opacity:.8">Averaged over <%= x.measured %> measured signal<%= x.measured===1?'':'s' %>.</span><% } %>
          </div>

          <% if (isAgencyUser) { %>
            <div class="vd-act"><a class="btn btn-sm" href="/ai-visibility">See the answers</a></div>
          <% } %>
        </div>
      </div>

      <div class="breakdown" style="--bd-cols:2">
        <% Object.keys(LABEL).forEach(function(k){ var v = bd[k]; var hp = HELP[k]; %>
          <div class="bd">
            <div class="bl" style="display:flex; align-items:center; gap:6px">
              <span><%= LABEL[k] %></span>

              <span class="rr-end"><%- h.ihelp(LABEL[k],
                h.esc(hp.t)
                + (v == null ? '<br><br>Not measured in this run, so left out of the score.' : '')
                + '<br><br>' + h.esc(hp.s)) %></span>
            </div>
            <div class="bv tnum"><%- h.sigVal(k, v) %></div>
            <div class="bm"><span style="width:<%= v!=null ? v : 0 %>%"></span></div>
          </div>
        <% }) %>
      </div>
    </div>
  </div>

  <%

    var _weakEdge = function (v) {
      if (v === 'correct') return 'var(--neg)';
      if (v === 'wrong') return 'var(--muted-2)';
      return 'var(--line)';
    };

    var _rows = typeof weaknesses !== 'undefined' ? (weaknesses || []) : [];
  %>

  <div class="card b7 bh-case">

    <div class="card-h card-h-stack">
      <h3>The case against you</h3>
      <span class="hint">what AI says when asked for your weaknesses</span>
      <span class="rr-end"><%- h.ihelp('Where this comes from',
        'Each connected engine is asked: <i>what are this company\'s weaknesses compared with similar companies, '
        + 'and where does that impression come from?</i>'
        + '<br><br>The bold line is our summary; the quote under it is the engine\'s own words. '
        + 'The full answer is further down this page.') %></span>
    </div>
    <div class="card-p bh-case-list">
      <% if(!_rows.length){ %>
        <div class="rr-meta" style="padding:30px 8px; text-align:center">
          No answers yet.
        </div>
      <% } %>
      <% _rows.forEach(function(row){ var lead = row.lead; var f = lead.fact; %>

        <div class="bubble bidi"<%- h.dirAttr(f.answer) %> style="border-inline-start:3px solid <%= _weakEdge(row.verdict) %>">

          <div class="row-between" dir="ltr" style="margin-bottom:7px; gap:10px">
            <span class="bh-engines">

              <% row.engines.forEach(function(e, i){ %><%- include('../partials/engine-mark', { engine: e.engine, size: 'sm', bare: true }) %><span><%= e.engine %></span><% if (i < row.engines.length - 1) { %><span class="bh-plus">+</span><% } %><% }) %>
            </span>
            <span style="display:inline-flex; gap:6px; align-items:center">
              <% if (row.agree) { %><span class="chip neg" title="<%= row.engines.length %> engines independently made this same point. Agreement across models is stronger evidence than any one of them alone.">agreed by <%= row.engines.length %></span><% } %>

              <% if(row.verdict==='correct'){ %><span class="chip neg" title="Somebody on your side agreed this is a real weakness.">we agree</span>
              <% } else if(row.verdict==='wrong'){ %><span class="chip flat" title="Marked wrong on this page: the engine is saying something untrue about you. The fix is in the answer.">disputed</span>
              <% } else { %><span class="chip flat" title="Nobody has ruled on this yet. Mark it correct or wrong further down the page.">not checked</span><% } %>
            </span>
          </div>

          <% if (row.gist) { %>
            <div class="bh-claim"><%= row.gist %></div>
            <div class="bh-said">In <%= lead.engine %>’s words: “<%- h.answer(lead.excerpt) %>”</div>
          <% } else if (row.gist === '') { %>
            <div class="bh-none"><%= lead.engine %> named no weakness.</div>
            <div class="bh-said">“<%- h.answer(lead.excerpt) %>”</div>
          <% } else { %>
            <div class="bh-said" style="margin-top:0">“<%- h.answer(lead.excerpt) %>”</div>
          <% } %>
          <div class="rr-meta" dir="ltr" style="margin-top:7px; display:flex; gap:10px; flex-wrap:wrap; align-items:center">

            <a href="#brand-knowledge">Full answer, sources and verdict ↓</a>

            <% if (row.stale) { %>
              <span class="bh-stale" title="This engine did not answer on the most recent check, so its previous answer is still showing.">from an earlier check · <%= h.date(lead.askedAt) %></span>
            <% } %>
          </div>
        </div>
      <% }) %>
    </div>
  </div>

  <% if (_shelf.length) { %>
    <% var _tints = ['sc-violet', 'sc-lime', 'sc-navy', 'sc-sky', 'sc-sand', 'sc-rose']; %>
    <div class="shelf-row b12" style="--shelf-n:<%= _shelf.length %>">
      <% _shelf.forEach(function (s, i) { %>
        <div class="card shelf-c <%= _tints[i % _tints.length] %>">
          <div class="cl"><%= s.l %></div>
          <div class="cv tnum"><%= s.v %><%- s.x %></div>
        </div>
      <% }) %>
    </div>
  <% } %>

  <% if (_off.length) { %>

  <div class="voff b12">
    <div class="voff-h"><b>Not connected yet</b></div>
    <% _off.forEach(function (o) { %>
      <div class="voff-i">
        <span class="n"><%= o.n %></span>
        <% if (o.href) { %><a href="<%= o.href %>"><%= o.cta %></a><% } else { %><span class="n"><%= o.cta %></span><% } %>
      </div>
    <% }) %>
  </div>
  <% } %>

  <div class="card b12" id="brand-knowledge">
    <div class="card-h">
      <h3>What AI knows about you</h3>
      <span class="hint">
        <% if(typeof lastAsked !== 'undefined' && lastAsked){ %>asked <%= h.timeAgo(lastAsked) %><% } else { %>never asked<% } %>
      </span>

      <% if(isAgencyUser){ %>
        <form method="POST" action="/api/brand-knowledge/probe" class="inline-form" style="margin-left:auto"
              onsubmit="return confirm('This asks every connected engine <%= (locals.questions || []).length %> questions about this client. It costs money. Run it now?')">
          <button class="btn btn-sm" type="submit">Ask the engines</button>
        </form>
      <% } %>
      <span class="rr-end"><%- h.ihelp('What this section asks',
        'Each engine is asked about you directly ('
        + h.esc((locals.questions || []).map(function(q){ return q.label.toLowerCase(); }).join(', '))
        + ') and the reply is stored word for word. <b>Correct</b> and <b>Wrong</b> are set by your VOCTOS team. Runs monthly.') %></span>
    </div>

    <% if(!kn.length){ %>
      <%- include('../partials/empty', { title: 'No answers yet', line: isAgencyUser ? 'Use <b>Ask the engines</b> above. It takes about a minute.' : 'Your VOCTOS team runs this monthly.' }) %>
    <% } else { %>
      <% if(wrongN || uncheckedN){ %>
        <div class="card-p" style="padding-bottom:0">
          <div class="note" style="margin-bottom:0">
            <span class="ic" style="background:<%= wrongN ? 'var(--neg)' : 'var(--muted-2)' %>"><%= wrongN ? '!' : 'i' %></span>
            <div>
              <% if(wrongN){ %><b><%= wrongN %> answer<%= wrongN===1?'':'s' %> confirmed wrong about you.</b>
                We fix these by getting the correct information onto pages the engines cite.<% } %>
              <% if(uncheckedN){ %><%= wrongN ? ' ' : '' %><%= uncheckedN %> answer<%= uncheckedN===1?'':'s' %> not checked yet<%= isAgencyUser ? '. Mark each one below.' : '.' %><% } %>
            </div>
          </div>
        </div>
      <% } %>

      <div class="card-p" style="display:flex; flex-direction:column; gap:20px">
        <% kn.forEach(function(g){ var split = disagree(g.answers);

             var qs = g.answers.map(function(f){ return f.question; }).filter(Boolean);
             var qMixed = qs.length > 1 && qs.some(function(q){ return q !== qs[0]; });
             var qLatest = g.answers.slice().sort(function(a,b){
               return new Date(b.askedAt || 0) - new Date(a.askedAt || 0); })[0];
             var prompt = (qLatest && qLatest.question) || ''; %>
          <%

            var _wrong = g.answers.filter(function(f){ return f.verdict === 'wrong'; }).length;
            var _needs = _wrong > 0 || split;
          %>
          <details class="qgrp" <%= _needs ? 'open' : '' %>>
            <summary>
              <span class="q-l"><%= g.label %></span>
              <span class="q-eng">
                <% g.answers.forEach(function(f){ %>
                  <span class="q-dot <%= f.verdict==='wrong' ? 'bad' : (f.verdict==='correct' ? 'ok' : '') %>"
                        title="<%= f.engine %> (<%= f.verdict || 'not checked' %>)"><%= f.engine %></span>
                <% }) %>
              </span>
              <% if(split){ %><span class="chip warn" title="One engine is marked correct and another wrong for this same question.">engines contradict</span><% } %>
              <% if(_wrong){ %><span class="chip neg"><%= _wrong %> wrong</span><% } %>

              <% var _unchecked = g.answers.filter(function(f){ return !f.verdict; }).length; %>
              <% if(_unchecked){ %><span class="q-meta"><%= _unchecked %> not checked</span><% } %>
              <svg class="q-chev" viewBox="0 0 12 12" fill="none" width="12" height="12" aria-hidden="true"><path d="M2.5 4.5L6 8l3.5-3.5" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/></svg>
            </summary>
            <div class="q-body">

            <% if (prompt) { %>

              <div class="copy-row" style="display:flex; align-items:center; gap:7px; font-size:var(--fs-xs); color:var(--muted)">
                <button type="button" class="copy-prompt" data-copy-icon data-copy="<%= prompt %>"
                        aria-label="Copy the prompt used for &quot;<%= g.label %>&quot;"
                        title="<%= qMixed ? 'Copy the prompt. The wording changed between runs, so this is the most recent one.' : 'Copy the exact prompt that produced these answers.' %>"><svg viewBox="0 0 16 16" fill="none" aria-hidden="true" width="14" height="14"><rect x="5.4" y="5.4" width="8.2" height="8.2" rx="1.8" stroke="currentColor" stroke-width="1.4"/><path d="M10.6 5.4V4.2a1.8 1.8 0 00-1.8-1.8H4.2a1.8 1.8 0 00-1.8 1.8v4.6a1.8 1.8 0 001.8 1.8h1.2" stroke="currentColor" stroke-width="1.4" stroke-linecap="round"/></svg></button>
                copy the prompt behind these answers
              </div>
            <% } %>
              <% g.answers.forEach(function(f){
                   var bc = f.verdict==='wrong' ? 'var(--neg)' : (f.verdict==='correct' ? 'var(--pos)' : 'var(--line)'); %>
                <div class="bubble" style="border-left:3px solid <%= bc %>">
                  <div class="row-between" style="margin-bottom:6px; gap:10px">
                    <span style="font-weight:600; font-size:var(--fs-sm); display:inline-flex; align-items:center; gap:7px"><%- include('../partials/engine-mark', { engine: f.engine, size: 'sm' }) %><%= f.engine %></span>
                    <span style="display:inline-flex; gap:7px; align-items:center">
                      <% if(f.verdict==='wrong'){ %><span class="chip neg">wrong</span>
                      <% } else if(f.verdict==='correct'){ %><span class="chip pos">correct</span>
                      <% } else { %><span class="chip flat">not checked</span><% } %>

                      <% if(f.changedAt && f.previous){ %>
                        <% if(f.promptChanged){ %><span class="chip flat" title="We changed the wording of the question, so this answer is to a different question, not a change of mind.">new question</span>
                        <% } else { %><span class="chip flat" title="This answer changed since the previous run">changed</span><% } %>
                      <% } %>
                    </span>
                  </div>

                  <details class="ans"><summary><div class="txt ansdoc"><%- h.answerDoc(f.answer) %></div></summary></details>

                  <%

                    var srcs = (f.sources || []).filter(function (s2) { return s2 && s2.url; });
                    var host = function (u) {
                      try { return String(u).replace(/^https?:\/\//i, '').replace(/^www\./, '').split('/')[0]; }
                      catch (e) { return u; }
                    };

                    var label = function (sc) {
                      if (sc.title) return sc.title;
                      var u = String(sc.url || '').replace(/^https?:\/\//i, '').replace(/^www\./, '').replace(/\/$/, '');
                      return u.length > 64 ? u.slice(0, 63) + '…' : u;
                    };
                  %>
                  <div class="fsrc">
                    <% if (srcs.length) { %>
                      <details class="fsrc-d">
                        <summary><%= srcs.length %> source<%= srcs.length===1?'':'s' %> <span class="rr-meta">(what <%= f.engine %> cited)</span></summary>
                      <ol class="fsrc-l">
                        <% srcs.forEach(function (sc) { %>
                          <li>
                            <a href="<%= sc.url %>" target="_blank" rel="noopener nofollow" title="<%= sc.url %>"><%= label(sc) %></a>
                            <% if (sc.title) { %><span class="rr-meta"><%= host(sc.url) %></span><% } %>
                          </li>
                        <% }) %>
                      </ol>
                      </details>
                    <% } else { %>

                      <div class="fsrc-none">
                        No sources: <%= f.engine %> answered from memory.
                      </div>
                    <% } %>

                    <% if (f.askUrl) { %>
                      <a class="fsrc-ask" href="<%= f.askUrl %>" target="_blank" rel="noopener"
                         title="<%= f.askPrefilled ? 'Opens ' + f.engine + ' with this exact prompt ready to send. It runs again now, so the answer may differ.' : 'Opens ' + f.engine + '. Paste the prompt with the copy button above.' %>">
                        <%= f.askPrefilled ? 'Ask ' + f.engine + ' yourself' : 'Open ' + f.engine %> ↗
                      </a>
                    <% } %>
                  </div>

                  <% if(f.verdict==='wrong' && f.correction){ %>
                    <div class="rr-meta" style="margin-top:8px; padding-top:8px; border-top:1px solid var(--line)">
                      <b style="color:var(--ink)">Actually:</b> <%= f.correction %>
                    </div>
                  <% } %>

                  <% if(f.verdict==='wrong' && isAgencyUser){ %>
                    <% var onGoals = (locals.goaled || []).indexOf(String(f._id)) > -1; %>
                    <div style="margin-top:9px">
                      <% if(onGoals){ %>
                        <span class="rr-meta" style="display:inline-flex; align-items:center; gap:5px">
                          <svg viewBox="0 0 16 16" fill="none" width="12" height="12" aria-hidden="true"><path d="M3.5 8.4l3 3 6-6.6" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/></svg>
                          On the <a href="/goals">Goals</a> page
                        </span>
                      <% } else { %>
                        <form method="POST" action="/api/brand-knowledge/<%= f._id %>/goal" class="inline-form js-ajax-form" data-refresh="#brand-knowledge">
                          <button class="btn btn-sm" type="submit">+ Add to goals</button>
                        </form>
                      <% } %>
                    </div>
                  <% } %>

                  <% if(f.previous){ %>

                    <details class="prev-answer" style="margin-top:8px">

                      <summary class="more" style="cursor:pointer; font-size:var(--fs-xs)"><%= f.promptChanged ? 'What it said to the older question' : 'What it said before' %></summary>
                      <div class="rr-meta ansdoc" style="margin-top:6px"><%- h.answerDoc(f.previous) %></div>
                    </details>
                  <% } %>

                  <% if(isAgencyUser){ %>
                    <details style="margin-top:9px">

                      <summary class="more" style="cursor:pointer; font-size:var(--fs-xs)"><%= f.verdict ? 'Change verdict' : 'Is this right?' %></summary>

                      <form class="editform js-ajax-form" data-refresh="#brand-knowledge" method="POST" action="/api/brand-knowledge/<%= f._id %>/verdict" style="margin-top:8px">
                        <div class="fld"><label for="bh-verdict-<%= f._id %>">Verdict</label>
                          <select id="bh-verdict-<%= f._id %>" name="verdict">
                            <option value="" <%= !f.verdict?'selected':'' %>>(not checked)</option>
                            <option value="correct" <%= f.verdict==='correct'?'selected':'' %>>Correct</option>
                            <option value="wrong" <%= f.verdict==='wrong'?'selected':'' %>>Wrong</option>
                          </select>
                        </div>
                        <div class="fld"><label for="bh-correction-<%= f._id %>">If wrong, what's the truth? <span class="rr-meta">(shown to the client)</span></label>
                          <input id="bh-correction-<%= f._id %>" name="correction" value="<%= f.correction || '' %>" placeholder="e.g. We're based in Cairo, not Dubai.">
                        </div>
                        <button class="btn btn-primary btn-sm" type="submit">Save</button>
                      </form>
                    </details>
                  <% } %>

                  <div class="rr-meta" style="margin-top:7px; font-size:var(--fs-xs)">
                    Asked <%= h.timeAgo(f.askedAt) %><% if(f.verifiedAt){ %> · checked <%= h.timeAgo(f.verifiedAt) %><% } %>
                  </div>
                </div>
              <% }) %>
            </div>
          </details>
        <% }) %>
      </div>
    <% } %>
  </div>

  <%

    var sh = (typeof sentimentHistory !== 'undefined' && sentimentHistory) ? sentimentHistory : [];
    var sN = sh.length;
    var sL = 46, sR = 668, sTOP = 34, sBOT = 196;
    var sY = function (v) { return sBOT - (Math.max(0, Math.min(100, v)) / 100) * (sBOT - sTOP); };
    var sT0 = sN ? new Date(sh[0].at).getTime() : 0;
    var sT1 = sN ? new Date(sh[sN - 1].at).getTime() : 0;
    var sSpanOk = sN >= 2 && sT1 > sT0;
    var sX = function (p, i) {
      if (!sSpanOk) return sL + (sN <= 1 ? 0 : (i / (sN - 1)) * (sR - sL));
      return sL + ((new Date(p.at).getTime() - sT0) / (sT1 - sT0)) * (sR - sL);
    };
    var sLine = sh.map(function (p, i) { return Math.round(sX(p, i)) + ',' + Math.round(sY(p.sentiment)); }).join(' ');
    var sArea = sN >= 2 ? ('M' + sLine.split(' ').join(' L').replace(/^ L/, '') + ' L' + Math.round(sX(sh[sN-1], sN-1)) + ',' + sBOT + ' L' + Math.round(sX(sh[0], 0)) + ',' + sBOT + ' Z') : '';
    var sTickLabel = function (p) { return new Date(p.at).toLocaleDateString('en-GB', { day: 'numeric', month: 'short' }); };
    var sTickIdx = [];
    if (sN) {
      var sWant = Math.min(5, sN);
      var sRaw = [];
      for (var st = 0; st < sWant; st++) sRaw.push(Math.round(st * (sN - 1) / Math.max(1, sWant - 1)));
      sRaw = sRaw.filter(function (v, i, a) { return a.indexOf(v) === i; });
      var sSeen = {};
      sRaw.forEach(function (idx) {
        var lbl = sTickLabel(sh[idx]);
        var isEdge = (idx === 0 || idx === sN - 1);
        if (isEdge || !sSeen[lbl]) { sTickIdx.push(idx); sSeen[lbl] = true; }
      });
    }
    var sLast = sN ? sh[sN - 1] : null;
    var sFirst = sN ? sh[0] : null;
    var sMv = (sN >= 2) ? Math.round(sLast.sentiment - sFirst.sentiment) : null;
  %>

  <div class="card b12">
    <div class="card-h">
      <h3>Sentiment over time</h3>

      <span class="hint">one point per update</span>
      <% if (sMv !== null) { %>
        <span style="margin-left:auto" class="chip <%= sMv > 0 ? 'pos' : (sMv < 0 ? 'neg' : 'flat') %>">
          <%- sMv > 0 ? '▲' : (sMv < 0 ? '▼' : '<span class="flatbar" role="img" aria-label="unchanged"></span>') %> <%= Math.abs(sMv) %> pts across this period
        </span>
      <% } %>
      <span class="rr-end"><%- h.ihelp('How this trend is built',
        'Each update stores that day\'s sentiment reading, and the trend is drawn from those stored '
        + 'points. It starts from the first update and fills in from there.'
        + (locals.showStaff ? '<br><br>Recompute after each AI Visibility run to keep it dense.' : '')) %></span>
    </div>
    <div class="card-p" style="padding-top:12px">
      <% if (sN >= 2) { %>
        <%
          var sChartPts = sh.map(function (p, i) {
            return {
              x: Math.round(sX(p, i)),
              label: sTickLabel(p),
              rows: [{
                k: 'Sentiment', v: Math.round(p.sentiment) + '%', y: Math.round(sY(p.sentiment)),
                c: 'var(--teal)', d: i === 0 ? null : Math.round(p.sentiment - sh[i - 1].sentiment), u: ' pts'
              }]
            };
          });
        %>
        <div class="vchart-wrap">
        <svg class="chart vchart" viewBox="0 0 700 244" role="img" tabindex="0"
             data-points="<%= JSON.stringify(sChartPts) %>"
             aria-label="Sentiment over time, from <%= Math.round(sFirst.sentiment) %>% to <%= Math.round(sLast.sentiment) %>%. Use the arrow keys to read each update.">
          <line class="ax" x1="<%= sL %>" y1="<%= sTOP %>" x2="<%= sL %>" y2="<%= sBOT %>"/>
          <line class="ax" x1="<%= sL %>" y1="<%= sBOT %>" x2="<%= sR %>" y2="<%= sBOT %>"/>
          <% [0,25,50,75,100].forEach(function(v){ %>
            <line x1="<%= sL %>" y1="<%= sY(v) %>" x2="<%= sR %>" y2="<%= sY(v) %>" stroke="var(--line-2)" stroke-width="1"/>
            <text class="ylab" x="<%= sL - 10 %>" y="<%= sY(v) + 4 %>" text-anchor="end" font-size="11" fill="var(--muted-2)"><%= v %>%</text>
          <% }) %>

          <path d="<%= sArea %>" fill="var(--teal)" opacity=".07"/>
          <polyline points="<%= sLine %>" fill="none" stroke="var(--teal)" stroke-width="2.6"
                    stroke-linecap="round" stroke-linejoin="round"/>

          <% sh.forEach(function(p, i){ %>
            <circle cx="<%= Math.round(sX(p,i)) %>" cy="<%= Math.round(sY(p.sentiment)) %>" r="3.5"
                    fill="var(--surface)" stroke="var(--teal)" stroke-width="2"><title><%= sTickLabel(p) %> · <%= Math.round(p.sentiment) %>%</title></circle>
          <% }) %>

          <text x="<%= Math.round(Math.min(sR, sX(sLast, sN-1))) %>" y="<%= Math.round(sY(sLast.sentiment)) - 11 %>"
                text-anchor="end" font-size="12" font-weight="700" fill="var(--teal)"><%= Math.round(sLast.sentiment) %>%</text>

          <% sTickIdx.forEach(function(i){ var p = sh[i]; %>
            <text class="tick" x="<%= Math.round(Math.max(sL, Math.min(sR, sX(p, i)))) %>" y="<%= sBOT + 16 %>"
                  text-anchor="<%= i === 0 ? 'start' : (i === sN-1 ? 'end' : 'middle') %>"
                  font-size="11" fill="var(--muted-2)"><%= sTickLabel(p) %></text>
          <% }) %>

          <line class="vc-cross" x1="0" y1="<%= sTOP - 8 %>" x2="0" y2="<%= sBOT %>"/>
          <circle class="vc-dot" cx="0" cy="0" r="6"/>
        </svg>
          <div class="vchart-tip" hidden aria-live="polite"></div>
        </div>
      <% } else if (sN === 1) { %>
        <div class="rr-meta" style="padding:44px 8px; text-align:center">
          One reading so far, <b style="color:var(--ink)"><%= Math.round(sh[0].sentiment) %>%</b> on <%= sTickLabel(sh[0]) %>.<br>
          The line appears after the next reading.
        </div>
      <% } else { %>

        <div class="rr-meta" style="padding:30px 8px; text-align:center"><% if (bh) { %>Brand Health was not updated during <b><%= range.label.toLowerCase() %></b>. Widen the period above<%= locals.showStaff ? ', or recompute to add a point here' : '' %>.<% } else { %>The sentiment trend builds here as Brand Health is updated over time.<%= locals.showStaff ? ' Recompute after each AI Visibility run to add points.' : '' %><% } %></div>
      <% } %>
    </div>
  </div>
</div>
