/* Analysts — ranked directory of buy- and sell-side analysts covering the universe.
   Performance-ranked (hit rate · avg return per call · sample size), every research
   note carries an expiry date (ACTIVE/EXPIRED). Rows expand to a profile: portrait,
   details, recent calls with outcomes. Our own take on the analyst-ranking genre. */

const ANALYSTS = [
  { rank: 1, name: "Stacy Rasgon", firm: "Bernstein Research", side: "SELL-SIDE", sectors: "Semiconductors", hit: 71, avg: "+9,4 %", n: 142, stars: 5,
    bio: "Covers global semis; the desk's reference voice on Nvidia gross-margin scenarios. Followed in our AI-cycle saga since 2025.",
    calls: [["18. mai", "NVDA", "BUY", "$1 050", "+12,1 %", "18. aug", true], ["2. apr", "AMD", "HOLD", "$162", "+1,8 %", "2. jul", true], ["12. feb", "INTC", "SELL", "$19", "+8,4 %", "12. mai", false]] },
  { rank: 2, name: "Ingrid Solberg", firm: "SEB Equities", side: "SELL-SIDE", sectors: "Energy · Oslo", hit: 68, avg: "+7,8 %", n: 96, stars: 5,
    bio: "Lead Equinor/Aker BP coverage. Early on the gas-trading optionality thesis our auto-research later confirmed.",
    calls: [["2. jun", "EQNR", "BUY", "NOK 312", "+4,2 %", "2. sep", true], ["14. mai", "AKER", "BUY", "NOK 660", "+2,8 %", "14. aug", true], ["28. mar", "VAR", "HOLD", "NOK 40", "−1,1 %", "28. jun", true]] },
  { rank: 3, name: "Mads Eriksen", firm: "Folketrygdfondet", side: "BUY-SIDE", sectors: "Industrials · Defence", hit: 66, avg: "+11,2 %", n: 41, stars: 4,
    bio: "Buy-side PM whose disclosed defence positioning front-ran the NATO re-rating. Tracked via filings + public commentary.",
    calls: [["8. apr", "KOG", "BUY", "—", "+18,6 %", "8. okt", true], ["20. feb", "SAAB", "BUY", "—", "+9,2 %", "20. aug", true]] },
  { rank: 4, name: "Charlotte Berg", firm: "DNB Markets", side: "SELL-SIDE", sectors: "Banks · Financials", hit: 63, avg: "+5,1 %", n: 118, stars: 4,
    bio: "Norges Bank rate-path readthrough to bank NII; the November-cut call shaped consensus.",
    calls: [["4. jun", "DNB", "BUY", "NOK 214", "+1,9 %", "4. sep", true], ["8. mai", "SRBNK", "HOLD", "NOK 152", "+0,4 %", "8. aug", true], ["20. jan", "STB", "BUY", "NOK 124", "−2,2 %", "20. apr", false]] },
  { rank: 5, name: "Erik Wold", firm: "Pareto Securities", side: "SELL-SIDE", sectors: "Seafood · Shipping", hit: 59, avg: "+4,6 %", n: 87, stars: 3,
    bio: "Salmon-cycle specialist; biology-led framework with explicit downside triggers.",
    calls: [["28. mai", "MOWI", "HOLD", "NOK 176", "−0,8 %", "28. aug", true], ["2. mai", "SALM", "BUY", "NOK 660", "+3,1 %", "2. aug", true], ["4. mar", "FRO", "BUY", "$24", "−4,6 %", "4. jun", false]] },
  { rank: 6, name: "Anna Lindqvist", firm: "Kepler Cheuvreux", side: "SELL-SIDE", sectors: "Materials · Chemicals", hit: 56, avg: "+3,2 %", n: 64, stars: 3,
    bio: "Rare-earth substitution and aluminium supply; trimmed targets ahead of the May licensing tightening.",
    calls: [["14. mai", "NHY", "HOLD", "NOK 64", "+1,2 %", "14. aug", true], ["2. apr", "YAR", "BUY", "NOK 380", "+0,6 %", "2. jul", true]] },
];

function AnTone(v) { return v >= 65 ? "var(--data-up)" : v >= 58 ? "var(--brand-accent)" : "var(--fg-3)"; }
function AnAvatar({ name, size }) {
  const init = name.split(" ").map(w => w[0]).join("");
  const hues = ["#1F8A5B", "#2A6FDB", "#8A4FBF", "#B4631B", "#3E7C8A", "#7A4242"];
  const h = hues[(name.charCodeAt(0) + name.length) % hues.length];
  return <span aria-hidden="true" style={{ width: size, height: size, flexShrink: 0, display: "inline-flex", alignItems: "center", justifyContent: "center", background: h, color: "#fff", fontFamily: "var(--font-display)", fontWeight: 800, fontSize: size * 0.36, letterSpacing:"-0.01em" }}>{init}</span>;
}

function AnalystsPage() {
  React.useEffect(() => { document.title = "Analysts — Handelsavisen"; }, []);
  const [open, setOpen] = React.useState(null);
  const [side, setSide] = React.useState("All");
  const rows = ANALYSTS.filter(a => side === "All" || a.side === side);
  return (
    <React.Fragment>
      <Masthead active="companies" />
      <TickerTape />
      <IndicativeRibbon />
      <main className="container" style={{ paddingTop: 24, paddingBottom: 60 }}>
        <div className="eyebrow" style={{ marginBottom: 8 }}>Companies · Analyst rankings</div>
        <div style={{ display: "flex", alignItems: "flex-end", justifyContent: "space-between", flexWrap: "wrap", gap: 16, borderBottom: "2px solid var(--fg-1)", paddingBottom: 14 }}>
          <div>
            <h1 style={{ fontFamily: "var(--font-display)", fontFeatureSettings: "var(--feat-display)", fontSize: 42, fontWeight: 800, letterSpacing:"-0.02em", lineHeight: 1.02, margin: 0, color: "var(--fg-1)" }}>Analysts, ranked.</h1>
            <p style={{ fontFamily: "var(--font-sans)", fontSize: 14.5, color: "var(--fg-2)", margin: "8px 0 0", maxWidth: 640, textWrap: "pretty" }}>Every buy- and sell-side analyst covering our universe, scored on what their calls actually did — and every note carries an expiry date, because research goes stale.</p>
          </div>
          <div role="group" aria-label="Filter by side" style={{ display: "flex", gap: 6 }}>
            {["All", "SELL-SIDE", "BUY-SIDE"].map(s => (
              <button key={s} onClick={() => setSide(s)} aria-pressed={side === s} style={{ fontFamily: "var(--font-sans)", fontSize: 11.5, fontWeight: 600, padding: "6px 13px", borderRadius: 999, cursor: "pointer", background: side === s ? "var(--fg-1)" : "transparent", color: side === s ? "var(--bg-page)" : "var(--fg-3)", border: "1px solid " + (side === s ? "var(--fg-1)" : "var(--rule)") }}>{s === "All" ? "All" : s === "SELL-SIDE" ? "Sell-side" : "Buy-side"}</button>
            ))}
          </div>
        </div>

        {/* Stats band */}
        <div style={{ display: "grid", gridTemplateColumns: "repeat(4,1fr)", border: "1px solid var(--rule)", borderTop: "none", marginBottom: 22 }}>
          {[["Analysts tracked", "248"], ["Avg hit rate", "57 %"], ["Calls with outcomes", "12 400"], ["Notes expiring this month", "61"]].map(([l, v], i) => (
            <div key={l} style={{ padding: "11px 14px", borderRight: i < 3 ? "1px solid var(--rule)" : "none" }}>
              <div style={{ fontFamily: "var(--font-sans)", fontSize: 9.5, fontWeight: 700, letterSpacing: "0.08em", textTransform: "uppercase", color: "var(--fg-3)" }}>{l}</div>
              <div style={{ fontFamily: "var(--font-mono)", fontSize: 17, fontWeight: 700, color: "var(--fg-1)", marginTop: 3 }}>{v}</div>
            </div>
          ))}
        </div>

        {/* Ranked list */}
        <div style={{ border: "1px solid var(--rule)", background: "var(--bg-elev-1)" }} data-ssi-slot="analyst-rankings">
          {rows.map((a, i) => {
            const isOpen = open === a.rank;
            return (
              <div key={a.rank} style={{ borderBottom: i < rows.length - 1 ? "1px solid var(--rule)" : "none" }}>
                <button onClick={() => setOpen(isOpen ? null : a.rank)} aria-expanded={isOpen} data-kb-row style={{ display: "grid", gridTemplateColumns: "44px 34px 1fr 110px 90px 90px 70px 24px", gap: 12, alignItems: "center", width: "100%", textAlign: "left", padding: "12px 16px", background: isOpen ? "var(--bg-elev-2)" : "transparent", border: "none", cursor: "pointer" }}>
                  <span style={{ fontFamily: "var(--font-mono)", fontSize: 16, fontWeight: 700, color: a.rank <= 3 ? "var(--brand-accent)" : "var(--fg-3)" }}>#{a.rank}</span>
                  <AnAvatar name={a.name} size={34} />
                  <span style={{ minWidth: 0 }}>
                    <span style={{ display: "block", fontFamily: "var(--font-sans)", fontSize: 14.5, fontWeight: 700, color: "var(--fg-1)" }}>{a.name}</span>
                    <span style={{ fontFamily: "var(--font-sans)", fontSize: 11, color: "var(--fg-3)" }}>{a.firm} · <span style={{ fontWeight: 700, color: a.side === "BUY-SIDE" ? "var(--color-blue,#2563EB)" : "var(--fg-2)" }}>{a.side.toLowerCase()}</span> · {a.sectors}</span>
                  </span>
                  <span aria-label={a.stars + " of 5 stars"} style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: 2, color: "var(--brand-accent)" }}>{"★".repeat(a.stars)}<span style={{ color: "var(--rule-strong)" }}>{"★".repeat(5 - a.stars)}</span></span>
                  <span style={{ textAlign: "right" }}><span style={{ fontFamily: "var(--font-mono)", fontSize: 14, fontWeight: 700, color: AnTone(a.hit) }}>{a.hit} %</span><span style={{ display: "block", fontFamily: "var(--font-sans)", fontSize: 8.5, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--fg-4)" }}>hit rate</span></span>
                  <span style={{ textAlign: "right" }}><span style={{ fontFamily: "var(--font-mono)", fontSize: 14, fontWeight: 700, color: "var(--data-up)" }}>{a.avg}</span><span style={{ display: "block", fontFamily: "var(--font-sans)", fontSize: 8.5, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--fg-4)" }}>avg return</span></span>
                  <span style={{ textAlign: "right" }}><span style={{ fontFamily: "var(--font-mono)", fontSize: 14, fontWeight: 600, color: "var(--fg-2)" }}>{a.n}</span><span style={{ display: "block", fontFamily: "var(--font-sans)", fontSize: 8.5, textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--fg-4)" }}>calls</span></span>
                  <span aria-hidden="true" style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--fg-4)", textAlign: "center" }}>{isOpen ? "▴" : "▾"}</span>
                </button>
                {isOpen && (
                  <div style={{ display: "grid", gridTemplateColumns: "150px 1fr", gap: 20, padding: "16px 16px 18px", borderTop: "1px solid var(--rule)" }}>
                    <div>
                      <AnAvatar name={a.name} size={150} />
                      <div style={{ fontFamily: "var(--font-mono)", fontSize: 8.5, letterSpacing: "0.07em", color: "var(--fg-4)", marginTop: 6 }}>PORTRAIT TO COME</div>
                    </div>
                    <div style={{ minWidth: 0 }}>
                      <p style={{ fontFamily: "var(--font-sans)", fontSize: 13.5, lineHeight: 1.55, color: "var(--fg-2)", margin: "0 0 12px", maxWidth: 620 }}>{a.bio}</p>
                      <div style={{ fontFamily: "var(--font-sans)", fontSize: 9.5, fontWeight: 700, letterSpacing: "0.10em", textTransform: "uppercase", color: "var(--fg-3)", marginBottom: 6 }}>Recent calls · outcome measured to target horizon · <a href={"alerts.html?sym=" + a.name.split(" ").pop().toUpperCase() + "&cond=rating%20change"} style={{ color: "var(--brand-accent)", textDecoration: "none", textTransform: "none", letterSpacing: 0 }}>notify on rating change →</a></div>
                      {a.calls.map((c, j) => (
                        <div key={j} style={{ display: "grid", gridTemplateColumns: "56px 52px 46px 70px 70px 1fr", gap: 10, alignItems: "baseline", padding: "7px 0", borderBottom: j < a.calls.length - 1 ? "1px solid var(--rule)" : "none" }}>
                          <span style={{ fontFamily: "var(--font-mono)", fontSize: 10.5, color: "var(--fg-3)" }}>{c[0]}</span>
                          <a href={"company.html?sym=" + c[1]} style={{ fontFamily: "var(--font-mono)", fontSize: 11, fontWeight: 700, color: "var(--brand-accent)", textDecoration: "none" }}>{c[1]}</a>
                          <span style={{ fontFamily: "var(--font-sans)", fontSize: 10.5, fontWeight: 700, color: c[2] === "BUY" ? "var(--data-up)" : c[2] === "SELL" ? "var(--color-red-a11y,#FCA5A5)" : "var(--fg-3)" }}>{c[2]}</span>
                          <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, color: "var(--fg-2)", textAlign: "right" }}>{c[3]}</span>
                          <span style={{ fontFamily: "var(--font-mono)", fontSize: 11.5, fontWeight: 700, textAlign: "right", color: String(c[4]).startsWith("−") ? "var(--data-down)" : "var(--data-up)" }}>{c[4]}</span>
                          <span style={{ textAlign: "right" }}>
                            <span style={{ fontFamily: "var(--font-mono)", fontSize: 9, fontWeight: 700, letterSpacing: "0.05em", padding: "2px 8px", borderRadius: 999, color: c[6] ? "var(--data-up)" : "var(--fg-4)", border: "1px solid " + (c[6] ? "var(--data-up)" : "var(--rule)") }}>{c[6] ? "ACTIVE · expires " + c[5] : "EXPIRED " + c[5]}</span>
                          </span>
                        </div>
                      ))}
                      <div style={{ fontFamily: "var(--font-sans)", fontSize: 10.5, color: "var(--fg-4)", marginTop: 10 }}>Expiry = the note's stated target horizon; expired research is excluded from the live consensus on company pages.</div>
                    </div>
                  </div>
                )}
              </div>
            );
          })}
        </div>
        <p style={{ fontFamily: "var(--font-mono)", fontSize: 10, color: "var(--fg-4)", marginTop: 14 }}>Rankings from outcome-measured public calls and disclosed positions · methodology public · indicative sample data</p>
      </main>
      <Footer />
    </React.Fragment>
  );
}

const root = ReactDOM.createRoot(document.getElementById("app"));
root.render(<AnalystsPage />);
