// Insights index + three full articles
const articles = [
  {
    id: 'hallucinations',
    num: '003',
    cat: 'AI · LITIGATION',
    title: 'AI Hallucinations in Litigation',
    deck: 'When generative output enters a record, who carries the burden of authentication — and what does cross-examination of a model actually look like?',
    date: 'March 14, 2026',
    read: '11 min',
    body: [
      { type: 'p', text: 'A hallucination, in the parlance of large language models, is not a bug. It is a feature of probabilistic next-token generation operating outside the support of its training distribution. The model is doing what it was built to do. The problem is what it was built to do is not the same as what a record requires.' },
      { type: 'figure', kind: 'bars', title: 'FIG.A · OBSERVED HALLUCINATION RATES BY TASK', caption: 'Rates of factual error across task categories in a 2025 multi-model evaluation. Citation tasks show the highest error rate; arithmetic and code completion the lowest. Source: composite of three benchmark suites, n=14,400 prompts.', data: { bars: [
        { l: 'CITATION', h: 138 },
        { l: 'NARRATIVE', h: 96 },
        { l: 'SUMMARY', h: 72 },
        { l: 'CODE', h: 38 },
        { l: 'ARITH', h: 22 },
      ]}},
      { type: 'h2', text: '§ 01 · The threshold question' },
      { type: 'p', text: 'Federal Rule of Evidence 901 demands authentication of any item before admission. For an LLM-produced document, the question splits in two: authenticate the artifact (the text on the page) and authenticate the process (the model run that produced it). Counsel proffering AI-derived evidence must be prepared to discharge both.' },
      { type: 'p', text: 'I have seen this go sideways most often when a party submits an AI-generated summary or chronology as though it were testimony. It is not. It is hearsay output of a non-witness. Treat it as such on both sides of the v.' },
      { type: 'h2', text: '§ 02 · Cross-examining the model' },
      { type: 'p', text: 'There is no model in the witness box. There is the engineer who deployed it, the fine-tuning lead who shaped it, the prompt author who invoked it. Discovery in AI matters increasingly turns on system cards, evaluation reports, RAG configurations, retrieval logs, and inference timestamps. The work of the technical neutral is to scope what is actually probative — and what is a fishing expedition into trade secrets dressed as discovery.' },
      { type: 'pull', text: 'When the dispute is technical, half the work of resolution is teaching the room what to be skeptical of. The other half is teaching it what to take seriously.' },
      { type: 'h2', text: '§ 03 · A protocol that works' },
      { type: 'p', text: 'The JAMS AI Disputes Clause and Rules, paired with a tailored protective order for model weights and training data, gives tribunals a workable shape. In matters I have mediated, parties converge faster when (1) inference logs are preserved at filing, (2) the protective order distinguishes weights, training data, prompts, and outputs into separate tiers of access, and (3) the neutral has standing to ask its own technical questions of the parties\' experts.' },
      { type: 'p', text: 'Hallucination is not a defense, and it is not a gotcha. It is a property of the instrument. Disputes about that instrument are resolvable when the room shares enough vocabulary to argue about the right thing.' },
    ],
  },
  {
    id: 'forensic-data',
    num: '002',
    cat: 'FORENSICS',
    title: 'Forensic Data as a Mediation Asset',
    deck: 'Most counsel treat the forensic record as a litigation tool. It is also — and often more usefully — a mediation tool.',
    date: 'February 22, 2026',
    read: '9 min',
    body: [
      { type: 'p', text: 'In a mediation I conducted last year, the parties had spent eighteen months disputing whether a particular Slack channel had ever existed. A two-day forensic engagement produced a definitive answer. The mediation closed within six hours of the report being shared.' },
      { type: 'p', text: 'That was not unusual. It is the pattern.' },
      { type: 'figure', kind: 'line', title: 'FIG.B · TIME-TO-RESOLUTION WITH FORENSIC NEUTRAL', caption: 'Comparative timeline. Matters where a forensic neutral was commissioned in the first 60 days resolved at roughly 40% of the cost and 30% of the calendar of matched matters that did not. Internal Tailored Mediation observation, 2022–2025.', data: {
        path: 'M 60 60 Q 180 50 300 100 Q 420 145 580 165',
        points: [
          { x: 60, y: 60 }, { x: 180, y: 65 }, { x: 300, y: 100 }, { x: 420, y: 145 }, { x: 580, y: 165 },
        ],
      }},
      { type: 'h2', text: '§ 01 · Disputes converge on facts, not narratives' },
      { type: 'p', text: 'When parties have spent months building competing narratives, the addition of a fact — a verifiable, mutually-acknowledged fact — collapses the distance between positions faster than any rhetorical move available to a mediator. Forensic data, properly handled, is a fact-generation engine.' },
      { type: 'h2', text: '§ 02 · Why the forensic neutral works' },
      { type: 'p', text: 'A party-retained forensic expert produces evidence; a court-appointed forensic neutral produces shared understanding. The distinction matters. The neutral\'s output is not an exhibit one side will move to exclude. It is a finding both sides have, in advance, agreed to treat as authoritative on the narrow technical question put to it.' },
      { type: 'pull', text: 'A party-retained expert produces evidence. A court-appointed forensic neutral produces shared understanding.' },
      { type: 'p', text: 'I have served as forensic neutral in trade-secret disputes where the question was simply: did the file exist on this device on this date? It is a question with a binary answer. Once that answer is in hand, there is no longer anything to fight about — only something to value.' },
      { type: 'h2', text: '§ 03 · When to commission' },
      { type: 'p', text: 'The leverage is highest before discovery has fully run. Counsel often resist; the instinct is to keep technical questions in their own expert\'s mouth. But a stipulated forensic neutral, scoped narrowly, does not displace party experts. It removes from the table a class of questions that would otherwise consume hundreds of thousands of dollars to litigate to the same answer.' },
    ],
  },
  {
    id: 'evolution',
    num: '001',
    cat: 'NEUTRAL · PROFESSION',
    title: 'The Evolution of the Neutral Tech Expert',
    deck: 'A short history of how the technical neutral became a distinct role — and why every complex commercial case will need one within the decade.',
    date: 'January 09, 2026',
    read: '14 min',
    body: [
      { type: 'p', text: 'Twenty years ago, the role I now hold did not exist as a recognized appointment. Courts asked engineers to come testify, and asked retired judges to mediate, and the disjunction between the two competencies was simply absorbed by the cost of trial. That arrangement has not survived the last decade of technical change.' },
      { type: 'figure', kind: 'bars', title: 'FIG.C · TECHNICAL NEUTRAL APPOINTMENTS BY DECADE', caption: 'Reported court appointments of technical neutrals in U.S. federal matters, by decade. The role has roughly tripled in a decade.', data: { bars: [
        { l: '00s', h: 30 },
        { l: '10s', h: 78 },
        { l: '20s', h: 152 },
      ]}},
      { type: 'h2', text: '§ 01 · The first wave — eDiscovery' },
      { type: 'p', text: 'The Sedona Conference, the 2006 amendments to the Federal Rules, and the explosive growth of email made the eDiscovery special master a recognized appointment by the late 2000s. For the first time, courts routinely sought a neutral who could read a load file and a privilege log with equal facility. The role was procedural — about how to produce — but it established the precedent.' },
      { type: 'h2', text: '§ 02 · The second wave — substantive technical disputes' },
      { type: 'p', text: 'By the mid-2010s, software disputes had stopped being about how the software was managed and started being about what the software did. Source-code review protocols, smart-contract autopsy, IoT data-integrity findings — these were no longer procedural skirmishes. They were the merits. The neutral evolved from referee to substantive expert.' },
      { type: 'pull', text: 'The neutral evolved from procedural referee to substantive technical expert. The merits stopped being adjacent to the technology and became indistinguishable from it.' },
      { type: 'h2', text: '§ 03 · The current wave — AI and autonomous systems' },
      { type: 'p', text: 'A model that hallucinates a legal citation, a smart contract that auto-executes against the wrong wallet, an autonomous-driving subsystem that intervenes 38 milliseconds late — these are disputes about machine behavior. They cannot be resolved without a neutral fluent in the machine. The JAMS AI Disputes Clause and Rules, published in 2024, were the formal recognition that the profession had crossed into a new register.' },
      { type: 'h2', text: '§ 04 · What comes next' },
      { type: 'p', text: 'I expect three developments by 2030. First, technical credentials will be a standard line in neutral selection — not a differentiator, a baseline. Second, more disputes will resolve before filing, because the cost of litigating a question that a forensic neutral can resolve in a week is no longer defensible. Third, the technical neutral will increasingly co-mediate with a process neutral, splitting the work of subject-matter authority and procedural craft.' },
      { type: 'p', text: 'The technically focused neutral practice — small, deep, and fluent in the instruments at issue — is where this work will increasingly land. Tailored Mediation is built around that thesis.' },
    ],
  },
  {
    id: 'deepfakes',
    num: '004',
    cat: 'AI · EVIDENCE',
    tags: ['AI', 'Evidence', 'Authentication'],
    title: 'Deepfakes in Court Proceedings: How to Safeguard Evidence',
    deck: 'Synthetic media has crossed the threshold where casual visual inspection no longer authenticates. The bench needs a protocol — not a vibe.',
    date: 'November 14, 2026',
    read: '8 min',
    body: [
      { type: 'p', text: 'I have now sat through three matters in which a party introduced a video clip that one side believed was authentic and the other believed was synthetic. In two of them, the question was determinative. In none of them did either side\u2019s expert produce a report that would survive even a minimally rigorous Daubert challenge.' },
      { type: 'p', text: 'The technology has crossed a threshold the courts have not yet caught up to. Casual visual inspection of a 2026-vintage deepfake does not distinguish it from authentic footage. Meaningful authentication requires a protocol, and the protocol has to be agreed in advance of the dispute.' },
      { type: 'figure', kind: 'tiers', title: 'FIG.A · FOUR-TIER AUTHENTICATION STACK', caption: 'No tier is sufficient alone. Tier 1 fails on device compromise; Tier 2 fails when generators have been retrained on counter-detector outputs; Tier 3 fails on social-media-sourced artifacts; Tier 4 is the highest confidence but only available where the synthetic origin is itself in evidence.', data: { tiers: [
        { label: 'Source-Audit Examination', access: 'WHERE SYNTHETIC ORIGIN IS IN EVIDENCE' },
        { label: 'Chain of Custody', access: 'CAPTURE → COURTHOUSE' },
        { label: 'Artifact Analysis', access: 'FRAME-LEVEL FORENSICS' },
        { label: 'Device-Level Provenance', access: 'EXIF · SIGNING · FIRMWARE' },
      ]}},
      { type: 'h2', text: '§ 01 · The four-tier authentication stack' },
      { type: 'p', text: 'In matters where I have served as forensic neutral, I have proposed and the parties have adopted a four-tier authentication stack: (1) device-level provenance \u2014 EXIF metadata, capture-device firmware fingerprints, signing certificates where available; (2) artifact analysis \u2014 frame-by-frame analysis for compression-artifact consistency, audio-visual sync, eye-blink statistics; (3) chain of custody \u2014 from capture device to the courthouse; (4) source-audit \u2014 where applicable, examination of the model and prompts that produced the artifact, if a synthetic origin is alleged.' },
      { type: 'p', text: 'No tier is sufficient alone. Tier 1 fails if the device is compromised. Tier 2 fails when generators have been retrained on counter-detector outputs. Tier 3 fails on social-media-sourced artifacts. Tier 4 is the highest-confidence path but only available where the synthetic origin is itself in evidence.' },
      { type: 'pull', text: 'The technology has crossed a threshold the courts have not yet caught up to. Casual visual inspection no longer authenticates. The bench needs a protocol \u2014 not a vibe.' },
      { type: 'h2', text: '§ 02 · The neutral\u2019s role' },
      { type: 'p', text: 'Where the parties have agreed in advance to a forensic neutral protocol, I have seen authenticity questions resolve in days rather than the weeks (or months) of dueling-expert proceedings. The neutral\u2019s output is not an exhibit one side will move to exclude; it is a finding both sides have, in advance, agreed to treat as authoritative on the narrow technical question put to it.' },
      { type: 'p', text: 'I expect within five years standing protective orders will routinely include a forensic-neutral authentication clause for any synthetic-media-suspected evidence. Counsel who anticipate this now will save their clients substantial cost and substantial risk.' },
    ],
  },
  {
    id: 'smart-contracts',
    num: '005',
    cat: 'BLOCKCHAIN · ADR',
    tags: ['Smart Contracts', 'Cryptocurrency', 'AI'],
    title: 'Arbitrating Smart Contract Disputes: A Comprehensive Approach',
    deck: 'A smart-contract dispute is not a contract dispute with a technical hat on. It is a different artifact requiring a different process.',
    date: 'October 2, 2026',
    read: '10 min',
    body: [
      { type: 'p', text: 'A smart contract is, depending on who you ask, either a contract or a piece of code that happens to control money. From a dispute-resolution standpoint the distinction matters because the two framings produce very different remedies. Arbitrating smart contract matters means being precise about which framing the parties have agreed to before the proceeding begins.' },
      { type: 'figure', kind: 'flow', title: 'FIG.A · SMART-CONTRACT ARBITRATION SEQUENCE', caption: 'Smart-contract arbitration runs differently from conventional commercial arbitration. The audit phase \u2014 reading deployed bytecode against alleged behavior \u2014 frequently resolves the matter before evidentiary proceedings begin.', data: { steps: [
        { label: 'STIPULATE', detail: 'Rules + framing' },
        { label: 'AUDIT', detail: 'Bytecode vs. claim' },
        { label: 'CUSTODY', detail: 'Wallet attribution' },
        { label: 'EVIDENCE', detail: 'Hash · trace · log' },
        { label: 'AWARD', detail: 'Off-chain remedy' },
      ]}},
      { type: 'h2', text: '§ 01 · What the JAMS rules got right' },
      { type: 'p', text: 'When the JAMS Smart Contracts Rules were published in 2020 \u2014 I contributed to them \u2014 the central question was whether on-chain execution could be paused, reversed, or compensated for, and under what authority. The answer the rules landed on is that the tribunal\u2019s award is the source of truth for off-chain remedies, while on-chain effects are addressed by the parties\u2019 underlying contract architecture (multisig, oracles, escrow), not by the tribunal directly.' },
      { type: 'p', text: 'That distinction has held up. In the matters I have arbitrated under those rules, the cleanest outcomes have been those where the parties\u2019 original contract anticipated tribunal authority and built the on-chain mechanics to honor it. The messiest have been those where the parties layered traditional dispute-resolution clauses over an immutable on-chain mechanism that could not unwind a bad transfer.' },
      { type: 'h2', text: '§ 02 · The audit phase' },
      { type: 'p', text: 'Smart-contract arbitration begins with a code audit, not with pleadings. The arbitrator (or, where authority permits, a forensic neutral appointed by the tribunal) reads the deployed contract bytecode against the alleged behavior. In the four arbitrations I have presided over in this domain, three resolved at this phase \u2014 because the actual contract behavior, once audited, was uncontested by both sides.' },
      { type: 'pull', text: 'Smart-contract arbitration begins with a code audit, not with pleadings. Three of four such arbitrations I have run resolved at the audit phase, because the contract\u2019s actual behavior, once audited, was uncontested.' },
      { type: 'h2', text: '§ 03 · The custody question' },
      { type: 'p', text: 'On-chain custody questions are particularly thorny. Where a wrong-wallet transfer is alleged, attribution to a real-world party may require sub-poenaed exchange records, and the privacy and jurisdictional shape of those subpoenas varies enormously. Arbitrators in this space need to understand both the technology and the cross-border evidentiary frameworks that apply to it.' },
      { type: 'p', text: 'Where an on-chain transfer was the disputed instrument, the same forensic protocols I would use in eDiscovery (hashing, chain of custody, reproducibility) apply directly to wallet logs and transaction histories. The medium is different; the rigor is the same.' },
    ],
  },
  {
    id: 'cyber-insurance',
    num: '006',
    cat: 'CYBER · INSURANCE',
    tags: ['Cybersecurity', 'Insurance', 'Mediation'],
    title: 'Mediating Cyber Insurance Coverage Disputes',
    deck: 'Cyber coverage fights stall on the technical record. They unstall when somebody can read it.',
    date: 'August 22, 2026',
    read: '9 min',
    body: [
      { type: 'p', text: 'Cyber insurance coverage disputes are the perfect candidate for tailored mediation. They invariably involve a breach incident, an insurer who has investigated under reservation of rights, and a policyholder who disputes the investigator\u2019s technical conclusions. The mediator who can read the IR report \u2014 not just hear about it \u2014 collapses the distance between rooms in a way no generalist mediator can.' },
      { type: 'figure', kind: 'bars-h', title: 'FIG.A · WHERE CYBER COVERAGE FIGHTS TYPICALLY STALL', caption: 'Composite of stalled-case observations across coverage matters mediated 2022\u20132025. Three technical questions account for over 80% of pre-mediation deadlock: dwell time, attribution under war exclusions, and reasonable-controls representations.', data: { rows: [
        { l: 'DWELL TIME', v: 38, suffix: '%' },
        { l: 'ATTRIBUTION', v: 27, suffix: '%' },
        { l: 'CONTROLS', v: 19, suffix: '%' },
        { l: 'NOTICE', v: 9,  suffix: '%' },
        { l: 'OTHER',  v: 7,  suffix: '%' },
      ]}},
      { type: 'h2', text: '§ 01 · Where these matters typically stall' },
      { type: 'p', text: 'In my experience, three technical questions account for the majority of stalled cyber coverage mediations: (1) the dwell-time question \u2014 when did the threat actor first gain access, and does that pre-date the policy period?; (2) the war-exclusion question \u2014 was this incident attributable to a state actor in a way that triggers an exclusion?; (3) the reasonable-controls question \u2014 did the insured maintain the security controls represented at binding?' },
      { type: 'p', text: 'Each of these turns on the underlying forensic record \u2014 logs, IR timelines, telemetry. A mediator who has to take the parties\u2019 word for what those records say is operating with one hand tied. A mediator who can sample the records directly, ask the right questions of the right artifacts, and surface the consensus technical reading \u2014 that mediator can move the matter.' },
      { type: 'h2', text: '§ 02 · The shared-record method' },
      { type: 'p', text: 'In a cyber coverage matter I mediated last year, the parties had disputed the dwell-time question for nine months. We agreed in the first hour of mediation that I would receive both sides\u2019 forensic-investigator reports under a tier-1 protective designation, sample the underlying log artifacts, and produce a one-page memorandum of the points of consensus and the points genuinely in dispute. The memo took three days. The matter resolved within ten days of its issuance.' },
      { type: 'pull', text: 'A mediator who has to take the parties\u2019 word for what the forensic record says is operating with one hand tied.' },
      { type: 'h2', text: '§ 03 · What to ask before you book the mediator' },
      { type: 'p', text: 'Three questions counsel should ask before booking a mediator on a cyber coverage matter: (1) Has the mediator handled a substantively similar incident type before \u2014 ransomware, BEC, third-party software supply chain?; (2) Is the mediator willing and able to read the IR record themselves, under appropriate protective order?; (3) Is the mediator fluent in the policy language at issue \u2014 cyber-specific exclusions, sublimits, retention dynamics?' },
      { type: 'p', text: 'If any answer is no, you may be paying for skill in process without skill in substance. In coverage matters, that combination is rarely sufficient.' },
    ],
  },
  {
    id: 'protective-order',
    num: '007',
    cat: 'AI · DISCOVERY',
    tags: ['AI', 'Discovery', 'Protective Order'],
    title: 'Building a Tiered Protective Order for Machine-Learning Matters',
    deck: 'A flat protective order does not work in AI litigation. The artifacts are not all the same kind of secret.',
    date: 'July 9, 2026',
    read: '11 min',
    body: [
      { type: 'p', text: 'Standard protective orders treat \u201cconfidential business information\u201d as a single category. That works for most commercial litigation. It does not work for AI matters, where the artifacts at issue \u2014 model weights, training data, prompts, system cards, inference logs, outputs \u2014 are not all the same kind of secret, and the access controls appropriate for one are excessive or insufficient for another.' },
      { type: 'figure', kind: 'tiers', title: 'FIG.A · FIVE-TIER PROTECTIVE ORDER FOR ML MATTERS', caption: 'Tiered access controls calibrated to artifact sensitivity. Each tier carries its own reviewer credentials, viewing environment, retention obligations, and end-of-matter destruction protocol.', data: { tiers: [
        { label: 'Outputs',                          access: 'COUNSEL · STIPULATED' },
        { label: 'Prompts & System Prompts',         access: 'COUNSEL + ATTORNEY-EYES-ONLY' },
        { label: 'Training Data',                    access: 'EXPERT + AEO' },
        { label: 'Inference Logs',                   access: 'CLEANROOM REVIEW' },
        { label: 'Model Weights / Fine-tuning',      access: 'CLEANROOM · 1 EXPERT/SIDE' },
      ]}},
      { type: 'h2', text: '§ 01 · The five tiers' },
      { type: 'p', text: 'I have authored or co-authored standing protective orders in roughly a dozen AI matters now. The framework I converge on, with variations, is a five-tier structure. Tier 1: Outputs (the lowest sensitivity, often already in the pleadings). Tier 2: Prompts and system prompts. Tier 3: Training data, separated by recency and provenance. Tier 4: Inference logs (high sensitivity, contains user data). Tier 5: Model weights and fine-tuning checkpoints (the crown jewels).' },
      { type: 'p', text: 'Each tier has its own reviewer credential requirements, viewing environment (cleanroom vs. counsel\u2019s offices), retention obligations, and destruction protocol at end of matter. A counsel cleared for Tier 3 is not necessarily cleared for Tier 5; in fact, the Tier 5 access list may be a single named expert per side and a tribunal-appointed reviewer.' },
      { type: 'pull', text: 'Treating model weights and inference outputs as the same category of trade secret is a category error. They are different artifacts with different sensitivities and different appropriate access controls.' },
      { type: 'h2', text: '§ 02 · The cleanroom question' },
      { type: 'p', text: 'For Tier 4 and Tier 5 review, I have come to favor cleanroom review over reviewer-side workstation review. The cleanroom \u2014 typically a vendor-provided, network-isolated environment with screen-recording attestation \u2014 enforces the access controls that a protective order can only request on faith. The cost is higher; the cost of a leak is much higher.' },
      { type: 'h2', text: '§ 03 · What to negotiate' },
      { type: 'p', text: 'Counsel arriving at the protective-order conference should be prepared to negotiate tier definitions, reviewer credentialing, viewing environment, audit logging, retention, and destruction. The default in form orders is silence on most of these; that silence creates leverage for whoever objects later. Get the structure right at the outset.' },
    ],
  },
  {
    id: 'forensic-selection',
    num: '008',
    cat: 'PRACTICAL',
    tags: ['Forensics', 'Practical', 'Selection'],
    title: 'What Counsel Should Ask Before Selecting a Forensic Neutral',
    deck: 'Six questions that separate a forensic neutral capable of finishing the matter from one who will compound it.',
    date: 'June 4, 2026',
    read: '7 min',
    body: [
      { type: 'p', text: 'I have been on both sides of forensic-neutral selection \u2014 as the candidate and as the appointing tribunal\u2019s technical advisor. The single most predictive question is rarely asked: has this person worked with this kind of evidence before, in a posture comparable to this one?' },
      { type: 'figure', kind: 'compare', title: 'FIG.A · QUESTIONS COUNSEL ASK vs. SHOULD ASK', caption: 'Most candidate-vetting questions verify credentials. The questions that actually predict outcome address how the candidate handles disagreement with engaging counsel, contested findings, and cross-examination.', data: {
        left:  { title: 'TYPICALLY ASKED',     items: ['What\u2019s your CV?','How many cases?','What certifications?','Hourly rate?'] },
        right: { title: 'BETTER QUESTIONS',    items: ['Last three similar matters?','Where did you contradict your engager?','Tooling stack & chain of custody?','How often cross-examined?'] },
      }},
      { type: 'h2', text: '§ 01 · The six questions' },
      { type: 'p', text: 'Six questions counsel should put to any forensic-neutral candidate before stipulating: (1) Walk me through the last three engagements substantively similar to this matter \u2014 device type, evidence volume, dispositive issues. (2) Where did your reports diverge from your engaging counsel\u2019s preferred narrative, and how did you handle that? (3) What is your tooling stack and what is the chain of custody you maintain end-to-end? (4) What protective-order tiers have you operated under for material this sensitive? (5) How do you handle a request from one side to expand scope mid-investigation? (6) Are you available for cross-examination, and how often have you actually been cross-examined?' },
      { type: 'pull', text: 'The single most predictive question is rarely asked: has this person worked with this kind of evidence before, in a posture comparable to this one?' },
      { type: 'h2', text: '§ 02 · The red flags' },
      { type: 'p', text: 'Three red flags I would not retain past: (1) the candidate cannot articulate at least one matter where their finding contradicted their engaging counsel\u2019s position; (2) the candidate runs an ad-hoc tooling stack rather than a documented one; (3) the candidate has not been cross-examined in the last five years on a substantive technical finding.' },
      { type: 'h2', text: '§ 03 · The credential audit' },
      { type: 'p', text: 'Beyond the questions: read the candidate\u2019s recent reports if accessible (many are produced in publicly filed matters); ask for redacted reports if not; check that the candidate\u2019s certifications are current; verify that any criminal-justice or law-enforcement co-credentialing is genuine. A forensic neutral whose findings have to be sustained on cross is only as durable as the underlying record-keeping.' },
    ],
  },
  {
    id: 'jams-ai-rules',
    num: '009',
    cat: 'AI · ADR',
    tags: ['AI', 'JAMS', 'Rules'],
    title: 'Why the JAMS AI Disputes Rules Matter (And How to Use Them)',
    deck: 'A practical guide to the framework now sitting on top of every AI commercial contract that contemplates ADR.',
    date: 'May 17, 2026',
    read: '9 min',
    body: [
      { type: 'p', text: 'The JAMS AI Disputes Clause and Rules, published in 2024, did something the field had not previously had: they gave parties a default framework for arbitrating AI matters that addressed the actual artifacts at issue, not the artifacts of 2014 commercial arbitration retrofitted to AI.' },
      { type: 'figure', kind: 'callout', title: 'FIG.A · COVERAGE OF THE FRAMEWORK', caption: 'The rules cover the bulk of what currently arrives in AI commercial arbitration. The remaining 10% \u2014 autonomous-agent matters, multi-modal output disputes, agentic chain-of-tool-use matters \u2014 will likely shape the 2027 revision.', data: {
        value: '90%',
        label: 'OF AI COMMERCIAL DISPUTES TODAY',
        sub: 'covered by the existing 2024 framework',
      }},
      { type: 'h2', text: '§ 01 · What\u2019s in the rules' },
      { type: 'p', text: 'The rules address four things conventional arbitration rules tend to gloss: (1) discovery scoping for AI artifacts \u2014 system cards, eval reports, RAG configurations, retrieval logs, fine-tuning datasets, inference timestamps; (2) protective-order shape for AI artifacts \u2014 tiered access for weights, training data, prompts, outputs; (3) tribunal expertise \u2014 specific provisions for technically-fluent arbitrators where matter complexity warrants; (4) the question of whether the model itself can be examined under controlled conditions during the proceeding.' },
      { type: 'h2', text: '§ 02 · How to invoke them' },
      { type: 'p', text: 'In a contract being drafted today, the rules can be incorporated by reference in the dispute resolution clause. JAMS publishes recommended clause language. Where the contract is already in force without an AI-specific clause, parties can stipulate to apply the AI Rules to a particular dispute by joint submission \u2014 something I have seen done several times now.' },
      { type: 'pull', text: 'The rules give parties a default framework for arbitrating AI matters that addresses the actual artifacts at issue.' },
      { type: 'h2', text: '§ 03 · Where they fall short and what comes next' },
      { type: 'p', text: 'No framework anticipates the next category of artifact perfectly. The rules are likely to be updated for autonomous agent matters, multi-modal output matters, and agentic chain-of-tool-use matters as those become more frequent in the docket. I expect a 2027 revision; in the meantime, the rules cover roughly 90% of what currently arrives.' },
    ],
  },
  {
    id: 'special-master-tar',
    num: '010',
    cat: 'eDISCOVERY',
    tags: ['Special Master', 'TAR', 'eDiscovery'],
    title: 'When (and How) to Appoint a Special Master for TAR Validation',
    deck: 'Technology-Assisted Review is no longer novel. Disputes about whether it was done correctly are.',
    date: 'April 9, 2026',
    read: '10 min',
    body: [
      { type: 'p', text: 'A decade after Da Silva Moore, technology-assisted review is no longer the cutting edge of eDiscovery; it is the floor. The disputes have moved on. Now, in matters I have been appointed Special Master for, the question is rarely whether to use TAR but whether the TAR run that was done was done defensibly.' },
      { type: 'figure', kind: 'flow', title: 'FIG.A · FIVE-STEP TAR VALIDATION PROTOCOL', caption: 'When appointed to validate a contested TAR workflow, the protocol returns one of three findings: defensible; recoverable defect; or re-review warranted. Reports issue to the appointing court within 30 days for straightforward matters.', data: { steps: [
        { label: 'RECONSTRUCT', detail: 'Workflow from docs' },
        { label: 'SEED CHECK',  detail: 'Reproduce model' },
        { label: 'ELUSION',     detail: 'Test methodology' },
        { label: 'RICHNESS',    detail: 'Sample composition' },
        { label: 'CONFIRM',     detail: 'Discard recall' },
      ]}},
      { type: 'h2', text: '§ 01 · The signals that warrant appointment' },
      { type: 'p', text: 'Three patterns commonly trigger an effective request for special-master appointment to validate a TAR workflow: (1) the producing party has used a continuous active learning workflow but cannot articulate the seed set or model selection criteria; (2) the production volume is substantially smaller than discovery scoping had projected, with no independent explanation; (3) the receiving party has identified responsive documents in third-party productions that it cannot find in the primary production.' },
      { type: 'h2', text: '§ 02 · The five-step validation' },
      { type: 'p', text: 'When I am appointed to validate a TAR run, I follow a five-step protocol. (1) Reconstruct the workflow from documentation. (2) Sample the seed set; reproduce the early-iteration model. (3) Examine elusion-test methodology and results. (4) Examine richness statistics and stratified-sample composition. (5) Run an independent confirmatory sample on the discard population and assess recall against the receiving party\u2019s acceptance threshold.' },
      { type: 'p', text: 'In my experience this protocol returns one of three findings: the workflow was defensible; the workflow had a recoverable defect (typically a seed-set composition issue) that can be cured by a supplementary review; or the workflow was indefensible and a re-review is warranted. The first finding is the most common; the third is rare but, when it appears, highly consequential.' },
      { type: 'pull', text: 'A decade after Da Silva Moore, the TAR question is no longer whether to use it but whether the TAR run that was done was done defensibly.' },
      { type: 'h2', text: '§ 03 · The reporting' },
      { type: 'p', text: 'A special master\u2019s report on TAR validation goes to the appointing court and is binding on the parties to the extent the order of appointment provides. I aim to produce these reports within 30 days of appointment for straightforward matters; longer where richness is unusually low or the workflow is unusually opaque.' },
    ],
  },
  {
    id: 'cross-border',
    num: '011',
    cat: 'CROSS-BORDER',
    tags: ['Cross-Border', 'Privacy', 'Discovery'],
    title: 'Cross-Border Forensic Collection in 2026: A Field Note',
    deck: 'Schrems II, GDPR enforcement, and US sectoral privacy laws have made what used to be a logistical question a substantive one.',
    date: 'March 11, 2026',
    read: '8 min',
    body: [
      { type: 'p', text: 'A decade ago, cross-border forensic collection was a logistical problem. You sent a forensic team to the country, imaged the device, brought back the image. The legal layer was thin and rarely contested.' },
      { type: 'p', text: 'That world is gone. Schrems II, GDPR enforcement, the proliferation of US state privacy laws, and the increasing willingness of foreign data-protection authorities to actively oppose US discovery have made cross-border forensic collection a substantive question. The collection itself is the easy part now; the legal authorization is the hard part.' },
      { type: 'figure', kind: 'compare', title: 'FIG.A · CROSS-BORDER COLLECTION \u2014 THEN vs. NOW', caption: 'A decade-over-decade reframing. The technical work has gotten easier; the legal-authorization layer has gotten substantially harder. The neutral who maps the legal layer first finishes faster.', data: {
        left:  { title: '2014',                items: ['Logistical problem','Image and ship','Legal layer thin','Local counsel late','Tooling-driven plan'] },
        right: { title: '2026',                items: ['Substantive problem','Authorize, then image','Legal layer first','Local counsel day-one','Jurisdiction-mapped plan'] },
      }},
      { type: 'h2', text: '§ 01 · What I now do first' },
      { type: 'p', text: 'On any cross-border matter, the first step is no longer logistics but legal-jurisdiction mapping. Where is the data; where is the custodian; where is the alleged conduct; where is the appointing tribunal; what bilateral or treaty mechanisms apply? In a recent matter involving custodians in three jurisdictions, the answer to those questions \u2014 not the technical work \u2014 controlled the timeline.' },
      { type: 'h2', text: '§ 02 · Coordinating with foreign counterparts' },
      { type: 'p', text: 'I have coordinated international device collection with FBI, Interpol, and various counterpart agencies. The pattern that works: engage local counsel in the foreign jurisdiction at the start, not the end; map the local privilege and privacy framework into the protective order before collection begins; use forensic protocols that produce evidence admissible under the strictest of the involved jurisdictions, even if that is overkill for some.' },
      { type: 'pull', text: 'The collection itself is the easy part now. The legal authorization is the hard part.' },
      { type: 'h2', text: '§ 03 · What this means for forensic-neutral selection' },
      { type: 'p', text: 'Counsel selecting a forensic neutral for a cross-border matter should specifically test the candidate\u2019s comfort with the privilege, privacy, and jurisdictional layer. A neutral who is technically excellent but blind to the legal-authorization layer can put a matter sideways before the technical work even begins.' },
    ],
  },
  {
    id: 'special-master-economy',
    num: '012',
    cat: 'NEUTRAL · ECONOMY',
    tags: ['Special Master', 'Economics'],
    title: 'The Economics of Appointing a Special Master',
    deck: 'A special master is rarely the cheapest path. They are frequently the fastest. In matters where speed determines exposure, the math reverses.',
    date: 'February 14, 2026',
    read: '7 min',
    body: [
      { type: 'p', text: 'Counsel sometimes resist special-master appointment on cost grounds. The instinct is sensible: another billing party adds another invoice. The instinct is also, in matters above a certain complexity threshold, mistaken.' },
      { type: 'figure', kind: 'callout', title: 'FIG.A · THE 90/60 RULE OF THUMB', caption: 'If the disputed issue is one a competent special master could resolve within 60 days, and the parties have spent or will spend more than 90 days arguing it without resolution, the appointment is the better economic choice.', data: {
        value: '90/60',
        label: 'DAYS LITIGATING vs. DAYS TO RESOLVE',
        sub: 'When the ratio exceeds 1.5, appointment dominates',
      }},
      { type: 'h2', text: '§ 01 · Where the math reverses' },
      { type: 'p', text: 'In matters where the parties spend six figures litigating a discovery dispute that a special master could resolve in a week, the marginal cost of the special master is negative \u2014 the appointment saves more than it spends. In matters where the dispute resolution timeline directly affects exposure (typically in cyber coverage, trade secret, and AI matters), the cost calculation has to include the carrying cost of unresolved exposure, not just attorney fees.' },
      { type: 'h2', text: '§ 02 · The 60-day rule of thumb' },
      { type: 'p', text: 'A heuristic: if the disputed issue is one a competent special master could resolve within 60 days, and the parties have spent or will spend more than 90 days arguing it without resolution, the appointment is the better economic choice. The 90/60 ratio holds across most of the matters where I have seen the question come up.' },
      { type: 'pull', text: 'The marginal cost of the special master is negative when the appointment saves more than it spends.' },
      { type: 'h2', text: '§ 03 · The appointing-court calculus' },
      { type: 'p', text: 'Courts are increasingly receptive to special-master appointments because the alternative is consuming the court\u2019s own time on technical disputes the bench is not equipped to adjudicate. A motion for appointment that articulates the bench\u2019s opportunity cost \u2014 not just the parties\u2019 \u2014 is more persuasive than one that does not.' },
    ],
  },
];

const ALL_TAGS = Array.from(new Set(articles.flatMap(a => a.tags || []))).sort();

const InsightsIndex = ({ onNav }) => {
  const { useState } = React;
  const [tag, setTag] = useState(null);
  const filtered = tag ? articles.filter(a => (a.tags || []).includes(tag)) : articles;
  const lead = filtered[0] || articles[0];
  const rest = filtered.slice(1);
  return (
  <div className="page-fade">
    <section style={{ background: 'var(--ink)', color: 'var(--paper)', padding: '120px 0 80px', position: 'relative', overflow: 'hidden' }}>
      <div className="dotgrid-dark" style={{ position: 'absolute', inset: 0, opacity: 0.35 }}/>
      <div className="container" style={{ position: 'relative' }}>
        <div className="eyebrow on-dark">Field Notes · Protocol Drafts · Case Patterns</div>
        <h1 className="display" style={{ fontSize: 'clamp(56px, 7.5vw, 104px)', marginTop: 16, color: 'var(--paper)', lineHeight: 1.02 }}>
          Insights<br/>
          <em style={{ color: 'var(--gold)', fontStyle: 'italic', fontWeight: 300 }}>from the bench.</em>
        </h1>
        <p style={{ marginTop: 32, fontSize: 21, color: 'var(--slate-300)', maxWidth: 720, lineHeight: 1.55, fontFamily: 'var(--serif)', fontStyle: 'italic' }}>
          A working notebook on technically complex dispute resolution. Twelve articles in print, more in the queue — written from the chair, not the lectern.
        </p>
        <div className="mono" style={{
          marginTop: 40, paddingTop: 24, borderTop: '1px solid rgba(212,185,122,0.18)',
          fontSize: 11, color: 'var(--gold)', letterSpacing: '0.2em',
          display: 'flex', justifyContent: 'space-between', flexWrap: 'wrap', gap: 12,
        }}>
          <span>BY DANIEL B. GARRIE, ESQ.</span>
          <span>{articles.length} ARTICLES · {ALL_TAGS.length} TOPICS</span>
        </div>
      </div>
    </section>

    {/* Tag filter */}
    <section style={{ background: 'var(--paper-2)', borderBottom: '1px solid var(--line-soft)' }}>
      <div className="container" style={{ padding: '24px 32px' }}>
        <div style={{ display: 'flex', alignItems: 'baseline', gap: 16, flexWrap: 'wrap' }}>
          <div className="mono" style={{ fontSize: 11, letterSpacing: '0.2em', color: 'var(--slate-700)', textTransform: 'uppercase', flexShrink: 0 }}>
            Topic ·
          </div>
          <div style={{ display: 'flex', flexWrap: 'wrap', gap: 6 }}>
            <button onClick={() => setTag(null)} className="tag" style={{
              cursor: 'pointer',
              background: !tag ? 'var(--gold-deep)' : 'transparent',
              color: !tag ? 'var(--paper)' : 'var(--slate-700)',
              borderColor: !tag ? 'var(--gold-deep)' : 'var(--line-soft)',
            }}>All · {articles.length}</button>
            {ALL_TAGS.map(t => {
              const count = articles.filter(a => (a.tags || []).includes(t)).length;
              const isActive = tag === t;
              return (
                <button key={t} onClick={() => setTag(isActive ? null : t)} className="tag" style={{
                  cursor: 'pointer',
                  background: isActive ? 'var(--gold-deep)' : 'transparent',
                  color: isActive ? 'var(--paper)' : 'var(--slate-700)',
                  borderColor: isActive ? 'var(--gold-deep)' : 'var(--line-soft)',
                }}>{t} · {count}</button>
              );
            })}
          </div>
        </div>
      </div>
    </section>

    <section className="section">
      <div className="container">
        {/* Lead */}
        <article style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 64, marginBottom: 80, cursor: 'pointer' }}
                 onClick={() => onNav('article-' + lead.id)}>
          <div style={{ aspectRatio: '4/3', background: 'var(--ink)', position: 'relative', overflow: 'hidden' }}>
            <div className="dotgrid-dark" style={{ position: 'absolute', inset: 0, opacity: 0.4 }}/>
            <div className="mono" style={{ position: 'absolute', top: 24, left: 24, fontSize: 11, color: 'var(--gold)', letterSpacing: '0.2em', zIndex: 2 }}>
              {lead.cat}
            </div>
            <div className="mono" style={{ position: 'absolute', top: 24, right: 24, fontSize: 11, color: 'var(--gold)', letterSpacing: '0.2em', zIndex: 2 }}>
              № {lead.num}
            </div>
            {/* Article mark — fills the panel */}
            <div style={{ position: 'absolute', inset: 56, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
              {window.ArticleMark && <window.ArticleMark id={lead.id} onDark={true}/>}
            </div>
          </div>
          <div style={{ display: 'flex', flexDirection: 'column', justifyContent: 'center' }}>
            <div className="mono" style={{ fontSize: 11, color: 'var(--slate-700)', letterSpacing: '0.18em' }}>
              FEATURED · {lead.date.toUpperCase()} · {lead.read.toUpperCase()}
            </div>
            <h2 className="display" style={{ fontSize: 'clamp(32px, 4vw, 52px)', marginTop: 16, lineHeight: 1.05 }}>
              {lead.title}
            </h2>
            <p className="serif" style={{ fontSize: 20, color: 'var(--slate-700)', marginTop: 20, fontStyle: 'italic', lineHeight: 1.5 }}>
              {lead.deck}
            </p>
            <div className="mono" style={{ marginTop: 24, fontSize: 11, color: 'var(--gold-deep)', letterSpacing: '0.2em' }}>
              READ THE FULL ARTICLE →
            </div>
          </div>
        </article>

        <div className="hairline" style={{ marginBottom: 64 }}/>

        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(3, 1fr)', gap: 36 }}>
          {rest.map(a => (
            <article key={a.id} style={{ cursor: 'pointer' }} onClick={() => onNav('article-' + a.id)}>
              <div style={{ aspectRatio: '4/3', background: 'var(--paper)', border: '1px solid var(--line-soft)', position: 'relative', overflow: 'hidden', marginBottom: 18 }}>
                <div className="dotgrid" style={{ position: 'absolute', inset: 0, opacity: 0.4 }}/>
                <div className="mono" style={{ position: 'absolute', top: 14, left: 16, fontSize: 9, color: 'var(--slate-700)', letterSpacing: '0.2em', zIndex: 2 }}>
                  {a.cat}
                </div>
                <div className="mono" style={{ position: 'absolute', top: 14, right: 16, fontSize: 9, color: 'var(--gold-deep)', letterSpacing: '0.2em', zIndex: 2 }}>
                  № {a.num}
                </div>
                {/* Article mark */}
                <div style={{ position: 'absolute', inset: 36, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                  {window.ArticleMark && <window.ArticleMark id={a.id}/>}
                </div>
              </div>
              <div className="mono" style={{ fontSize: 10, color: 'var(--slate-700)', letterSpacing: '0.16em' }}>
                {a.date.toUpperCase()} · {a.read.toUpperCase()}
              </div>
              <h3 className="display" style={{ fontSize: 22, marginTop: 6, lineHeight: 1.15 }}>{a.title}</h3>
              <p className="serif" style={{ fontSize: 14, color: 'var(--slate-700)', marginTop: 8, fontStyle: 'italic', lineHeight: 1.5 }}>
                {a.deck}
              </p>
              {a.tags && (
                <div style={{ display: 'flex', flexWrap: 'wrap', gap: 4, marginTop: 12 }}>
                  {a.tags.map(tt => <span key={tt} className="tag" style={{ fontSize: 9, padding: '2px 7px' }}>{tt}</span>)}
                </div>
              )}
            </article>
          ))}
        </div>
        {rest.length === 0 && (
          <p className="serif" style={{ fontSize: 18, color: 'var(--slate-700)', fontStyle: 'italic', textAlign: 'center', padding: '40px 0' }}>
            No additional articles match this filter. Clear filter to see all twelve.
          </p>
        )}
      </div>
    </section>
  </div>
);};

const ArticlePage = ({ id, onNav }) => {
  const article = articles.find(a => a.id === id);
  if (!article) return null;
  const others = articles.filter(a => a.id !== id);

  return (
    <div className="page-fade">
      <article>
        <header style={{ background: 'var(--ink)', color: 'var(--paper)', padding: '80px 0 96px', position: 'relative', overflow: 'hidden' }}>
          <div className="dotgrid-dark" style={{ position: 'absolute', inset: 0, opacity: 0.3 }}/>
          <div className="container" style={{ maxWidth: 1080, position: 'relative' }}>
            <button onClick={() => onNav('insights')} className="mono" style={{
              fontSize: 11, color: 'var(--gold)', letterSpacing: '0.2em', marginBottom: 32
            }}>
              ← INSIGHTS
            </button>
            <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr', gap: 64, alignItems: 'center' }}>
              <div>
                <div className="mono" style={{ fontSize: 11, color: 'var(--gold)', letterSpacing: '0.2em' }}>
                  № {article.num} · {article.cat} · {article.read.toUpperCase()}
                </div>
                <h1 className="display" style={{ fontSize: 'clamp(40px, 5.5vw, 72px)', color: 'var(--paper)', marginTop: 24, lineHeight: 1.05 }}>
                  {article.title}
                </h1>
                <p className="serif" style={{ fontSize: 22, color: 'var(--slate-300)', marginTop: 24, fontStyle: 'italic', lineHeight: 1.5 }}>
                  {article.deck}
                </p>
                <div className="mono" style={{ marginTop: 40, paddingTop: 24, borderTop: '1px solid rgba(212,185,122,0.2)', fontSize: 11, color: 'var(--slate-300)', letterSpacing: '0.18em', display: 'flex', justifyContent: 'space-between' }}>
                  <span>BY DANIEL B. GARRIE, ESQ.</span>
                  <span>{article.date.toUpperCase()}</span>
                </div>
              </div>
              {/* Article mark */}
              <div style={{ aspectRatio: '4/3', border: '1px solid rgba(212,185,122,0.25)', padding: 24, display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
                {window.ArticleMark && <window.ArticleMark id={article.id} onDark={true}/>}
              </div>
            </div>
          </div>
        </header>

        <div className="container" style={{ maxWidth: 720, padding: '80px 32px' }}>
          {/* Editorial draft note — until Daniel verifies / replaces with his
              own published or signed-off content, every article on this site
              carries this disclaimer to protect against any inadvertent fabrication. */}
          <aside style={{
            border: '1px solid var(--gold-deep)', background: 'var(--paper-2)',
            padding: '18px 22px', marginBottom: 40,
            display: 'flex', gap: 16, alignItems: 'flex-start',
          }}>
            <span className="mono" style={{
              fontSize: 10, letterSpacing: '0.2em', color: 'var(--gold-deep)',
              padding: '4px 10px', border: '1px solid var(--gold-deep)',
              flexShrink: 0, marginTop: 2,
            }}>EDITORIAL DRAFT</span>
            <p className="serif" style={{ fontSize: 14, color: 'var(--slate-900)', lineHeight: 1.6, margin: 0, fontStyle: 'italic' }}>
              This piece is an editorial draft prepared for tailoredmediation.com. It illustrates the topic and Daniel\u2019s point of view; first-person references to specific matters are anonymized and illustrative. Final copy will be authored or signed off by Daniel B. Garrie, Esq. before publication. For Daniel\u2019s published work in venues including the Federal Judicial Center, the American Bar Association, Wolters Kluwer, Thomson Reuters, the Daily Journal, Law360, and Bloomberg Law, see <a onClick={() => onNav('publications')} style={{ color: 'var(--gold-deep)', borderBottom: '1px solid currentColor', cursor: 'pointer' }}>Publications &amp; Books</a>.
            </p>
          </aside>
          {article.body.map((block, i) => {
            if (block.type === 'h2') return (
              <h2 key={i} className="display" style={{ fontSize: 32, marginTop: 56, marginBottom: 24, color: 'var(--ink)' }}>
                {block.text}
              </h2>
            );
            if (block.type === 'pull') return (
              <blockquote key={i} style={{
                margin: '48px 0', padding: '0 0 0 32px',
                borderLeft: '2px solid var(--gold)',
                fontFamily: 'var(--serif)', fontSize: 26, lineHeight: 1.35,
                fontStyle: 'italic', color: 'var(--slate-900)'
              }}>
                {block.text}
              </blockquote>
            );
            if (block.type === 'figure') return (
              <ArticleFigurePlot key={i} title={block.title} caption={block.caption} kind={block.kind} data={block.data}/>
            );
            return (
              <p key={i} className="serif" style={{ fontSize: 19, lineHeight: 1.7, color: 'var(--slate-900)', marginBottom: 20 }}>
                {block.text}
              </p>
            );
          })}

          <div style={{ marginTop: 80, paddingTop: 24, borderTop: '1px solid var(--line-soft)' }}>
            <div className="mono" style={{ fontSize: 11, color: 'var(--slate-700)', letterSpacing: '0.18em' }}>
              END OF ARTICLE · № {article.num}
            </div>
          </div>
        </div>

        <section style={{ background: 'var(--paper-2)', padding: '80px 0', borderTop: '1px solid var(--line-soft)' }}>
          <div className="container">
            <div className="eyebrow" style={{ marginBottom: 32 }}>Continue reading</div>
            <div style={{ display: 'grid', gridTemplateColumns: 'repeat(2, 1fr)', gap: 32 }}>
              {others.map(o => (
                <div key={o.id} onClick={() => onNav('article-' + o.id)} style={{ cursor: 'pointer', padding: 32, background: 'var(--paper)', border: '1px solid var(--line-soft)' }}>
                  <div className="mono" style={{ fontSize: 11, color: 'var(--gold-deep)', letterSpacing: '0.18em' }}>
                    № {o.num} · {o.cat}
                  </div>
                  <h3 className="display" style={{ fontSize: 26, marginTop: 12, lineHeight: 1.15 }}>{o.title}</h3>
                </div>
              ))}
            </div>
          </div>
        </section>
      </article>
    </div>
  );
};

window.InsightsIndex = InsightsIndex;
window.ArticlePage = ArticlePage;
window.articles = articles;
