The Nordic Pulse | 2026:17
Idag, 08:26
Idag, 08:26
The post The Nordic Pulse | 2026:17 appeared first on Biostock.
Nordic Life Science Weekly
Key Insights1. Market Snapshot2. Major Events3. Financial Impact4. Dev & Research5. Catalyst WatchReferencesReport data pending
Report data pending
Company | Weekly Chg |
Report data pending
No eligible events this week
Report data pending
Report data pending
Report data pending
BinaryLarge price move likelyAsymmetricPartially pricedIncrementalLower impactReport data pending
const meta = { reportTitle: "BioStock Nordic Life Science Weekly – Week 17, 2026", weekLabel: "Week 17, 2026", dateRange: "20–26 April 2026", heroTitle: "Orion advances ODM-212,\nColoplast warns on Kerecis", heroLead: "Orion received an FDA Orphan Drug Designation and initiated a combination basket trial for ODM-212. Ascendis completed its ADS-to-ordinary-share exchange and called $575 million in convertible notes for redemption. Coloplast cut guidance and wrote down DKK 3.0 billion against Kerecis. All three sector benchmarks fell roughly 3.6–3.9 per cent.", summaryTitle: "The week in six data points", summaryDesc: "A risk-off week across Nordic life science saw broad index declines of 3.6–3.9 per cent. Orion's dual pipeline advances in oncology contrasted with Coloplast's material guidance cut. Capital markets activity centred on Ascendis's convertible note redemption and two Nordic rights issues.", marketSubtitle: "Week-over-week index returns, Friday close 24 April 2026", marketSourceNote: "Sources: Nasdaq, HealthCap Nordic HC SEK GI. All figures reflect Friday closing levels.", eventsSubtitle: "20–26 April 2026", methodologyText: "This week's report covers Nordic life science events distributed via MFN, Cision, and GlobeNewswire during the reporting interval (2026-04-20\u20132026-04-26). 7 event(s) were excluded due to insufficient material relevance (routine share buy-back transactions, standard AGM notices, routine share repurchase programme updates, and routine incentive programme grants). All index data reflects official closing levels as described in the methodology note above.", catalystNote: "Hansa Biopharma's imlifidase PDUFA target date (19 December 2026) falls outside the 6-week horizon but remains a key sector catalyst to monitor. The ConfIdeS phase III oral presentation at ATC in June 2026 may provide an interim read-through.", liquidityText: "Moberg Pharma (+17.46%): The week's strongest gainer. Moberg Pharma's Terclara nail fungus treatment achieved a 42 per cent value share in Sweden and a 34 per cent value share in Norway for the full year 2025, and the company entered an exclusive licence agreement with Karo Healthcare in November 2025 covering 19 European markets for a coordinated rollout under the Lamisil brand.\n\nCellaVision (\u201325.62%): CellaVision reported its Q1 2026 results during the week, with net sales of SEK 166 million, a 14.6 per cent decline from the prior year. The EMEA region declined 32 per cent, attributed to inventory adjustments with the company's main distribution partner.\n\nHansa Biopharma (\u201313.57%): Hansa Biopharma reported its Q1 2026 results during the week. First-quarter revenue totalled SEK 34.6 million versus SEK 66.3 million in Q1 2025, with IDEFIRIX product sales of SEK 33.9 million versus SEK 65.7 million in Q1 2025. The revenue decline reflects the expected short-term impact of a European commercial reorganisation.\n\nPCI Biotech (\u201325.81%): The week's steepest decliner. The move occurred against low liquidity conditions typical for micro-cap companies, and no specific in-interval press release was identified.", liquidityRefIds: [ ["moberg-year-end-2025","moberg-karo-license"], ["cellavision-q1-2026"], ["hansa-q1-2026"], [] ], aiDisclosure: "This report's information has been sourced with AI, screened and verified by the BioStock editorial team." }; const reportData = { keyInsights: [ { label: "Orion advanced its oncology pipeline on two fronts:", text: "ODM-212 received Orphan Drug Designation from the US FDA for mesothelioma, and the company initiated the TEADCO phase Ib/II basket trial evaluating ODM-212 in combination with standard of care in mesothelioma, KRAS G12C-mutated NSCLC, and pancreatic cancer.", refIds: ["orion-odd-mesothelioma","orion-teadco-trial"] }, { label: "Ascendis Pharma completed a dual structural event:", text: "the company mandatorily exchanged all outstanding ADSs for ordinary shares, commencing direct trading on Nasdaq on 20 April, and one day later called all $575.0 million of its outstanding 2.25% Convertible Senior Notes due 2028 for redemption on 6 May 2026.", refIds: ["ascendis-ordinary-shares","ascendis-convertible-redemption"] }, { label: "Coloplast issued a profit warning,", text: "cutting FY 2025/26 organic growth guidance to 5\u20136 per cent from approximately 7 per cent, and EBIT growth to approximately 5 per cent from approximately 7 per cent, accompanied by a DKK 3.0 billion goodwill impairment against Kerecis.", refIds: ["coloplast-guidance-cut"] }, { label: "Elicera Therapeutics announced a rights issue of approximately SEK 72.8 million", text: "to complete the ongoing CARMA study and advance preparations for a planned phase I/Ib clinical trial of ELC-401.", refIds: ["elicera-rights-issue"] }, { label: "AlzeCure Pharma announced a rights issue of approximately SEK 30.1 million", text: "t to strengthen the cash position and provide resources for business development, pending discussions around licensing and collaboration agreements.", refIds: ["alzecure-rights-issue"] }, { label: "Nordic health care indices declined broadly,", text: "with the Nordic HC SEK GI down \u20133.57 per cent, NBI down \u20133.79 per cent, and XBI down \u20133.89 per cent, amid persistent macro headwinds. CellaVision and Hansa Biopharma were the sharpest decliners following weak Q1 reports.", refIds: ["cellavision-q1-2026","hansa-q1-2026"] } ], summaryCards: [ { label: "Index Move", text: "Broad risk-off sentiment drove all three benchmarks down 3.6\u20133.9 per cent week-over-week." }, { label: "Top Gainer", text: "Moberg Pharma +17.46 per cent \u2013 continued positive sentiment around European commercial expansion for Terclara." }, { label: "Top Decliner", text: "PCI Biotech \u201325.81 per cent, a steep drop on thin micro-cap liquidity with no identified in-interval catalyst." }, { label: "Regulatory", text: "Orion\u2019s ODM-212 granted FDA Orphan Drug Designation for mesothelioma, conferring 7-year market exclusivity eligibility." }, { label: "Capital Markets", text: "Ascendis called $575 million in convertible notes for redemption; Bioretec gained gross proceeds of ~EUR 13 million from a rights issue; Elicera and AlzeCure announces upcoming rights issues." }, { label: "Guidance Change", text: "Coloplast cut FY 2025/26 organic growth to 5\u20136 per cent and recognised a DKK 3.0 billion goodwill impairment against Kerecis." } ], marketPills: [ { label: "NBI", value: "\u20133.79%", direction: "down", fullName: "NASDAQ Biotechnology (NBI)" }, { label: "Nordic HC SEK GI", value: "\u20133.57%", direction: "down", fullName: "Nordic HC SEK GI" }, { label: "XBI", value: "\u20133.89%", direction: "down", fullName: "SPDR S&P Biotech ETF (XBI)" } ], marketSeries: { labels: ["Wk 17"], indices: [ { key: "NBI", name: "NASDAQ Biotechnology (NBI)", data: [-3.79] }, { key: "NordicHC", name: "Nordic HC SEK GI", data: [-3.57] }, { key: "XBI", name: "SPDR S&P Biotech ETF (XBI)", data: [-3.89] } ] }, moversTable: [ { company: "Moberg Pharma", chg: 17.46 }, { company: "Vitrolife", chg: 7.31 }, { company: "ALK-Abell\u00f3", chg: 7.01 }, { company: "SynAct Pharma", chg: 6.78 }, { company: "Lundbeck", chg: 4.38 }, { company: "Sprint Bioscience", chg: -12.98 }, { company: "Hansa Biopharma", chg: -13.57 }, { company: "Immunovia", chg: -13.83 }, { company: "CellaVision", chg: -25.62 }, { company: "PCI Biotech", chg: -25.81 } ], events: [ { title: "Orion Corporation \u2013 ODM-212 receives FDA Orphan Drug Designation for mesothelioma", tag: "Regulatory", text: "Orion Pharma announced that ODM-212 received Orphan Drug Designation from the US FDA for the treatment of mesothelioma. ODM-212 is an oral small-molecule pan-TEAD inhibitor being tested in a phase II clinical study (TEADES) for malignant pleural mesothelioma, epithelioid hemangioendothelioma, and other solid tumours with Hippo pathway dysfunction.", implication: "The designation confers incentives including tax credits, user fee exemptions, and eligibility for a 7-year period of market exclusivity following approval.", marketReaction: null, source: "GlobeNewswire, 20 Apr 2026", refIds: ["orion-odd-mesothelioma"] }, { title: "Orion Corporation \u2013 TEADCO phase Ib/II basket trial initiated", tag: "Clinical", text: "Orion announced initiation of TEADCO, a phase Ib/II basket trial evaluating ODM-212 in combination with standard of care in advanced mesothelioma, KRAS G12C-mutated NSCLC, and pancreatic cancer. The first cohort evaluates ODM-212 in combination with ipilimumab and nivolumab as a first-line treatment for advanced malignant pleural mesothelioma.", implication: "The trial broadens the clinical programme from monotherapy (TEADES) to combination regimens across multiple tumour types.", marketReaction: null, source: "GlobeNewswire, 23 Apr 2026", refIds: ["orion-teadco-trial"] }, { title: "Ascendis Pharma \u2013 Redemption of $575 million convertible notes", tag: "Financing", text: "Ascendis Pharma called all $575.0 million of its outstanding 2.25% Convertible Senior Notes due 2028 for redemption on 6 May 2026, triggered after the share price exceeded 130 per cent of the conversion price on at least 20 of the prior 30 trading days.", implication: "Noteholders may convert at an enhanced rate of 6.3232 shares per $1,000 during the make-whole period, equivalent to approximately $158.15 per share, potentially resulting in up to 3.64 million new shares. The move deleverages the balance sheet but introduces near-term dilution risk.", marketReaction: null, source: "GlobeNewswire, 21 Apr 2026", refIds: ["ascendis-convertible-redemption"] }, { title: "Ascendis Pharma \u2013 Ordinary shares commence Nasdaq trading", tag: "Corporate", text: "Ascendis Pharma commenced trading of its ordinary shares on the Nasdaq Global Select Market, replacing the listing of American Depositary Shares. The ordinary shares trade under the same ticker symbol \u201cASND\u201d. As of 20 April 2026, the company had exchanged all outstanding ADSs for ordinary shares.", implication: "The direct listing is intended to facilitate potential equity index inclusion and broaden institutional access.", marketReaction: null, source: "GlobeNewswire, 20 Apr 2026", refIds: ["ascendis-ordinary-shares"] }, { title: "Coloplast \u2013 Guidance cut and DKK 3.0 billion Kerecis impairment", tag: "Corporate", text: "Coloplast cut FY 2025/26 guidance, now expecting 5\u20136 per cent organic growth (from approximately 7 per cent) and approximately 5 per cent EBIT growth in constant currencies (from approximately 7 per cent). The company recognised a DKK 3.0 billion goodwill impairment against Kerecis, reducing its carrying book value to approximately DKK 6 billion.", implication: "The impairment reflects significant sales disruption from the Medicare reimbursement change in the outpatient setting.", marketReaction: null, source: "GlobeNewswire, 23 Apr 2026", refIds: ["coloplast-guidance-cut"] }, { title: "Elicera Therapeutics \u2013 Rights issue of approximately SEK 72.8 million", tag: "Financing", text: "Elicera\u2019s Board of Directors resolved to carry out a rights issue of approximately SEK 72.8 million to complete the ongoing CARMA study and advance preparations for a planned phase I/Ib clinical trial of ELC-401.", implication: "The rights issue is covered to 75.0 per cent by subscription undertakings and guarantee commitments. The subscription price is SEK 3.0 per share, representing a discount of approximately 31.4 per cent to the theoretical ex-rights price.", marketReaction: null, source: "Cision, 21 Apr 2026", refIds: ["elicera-rights-issue"] }, { title: "AlzeCure Pharma \u2013 Rights issue of approximately SEK 30.1 million", tag: "Financing", text: "AlzeCure Pharma\u2019s Board of Directors resolved to carry out a fully secured rights issue of approximately SEK 30.1 million to strengthen the company's cash position and intensify out-licensing efforts, pending active discussions with several external parties regarding potential licensing and collaboration agreements.", implication: "The rights issue is fully secured to 100 per cent by subscription undertakings from existing shareholders, board members and management, together with guarantee commitments from the company's two largest shareholders. The subscription price is SEK 1.31 per share, representing a discount of approximately 6 per cent to the theoretical ex-rights price.", marketReaction: null, source: "MFN, 21 Apr 2026", refIds: ["alzecure-rights-issue"] }, { title: "Bioretec \u2013 Rights issue completed at 87.1 per cent subscription", tag: "Financing", text: "Bioretec\u2019s rights issue attracted subscriptions for approximately 87.1 per cent of the 1,477,828,416 new shares offered. The company will receive gross proceeds of approximately EUR 12.9 million from the offering.", implication: "The total number of shares will increase from 30,788,092 to 1,341,785,963, with new shares representing approximately 97.7 per cent of all shares following completion \u2013 a significant dilutive event for existing shareholders.", marketReaction: null, source: "Cision, 23\u201324 Apr 2026", refIds: ["bioretec-rights-issue"] } ], finance: [ { company: "Ascendis Pharma", tag: "Capital Raise", tagTone: "grey", text: "The $575 million convertible note redemption is a balance sheet restructuring event. The notes will be redeemed on 6 May 2026, with noteholders receiving cash equal to 100 per cent of principal plus accrued interest, or the option to convert into ordinary shares. If fully converted during the make-whole period, up to 3,635,840 ordinary shares could be issued. The redemption eliminates the 2.25 per cent coupon obligation and simplifies the capital structure but may pressure the stock near-term through conversion-related flows.", source: "GlobeNewswire, 21 Apr 2026", refIds: ["ascendis-convertible-redemption"] }, { company: "Elicera Therapeutics", tag: "Capital Raise", tagTone: "green", text: "The SEK 72.8 million rights issue, covered to 75.0 per cent by subscription undertakings and guarantees, is designed to fund operations through the completion of the CARMA study and initial preparation for ELC-401. The secured amount is expected to finance operations through the end of 2028.", source: "Cision, 21 Apr 2026", refIds: ["elicera-rights-issue"] }, { company: "AlzeCure Pharma", tag: "Capital Raise", tagTone: "green", text: "The SEK 30.1 million rights issue, fully secured to 100 per cent by subscription undertakings from existing shareholders, board members and management, together with guarantee commitments from the two largest shareholders, is designed to strengthen AlzeCure's cash position and intensify out-licensing efforts for its drug candidates. No compensation is payable in connection with the guarantee commitments.", source: "MFN, 21 Apr 2026", refIds: ["alzecure-rights-issue"] }, { company: "Bioretec", tag: "Capital Raise", tagTone: "red", text: "The EUR 12.9 million rights issue results in new shares representing approximately 97.7 per cent of all shares post-completion, implying substantial dilution. Proceeds are earmarked for expanding the commercial offering for RemeOs and building a stronger US-based commercial organisation.", source: "Cision, 23\u201324 Apr 2026", refIds: ["bioretec-rights-issue"] }, { company: "Coloplast", tag: "Valuation Shift", tagTone: "red", text: "Coloplast recognised an impairment loss of DKK 3.0 billion against Kerecis goodwill, with total carrying book value now approximately DKK 6 billion. The write-down, combined with flattened Kerecis sales assumptions, recalibrates market expectations for the biologics wound care acquisition.", source: "GlobeNewswire, 23 Apr 2026", refIds: ["coloplast-guidance-cut"] } ], research: { biotech: [ { title: "Orion Corporation \u2013 ODM-212 dual pipeline advancement", badge: "Phase Ib/II", text: "Orion advanced ODM-212 on two parallel tracks within the same week. ODM-212 is currently in a phase II study (TEADES) for malignant pleural mesothelioma, epithelioid hemangioendothelioma, and other Hippo-pathway-dysregulated solid tumours. The FDA Orphan Drug Designation provides regulatory incentives for the mesothelioma indication. The newly initiated TEADCO trial is a multi-centre, open-label basket trial designed to evaluate efficacy, safety, dose, and tolerability of ODM-212 in combination with standard of care across three tumour types. This broadens the clinical data set from monotherapy to combination settings and represents an important expansion of Orion\u2019s oncology pipeline.", source: "GlobeNewswire, 20 & 23 Apr 2026", refIds: ["orion-odd-mesothelioma","orion-teadco-trial"] }, { title: "Elicera Therapeutics \u2013 CAR T-cell programme advancement", badge: "Pre-clinical / phase I prep", text: "Elicera continues to advance its CAR T-cell programme. The company is simultaneously preparing for a phase I/Ib dose-escalation/expansion trial of ELC-401 for the treatment of glioblastoma. Preclinical development was concluded in February 2026, and a scientific advice meeting with the Swedish MPA is scheduled for mid-June 2026.", source: "Cision, 21 Apr 2026", refIds: ["elicera-rights-issue"] }, { title: "AlzeCure Pharma \u2013 CNS pipeline advancement", badge: "Phase IIa", text: "AlzeCure continues to advance its CNS drug pipeline across three research platforms. The company is preparing NeuroRestore ACD856 for a planned phase IIa clinical study in patients with early Alzheimer's disease, co-funded by the European Innovation Council. In the pain area, ACD440 has received orphan drug designation from both the FDA and EMA for erythromelalgia, with positive FDA feedback received for a registration-enabling phase IIb/III study and active out-licensing discussions ongoing.", source: "MFN, 21 Apr 2026", refIds: ["alzecure-rights-issue"] } ], medtech: [ { title: "Vitrolife \u2013 Q1 2026 interim results", badge: "Earnings", text: "Vitrolife reported Q1 2026 sales of SEK 807 million, an increase of 5 per cent in local currencies. Gross margin increased to 59.9 per cent, and organic growth in the Americas reached 11 per cent. The market responded positively, contributing to Vitrolife\u2019s +7.31 per cent weekly gain.", source: "Cision, Q1 2026 interim report", refIds: ["vitrolife-q1-2026"] }, { title: "Bioretec \u2013 RemeOs platform commercial expansion", badge: "Commercial", text: "Bioretec completed its rights issue with the ~EUR 13 million proceeds directed toward expanding the RemeOs biodegradable implant platform\u2019s commercial reach and building a US-based commercial organisation.", source: "Cision, 23\u201324 Apr 2026", refIds: ["bioretec-rights-issue"] } ] }, catalysts: [ { date: "4\u20136 May 2026", company: "Ascendis Pharma", event: "Convertible note conversion period closes 4 May; cash redemption date 6 May. The split between cash redemption and equity conversion will determine near-term dilution impact.", type: "Binary", accent: "teal" }, { date: "5 May 2026", company: "Vitrolife", event: "Annual General Meeting.", type: "Incremental", accent: "light" }, { date: "8 May 2026", company: "Elicera Therapeutics", event: "Extraordinary general meeting to approve the rights issue; MPA scientific advice meeting for ELC-401 scheduled mid-June.", type: "Incremental", accent: "light" }, { date: "12 May 2026", company: "Coloplast", event: "H1 2025/26 Interim Report \u2013 market will reassess Kerecis trajectory following the guidance cut and DKK 3.0 billion impairment.", type: "Asymmetric", accent: "gold" }, { date: "June 2026", company: "Hansa Biopharma", event: "ConfIdeS phase III results accepted for oral presentation at ATC. Imlifidase FDA BLA PDUFA target date is 19 December 2026.", type: "Binary", accent: "teal" } ], refs: [ { section: "Major Events & News", items: [ { id: "orion-odd-mesothelioma", citation: "Orion Pharma \u2013 ODM-212 granted Orphan Drug Designation in mesothelioma by the US FDA.", url: "https://www.globenewswire.com/news-release/2026/04/20/3277035/0/en/orion-pharma-s-odm-212-granted-orphan-drug-designation-in-mesothelioma-by-the-us-fda.html", accessed: "26 Apr 2026" }, { id: "orion-teadco-trial", citation: "Orion Pharma initiates TEADCO phase Ib/II basket trial evaluating ODM-212 in combination with standard of care treatments.", url: "https://www.globenewswire.com/news-release/2026/04/23/3279581/0/en/Orion-Pharma-initiates-TEADCO-Phase-1b-2-basket-trial-evaluating-ODM-212-in-combination-with-standard-of-care-treatments-in-patients-with-select-advanced-solid-tumours.html", accessed: "26 Apr 2026" }, { id: "ascendis-ordinary-shares", citation: "Ascendis Pharma announces commencement of trading of its ordinary shares on Nasdaq.", url: "https://www.globenewswire.com/news-release/2026/04/20/3276963/0/en/ascendis-pharma-announces-commencement-of-trading-of-its-ordinary-shares-on-nasdaq.html", accessed: "26 Apr 2026" }, { id: "ascendis-convertible-redemption", citation: "Ascendis announces redemption of all $575 million of outstanding 2.25% Convertible Senior Notes due 2028.", url: "https://www.globenewswire.com/news-release/2026/04/21/3278485/0/en/Ascendis-Announces-Redemption-of-All-575-Million-of-Outstanding-2-25-Convertible-Senior-Notes-Due-2028.html", accessed: "26 Apr 2026" }, { id: "coloplast-guidance-cut", citation: "Coloplast revises financial guidance for FY 2025/26 to reflect reduced growth outlook for Kerecis.", url: "https://www.globenewswire.com/news-release/2026/04/23/3280301/0/en/Coloplast-A-S-Coloplast-revises-financial-guidance-for-FY-2025-26-to-reflect-reduced-growth-outlook-for-Kerecis.html", accessed: "26 Apr 2026" }, { id: "elicera-rights-issue", citation: "Elicera Therapeutics carries out a rights issue of approximately SEK 73 million.", url: "https://news.cision.com/elicera-therapeutics/r/elicera-therapeutics-carries-out-a-rights-issue-of-approximately-sek-73-million,c4337398", accessed: "26 Apr 2026" }, { id: "alzecure-rights-issue", citation: "AlzeCure Pharma carries out a fully secured rights issue of approximately SEK 30.1 million.", url: "https://mfn.se/a/alzecure-pharma/alzecure-pharma-carries-out-a-fully-secured-rights-issue-of-approximately-sek-30-1-million", accessed: "26 Apr 2026" }, { id: "bioretec-rights-issue", citation: "Final results of Bioretec Ltd\u2019s rights issue.", url: "https://news.cision.com/bioretec/r/final-results-of-bioretec-ltd-s-rights-issue,c4340113", accessed: "26 Apr 2026" } ] }, { section: "Liquidity & Volatility", items: [ { id: "cellavision-q1-2026", citation: "CellaVision \u2013 Softer quarter due to lower sales in EMEA (Interim Report Q1 2026). MFN, 24 April 2026.", url: "https://mfn.se/a/cellavision/softer-quarter-due-to-lower-sales-in-emea", accessed: "26 Apr 2026" }, { id: "hansa-q1-2026", citation: "Hansa Biopharma rapporterar finansiella resultat f\u00f6r f\u00f6rsta kvartalet 2026 (Interim Report Q1 2026). Cision, 23 April 2026.", url: "https://news.cision.com/se/hansa-biopharma-ab/r/hansa-biopharma-rapporterar-finansiella-resultat-for-forsta-kvartalet-2026,c4338924", accessed: "26 Apr 2026" }, { id: "moberg-year-end-2025", citation: "Moberg Pharma Year-end report 2025 (full-year market share data for Terclara). Cision, 17 February 2026.", url: "https://news.cision.com/moberg-pharma/r/moberg-pharma-year-end-report-2025,c4308335", accessed: "26 Apr 2026" }, { id: "moberg-karo-license", citation: "Moberg Pharma and Karo Healthcare enter exclusive license agreement for MOB-015/Terclara in Europe. Cision, 5 November 2025.", url: "https://news.cision.com/moberg-pharma/r/moberg-pharma-and-karo-healthcare-enter-exclusive-license-agreement-for-mob-015-terclara-in-europe--,c4261942", accessed: "26 Apr 2026" } ] }, { section: "Development & Research", items: [ { id: "vitrolife-q1-2026", citation: "Vitrolife AB \u2013 Interim report Q1 2026: strong growth in consumables and technologies.", url: "https://news.cision.com/vitrolife-ab--publ-/r/interim-report-q1--2026--strong-growth-in-consumables-and-technologies,c4338311", accessed: "26 Apr 2026" } ] } ] }; // ================================================================= // UTILITIES // ================================================================= const $ = id => document.getElementById(id); const show = el => el && el.classList.remove('hidden'); const hide = el => el && el.classList.add('hidden'); const el = (tag, cls) => { const e = document.createElement(tag); if (cls) e.className = cls; return e; }; const txt = (e, t) => { e.textContent = t == null ? "" : String(t); }; function safeUrl(url) { const u = (url || "").trim(); if (!u) return ""; try { new URL(u); return u; } catch (e) { return ""; } } // ================================================================= // REFERENCE MAP — built once at boot from refs[]. // Maps each ref id to {number, anchorId} based on render order. // ================================================================= const refMap = {}; function buildRefMap() { let n = 1; (reportData.refs || []).forEach(function(group) { (group.items || []).forEach(function(item) { if (!item.id) return; const anchorId = 'ref-' + item.id; refMap[item.id] = { number: n, anchorId: anchorId }; item._number = n; item._anchorId = anchorId; n++; }); }); } // Returns an HTML string for a list of refIds, or "" if empty/missing. // Format: <sup class="bs-refsup">[<a href="#ref-x">1</a>,<a>2</a>]</sup> function refSupHtml(refIds) { if (!refIds || !refIds.length) return ""; const parts = []; for (let i = 0; i < refIds.length; i++) { const r = refMap[refIds[i]]; if (!r) continue; parts.push('<a href="#' + r.anchorId + '">' + r.number + '</a>'); } if (!parts.length) return ""; return '<sup class="bs-refsup">[' + parts.join(',') + ']</sup>'; } // ================================================================= // DATA VALIDATION // ================================================================= function validateData() { const w = []; if (!meta.weekLabel) w.push("meta.weekLabel is empty"); if (!meta.dateRange) w.push("meta.dateRange is empty"); const pills = reportData.marketPills || []; if (pills.length !== 3) w.push("marketPills: expected 3, got " + pills.length); const insights = reportData.keyInsights || []; if (insights.length < 2) w.push("keyInsights: minimum 2 required, got " + insights.length); if (insights.length > 6) w.push("keyInsights: maximum 6 allowed, got " + insights.length); const events = reportData.events || []; if (events.length > 7) w.push("events: maximum 7 allowed, got " + events.length); const validTags = ["Clinical","Regulatory","Financing","M&A","Commercial","Corporate"]; events.forEach((ev, i) => { if (!validTags.includes(ev.tag)) w.push("events[" + i + "]: invalid tag \u201c" + ev.tag + "\u201d"); }); const cats = reportData.catalysts || []; const validTypes = ["Binary","Asymmetric","Incremental"]; cats.forEach((c, i) => { if (!validTypes.includes(c.type)) w.push("catalysts[" + i + "]: invalid type \u201c" + c.type + "\u201d"); }); if (w.length) { console.group("[BioStock] Validation: " + w.length + " warning(s)"); w.forEach(x => console.warn(x)); console.groupEnd(); } } // ================================================================= // RENDER: HERO ZONE // ================================================================= function renderHero() { const topbarWrap = $('npl-topbar-wrap'); topbarWrap.innerHTML = '<div class="npl-topbar">' + '<div class="npl-logo">' + '<div class="npl-logo-mark">B</div>' + '<div><div class="npl-logo-text">BioStock Analytics</div>' + '<div class="npl-logo-sub">Nordic Life Science Weekly</div></div>' + '</div>' + '<span class="npl-topbar-right">' + (meta.weekLabel || '') + (meta.dateRange ? ' \u00b7 ' + meta.dateRange : '') + '</span>' + '</div>'; const titleParts = (meta.heroTitle || meta.weekLabel || "").split("\n"); const mainTitle = titleParts[0] || ""; const italicPart = titleParts[1] || ""; const titleHtml = mainTitle + (italicPart ? '<br><em>' + italicPart + '</em>' : ''); const pills = reportData.marketPills || []; const idxRows = pills.map(function(p) { const dir = (p.direction || "").toLowerCase(); const cls = dir === 'up' ? 'up' : dir === 'down' ? 'dn' : 'fl'; const prefix = dir === 'up' ? '+' : ''; return '<div class="npl-idx-row">' + '<span class="npl-idx-name">' + (p.fullName || p.label) + '</span>' + '<span class="npl-idx-val ' + cls + '">' + prefix + p.value + '</span>' + '</div>'; }).join(''); const movers = reportData.moversTable || []; let moverHtml = ''; if (movers.length) { const gainer = movers[0]; const decliner = movers[movers.length - 1]; const gPfx = Number(gainer.chg) >= 0 ? '+' : ''; const dPfx = Number(decliner.chg) >= 0 ? '+' : ''; moverHtml = '<div class="npl-panel-div"></div>' + '<div class="npl-mover-lbl">Top gainer</div>' + '<div class="npl-mover-row" style="margin-bottom:16px">' + '<span class="npl-mover-name">' + gainer.company + '</span>' + '<span class="npl-mover-val up">' + gPfx + Number(gainer.chg).toFixed(2) + '%</span>' + '</div>' + '<div class="npl-mover-lbl">Top decliner</div>' + '<div class="npl-mover-row">' + '<span class="npl-mover-name">' + decliner.company + '</span>' + '<span class="npl-mover-val dn">' + dPfx + Number(decliner.chg).toFixed(2) + '%</span>' + '</div>'; } $('npl-hero-wrap').innerHTML = '<section class="npl-hero">' + '<div class="npl-hero-inner">' + '<div>' + '<div class="npl-issue-tag">' + (meta.weekLabel || '') + (meta.dateRange ? ' \u00b7 ' + meta.dateRange : '') + '</div>' + '<h1 class="npl-hero-title">' + titleHtml + '</h1>' + '<p class="npl-hero-lead">' + (meta.heroLead || '') + '</p>' + '<a href="#biostock-report" class="npl-hero-anchor">Read the full report ' + '<svg viewBox="0 0 20 20" fill="currentColor" width="15" height="15">' + '<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v10.586l3.293-3.293a1 1 0 111.414 1.414l-5 5a1 1 0 01-1.414 0l-5-5a1 1 0 111.414-1.414L9 14.586V4a1 1 0 011-1z" clip-rule="evenodd"/>' + '</svg>' + '</a>' + '</div>' + '<div class="npl-index-panel">' + '<div class="npl-panel-label">Index performance \u00b7 week-over-week</div>' + idxRows + moverHtml + '</div>' + '</div>' + '</section>'; } // ================================================================= // RENDER: TICKER TAPE // ================================================================= function renderTicker() { const movers = reportData.moversTable || []; if (!movers.length) return; const items = movers.map(function(m) { const pfx = Number(m.chg) >= 0 ? '+' : ''; return '<span class="npl-ticker-item">' + m.company + ' ' + pfx + Number(m.chg).toFixed(2) + '%' + '<span class="npl-ticker-sep">\u00b7</span></span>'; }).join(''); $('npl-ticker-wrap').innerHTML = '<div class="npl-ticker"><div class="npl-ticker-inner">' + items + items + '</div></div>'; } // ================================================================= // RENDER: EXECUTIVE SUMMARY CARDS // ================================================================= function renderSummaryCards() { const cards = reportData.summaryCards || []; if (!cards.length && !meta.summaryTitle) return; const cardsHtml = cards.map(function(c) { return '<div class="npl-data-card">' + '<div class="npl-data-card-label">' + (c.label || '') + '</div>' + '<div class="npl-data-card-text">' + (c.text || '') + '</div>' + '</div>'; }).join(''); $('npl-summary-wrap').innerHTML = '<div class="npl-preview">' + '<div class="npl-eyebrow">Executive Summary</div>' + '<h2 class="npl-section-title">' + (meta.summaryTitle || '') + '</h2>' + '<div class="npl-section-line"></div>' + (meta.summaryDesc ? '<p class="npl-section-desc">' + meta.summaryDesc + '</p>' : '') + (cardsHtml ? '<div class="npl-data-grid">' + cardsHtml + '</div>' : '') + '</div>'; } // ================================================================= // RENDER: META // ================================================================= function renderMeta() { if (meta.reportTitle) document.title = meta.reportTitle; txt($('meta-week'), meta.weekLabel); txt($('meta-dates'), meta.dateRange); txt($('market-subtitle'), meta.marketSubtitle); txt($('market-source'), meta.marketSourceNote); txt($('events-subtitle'), meta.eventsSubtitle); txt($('methodology-text'), meta.methodologyText); txt($('catalyst-note'), meta.catalystNote); txt($('ai-disclosure-text'), meta.aiDisclosure); if (meta.liquidityText) { show($('liquidity-wrap')); const liqWrap = $('liquidity-text'); liqWrap.innerHTML = ""; const liqRefs = meta.liquidityRefIds || []; meta.liquidityText.split("\n\n").forEach(function(para, i) { const trimmed = para.trim(); if (!trimmed) return; const p = el('p', 'text-sm leading-relaxed' + (i > 0 ? ' mt-3' : '')); p.style.color = 'var(--text-mid)'; const sup = refSupHtml(liqRefs[i]); if (sup) { p.innerHTML = trimmed.replace(/[<>&"']/g, function(c){ return {'<':'<','>':'>','&':'&','"':'"',"'":'''}[c]; }) + sup; } else { txt(p, trimmed); } liqWrap.appendChild(p); }); } } // ================================================================= // RENDER: KEY INSIGHTS // ================================================================= function renderInsights() { const list = $('insights-list'); list.innerHTML = ""; const items = reportData.keyInsights || []; if (!items.length) { show($('insights-empty')); return; } hide($('insights-empty')); items.forEach(function(item) { const li = el('li', 'pl-1'); if (item.label) { const s = el('span', 'font-semibold'); s.style.color = 'var(--teal-dark)'; txt(s, item.label); li.appendChild(s); li.appendChild(document.createTextNode(" ")); } li.appendChild(document.createTextNode(item.text || "")); const sup = refSupHtml(item.refIds); if (sup) { const supWrap = document.createElement('span'); supWrap.innerHTML = sup; li.appendChild(supWrap); } list.appendChild(li); }); } // ================================================================= // RENDER: MARKET PILLS & MOVERS // ================================================================= function renderMarketPills() { const wrap = $('market-pills'); wrap.innerHTML = ""; (reportData.marketPills || []).forEach(function(p) { const dir = (p.direction || "").toLowerCase(); const cls = dir === 'up' ? 'pill-up' : dir === 'down' ? 'pill-dn' : 'pill-flat'; const prefix = dir === 'up' ? '\u25b2 ' : dir === 'down' ? '\u25bc ' : ''; const span = el('span', 'inline-flex items-center px-2.5 py-1 rounded text-xs font-medium font-mono border ' + cls); txt(span, p.label + ": " + prefix + p.value); wrap.appendChild(span); }); } function renderMovers() { const tbody = $('movers-body'); tbody.innerHTML = ""; const rows = reportData.moversTable || []; if (!rows.length) { show($('movers-empty')); return; } hide($('movers-empty')); rows.forEach(function(r) { const tr = document.createElement('tr'); const td1 = el('td', 'px-2 py-2 text-xs font-medium'); td1.style.color = 'var(--text)'; txt(td1, r.company || ""); const td2 = el('td', 'px-2 py-2 text-right text-xs font-mono font-medium'); const chg = Number(r.chg); if (isFinite(chg)) { const pfx = chg >= 0 ? '+' : ''; td2.classList.add(chg >= 0 ? 'chg-up' : 'chg-dn'); txt(td2, pfx + chg.toFixed(1) + "%"); } else { txt(td2, "\u2014"); td2.style.color = 'var(--text-light)'; } tr.appendChild(td1); tr.appendChild(td2); tbody.appendChild(tr); }); } // ================================================================= // RENDER: CHART // ================================================================= let marketChart = null; function initMarketChart() { const labels = (reportData.marketSeries && reportData.marketSeries.labels) || []; const indices = (reportData.marketSeries && reportData.marketSeries.indices) || []; if (!labels.length || !indices.length) { show($('market-empty')); return; } hide($('market-empty')); const ctx = $('marketChart').getContext('2d'); const colors = ['#2c5a6b', '#b8975c', '#3a7389']; const datasets = indices.map(function(s, i) { return { label: s.name || s.key, data: Array.isArray(s.data) ? s.data : [], backgroundColor: colors[i] || '#888', borderColor: colors[i] || '#888', borderWidth: 1, borderRadius: 3, barPercentage: 0.7, categoryPercentage: 0.85 }; }); if (marketChart) marketChart.destroy(); marketChart = new Chart(ctx, { type: 'bar', data: { labels: labels, datasets: datasets }, options: { responsive: true, maintainAspectRatio: false, interaction: { mode: 'index', intersect: false }, plugins: { legend: { position: 'bottom', labels: { boxWidth: 8, usePointStyle: true, pointStyleWidth: 8, font: { family: "'Plus Jakarta Sans', sans-serif", size: 11 }, padding: 16 } }, tooltip: { backgroundColor: 'rgba(30,63,77,0.95)', titleFont: { family: "'Plus Jakarta Sans', sans-serif", size: 12 }, bodyFont: { family: "'JetBrains Mono', monospace", size: 11 }, padding: 10, cornerRadius: 3, callbacks: { label: function(ctx) { var v = ctx.parsed.y; return " " + ctx.dataset.label + ": " + (v >= 0 ? '+' : '') + v.toFixed(2) + "%"; } } } }, scales: { x: { grid: { display: false }, ticks: { font: { family: "'Plus Jakarta Sans', sans-serif", size: 10 }, color: '#888' } }, y: { grid: { color: '#e8e4df', drawBorder: false }, ticks: { font: { family: "'JetBrains Mono', monospace", size: 10 }, color: '#888', callback: function(v) { return (v >= 0 ? '+' : '') + v.toFixed(1) + '%'; } } } } } }); } // ================================================================= // RENDER: MAJOR EVENTS // ================================================================= function renderEvents() { const wrap = $('events-list'); wrap.innerHTML = ""; const items = reportData.events || []; if (!items.length) { show($('events-empty')); hide(wrap); return; } hide($('events-empty')); show(wrap); items.forEach(function(a) { const block = el('div', 'event-row pl-4'); const head = el('div', 'flex flex-wrap items-center gap-2 mb-1'); const h = el('h3', 'text-sm font-bold'); h.style.color = 'var(--teal-dark)'; const sup = refSupHtml(a.refIds); if (sup) { h.innerHTML = (a.title || "").replace(/[<>&"']/g, function(c){ return {'<':'<','>':'>','&':'&','"':'"',"'":'''}[c]; }) + sup; } else { txt(h, a.title || ""); } head.appendChild(h); if (a.tag) { const badge = el('span', 'text-[10px] font-mono px-2 py-0.5 rounded uppercase tracking-wider'); badge.style.cssText = 'background:var(--warm-dark);color:var(--text-mid)'; txt(badge, a.tag); head.appendChild(badge); } block.appendChild(head); if (a.text) { const p = el('p', 'text-sm leading-relaxed'); p.style.color = 'var(--text)'; txt(p, a.text); block.appendChild(p); } if (a.implication) { const imp = el('p', 'text-sm mt-1 leading-relaxed'); imp.style.color = 'var(--text-mid)'; txt(imp, a.implication); block.appendChild(imp); } if (a.marketReaction) { const mr = el('span', 'market-reaction'); txt(mr, '\u25b8 ' + a.marketReaction); const mrWrap = el('div', 'mt-2'); mrWrap.appendChild(mr); block.appendChild(mrWrap); } if (a.source) { const src = el('p', 'text-[10px] font-mono mt-2'); src.style.color = 'var(--text-light)'; txt(src, a.source); block.appendChild(src); } wrap.appendChild(block); }); } // ================================================================= // RENDER: FINANCIAL IMPACT // ================================================================= function renderFinance() { const wrap = $('finance-list'); wrap.innerHTML = ""; const items = reportData.finance || []; if (!items.length) { show($('finance-empty')); return; } hide($('finance-empty')); const grid = el('div', 'grid grid-cols-1 md:grid-cols-2 gap-4'); items.forEach(function(b) { const tile = el('div', 'fin-tile p-4'); const row = el('div', 'flex justify-between items-center mb-2'); const name = el('span', 'font-semibold text-sm'); name.style.color = 'var(--teal-dark)'; const sup = refSupHtml(b.refIds); if (sup) { name.innerHTML = (b.company || "").replace(/[<>&"']/g, function(c){ return {'<':'<','>':'>','&':'&','"':'"',"'":'''}[c]; }) + sup; } else { txt(name, b.company || ""); } row.appendChild(name); if (b.tag) { const tone = (b.tagTone || '').toLowerCase(); const cls = tone === 'green' ? 'tag-green' : tone === 'red' ? 'tag-red' : 'tag-grey'; const tag = el('span', 'text-[10px] font-mono px-2 py-0.5 rounded border ' + cls); txt(tag, b.tag); row.appendChild(tag); } tile.appendChild(row); const t = el('p', 'text-sm leading-relaxed'); t.style.color = 'var(--text)'; txt(t, b.text || ""); tile.appendChild(t); if (b.source) { const src = el('p', 'text-[10px] font-mono pt-2 mt-3'); src.style.cssText = 'color:var(--text-light);border-top:1px solid var(--warm-dark)'; txt(src, b.source); tile.appendChild(src); } grid.appendChild(tile); }); wrap.appendChild(grid); } // ================================================================= // RENDER: DEV & RESEARCH // ================================================================= function renderResearchItem(a, container) { const block = el('div', 'event-row pl-4'); const head = el('div', 'flex flex-wrap items-center gap-2 mb-1'); const h = el('h3', 'text-sm font-bold'); h.style.color = 'var(--teal-dark)'; const sup = refSupHtml(a.refIds); if (sup) { h.innerHTML = (a.title || "").replace(/[<>&"']/g, function(c){ return {'<':'<','>':'>','&':'&','"':'"',"'":'''}[c]; }) + sup; } else { txt(h, a.title || ""); } head.appendChild(h); if (a.badge) { const badge = el('span', 'text-[10px] font-mono px-2 py-0.5 rounded'); badge.style.cssText = 'background:var(--warm-dark);color:var(--text-mid)'; txt(badge, a.badge); head.appendChild(badge); } block.appendChild(head); if (a.text) { const p = el('p', 'text-sm leading-relaxed'); p.style.color = 'var(--text)'; txt(p, a.text); block.appendChild(p); } if (a.source) { const src = el('p', 'text-[10px] font-mono mt-2'); src.style.color = 'var(--text-light)'; txt(src, a.source); block.appendChild(src); } container.appendChild(block); } function renderResearch() { const biotech = (reportData.research && reportData.research.biotech) || []; const medtech = (reportData.research && reportData.research.medtech) || []; if (!biotech.length && !medtech.length) { show($('research-empty')); return; } hide($('research-empty')); var allP = $('rpanel-all'); allP.innerHTML = ""; if (biotech.length && medtech.length) { var l = el('p', 'text-[10px] font-bold uppercase tracking-widest mb-3'); l.style.color = 'var(--text-light)'; txt(l, 'Biotech & Pharma'); allP.appendChild(l); } biotech.forEach(function(a) { renderResearchItem(a, allP); }); if (biotech.length && medtech.length) { var l2 = el('p', 'text-[10px] font-bold uppercase tracking-widest mt-6 pt-5 border-t border-gray-200 mb-3'); l2.style.color = 'var(--text-light)'; txt(l2, 'MedTech & Diagnostics'); allP.appendChild(l2); } medtech.forEach(function(a) { renderResearchItem(a, allP); }); var btP = $('rpanel-biotech'); btP.innerHTML = ""; if (!biotech.length) { var e1 = el('p', 'text-sm italic py-6 text-center'); e1.style.color = 'var(--text-light)'; txt(e1, "No eligible items this week"); btP.appendChild(e1); } else { biotech.forEach(function(a) { renderResearchItem(a, btP); }); } var mtP = $('rpanel-medtech'); mtP.innerHTML = ""; if (!medtech.length) { var e2 = el('p', 'text-sm italic py-6 text-center'); e2.style.color = 'var(--text-light)'; txt(e2, "No eligible items this week"); mtP.appendChild(e2); } else { medtech.forEach(function(a) { renderResearchItem(a, mtP); }); } } function initResearchTabs() { var tabs = ['all', 'biotech', 'medtech']; tabs.forEach(function(t) { var btn = $('rtab-' + t); if (!btn) return; btn.addEventListener('click', function() { setResearchTab(t); }); btn.addEventListener('keydown', function(e) { if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') { e.preventDefault(); var idx = tabs.indexOf(t); var next = e.key === 'ArrowRight' ? (idx + 1) % tabs.length : (idx - 1 + tabs.length) % tabs.length; $('rtab-' + tabs[next]).focus(); setResearchTab(tabs[next]); } }); }); } function setResearchTab(name) { ['all', 'biotech', 'medtech'].forEach(function(t) { var btn = $('rtab-' + t); var panel = $('rpanel-' + t); var active = t === name; btn.setAttribute('aria-selected', active ? 'true' : 'false'); btn.setAttribute('tabindex', active ? '0' : '-1'); if (active) { show(panel); } else { hide(panel); } }); } // ================================================================= // RENDER: CATALYST WATCH // ================================================================= function renderCatalysts() { var ul = $('catalyst-timeline'); ul.innerHTML = ""; var items = reportData.catalysts || []; if (!items.length) { show($('catalyst-empty')); return; } hide($('catalyst-empty')); items.forEach(function(c) { var li = el('li', 'relative pl-8'); var acc = (c.accent || '').toLowerCase(); var dotStyle = acc === 'teal' ? 'border-color:var(--teal)' : acc === 'gold' ? 'border-color:var(--gold)' : 'border-color:var(--warm-dark)'; var dot = el('div', 'absolute left-0 top-1.5 h-[18px] w-[18px] rounded-full border-2 bg-white'); dot.style.cssText = dotStyle; li.appendChild(dot); var row = el('div', 'flex flex-col sm:flex-row sm:items-start sm:justify-between gap-1'); var left = el('div', ''); var dateLine = el('h4', 'text-xs font-bold'); dateLine.style.color = 'var(--teal-dark)'; txt(dateLine, c.date || ""); var detail = el('p', 'text-sm leading-relaxed'); detail.style.color = 'var(--text-mid)'; var company = (c.company || "").trim(); var event = (c.event || "").trim(); txt(detail, company && event ? company + ": " + event : (company || event)); left.appendChild(dateLine); left.appendChild(detail); var type = (c.type || "").trim(); var tl = type.toLowerCase(); var typeCls = tl === 'binary' ? 'catalyst-binary' : tl === 'asymmetric' ? 'catalyst-asymmetric' : tl === 'incremental' ? 'catalyst-incremental' : ''; var badge = el('span', 'text-[10px] font-medium px-2 py-0.5 rounded whitespace-nowrap ' + typeCls); txt(badge, type); row.appendChild(left); row.appendChild(badge); li.appendChild(row); ul.appendChild(li); }); } // ================================================================= // RENDER: REFERENCES // ================================================================= function renderRefs() { var wrap = $('ref-sections'); wrap.innerHTML = ""; var groups = reportData.refs || []; if (!groups.length) { show($('refs-empty')); return; } hide($('refs-empty')); groups.forEach(function(group) { var section = el('div', 'mb-3'); var heading = el('h4', 'text-[10px] font-semibold uppercase tracking-[0.1em] mb-1.5'); heading.style.color = 'var(--text-mid)'; txt(heading, group.section || "General"); section.appendChild(heading); var list = el('ul', 'space-y-1.5 list-none'); (group.items || []).forEach(function(r) { var li = el('li', 'bs-ref-item text-[10px] leading-relaxed'); li.style.color = 'var(--text-light)'; if (r.id) li.id = 'ref-' + r.id; var cite = (r.citation || "").trim(); var url = safeUrl(r.url); var accessed = (r.accessed || "").trim(); var content = cite ? (cite.endsWith('.') ? cite + ' ' : cite + '. ') : ''; if (typeof r._number === 'number') { var num = el('span', 'bs-refnum'); txt(num, '[' + r._number + ']'); li.appendChild(num); } if (url) { var span = el('span', ''); span.appendChild(document.createTextNode(content + 'Available at: ')); var a = el('a', 'underline transition-colors'); a.style.color = 'var(--teal)'; a.href = url; a.target = "_blank"; a.rel = "noopener noreferrer"; txt(a, url); span.appendChild(a); if (accessed) span.appendChild(document.createTextNode(' (Accessed: ' + accessed + ').')); li.appendChild(span); } else { li.appendChild(document.createTextNode(content)); } list.appendChild(li); }); section.appendChild(list); wrap.appendChild(section); }); } // ================================================================= // MOBILE NAV // ================================================================= function initMobileNav() { var btn = $('mobile-nav-btn'); var nav = $('mobile-nav'); var links = document.querySelectorAll('#sidebar-nav .nav-link'); var mobileWrap = $('mobile-nav-links'); links.forEach(function(link) { var a = link.cloneNode(true); a.className = 'block px-4 py-2 text-xs font-medium uppercase tracking-[0.08em]'; a.style.color = 'var(--text-mid)'; a.addEventListener('click', function() { nav.classList.remove('open'); }); mobileWrap.appendChild(a); }); btn.addEventListener('click', function() { var open = nav.classList.toggle('open'); btn.setAttribute('aria-expanded', open ? 'true' : 'false'); }); } // ================================================================= // SCROLLSPY // ================================================================= function initScrollSpy() { var links = Array.from(document.querySelectorAll('#sidebar-nav .nav-link')); var map = new Map(); links.forEach(function(a) { var id = a.getAttribute('href') && a.getAttribute('href').slice(1); var sec = id ? document.getElementById(id) : null; if (sec) map.set(sec, a); }); var setActive = function(target) { links.forEach(function(a) { a.classList.remove('active'); }); var a = map.get(target); if (a) a.classList.add('active'); }; var observer = new IntersectionObserver(function(entries) { var visible = entries.filter(function(e) { return e.isIntersecting; }) .sort(function(a, b) { return b.intersectionRatio - a.intersectionRatio; })[0]; if (visible && visible.target) setActive(visible.target); }, { root: null, rootMargin: '-25% 0px -65% 0px', threshold: [0.01, 0.1, 0.25, 0.5] }); map.forEach(function(_, sec) { observer.observe(sec); }); } // ================================================================= // WORDPRESS COMPATIBILITY // ================================================================= function initWPScrollFix() { var isWP = !!document.getElementById('wpadminbar') || document.body.className.indexOf('wp-') > -1 || document.body.className.indexOf('wordpress') > -1; var isMobile = window.innerWidth < 1024; var wpH = 0; document.querySelectorAll('#wpadminbar, .site-header, #masthead, nav.main-navigation').forEach(function(el) { if (el) { var pos = getComputedStyle(el).position; if (pos === 'fixed' || pos === 'sticky') wpH += el.offsetHeight; } }); var rptHeader = document.querySelector('#biostock-report header'); if (isWP && rptHeader) { if (isMobile) { rptHeader.style.top = wpH + 'px'; } else { rptHeader.style.position = 'relative'; } } if (isWP && wpH > 0) { var sidebar = document.querySelector('#biostock-report aside'); if (sidebar) sidebar.style.top = (wpH + 16) + 'px'; } var stickyH = wpH; if (rptHeader && getComputedStyle(rptHeader).position === 'sticky') stickyH += rptHeader.offsetHeight; var pad = isMobile ? (stickyH + 300) : (stickyH + 10); document.querySelectorAll('[id^="bs-"]').forEach(function(sec) { sec.style.setProperty('scroll-margin-top', pad + 'px', 'important'); }); document.querySelectorAll('#sidebar-nav .nav-link, #mobile-nav-links a').forEach(function(link) { link.addEventListener('click', function(e) { var targetId = this.getAttribute('href') && this.getAttribute('href').slice(1); var target = targetId ? document.getElementById(targetId) : null; if (target) { e.preventDefault(); e.stopPropagation(); target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); } // ================================================================= // BOOT // ================================================================= document.addEventListener('DOMContentLoaded', function() { validateData(); buildRefMap(); renderHero(); renderTicker(); renderSummaryCards(); renderMeta(); renderInsights(); renderMarketPills(); renderMovers(); initMarketChart(); renderEvents(); renderFinance(); renderResearch(); initResearchTabs(); setResearchTab('all'); renderCatalysts(); renderRefs(); initMobileNav(); initScrollSpy(); initWPScrollFix(); });Idag, 08:26
The post The Nordic Pulse | 2026:17 appeared first on Biostock.
Nordic Life Science Weekly
Key Insights1. Market Snapshot2. Major Events3. Financial Impact4. Dev & Research5. Catalyst WatchReferencesReport data pending
Report data pending
Company | Weekly Chg |
Report data pending
No eligible events this week
Report data pending
Report data pending
Report data pending
BinaryLarge price move likelyAsymmetricPartially pricedIncrementalLower impactReport data pending
const meta = { reportTitle: "BioStock Nordic Life Science Weekly – Week 17, 2026", weekLabel: "Week 17, 2026", dateRange: "20–26 April 2026", heroTitle: "Orion advances ODM-212,\nColoplast warns on Kerecis", heroLead: "Orion received an FDA Orphan Drug Designation and initiated a combination basket trial for ODM-212. Ascendis completed its ADS-to-ordinary-share exchange and called $575 million in convertible notes for redemption. Coloplast cut guidance and wrote down DKK 3.0 billion against Kerecis. All three sector benchmarks fell roughly 3.6–3.9 per cent.", summaryTitle: "The week in six data points", summaryDesc: "A risk-off week across Nordic life science saw broad index declines of 3.6–3.9 per cent. Orion's dual pipeline advances in oncology contrasted with Coloplast's material guidance cut. Capital markets activity centred on Ascendis's convertible note redemption and two Nordic rights issues.", marketSubtitle: "Week-over-week index returns, Friday close 24 April 2026", marketSourceNote: "Sources: Nasdaq, HealthCap Nordic HC SEK GI. All figures reflect Friday closing levels.", eventsSubtitle: "20–26 April 2026", methodologyText: "This week's report covers Nordic life science events distributed via MFN, Cision, and GlobeNewswire during the reporting interval (2026-04-20\u20132026-04-26). 7 event(s) were excluded due to insufficient material relevance (routine share buy-back transactions, standard AGM notices, routine share repurchase programme updates, and routine incentive programme grants). All index data reflects official closing levels as described in the methodology note above.", catalystNote: "Hansa Biopharma's imlifidase PDUFA target date (19 December 2026) falls outside the 6-week horizon but remains a key sector catalyst to monitor. The ConfIdeS phase III oral presentation at ATC in June 2026 may provide an interim read-through.", liquidityText: "Moberg Pharma (+17.46%): The week's strongest gainer. Moberg Pharma's Terclara nail fungus treatment achieved a 42 per cent value share in Sweden and a 34 per cent value share in Norway for the full year 2025, and the company entered an exclusive licence agreement with Karo Healthcare in November 2025 covering 19 European markets for a coordinated rollout under the Lamisil brand.\n\nCellaVision (\u201325.62%): CellaVision reported its Q1 2026 results during the week, with net sales of SEK 166 million, a 14.6 per cent decline from the prior year. The EMEA region declined 32 per cent, attributed to inventory adjustments with the company's main distribution partner.\n\nHansa Biopharma (\u201313.57%): Hansa Biopharma reported its Q1 2026 results during the week. First-quarter revenue totalled SEK 34.6 million versus SEK 66.3 million in Q1 2025, with IDEFIRIX product sales of SEK 33.9 million versus SEK 65.7 million in Q1 2025. The revenue decline reflects the expected short-term impact of a European commercial reorganisation.\n\nPCI Biotech (\u201325.81%): The week's steepest decliner. The move occurred against low liquidity conditions typical for micro-cap companies, and no specific in-interval press release was identified.", liquidityRefIds: [ ["moberg-year-end-2025","moberg-karo-license"], ["cellavision-q1-2026"], ["hansa-q1-2026"], [] ], aiDisclosure: "This report's information has been sourced with AI, screened and verified by the BioStock editorial team." }; const reportData = { keyInsights: [ { label: "Orion advanced its oncology pipeline on two fronts:", text: "ODM-212 received Orphan Drug Designation from the US FDA for mesothelioma, and the company initiated the TEADCO phase Ib/II basket trial evaluating ODM-212 in combination with standard of care in mesothelioma, KRAS G12C-mutated NSCLC, and pancreatic cancer.", refIds: ["orion-odd-mesothelioma","orion-teadco-trial"] }, { label: "Ascendis Pharma completed a dual structural event:", text: "the company mandatorily exchanged all outstanding ADSs for ordinary shares, commencing direct trading on Nasdaq on 20 April, and one day later called all $575.0 million of its outstanding 2.25% Convertible Senior Notes due 2028 for redemption on 6 May 2026.", refIds: ["ascendis-ordinary-shares","ascendis-convertible-redemption"] }, { label: "Coloplast issued a profit warning,", text: "cutting FY 2025/26 organic growth guidance to 5\u20136 per cent from approximately 7 per cent, and EBIT growth to approximately 5 per cent from approximately 7 per cent, accompanied by a DKK 3.0 billion goodwill impairment against Kerecis.", refIds: ["coloplast-guidance-cut"] }, { label: "Elicera Therapeutics announced a rights issue of approximately SEK 72.8 million", text: "to complete the ongoing CARMA study and advance preparations for a planned phase I/Ib clinical trial of ELC-401.", refIds: ["elicera-rights-issue"] }, { label: "AlzeCure Pharma announced a rights issue of approximately SEK 30.1 million", text: "t to strengthen the cash position and provide resources for business development, pending discussions around licensing and collaboration agreements.", refIds: ["alzecure-rights-issue"] }, { label: "Nordic health care indices declined broadly,", text: "with the Nordic HC SEK GI down \u20133.57 per cent, NBI down \u20133.79 per cent, and XBI down \u20133.89 per cent, amid persistent macro headwinds. CellaVision and Hansa Biopharma were the sharpest decliners following weak Q1 reports.", refIds: ["cellavision-q1-2026","hansa-q1-2026"] } ], summaryCards: [ { label: "Index Move", text: "Broad risk-off sentiment drove all three benchmarks down 3.6\u20133.9 per cent week-over-week." }, { label: "Top Gainer", text: "Moberg Pharma +17.46 per cent \u2013 continued positive sentiment around European commercial expansion for Terclara." }, { label: "Top Decliner", text: "PCI Biotech \u201325.81 per cent, a steep drop on thin micro-cap liquidity with no identified in-interval catalyst." }, { label: "Regulatory", text: "Orion\u2019s ODM-212 granted FDA Orphan Drug Designation for mesothelioma, conferring 7-year market exclusivity eligibility." }, { label: "Capital Markets", text: "Ascendis called $575 million in convertible notes for redemption; Bioretec gained gross proceeds of ~EUR 13 million from a rights issue; Elicera and AlzeCure announces upcoming rights issues." }, { label: "Guidance Change", text: "Coloplast cut FY 2025/26 organic growth to 5\u20136 per cent and recognised a DKK 3.0 billion goodwill impairment against Kerecis." } ], marketPills: [ { label: "NBI", value: "\u20133.79%", direction: "down", fullName: "NASDAQ Biotechnology (NBI)" }, { label: "Nordic HC SEK GI", value: "\u20133.57%", direction: "down", fullName: "Nordic HC SEK GI" }, { label: "XBI", value: "\u20133.89%", direction: "down", fullName: "SPDR S&P Biotech ETF (XBI)" } ], marketSeries: { labels: ["Wk 17"], indices: [ { key: "NBI", name: "NASDAQ Biotechnology (NBI)", data: [-3.79] }, { key: "NordicHC", name: "Nordic HC SEK GI", data: [-3.57] }, { key: "XBI", name: "SPDR S&P Biotech ETF (XBI)", data: [-3.89] } ] }, moversTable: [ { company: "Moberg Pharma", chg: 17.46 }, { company: "Vitrolife", chg: 7.31 }, { company: "ALK-Abell\u00f3", chg: 7.01 }, { company: "SynAct Pharma", chg: 6.78 }, { company: "Lundbeck", chg: 4.38 }, { company: "Sprint Bioscience", chg: -12.98 }, { company: "Hansa Biopharma", chg: -13.57 }, { company: "Immunovia", chg: -13.83 }, { company: "CellaVision", chg: -25.62 }, { company: "PCI Biotech", chg: -25.81 } ], events: [ { title: "Orion Corporation \u2013 ODM-212 receives FDA Orphan Drug Designation for mesothelioma", tag: "Regulatory", text: "Orion Pharma announced that ODM-212 received Orphan Drug Designation from the US FDA for the treatment of mesothelioma. ODM-212 is an oral small-molecule pan-TEAD inhibitor being tested in a phase II clinical study (TEADES) for malignant pleural mesothelioma, epithelioid hemangioendothelioma, and other solid tumours with Hippo pathway dysfunction.", implication: "The designation confers incentives including tax credits, user fee exemptions, and eligibility for a 7-year period of market exclusivity following approval.", marketReaction: null, source: "GlobeNewswire, 20 Apr 2026", refIds: ["orion-odd-mesothelioma"] }, { title: "Orion Corporation \u2013 TEADCO phase Ib/II basket trial initiated", tag: "Clinical", text: "Orion announced initiation of TEADCO, a phase Ib/II basket trial evaluating ODM-212 in combination with standard of care in advanced mesothelioma, KRAS G12C-mutated NSCLC, and pancreatic cancer. The first cohort evaluates ODM-212 in combination with ipilimumab and nivolumab as a first-line treatment for advanced malignant pleural mesothelioma.", implication: "The trial broadens the clinical programme from monotherapy (TEADES) to combination regimens across multiple tumour types.", marketReaction: null, source: "GlobeNewswire, 23 Apr 2026", refIds: ["orion-teadco-trial"] }, { title: "Ascendis Pharma \u2013 Redemption of $575 million convertible notes", tag: "Financing", text: "Ascendis Pharma called all $575.0 million of its outstanding 2.25% Convertible Senior Notes due 2028 for redemption on 6 May 2026, triggered after the share price exceeded 130 per cent of the conversion price on at least 20 of the prior 30 trading days.", implication: "Noteholders may convert at an enhanced rate of 6.3232 shares per $1,000 during the make-whole period, equivalent to approximately $158.15 per share, potentially resulting in up to 3.64 million new shares. The move deleverages the balance sheet but introduces near-term dilution risk.", marketReaction: null, source: "GlobeNewswire, 21 Apr 2026", refIds: ["ascendis-convertible-redemption"] }, { title: "Ascendis Pharma \u2013 Ordinary shares commence Nasdaq trading", tag: "Corporate", text: "Ascendis Pharma commenced trading of its ordinary shares on the Nasdaq Global Select Market, replacing the listing of American Depositary Shares. The ordinary shares trade under the same ticker symbol \u201cASND\u201d. As of 20 April 2026, the company had exchanged all outstanding ADSs for ordinary shares.", implication: "The direct listing is intended to facilitate potential equity index inclusion and broaden institutional access.", marketReaction: null, source: "GlobeNewswire, 20 Apr 2026", refIds: ["ascendis-ordinary-shares"] }, { title: "Coloplast \u2013 Guidance cut and DKK 3.0 billion Kerecis impairment", tag: "Corporate", text: "Coloplast cut FY 2025/26 guidance, now expecting 5\u20136 per cent organic growth (from approximately 7 per cent) and approximately 5 per cent EBIT growth in constant currencies (from approximately 7 per cent). The company recognised a DKK 3.0 billion goodwill impairment against Kerecis, reducing its carrying book value to approximately DKK 6 billion.", implication: "The impairment reflects significant sales disruption from the Medicare reimbursement change in the outpatient setting.", marketReaction: null, source: "GlobeNewswire, 23 Apr 2026", refIds: ["coloplast-guidance-cut"] }, { title: "Elicera Therapeutics \u2013 Rights issue of approximately SEK 72.8 million", tag: "Financing", text: "Elicera\u2019s Board of Directors resolved to carry out a rights issue of approximately SEK 72.8 million to complete the ongoing CARMA study and advance preparations for a planned phase I/Ib clinical trial of ELC-401.", implication: "The rights issue is covered to 75.0 per cent by subscription undertakings and guarantee commitments. The subscription price is SEK 3.0 per share, representing a discount of approximately 31.4 per cent to the theoretical ex-rights price.", marketReaction: null, source: "Cision, 21 Apr 2026", refIds: ["elicera-rights-issue"] }, { title: "AlzeCure Pharma \u2013 Rights issue of approximately SEK 30.1 million", tag: "Financing", text: "AlzeCure Pharma\u2019s Board of Directors resolved to carry out a fully secured rights issue of approximately SEK 30.1 million to strengthen the company's cash position and intensify out-licensing efforts, pending active discussions with several external parties regarding potential licensing and collaboration agreements.", implication: "The rights issue is fully secured to 100 per cent by subscription undertakings from existing shareholders, board members and management, together with guarantee commitments from the company's two largest shareholders. The subscription price is SEK 1.31 per share, representing a discount of approximately 6 per cent to the theoretical ex-rights price.", marketReaction: null, source: "MFN, 21 Apr 2026", refIds: ["alzecure-rights-issue"] }, { title: "Bioretec \u2013 Rights issue completed at 87.1 per cent subscription", tag: "Financing", text: "Bioretec\u2019s rights issue attracted subscriptions for approximately 87.1 per cent of the 1,477,828,416 new shares offered. The company will receive gross proceeds of approximately EUR 12.9 million from the offering.", implication: "The total number of shares will increase from 30,788,092 to 1,341,785,963, with new shares representing approximately 97.7 per cent of all shares following completion \u2013 a significant dilutive event for existing shareholders.", marketReaction: null, source: "Cision, 23\u201324 Apr 2026", refIds: ["bioretec-rights-issue"] } ], finance: [ { company: "Ascendis Pharma", tag: "Capital Raise", tagTone: "grey", text: "The $575 million convertible note redemption is a balance sheet restructuring event. The notes will be redeemed on 6 May 2026, with noteholders receiving cash equal to 100 per cent of principal plus accrued interest, or the option to convert into ordinary shares. If fully converted during the make-whole period, up to 3,635,840 ordinary shares could be issued. The redemption eliminates the 2.25 per cent coupon obligation and simplifies the capital structure but may pressure the stock near-term through conversion-related flows.", source: "GlobeNewswire, 21 Apr 2026", refIds: ["ascendis-convertible-redemption"] }, { company: "Elicera Therapeutics", tag: "Capital Raise", tagTone: "green", text: "The SEK 72.8 million rights issue, covered to 75.0 per cent by subscription undertakings and guarantees, is designed to fund operations through the completion of the CARMA study and initial preparation for ELC-401. The secured amount is expected to finance operations through the end of 2028.", source: "Cision, 21 Apr 2026", refIds: ["elicera-rights-issue"] }, { company: "AlzeCure Pharma", tag: "Capital Raise", tagTone: "green", text: "The SEK 30.1 million rights issue, fully secured to 100 per cent by subscription undertakings from existing shareholders, board members and management, together with guarantee commitments from the two largest shareholders, is designed to strengthen AlzeCure's cash position and intensify out-licensing efforts for its drug candidates. No compensation is payable in connection with the guarantee commitments.", source: "MFN, 21 Apr 2026", refIds: ["alzecure-rights-issue"] }, { company: "Bioretec", tag: "Capital Raise", tagTone: "red", text: "The EUR 12.9 million rights issue results in new shares representing approximately 97.7 per cent of all shares post-completion, implying substantial dilution. Proceeds are earmarked for expanding the commercial offering for RemeOs and building a stronger US-based commercial organisation.", source: "Cision, 23\u201324 Apr 2026", refIds: ["bioretec-rights-issue"] }, { company: "Coloplast", tag: "Valuation Shift", tagTone: "red", text: "Coloplast recognised an impairment loss of DKK 3.0 billion against Kerecis goodwill, with total carrying book value now approximately DKK 6 billion. The write-down, combined with flattened Kerecis sales assumptions, recalibrates market expectations for the biologics wound care acquisition.", source: "GlobeNewswire, 23 Apr 2026", refIds: ["coloplast-guidance-cut"] } ], research: { biotech: [ { title: "Orion Corporation \u2013 ODM-212 dual pipeline advancement", badge: "Phase Ib/II", text: "Orion advanced ODM-212 on two parallel tracks within the same week. ODM-212 is currently in a phase II study (TEADES) for malignant pleural mesothelioma, epithelioid hemangioendothelioma, and other Hippo-pathway-dysregulated solid tumours. The FDA Orphan Drug Designation provides regulatory incentives for the mesothelioma indication. The newly initiated TEADCO trial is a multi-centre, open-label basket trial designed to evaluate efficacy, safety, dose, and tolerability of ODM-212 in combination with standard of care across three tumour types. This broadens the clinical data set from monotherapy to combination settings and represents an important expansion of Orion\u2019s oncology pipeline.", source: "GlobeNewswire, 20 & 23 Apr 2026", refIds: ["orion-odd-mesothelioma","orion-teadco-trial"] }, { title: "Elicera Therapeutics \u2013 CAR T-cell programme advancement", badge: "Pre-clinical / phase I prep", text: "Elicera continues to advance its CAR T-cell programme. The company is simultaneously preparing for a phase I/Ib dose-escalation/expansion trial of ELC-401 for the treatment of glioblastoma. Preclinical development was concluded in February 2026, and a scientific advice meeting with the Swedish MPA is scheduled for mid-June 2026.", source: "Cision, 21 Apr 2026", refIds: ["elicera-rights-issue"] }, { title: "AlzeCure Pharma \u2013 CNS pipeline advancement", badge: "Phase IIa", text: "AlzeCure continues to advance its CNS drug pipeline across three research platforms. The company is preparing NeuroRestore ACD856 for a planned phase IIa clinical study in patients with early Alzheimer's disease, co-funded by the European Innovation Council. In the pain area, ACD440 has received orphan drug designation from both the FDA and EMA for erythromelalgia, with positive FDA feedback received for a registration-enabling phase IIb/III study and active out-licensing discussions ongoing.", source: "MFN, 21 Apr 2026", refIds: ["alzecure-rights-issue"] } ], medtech: [ { title: "Vitrolife \u2013 Q1 2026 interim results", badge: "Earnings", text: "Vitrolife reported Q1 2026 sales of SEK 807 million, an increase of 5 per cent in local currencies. Gross margin increased to 59.9 per cent, and organic growth in the Americas reached 11 per cent. The market responded positively, contributing to Vitrolife\u2019s +7.31 per cent weekly gain.", source: "Cision, Q1 2026 interim report", refIds: ["vitrolife-q1-2026"] }, { title: "Bioretec \u2013 RemeOs platform commercial expansion", badge: "Commercial", text: "Bioretec completed its rights issue with the ~EUR 13 million proceeds directed toward expanding the RemeOs biodegradable implant platform\u2019s commercial reach and building a US-based commercial organisation.", source: "Cision, 23\u201324 Apr 2026", refIds: ["bioretec-rights-issue"] } ] }, catalysts: [ { date: "4\u20136 May 2026", company: "Ascendis Pharma", event: "Convertible note conversion period closes 4 May; cash redemption date 6 May. The split between cash redemption and equity conversion will determine near-term dilution impact.", type: "Binary", accent: "teal" }, { date: "5 May 2026", company: "Vitrolife", event: "Annual General Meeting.", type: "Incremental", accent: "light" }, { date: "8 May 2026", company: "Elicera Therapeutics", event: "Extraordinary general meeting to approve the rights issue; MPA scientific advice meeting for ELC-401 scheduled mid-June.", type: "Incremental", accent: "light" }, { date: "12 May 2026", company: "Coloplast", event: "H1 2025/26 Interim Report \u2013 market will reassess Kerecis trajectory following the guidance cut and DKK 3.0 billion impairment.", type: "Asymmetric", accent: "gold" }, { date: "June 2026", company: "Hansa Biopharma", event: "ConfIdeS phase III results accepted for oral presentation at ATC. Imlifidase FDA BLA PDUFA target date is 19 December 2026.", type: "Binary", accent: "teal" } ], refs: [ { section: "Major Events & News", items: [ { id: "orion-odd-mesothelioma", citation: "Orion Pharma \u2013 ODM-212 granted Orphan Drug Designation in mesothelioma by the US FDA.", url: "https://www.globenewswire.com/news-release/2026/04/20/3277035/0/en/orion-pharma-s-odm-212-granted-orphan-drug-designation-in-mesothelioma-by-the-us-fda.html", accessed: "26 Apr 2026" }, { id: "orion-teadco-trial", citation: "Orion Pharma initiates TEADCO phase Ib/II basket trial evaluating ODM-212 in combination with standard of care treatments.", url: "https://www.globenewswire.com/news-release/2026/04/23/3279581/0/en/Orion-Pharma-initiates-TEADCO-Phase-1b-2-basket-trial-evaluating-ODM-212-in-combination-with-standard-of-care-treatments-in-patients-with-select-advanced-solid-tumours.html", accessed: "26 Apr 2026" }, { id: "ascendis-ordinary-shares", citation: "Ascendis Pharma announces commencement of trading of its ordinary shares on Nasdaq.", url: "https://www.globenewswire.com/news-release/2026/04/20/3276963/0/en/ascendis-pharma-announces-commencement-of-trading-of-its-ordinary-shares-on-nasdaq.html", accessed: "26 Apr 2026" }, { id: "ascendis-convertible-redemption", citation: "Ascendis announces redemption of all $575 million of outstanding 2.25% Convertible Senior Notes due 2028.", url: "https://www.globenewswire.com/news-release/2026/04/21/3278485/0/en/Ascendis-Announces-Redemption-of-All-575-Million-of-Outstanding-2-25-Convertible-Senior-Notes-Due-2028.html", accessed: "26 Apr 2026" }, { id: "coloplast-guidance-cut", citation: "Coloplast revises financial guidance for FY 2025/26 to reflect reduced growth outlook for Kerecis.", url: "https://www.globenewswire.com/news-release/2026/04/23/3280301/0/en/Coloplast-A-S-Coloplast-revises-financial-guidance-for-FY-2025-26-to-reflect-reduced-growth-outlook-for-Kerecis.html", accessed: "26 Apr 2026" }, { id: "elicera-rights-issue", citation: "Elicera Therapeutics carries out a rights issue of approximately SEK 73 million.", url: "https://news.cision.com/elicera-therapeutics/r/elicera-therapeutics-carries-out-a-rights-issue-of-approximately-sek-73-million,c4337398", accessed: "26 Apr 2026" }, { id: "alzecure-rights-issue", citation: "AlzeCure Pharma carries out a fully secured rights issue of approximately SEK 30.1 million.", url: "https://mfn.se/a/alzecure-pharma/alzecure-pharma-carries-out-a-fully-secured-rights-issue-of-approximately-sek-30-1-million", accessed: "26 Apr 2026" }, { id: "bioretec-rights-issue", citation: "Final results of Bioretec Ltd\u2019s rights issue.", url: "https://news.cision.com/bioretec/r/final-results-of-bioretec-ltd-s-rights-issue,c4340113", accessed: "26 Apr 2026" } ] }, { section: "Liquidity & Volatility", items: [ { id: "cellavision-q1-2026", citation: "CellaVision \u2013 Softer quarter due to lower sales in EMEA (Interim Report Q1 2026). MFN, 24 April 2026.", url: "https://mfn.se/a/cellavision/softer-quarter-due-to-lower-sales-in-emea", accessed: "26 Apr 2026" }, { id: "hansa-q1-2026", citation: "Hansa Biopharma rapporterar finansiella resultat f\u00f6r f\u00f6rsta kvartalet 2026 (Interim Report Q1 2026). Cision, 23 April 2026.", url: "https://news.cision.com/se/hansa-biopharma-ab/r/hansa-biopharma-rapporterar-finansiella-resultat-for-forsta-kvartalet-2026,c4338924", accessed: "26 Apr 2026" }, { id: "moberg-year-end-2025", citation: "Moberg Pharma Year-end report 2025 (full-year market share data for Terclara). Cision, 17 February 2026.", url: "https://news.cision.com/moberg-pharma/r/moberg-pharma-year-end-report-2025,c4308335", accessed: "26 Apr 2026" }, { id: "moberg-karo-license", citation: "Moberg Pharma and Karo Healthcare enter exclusive license agreement for MOB-015/Terclara in Europe. Cision, 5 November 2025.", url: "https://news.cision.com/moberg-pharma/r/moberg-pharma-and-karo-healthcare-enter-exclusive-license-agreement-for-mob-015-terclara-in-europe--,c4261942", accessed: "26 Apr 2026" } ] }, { section: "Development & Research", items: [ { id: "vitrolife-q1-2026", citation: "Vitrolife AB \u2013 Interim report Q1 2026: strong growth in consumables and technologies.", url: "https://news.cision.com/vitrolife-ab--publ-/r/interim-report-q1--2026--strong-growth-in-consumables-and-technologies,c4338311", accessed: "26 Apr 2026" } ] } ] }; // ================================================================= // UTILITIES // ================================================================= const $ = id => document.getElementById(id); const show = el => el && el.classList.remove('hidden'); const hide = el => el && el.classList.add('hidden'); const el = (tag, cls) => { const e = document.createElement(tag); if (cls) e.className = cls; return e; }; const txt = (e, t) => { e.textContent = t == null ? "" : String(t); }; function safeUrl(url) { const u = (url || "").trim(); if (!u) return ""; try { new URL(u); return u; } catch (e) { return ""; } } // ================================================================= // REFERENCE MAP — built once at boot from refs[]. // Maps each ref id to {number, anchorId} based on render order. // ================================================================= const refMap = {}; function buildRefMap() { let n = 1; (reportData.refs || []).forEach(function(group) { (group.items || []).forEach(function(item) { if (!item.id) return; const anchorId = 'ref-' + item.id; refMap[item.id] = { number: n, anchorId: anchorId }; item._number = n; item._anchorId = anchorId; n++; }); }); } // Returns an HTML string for a list of refIds, or "" if empty/missing. // Format: <sup class="bs-refsup">[<a href="#ref-x">1</a>,<a>2</a>]</sup> function refSupHtml(refIds) { if (!refIds || !refIds.length) return ""; const parts = []; for (let i = 0; i < refIds.length; i++) { const r = refMap[refIds[i]]; if (!r) continue; parts.push('<a href="#' + r.anchorId + '">' + r.number + '</a>'); } if (!parts.length) return ""; return '<sup class="bs-refsup">[' + parts.join(',') + ']</sup>'; } // ================================================================= // DATA VALIDATION // ================================================================= function validateData() { const w = []; if (!meta.weekLabel) w.push("meta.weekLabel is empty"); if (!meta.dateRange) w.push("meta.dateRange is empty"); const pills = reportData.marketPills || []; if (pills.length !== 3) w.push("marketPills: expected 3, got " + pills.length); const insights = reportData.keyInsights || []; if (insights.length < 2) w.push("keyInsights: minimum 2 required, got " + insights.length); if (insights.length > 6) w.push("keyInsights: maximum 6 allowed, got " + insights.length); const events = reportData.events || []; if (events.length > 7) w.push("events: maximum 7 allowed, got " + events.length); const validTags = ["Clinical","Regulatory","Financing","M&A","Commercial","Corporate"]; events.forEach((ev, i) => { if (!validTags.includes(ev.tag)) w.push("events[" + i + "]: invalid tag \u201c" + ev.tag + "\u201d"); }); const cats = reportData.catalysts || []; const validTypes = ["Binary","Asymmetric","Incremental"]; cats.forEach((c, i) => { if (!validTypes.includes(c.type)) w.push("catalysts[" + i + "]: invalid type \u201c" + c.type + "\u201d"); }); if (w.length) { console.group("[BioStock] Validation: " + w.length + " warning(s)"); w.forEach(x => console.warn(x)); console.groupEnd(); } } // ================================================================= // RENDER: HERO ZONE // ================================================================= function renderHero() { const topbarWrap = $('npl-topbar-wrap'); topbarWrap.innerHTML = '<div class="npl-topbar">' + '<div class="npl-logo">' + '<div class="npl-logo-mark">B</div>' + '<div><div class="npl-logo-text">BioStock Analytics</div>' + '<div class="npl-logo-sub">Nordic Life Science Weekly</div></div>' + '</div>' + '<span class="npl-topbar-right">' + (meta.weekLabel || '') + (meta.dateRange ? ' \u00b7 ' + meta.dateRange : '') + '</span>' + '</div>'; const titleParts = (meta.heroTitle || meta.weekLabel || "").split("\n"); const mainTitle = titleParts[0] || ""; const italicPart = titleParts[1] || ""; const titleHtml = mainTitle + (italicPart ? '<br><em>' + italicPart + '</em>' : ''); const pills = reportData.marketPills || []; const idxRows = pills.map(function(p) { const dir = (p.direction || "").toLowerCase(); const cls = dir === 'up' ? 'up' : dir === 'down' ? 'dn' : 'fl'; const prefix = dir === 'up' ? '+' : ''; return '<div class="npl-idx-row">' + '<span class="npl-idx-name">' + (p.fullName || p.label) + '</span>' + '<span class="npl-idx-val ' + cls + '">' + prefix + p.value + '</span>' + '</div>'; }).join(''); const movers = reportData.moversTable || []; let moverHtml = ''; if (movers.length) { const gainer = movers[0]; const decliner = movers[movers.length - 1]; const gPfx = Number(gainer.chg) >= 0 ? '+' : ''; const dPfx = Number(decliner.chg) >= 0 ? '+' : ''; moverHtml = '<div class="npl-panel-div"></div>' + '<div class="npl-mover-lbl">Top gainer</div>' + '<div class="npl-mover-row" style="margin-bottom:16px">' + '<span class="npl-mover-name">' + gainer.company + '</span>' + '<span class="npl-mover-val up">' + gPfx + Number(gainer.chg).toFixed(2) + '%</span>' + '</div>' + '<div class="npl-mover-lbl">Top decliner</div>' + '<div class="npl-mover-row">' + '<span class="npl-mover-name">' + decliner.company + '</span>' + '<span class="npl-mover-val dn">' + dPfx + Number(decliner.chg).toFixed(2) + '%</span>' + '</div>'; } $('npl-hero-wrap').innerHTML = '<section class="npl-hero">' + '<div class="npl-hero-inner">' + '<div>' + '<div class="npl-issue-tag">' + (meta.weekLabel || '') + (meta.dateRange ? ' \u00b7 ' + meta.dateRange : '') + '</div>' + '<h1 class="npl-hero-title">' + titleHtml + '</h1>' + '<p class="npl-hero-lead">' + (meta.heroLead || '') + '</p>' + '<a href="#biostock-report" class="npl-hero-anchor">Read the full report ' + '<svg viewBox="0 0 20 20" fill="currentColor" width="15" height="15">' + '<path fill-rule="evenodd" d="M10 3a1 1 0 011 1v10.586l3.293-3.293a1 1 0 111.414 1.414l-5 5a1 1 0 01-1.414 0l-5-5a1 1 0 111.414-1.414L9 14.586V4a1 1 0 011-1z" clip-rule="evenodd"/>' + '</svg>' + '</a>' + '</div>' + '<div class="npl-index-panel">' + '<div class="npl-panel-label">Index performance \u00b7 week-over-week</div>' + idxRows + moverHtml + '</div>' + '</div>' + '</section>'; } // ================================================================= // RENDER: TICKER TAPE // ================================================================= function renderTicker() { const movers = reportData.moversTable || []; if (!movers.length) return; const items = movers.map(function(m) { const pfx = Number(m.chg) >= 0 ? '+' : ''; return '<span class="npl-ticker-item">' + m.company + ' ' + pfx + Number(m.chg).toFixed(2) + '%' + '<span class="npl-ticker-sep">\u00b7</span></span>'; }).join(''); $('npl-ticker-wrap').innerHTML = '<div class="npl-ticker"><div class="npl-ticker-inner">' + items + items + '</div></div>'; } // ================================================================= // RENDER: EXECUTIVE SUMMARY CARDS // ================================================================= function renderSummaryCards() { const cards = reportData.summaryCards || []; if (!cards.length && !meta.summaryTitle) return; const cardsHtml = cards.map(function(c) { return '<div class="npl-data-card">' + '<div class="npl-data-card-label">' + (c.label || '') + '</div>' + '<div class="npl-data-card-text">' + (c.text || '') + '</div>' + '</div>'; }).join(''); $('npl-summary-wrap').innerHTML = '<div class="npl-preview">' + '<div class="npl-eyebrow">Executive Summary</div>' + '<h2 class="npl-section-title">' + (meta.summaryTitle || '') + '</h2>' + '<div class="npl-section-line"></div>' + (meta.summaryDesc ? '<p class="npl-section-desc">' + meta.summaryDesc + '</p>' : '') + (cardsHtml ? '<div class="npl-data-grid">' + cardsHtml + '</div>' : '') + '</div>'; } // ================================================================= // RENDER: META // ================================================================= function renderMeta() { if (meta.reportTitle) document.title = meta.reportTitle; txt($('meta-week'), meta.weekLabel); txt($('meta-dates'), meta.dateRange); txt($('market-subtitle'), meta.marketSubtitle); txt($('market-source'), meta.marketSourceNote); txt($('events-subtitle'), meta.eventsSubtitle); txt($('methodology-text'), meta.methodologyText); txt($('catalyst-note'), meta.catalystNote); txt($('ai-disclosure-text'), meta.aiDisclosure); if (meta.liquidityText) { show($('liquidity-wrap')); const liqWrap = $('liquidity-text'); liqWrap.innerHTML = ""; const liqRefs = meta.liquidityRefIds || []; meta.liquidityText.split("\n\n").forEach(function(para, i) { const trimmed = para.trim(); if (!trimmed) return; const p = el('p', 'text-sm leading-relaxed' + (i > 0 ? ' mt-3' : '')); p.style.color = 'var(--text-mid)'; const sup = refSupHtml(liqRefs[i]); if (sup) { p.innerHTML = trimmed.replace(/[<>&"']/g, function(c){ return {'<':'<','>':'>','&':'&','"':'"',"'":'''}[c]; }) + sup; } else { txt(p, trimmed); } liqWrap.appendChild(p); }); } } // ================================================================= // RENDER: KEY INSIGHTS // ================================================================= function renderInsights() { const list = $('insights-list'); list.innerHTML = ""; const items = reportData.keyInsights || []; if (!items.length) { show($('insights-empty')); return; } hide($('insights-empty')); items.forEach(function(item) { const li = el('li', 'pl-1'); if (item.label) { const s = el('span', 'font-semibold'); s.style.color = 'var(--teal-dark)'; txt(s, item.label); li.appendChild(s); li.appendChild(document.createTextNode(" ")); } li.appendChild(document.createTextNode(item.text || "")); const sup = refSupHtml(item.refIds); if (sup) { const supWrap = document.createElement('span'); supWrap.innerHTML = sup; li.appendChild(supWrap); } list.appendChild(li); }); } // ================================================================= // RENDER: MARKET PILLS & MOVERS // ================================================================= function renderMarketPills() { const wrap = $('market-pills'); wrap.innerHTML = ""; (reportData.marketPills || []).forEach(function(p) { const dir = (p.direction || "").toLowerCase(); const cls = dir === 'up' ? 'pill-up' : dir === 'down' ? 'pill-dn' : 'pill-flat'; const prefix = dir === 'up' ? '\u25b2 ' : dir === 'down' ? '\u25bc ' : ''; const span = el('span', 'inline-flex items-center px-2.5 py-1 rounded text-xs font-medium font-mono border ' + cls); txt(span, p.label + ": " + prefix + p.value); wrap.appendChild(span); }); } function renderMovers() { const tbody = $('movers-body'); tbody.innerHTML = ""; const rows = reportData.moversTable || []; if (!rows.length) { show($('movers-empty')); return; } hide($('movers-empty')); rows.forEach(function(r) { const tr = document.createElement('tr'); const td1 = el('td', 'px-2 py-2 text-xs font-medium'); td1.style.color = 'var(--text)'; txt(td1, r.company || ""); const td2 = el('td', 'px-2 py-2 text-right text-xs font-mono font-medium'); const chg = Number(r.chg); if (isFinite(chg)) { const pfx = chg >= 0 ? '+' : ''; td2.classList.add(chg >= 0 ? 'chg-up' : 'chg-dn'); txt(td2, pfx + chg.toFixed(1) + "%"); } else { txt(td2, "\u2014"); td2.style.color = 'var(--text-light)'; } tr.appendChild(td1); tr.appendChild(td2); tbody.appendChild(tr); }); } // ================================================================= // RENDER: CHART // ================================================================= let marketChart = null; function initMarketChart() { const labels = (reportData.marketSeries && reportData.marketSeries.labels) || []; const indices = (reportData.marketSeries && reportData.marketSeries.indices) || []; if (!labels.length || !indices.length) { show($('market-empty')); return; } hide($('market-empty')); const ctx = $('marketChart').getContext('2d'); const colors = ['#2c5a6b', '#b8975c', '#3a7389']; const datasets = indices.map(function(s, i) { return { label: s.name || s.key, data: Array.isArray(s.data) ? s.data : [], backgroundColor: colors[i] || '#888', borderColor: colors[i] || '#888', borderWidth: 1, borderRadius: 3, barPercentage: 0.7, categoryPercentage: 0.85 }; }); if (marketChart) marketChart.destroy(); marketChart = new Chart(ctx, { type: 'bar', data: { labels: labels, datasets: datasets }, options: { responsive: true, maintainAspectRatio: false, interaction: { mode: 'index', intersect: false }, plugins: { legend: { position: 'bottom', labels: { boxWidth: 8, usePointStyle: true, pointStyleWidth: 8, font: { family: "'Plus Jakarta Sans', sans-serif", size: 11 }, padding: 16 } }, tooltip: { backgroundColor: 'rgba(30,63,77,0.95)', titleFont: { family: "'Plus Jakarta Sans', sans-serif", size: 12 }, bodyFont: { family: "'JetBrains Mono', monospace", size: 11 }, padding: 10, cornerRadius: 3, callbacks: { label: function(ctx) { var v = ctx.parsed.y; return " " + ctx.dataset.label + ": " + (v >= 0 ? '+' : '') + v.toFixed(2) + "%"; } } } }, scales: { x: { grid: { display: false }, ticks: { font: { family: "'Plus Jakarta Sans', sans-serif", size: 10 }, color: '#888' } }, y: { grid: { color: '#e8e4df', drawBorder: false }, ticks: { font: { family: "'JetBrains Mono', monospace", size: 10 }, color: '#888', callback: function(v) { return (v >= 0 ? '+' : '') + v.toFixed(1) + '%'; } } } } } }); } // ================================================================= // RENDER: MAJOR EVENTS // ================================================================= function renderEvents() { const wrap = $('events-list'); wrap.innerHTML = ""; const items = reportData.events || []; if (!items.length) { show($('events-empty')); hide(wrap); return; } hide($('events-empty')); show(wrap); items.forEach(function(a) { const block = el('div', 'event-row pl-4'); const head = el('div', 'flex flex-wrap items-center gap-2 mb-1'); const h = el('h3', 'text-sm font-bold'); h.style.color = 'var(--teal-dark)'; const sup = refSupHtml(a.refIds); if (sup) { h.innerHTML = (a.title || "").replace(/[<>&"']/g, function(c){ return {'<':'<','>':'>','&':'&','"':'"',"'":'''}[c]; }) + sup; } else { txt(h, a.title || ""); } head.appendChild(h); if (a.tag) { const badge = el('span', 'text-[10px] font-mono px-2 py-0.5 rounded uppercase tracking-wider'); badge.style.cssText = 'background:var(--warm-dark);color:var(--text-mid)'; txt(badge, a.tag); head.appendChild(badge); } block.appendChild(head); if (a.text) { const p = el('p', 'text-sm leading-relaxed'); p.style.color = 'var(--text)'; txt(p, a.text); block.appendChild(p); } if (a.implication) { const imp = el('p', 'text-sm mt-1 leading-relaxed'); imp.style.color = 'var(--text-mid)'; txt(imp, a.implication); block.appendChild(imp); } if (a.marketReaction) { const mr = el('span', 'market-reaction'); txt(mr, '\u25b8 ' + a.marketReaction); const mrWrap = el('div', 'mt-2'); mrWrap.appendChild(mr); block.appendChild(mrWrap); } if (a.source) { const src = el('p', 'text-[10px] font-mono mt-2'); src.style.color = 'var(--text-light)'; txt(src, a.source); block.appendChild(src); } wrap.appendChild(block); }); } // ================================================================= // RENDER: FINANCIAL IMPACT // ================================================================= function renderFinance() { const wrap = $('finance-list'); wrap.innerHTML = ""; const items = reportData.finance || []; if (!items.length) { show($('finance-empty')); return; } hide($('finance-empty')); const grid = el('div', 'grid grid-cols-1 md:grid-cols-2 gap-4'); items.forEach(function(b) { const tile = el('div', 'fin-tile p-4'); const row = el('div', 'flex justify-between items-center mb-2'); const name = el('span', 'font-semibold text-sm'); name.style.color = 'var(--teal-dark)'; const sup = refSupHtml(b.refIds); if (sup) { name.innerHTML = (b.company || "").replace(/[<>&"']/g, function(c){ return {'<':'<','>':'>','&':'&','"':'"',"'":'''}[c]; }) + sup; } else { txt(name, b.company || ""); } row.appendChild(name); if (b.tag) { const tone = (b.tagTone || '').toLowerCase(); const cls = tone === 'green' ? 'tag-green' : tone === 'red' ? 'tag-red' : 'tag-grey'; const tag = el('span', 'text-[10px] font-mono px-2 py-0.5 rounded border ' + cls); txt(tag, b.tag); row.appendChild(tag); } tile.appendChild(row); const t = el('p', 'text-sm leading-relaxed'); t.style.color = 'var(--text)'; txt(t, b.text || ""); tile.appendChild(t); if (b.source) { const src = el('p', 'text-[10px] font-mono pt-2 mt-3'); src.style.cssText = 'color:var(--text-light);border-top:1px solid var(--warm-dark)'; txt(src, b.source); tile.appendChild(src); } grid.appendChild(tile); }); wrap.appendChild(grid); } // ================================================================= // RENDER: DEV & RESEARCH // ================================================================= function renderResearchItem(a, container) { const block = el('div', 'event-row pl-4'); const head = el('div', 'flex flex-wrap items-center gap-2 mb-1'); const h = el('h3', 'text-sm font-bold'); h.style.color = 'var(--teal-dark)'; const sup = refSupHtml(a.refIds); if (sup) { h.innerHTML = (a.title || "").replace(/[<>&"']/g, function(c){ return {'<':'<','>':'>','&':'&','"':'"',"'":'''}[c]; }) + sup; } else { txt(h, a.title || ""); } head.appendChild(h); if (a.badge) { const badge = el('span', 'text-[10px] font-mono px-2 py-0.5 rounded'); badge.style.cssText = 'background:var(--warm-dark);color:var(--text-mid)'; txt(badge, a.badge); head.appendChild(badge); } block.appendChild(head); if (a.text) { const p = el('p', 'text-sm leading-relaxed'); p.style.color = 'var(--text)'; txt(p, a.text); block.appendChild(p); } if (a.source) { const src = el('p', 'text-[10px] font-mono mt-2'); src.style.color = 'var(--text-light)'; txt(src, a.source); block.appendChild(src); } container.appendChild(block); } function renderResearch() { const biotech = (reportData.research && reportData.research.biotech) || []; const medtech = (reportData.research && reportData.research.medtech) || []; if (!biotech.length && !medtech.length) { show($('research-empty')); return; } hide($('research-empty')); var allP = $('rpanel-all'); allP.innerHTML = ""; if (biotech.length && medtech.length) { var l = el('p', 'text-[10px] font-bold uppercase tracking-widest mb-3'); l.style.color = 'var(--text-light)'; txt(l, 'Biotech & Pharma'); allP.appendChild(l); } biotech.forEach(function(a) { renderResearchItem(a, allP); }); if (biotech.length && medtech.length) { var l2 = el('p', 'text-[10px] font-bold uppercase tracking-widest mt-6 pt-5 border-t border-gray-200 mb-3'); l2.style.color = 'var(--text-light)'; txt(l2, 'MedTech & Diagnostics'); allP.appendChild(l2); } medtech.forEach(function(a) { renderResearchItem(a, allP); }); var btP = $('rpanel-biotech'); btP.innerHTML = ""; if (!biotech.length) { var e1 = el('p', 'text-sm italic py-6 text-center'); e1.style.color = 'var(--text-light)'; txt(e1, "No eligible items this week"); btP.appendChild(e1); } else { biotech.forEach(function(a) { renderResearchItem(a, btP); }); } var mtP = $('rpanel-medtech'); mtP.innerHTML = ""; if (!medtech.length) { var e2 = el('p', 'text-sm italic py-6 text-center'); e2.style.color = 'var(--text-light)'; txt(e2, "No eligible items this week"); mtP.appendChild(e2); } else { medtech.forEach(function(a) { renderResearchItem(a, mtP); }); } } function initResearchTabs() { var tabs = ['all', 'biotech', 'medtech']; tabs.forEach(function(t) { var btn = $('rtab-' + t); if (!btn) return; btn.addEventListener('click', function() { setResearchTab(t); }); btn.addEventListener('keydown', function(e) { if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') { e.preventDefault(); var idx = tabs.indexOf(t); var next = e.key === 'ArrowRight' ? (idx + 1) % tabs.length : (idx - 1 + tabs.length) % tabs.length; $('rtab-' + tabs[next]).focus(); setResearchTab(tabs[next]); } }); }); } function setResearchTab(name) { ['all', 'biotech', 'medtech'].forEach(function(t) { var btn = $('rtab-' + t); var panel = $('rpanel-' + t); var active = t === name; btn.setAttribute('aria-selected', active ? 'true' : 'false'); btn.setAttribute('tabindex', active ? '0' : '-1'); if (active) { show(panel); } else { hide(panel); } }); } // ================================================================= // RENDER: CATALYST WATCH // ================================================================= function renderCatalysts() { var ul = $('catalyst-timeline'); ul.innerHTML = ""; var items = reportData.catalysts || []; if (!items.length) { show($('catalyst-empty')); return; } hide($('catalyst-empty')); items.forEach(function(c) { var li = el('li', 'relative pl-8'); var acc = (c.accent || '').toLowerCase(); var dotStyle = acc === 'teal' ? 'border-color:var(--teal)' : acc === 'gold' ? 'border-color:var(--gold)' : 'border-color:var(--warm-dark)'; var dot = el('div', 'absolute left-0 top-1.5 h-[18px] w-[18px] rounded-full border-2 bg-white'); dot.style.cssText = dotStyle; li.appendChild(dot); var row = el('div', 'flex flex-col sm:flex-row sm:items-start sm:justify-between gap-1'); var left = el('div', ''); var dateLine = el('h4', 'text-xs font-bold'); dateLine.style.color = 'var(--teal-dark)'; txt(dateLine, c.date || ""); var detail = el('p', 'text-sm leading-relaxed'); detail.style.color = 'var(--text-mid)'; var company = (c.company || "").trim(); var event = (c.event || "").trim(); txt(detail, company && event ? company + ": " + event : (company || event)); left.appendChild(dateLine); left.appendChild(detail); var type = (c.type || "").trim(); var tl = type.toLowerCase(); var typeCls = tl === 'binary' ? 'catalyst-binary' : tl === 'asymmetric' ? 'catalyst-asymmetric' : tl === 'incremental' ? 'catalyst-incremental' : ''; var badge = el('span', 'text-[10px] font-medium px-2 py-0.5 rounded whitespace-nowrap ' + typeCls); txt(badge, type); row.appendChild(left); row.appendChild(badge); li.appendChild(row); ul.appendChild(li); }); } // ================================================================= // RENDER: REFERENCES // ================================================================= function renderRefs() { var wrap = $('ref-sections'); wrap.innerHTML = ""; var groups = reportData.refs || []; if (!groups.length) { show($('refs-empty')); return; } hide($('refs-empty')); groups.forEach(function(group) { var section = el('div', 'mb-3'); var heading = el('h4', 'text-[10px] font-semibold uppercase tracking-[0.1em] mb-1.5'); heading.style.color = 'var(--text-mid)'; txt(heading, group.section || "General"); section.appendChild(heading); var list = el('ul', 'space-y-1.5 list-none'); (group.items || []).forEach(function(r) { var li = el('li', 'bs-ref-item text-[10px] leading-relaxed'); li.style.color = 'var(--text-light)'; if (r.id) li.id = 'ref-' + r.id; var cite = (r.citation || "").trim(); var url = safeUrl(r.url); var accessed = (r.accessed || "").trim(); var content = cite ? (cite.endsWith('.') ? cite + ' ' : cite + '. ') : ''; if (typeof r._number === 'number') { var num = el('span', 'bs-refnum'); txt(num, '[' + r._number + ']'); li.appendChild(num); } if (url) { var span = el('span', ''); span.appendChild(document.createTextNode(content + 'Available at: ')); var a = el('a', 'underline transition-colors'); a.style.color = 'var(--teal)'; a.href = url; a.target = "_blank"; a.rel = "noopener noreferrer"; txt(a, url); span.appendChild(a); if (accessed) span.appendChild(document.createTextNode(' (Accessed: ' + accessed + ').')); li.appendChild(span); } else { li.appendChild(document.createTextNode(content)); } list.appendChild(li); }); section.appendChild(list); wrap.appendChild(section); }); } // ================================================================= // MOBILE NAV // ================================================================= function initMobileNav() { var btn = $('mobile-nav-btn'); var nav = $('mobile-nav'); var links = document.querySelectorAll('#sidebar-nav .nav-link'); var mobileWrap = $('mobile-nav-links'); links.forEach(function(link) { var a = link.cloneNode(true); a.className = 'block px-4 py-2 text-xs font-medium uppercase tracking-[0.08em]'; a.style.color = 'var(--text-mid)'; a.addEventListener('click', function() { nav.classList.remove('open'); }); mobileWrap.appendChild(a); }); btn.addEventListener('click', function() { var open = nav.classList.toggle('open'); btn.setAttribute('aria-expanded', open ? 'true' : 'false'); }); } // ================================================================= // SCROLLSPY // ================================================================= function initScrollSpy() { var links = Array.from(document.querySelectorAll('#sidebar-nav .nav-link')); var map = new Map(); links.forEach(function(a) { var id = a.getAttribute('href') && a.getAttribute('href').slice(1); var sec = id ? document.getElementById(id) : null; if (sec) map.set(sec, a); }); var setActive = function(target) { links.forEach(function(a) { a.classList.remove('active'); }); var a = map.get(target); if (a) a.classList.add('active'); }; var observer = new IntersectionObserver(function(entries) { var visible = entries.filter(function(e) { return e.isIntersecting; }) .sort(function(a, b) { return b.intersectionRatio - a.intersectionRatio; })[0]; if (visible && visible.target) setActive(visible.target); }, { root: null, rootMargin: '-25% 0px -65% 0px', threshold: [0.01, 0.1, 0.25, 0.5] }); map.forEach(function(_, sec) { observer.observe(sec); }); } // ================================================================= // WORDPRESS COMPATIBILITY // ================================================================= function initWPScrollFix() { var isWP = !!document.getElementById('wpadminbar') || document.body.className.indexOf('wp-') > -1 || document.body.className.indexOf('wordpress') > -1; var isMobile = window.innerWidth < 1024; var wpH = 0; document.querySelectorAll('#wpadminbar, .site-header, #masthead, nav.main-navigation').forEach(function(el) { if (el) { var pos = getComputedStyle(el).position; if (pos === 'fixed' || pos === 'sticky') wpH += el.offsetHeight; } }); var rptHeader = document.querySelector('#biostock-report header'); if (isWP && rptHeader) { if (isMobile) { rptHeader.style.top = wpH + 'px'; } else { rptHeader.style.position = 'relative'; } } if (isWP && wpH > 0) { var sidebar = document.querySelector('#biostock-report aside'); if (sidebar) sidebar.style.top = (wpH + 16) + 'px'; } var stickyH = wpH; if (rptHeader && getComputedStyle(rptHeader).position === 'sticky') stickyH += rptHeader.offsetHeight; var pad = isMobile ? (stickyH + 300) : (stickyH + 10); document.querySelectorAll('[id^="bs-"]').forEach(function(sec) { sec.style.setProperty('scroll-margin-top', pad + 'px', 'important'); }); document.querySelectorAll('#sidebar-nav .nav-link, #mobile-nav-links a').forEach(function(link) { link.addEventListener('click', function(e) { var targetId = this.getAttribute('href') && this.getAttribute('href').slice(1); var target = targetId ? document.getElementById(targetId) : null; if (target) { e.preventDefault(); e.stopPropagation(); target.scrollIntoView({ behavior: 'smooth', block: 'start' }); } }); }); } // ================================================================= // BOOT // ================================================================= document.addEventListener('DOMContentLoaded', function() { validateData(); buildRefMap(); renderHero(); renderTicker(); renderSummaryCards(); renderMeta(); renderInsights(); renderMarketPills(); renderMovers(); initMarketChart(); renderEvents(); renderFinance(); renderResearch(); initResearchTabs(); setResearchTab('all'); renderCatalysts(); renderRefs(); initMobileNav(); initScrollSpy(); initWPScrollFix(); });Analys
Rapporter
Valet 2026
Analys
Rapporter
Valet 2026
1 DAG %
Senast
OMX Stockholm 30
−0,06%
(09:44)
Telia Company
Idag, 09:40
Saab stiger – Telia backar
Asienbörserna
Idag, 07:40
Asienbörser på rekordnivåer
Saab
Idag, 07:38
Saab har fått en publik blankare
OMX Stockholm 30
1 DAG %
Senast
3 098,32