/* Metric family deep-dive — full page view for a company + metric family */

const STATUS_TONES = {
  'moss-solid': { color: '#F4F7EE', background: 'var(--moss-deep)', border: '1px solid var(--moss-deep)' },
  moss:  { color: 'var(--moss-deep)', background: 'var(--sage-tint)', border: '1px solid #D5DEC4' },
  amber: { color: '#8a6a1f', background: '#fdf6e3', border: '1px solid #ecd9a8' },
  red:   { color: '#8b4545', background: '#fdf0f0', border: '1px solid #e8c4c4' },
  grey:  { color: 'var(--ink-3)', background: 'var(--canvas-2)', border: '1px solid var(--line)' },
};

/* Hover definition bubble — portalled to <body> because transformed ancestors
   (e.g. .lift hover cards) re-anchor position:fixed and send it across the screen */
const TipBubble = ({ pos, children }) => ReactDOM.createPortal(
  <span style={{
    position: 'fixed', left: pos.x, top: pos.y,
    transform: pos.below ? 'translate(-50%, 0)' : 'translate(-50%, -100%)',
    width: 250, padding: '10px 12px', background: '#16240E', color: '#E8EFDF',
    border: '1px solid rgba(166,225,94,0.35)',
    borderRadius: 8, fontSize: 12, lineHeight: '17px', zIndex: 1000,
    fontFamily: 'var(--font-sans)', fontWeight: 400, textTransform: 'none', letterSpacing: 0,
    whiteSpace: 'normal', textAlign: 'left', boxShadow: '0 4px 16px rgba(22,36,14,0.3)',
    pointerEvents: 'none',
  }}>
    {children}
  </span>,
  document.body
);

const tipPosFor = (el) => {
  const r = el.getBoundingClientRect();
  const below = r.top < 120;
  return {
    x: Math.max(135, Math.min(window.innerWidth - 135, r.left + r.width / 2)),
    y: below ? r.bottom + 8 : r.top - 8,
    below,
  };
};

/* Wraps a technical term with a dotted underline + hover definition from GLOSSARY
   (or an explicit `def` override for generated definitions). */
const Gloss = ({ term, def: defProp, children, style }) => {
  const [pos, setPos] = React.useState(null);
  const def = defProp || (window.GLOSSARY || {})[term];
  if (!def) return children || term || null;
  return (
    <span onMouseEnter={(e) => setPos(tipPosFor(e.currentTarget))} onMouseLeave={() => setPos(null)}
      style={{ borderBottom: '1px dotted var(--ink-3)', cursor: 'help', ...style }}>
      {children || term}
      {pos && <TipBubble pos={pos}>{def}</TipBubble>}
    </span>
  );
};
window.Gloss = Gloss;

/* Explains any unit string — glossary first, then a generated explanation for
   compound intensity units like "ktCO2-e/kt Cu-eq". */
const unitTokenDef = (tok) => {
  const g = window.GLOSSARY || {};
  if (g[tok]) return g[tok];
  if (/cu.?-?eq/i.test(tok)) return 'Copper-equivalent — mixed commodity production expressed as the tonnage of copper with equivalent value.';
  if (/co2.?-?e/i.test(tok)) return 'CO2-equivalent — all greenhouse gases converted to the warming impact of CO2.';
  return null;
};

const unitDef = (u) => {
  if (!u) return null;
  const g = window.GLOSSARY || {};
  if (g[u]) return g[u];
  const parts = u.split('/');
  if (parts.length === 2) {
    const num = parts[0].trim();
    const den = parts[1].trim();
    const nd = unitTokenDef(num);
    const dd = unitTokenDef(den);
    const numDef = nd ? ` (${nd.replace(/\.$/, '').toLowerCase()})` : '';
    const denDef = dd ? ` (${dd.replace(/\.$/, '').toLowerCase()})` : '';
    return `An intensity ratio — ${num}${numDef} for every ${den}${denDef}. Lower means less impact per unit of activity.`;
  }
  return unitTokenDef(u);
};

const UnitGloss = ({ unit }) => {
  const def = unitDef(unit);
  return def ? <Gloss term={unit} def={def} /> : (unit || null);
};
window.UnitGloss = UnitGloss;

/* Splits text and glosses known technical tokens (Scope 1/2/3, GHG, safety rates) */
const TermedText = ({ text }) => {
  const parts = String(text).split(/(Scope 1|Scope 2|Scope 3|GHG|TRIFR|LTIFR|FIFR)/g);
  return <>{parts.map((p, i) => (window.GLOSSARY || {})[p] ? <Gloss key={i} term={p} /> : p)}</>;
};
window.TermedText = TermedText;

/* Renders prose with numeric figures (values, years, percentages, units) in white */
const FIG_RE = /(Scopes? \d(?:(?:, \d)*(?:,? and \d)?)?|\d[\d,]*(?:\.\d+)?(?:\s?(?:%|MtCO2-?e|ktCO2-?e|tCO2e(?:\/[A-Za-z]+)?|Mt|kt|TJ|PJ|GJ|MWh|GWh|ML|GL|ha))?)/g;
const HighlightFigures = ({ text }) => {
  const parts = String(text).split(FIG_RE);
  return <>{parts.map((p, i) => i % 2 === 1
    ? <span key={i} style={{ color: '#FFFFFF', fontWeight: 600 }}>{p}</span>
    : p)}</>;
};

const StatusChip = ({ status }) => {
  const [pos, setPos] = React.useState(null);
  if (!status) return null;
  const def = (window.GLOSSARY || {})[status.label];
  return (
    <span onMouseEnter={(e) => def && setPos(tipPosFor(e.currentTarget))} onMouseLeave={() => setPos(null)}
      style={{
        display: 'inline-flex', alignItems: 'center', padding: '3px 10px', borderRadius: 999,
        fontSize: 11, fontFamily: 'var(--mono)', fontWeight: 600, letterSpacing: '0.02em',
        whiteSpace: 'nowrap', cursor: def ? 'help' : 'default', ...STATUS_TONES[status.tone],
      }}>
      {status.label}
      {pos && <TipBubble pos={pos}>{def}</TipBubble>}
    </span>
  );
};
window.StatusChip = StatusChip;

const NotReported = () => (
  <span style={{ color: 'var(--ink-3)', fontStyle: 'italic', fontSize: 12 }}>Not reported</span>
);

/* Measures its container and renders the chart at full available width.
   Uses a layout effect + window resize listener as well as ResizeObserver —
   RO callbacks ride the paint pipeline and can stall in throttled tabs. */
const ResponsiveChart = ({ render }) => {
  const ref = React.useRef(null);
  const [w, setW] = React.useState(0);
  React.useLayoutEffect(() => {
    const el = ref.current;
    if (!el) return;
    const measure = () => { const cw = el.clientWidth; if (cw) setW(cw); };
    measure();
    window.addEventListener('resize', measure);
    let ro;
    if (typeof ResizeObserver !== 'undefined') {
      ro = new ResizeObserver(measure);
      ro.observe(el);
    }
    return () => { window.removeEventListener('resize', measure); if (ro) ro.disconnect(); };
  }, []);
  return <div ref={ref} style={{ width: '100%' }}>{w > 0 && render(w)}</div>;
};

/* Website-palette green ramp for donut segments (dark = largest → light), grey for "Other" */
const DONUT_GREENS = ['#3F4A30', '#4E5A41', '#6B7A5A', '#8A9A75', '#A8B894', '#C7D3B2'];
const DONUT_OTHER = 'var(--class-none)';

/* Donut with a plain key (legend) on the right.
   segs: [{label, value (pct), abs, color, o}] sorted largest-first. */
const AnnotatedDonut = ({ segs, total, unit, onSeg }) => {
  return (
    <ResponsiveChart render={(W) => {
      const stack = W < 380;                   // very narrow → legend under the donut
      const size = stack ? 150 : (W < 760 ? 150 : 172);
      const cx = size / 2, cy = size / 2;
      const ro = size / 2;
      const ri = ro - (size < 170 ? 20 : 26);
      const GAP = 0.014 * 2 * Math.PI;

      let acc = 0;
      const placed = segs.map((s) => {
        const frac = s.value / 100;
        const a0 = -Math.PI / 2 + 2 * Math.PI * acc;
        const a1 = -Math.PI / 2 + 2 * Math.PI * (acc + frac);
        acc += frac;
        return { ...s, a0, a1 };
      });

      const ptAt = (r, a) => `${cx + r * Math.cos(a)} ${cy + r * Math.sin(a)}`;
      const arcPath = (a0, a1) => {
        const large = (a1 - a0) > Math.PI ? 1 : 0;
        return `M ${ptAt(ro, a0)} A ${ro} ${ro} 0 ${large} 1 ${ptAt(ro, a1)} L ${ptAt(ri, a1)} A ${ri} ${ri} 0 ${large} 0 ${ptAt(ri, a0)} Z`;
      };
      const ringSvg = (
        <svg width={size} height={size} style={{ display: 'block', flexShrink: 0 }}>
          {placed.map((s, i) => {
            const g = Math.min(GAP / 2, (s.a1 - s.a0) / 2 - 0.002);
            return <path key={i} d={arcPath(s.a0 + g, s.a1 - g)} fill={s.color} />;
          })}
          <text x={cx} y={cy - 2} textAnchor="middle" fontSize={size < 170 ? 26 : 30} fontWeight="700" fill="var(--ink)" style={{ fontFamily: 'var(--font-sans)', letterSpacing: '-0.02em' }}>{formatValue(total)}</text>
          <text x={cx} y={cy + 15} textAnchor="middle" fontSize="9" fill="var(--ink-3)" style={{ fontFamily: 'var(--mono)', letterSpacing: '0.16em' }}>TOTAL</text>
          <text x={cx} y={cy + 29} textAnchor="middle" fontSize="10.5" fill="var(--ink-2)" style={{ fontFamily: 'var(--mono)' }}>{unit}</text>
        </svg>
      );

      // Plain key
      const legend = (
        <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', gap: 2 }}>
          {placed.map((s, i) => (
            <div key={i} onClick={s.o ? () => onSeg(s.o) : undefined}
              title={s.o ? 'View source' : undefined}
              style={{
                display: 'grid', gridTemplateColumns: '11px 1fr auto', gap: 9, alignItems: 'center',
                padding: '6px 0', borderBottom: i < placed.length - 1 ? '1px solid var(--line)' : 'none',
                cursor: s.o ? 'pointer' : 'default',
              }}>
              <span style={{ width: 11, height: 11, borderRadius: 2, background: s.color, display: 'inline-block' }} />
              <span style={{ fontSize: 13, color: 'var(--ink-2)', textTransform: 'capitalize', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
                {s.label}
              </span>
              <span style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
                <span style={{ fontFamily: 'var(--font-sans)', fontSize: 14, fontWeight: 700, color: 'var(--ink)' }}>{s.value.toFixed(0)}%</span>
                <span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-3)', minWidth: 52, textAlign: 'right' }}>{formatValue(s.abs)}</span>
              </span>
            </div>
          ))}
        </div>
      );

      return (
        <div style={{ display: 'flex', flexDirection: stack ? 'column' : 'row', alignItems: stack ? 'stretch' : 'center', gap: stack ? 14 : 28, marginTop: 8 }}>
          {stack ? <div style={{ display: 'flex', justifyContent: 'center' }}>{ringSvg}</div> : ringSvg}
          {legend}
        </div>
      );
    }} />
  );
};
window.AnnotatedDonut = AnnotatedDonut;

const cssId = (s) => s.replace(/[^a-zA-Z0-9-]/g, '-');
const srcKeyObs = (o) => cssId('src-' + o.metric_id + '-' + o.report_year + '-' + (o.dimension_type || 'group') + '-' + (o.dimension_value || ''));
const srcKeyTarget = (t) => cssId('src-target-' + (t.target_id || (t.metric_id + '-' + t.target_year)));

const SectionToggle = ({ open, onClick }) => (
  <button className="btn btn-ghost" data-toggle-btn data-open={String(!!open)}
    style={{ fontSize: 12, padding: '6px 14px', flexShrink: 0 }} onClick={onClick}>
    {open ? 'Collapse' : 'Expand'} <Icon name={open ? 'chevron-down' : 'chevron-right'} size={12} style={{ marginLeft: 4 }} />
  </button>
);

const MetricDeepDive = ({ companyId, family, setRoute }) => {
  const ready = useStrix();
  const [showBreakdowns, setShowBreakdowns] = React.useState(false);
  const [open, setOpen] = React.useState({ targets: false, meth: false, restate: false, events: false, sources: false });
  const [showAllEvents, setShowAllEvents] = React.useState(false);
  const [highlightSrc, setHighlightSrc] = React.useState(null);
  const [showTop, setShowTop] = React.useState(false);
  const [activePara, setActivePara] = React.useState(0);
  const [openReason, setOpenReason] = React.useState(null);
  const sourcesHeaderRef = React.useRef(null);
  const toggle = (k) => setOpen(o => ({ ...o, [k]: !o[k] }));
  const jumpToSource = (key) => {
    setOpen(o => ({ ...o, sources: true }));
    setHighlightSrc({ key, ts: Date.now() });
    setShowTop(true);
  };
  React.useEffect(() => {
    if (!highlightSrc) return;
    const el = document.getElementById(highlightSrc.key);
    if (el) el.scrollIntoView({ behavior: 'smooth', block: 'center' });
  }, [highlightSrc]);
  React.useEffect(() => {
    // Show once the sources-table header has scrolled out of view, or simply deep in the page
    const onScroll = () => {
      const hdr = sourcesHeaderRef.current;
      const pastSources = hdr ? hdr.getBoundingClientRect().bottom < 0 : false;
      setShowTop(pastSources || window.scrollY > 900);
    };
    window.addEventListener('scroll', onScroll, { passive: true });
    onScroll();
    return () => window.removeEventListener('scroll', onScroll);
  }, []);
  const c = byId(companyId);
  if (!c || !ready) return null;

  const strixId = strixForCompany(companyId);
  const allObs = strixObsForCompany(companyId);
  const groupObs = allObs.filter(o => o.family === family && o.dimension_type === 'group');
  const breakdownObs = allObs.filter(o => o.family === family && o.dimension_type !== 'group');
  const targets = strixTargetsForCompany(companyId).filter(t => {
    const m = STRIX_METRICS[t.metric_id];
    return m && m.family === family;
  });
  const dropped = strixDroppedTargetsForCompany(companyId).filter(dt => {
    const m = STRIX_METRICS[dt.metric_id];
    return m && m.family === family;
  });
  const meth = strixMethodologyForCompany(companyId).filter(m => m.metric_family === family);
  const restatements = strixRestatementsForCompany(companyId)
    .filter(r => (STRIX_METRICS[r.metric_id] || {}).family === family)
    // Drop unit-scale artifacts: a ~1000x gap between original and restated is the same
    // value in different units ($ vs $m), not a real restatement.
    .filter(r => {
      const a = Math.abs(r.original_value), b = Math.abs(r.restated_value);
      if (!a || !b) return true;
      return Math.max(a, b) / Math.min(a, b) < 50;
    })
    .sort((a, b) => b.fiscal_year - a.fiscal_year || strixMetricName(a.metric_id).localeCompare(strixMetricName(b.metric_id)));
  const events = strixEventsForCompany(companyId);
  const rawAnalysis = strixAnalysis(companyId, family);
  let analysisText = rawAnalysis ? rawAnalysis.replace(/^#.*$/gm, '').replace(/\*\*/g, '').trim() : null;
  if (analysisText && !/[.!?]$/.test(analysisText)) {
    // Truncated mid-sentence (token cap) — trim back to the last complete sentence
    const cut = Math.max(analysisText.lastIndexOf('.'), analysisText.lastIndexOf('!'), analysisText.lastIndexOf('?'));
    if (cut > 100) analysisText = analysisText.slice(0, cut + 1);
  }
  const analysisParas = analysisText
    ? analysisText.split(/\n\s*\n/).map(p => p.replace(/\s+/g, ' ').trim()).filter(Boolean)
    : [];

  if (!groupObs.length) return null;

  const metricIds = [...new Set(groupObs.map(o => o.metric_id))];
  const latestYear = Math.max(...groupObs.map(o => o.report_year));
  const latestObs = groupObs.filter(o => o.report_year === latestYear);
  const allYears = [...new Set(groupObs.map(o => o.report_year))].sort();
  const unit = latestObs[0]?.unit || '';

  const chartSeries = metricIds.slice(0, 6).map(mid => ({
    mid,
    name: strixMetricName(mid),
    unit: STRIX_METRICS[mid]?.unit || '',
    data: groupObs.filter(o => o.metric_id === mid).map(o => ({ year: o.report_year, value: o.value })),
  }));

  const yoyChange = (mid) => {
    const sorted = groupObs.filter(o => o.metric_id === mid).sort((a, b) => b.report_year - a.report_year);
    if (sorted.length < 2 || sorted[0].value == null || sorted[1].value == null) return null;
    const prev = sorted[1].value;
    if (prev === 0) return null;
    return ((sorted[0].value - prev) / Math.abs(prev) * 100);
  };

  const methYears = [...new Set(meth.map(m => m.report_year))].sort();

  const breakdownTypes = [...new Set(breakdownObs.map(o => o.dimension_type))];

  return (
    <section className="section first">
      <div className="site-wrap">
        {/* Header — forest-green hero panel, electric-green highlights, floating stat chips */}
        {(() => {
          const chips = [
            // bobDur/bobDelay are deliberately mismatched so the chips never bob in unison
            { label: 'Observations', value: groupObs.length, top: 8, left: 20, w: 172, delay: 200, bobDur: 4.4, bobDelay: 0 },
            { label: 'Breakdowns', value: breakdownObs.length, top: 84, right: 0, w: 172, delay: 320, bobDur: 5.2, bobDelay: -2.6 },
            { label: 'Targets', value: targets.length, bottom: 60, left: 4, w: 160, delay: 440, bobDur: 3.9, bobDelay: -1.1 },
            { label: 'Restated values', value: restatements.length, bottom: 0, right: 26, w: 196, delay: 560, bobDur: 5.7, bobDelay: -3.4, warn: restatements.length > 0 },
          ];
          return (
            <div className="dark-section m-hero-pad" style={{ borderRadius: 20, padding: '34px 44px 40px', marginBottom: 8 }}>
              <div className="site-wrap" style={{ padding: 0 }}>
                <button onClick={() => setRoute({ page: 'company', id: companyId })}
                  style={{
                    display: 'inline-flex', alignItems: 'center', gap: 8, marginBottom: 26,
                    background: 'transparent', border: 'none', cursor: 'pointer', padding: 0,
                    fontSize: 13, color: '#9DAC8C', fontFamily: 'var(--font-sans)',
                  }}>
                  <Icon name="arrow-left" size={12} /> {c.name}
                </button>

                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 40, flexWrap: 'wrap' }}>
                  <div className="m-flexfull" style={{ flex: '1 1 440px', minWidth: 300 }}>
                    <EyebrowRow label={strixFamilyName(family)} />
                    <h1 className="spade-h m-bigh" style={{ fontSize: 58, marginTop: 4 }}>
                      {c.name} — <span className="hl">{strixFamilyName(family)}</span>
                    </h1>
                    <p className="lede" style={{ marginTop: 18, maxWidth: 520, color: '#C2CDB5' }}>
                      {groupObs.length} group-level observations across {allYears.length} years
                      ({allYears[0]}&ndash;{allYears[allYears.length - 1]}).
                      {breakdownObs.length > 0 ? ` Plus ${breakdownObs.length} dimensional breakdowns.` : ''}
                    </p>
                  </div>

                  {/* Floating stat labels */}
                  <div className="m-hide" style={{ position: 'relative', flex: '0 0 460px', height: 300, minWidth: 320 }}>
                    {chips.map((ch) => (
                      <div key={ch.label} className="chip-float" style={{
                        position: 'absolute', width: ch.w, animationDelay: `${ch.delay}ms`,
                        top: ch.top, left: ch.left, right: ch.right, bottom: ch.bottom,
                      }}>
                        {/* inner wrapper carries the gentle continuous bob; outer handles entrance.
                            Uses the .drift class so prefers-reduced-motion disables it automatically. */}
                        <div className="drift" style={{ animationDuration: `${ch.bobDur}s`, animationDelay: `${ch.bobDelay}s` }}>
                          <CornerFrame style={{ padding: '15px 18px', textAlign: 'center' }}>
                            <div style={{
                              fontFamily: 'var(--mono)', fontSize: 10, fontWeight: 500,
                              letterSpacing: '0.13em', textTransform: 'uppercase', color: '#FFFFFF',
                              marginBottom: 9, display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 6,
                            }}>
                              <span style={{ color: 'var(--lime)', fontSize: 7 }}>►</span> {ch.label}
                            </div>
                            <div style={{
                              fontFamily: 'var(--font-sans)', fontSize: 27, fontWeight: 700,
                              letterSpacing: '-0.02em', lineHeight: 1, color: ch.warn ? '#E89A9A' : 'var(--lime)',
                            }}>
                              <AnimatedNumber value={ch.value} decimals={0} />
                            </div>
                          </CornerFrame>
                        </div>
                      </div>
                    ))}
                  </div>
                </div>
              </div>
            </div>
          );
        })()}

        {/* Metric charts — each metric gets its own panel with independent Y-axis */}
        <Reveal>
          <div style={{ marginTop: 48 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 20 }}>
              <div className="eyebrow">{strixFamilyName(family)} — time series</div>
              <div style={{ fontSize: 12, color: 'var(--ink-3)', fontFamily: 'var(--mono)' }}>
                {chartSeries.length} metric{chartSeries.length > 1 ? 's' : ''} · independent scales · click a point for its source
              </div>
            </div>
            <div className="m-1col" style={{ display: 'grid', gridTemplateColumns: chartSeries.length === 1 ? '1fr' : '1fr 1fr', gap: 20 }}>
              {chartSeries.map((s, i) => {
                const sorted = s.data.filter(d => d.value != null).sort((a, b) => b.year - a.year);
                return (
                  <div key={i} style={{
                    padding: '24px 28px', border: '1px solid var(--line)', borderRadius: 14, background: 'var(--canvas)',
                  }} className="lift">
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 12, gap: 12 }}>
                      <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink)' }}><TermedText text={s.name} /></div>
                      <div style={{ fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)', flexShrink: 0 }}>
                        {s.unit ? <Gloss term={s.unit} /> : null}
                      </div>
                    </div>
                    {sorted.length === 0 ? (
                      <div style={{
                        padding: '36px 0', textAlign: 'center',
                        fontSize: 13, color: 'var(--ink-3)', fontStyle: 'italic',
                      }}>
                        Not reported in canonical units
                      </div>
                    ) : (
                      <>
                        <ResponsiveChart render={(w) => (
                          <InteractiveLineChart
                            series={[s]}
                            width={w}
                            height={chartSeries.length === 1 ? 320 : 220}
                            onPointClick={(pt) => {
                              const hit = s.data.find(d => d.year === pt.year && d.value != null);
                              if (!hit) return;
                              jumpToSource(srcKeyObs({ metric_id: s.mid, report_year: pt.year, dimension_type: 'group', dimension_value: '' }));
                            }}
                          />
                        )} />
                        <div style={{ marginTop: 8, display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', fontSize: 12 }}>
                          <span style={{ fontFamily: 'var(--mono)', fontWeight: 600, color: 'var(--ink)' }}>
                            {formatValue(sorted[0].value)} <span style={{ color: 'var(--ink-3)', fontWeight: 400 }}>{s.unit ? <Gloss term={s.unit} /> : null} · {sorted[0].year}</span>
                          </span>
                          {sorted.length >= 2 ? (() => {
                            const change = ((sorted[0].value - sorted[1].value) / Math.abs(sorted[1].value || 1)) * 100;
                            const dir = metricDirection(s.mid);
                            const improving = Math.abs(change) <= 1 ? null : dir === 'lower' ? change < 0 : dir === 'higher' ? change > 0 : null;
                            return (
                              <span style={{
                                fontFamily: 'var(--mono)', fontWeight: 600,
                                color: improving === true ? 'var(--moss-deep)' : improving === false ? '#8b4545' : 'var(--ink-3)',
                              }}>
                                {change > 0 ? '↑' : change < 0 ? '↓' : '—'} {Math.abs(change).toFixed(1)}% YoY
                              </span>
                            );
                          })() : (
                            <span style={{ fontFamily: 'var(--mono)', fontSize: 11, color: 'var(--ink-3)' }}>single year reported</span>
                          )}
                        </div>
                      </>
                    )}
                  </div>
                );
              })}
            </div>
          </div>
        </Reveal>

        {/* Key metrics table */}
        <Reveal delay={80}>
          <div style={{ marginTop: 32, padding: '28px 32px', border: '1px solid var(--line)', borderRadius: 16, background: 'var(--canvas)' }} className="lift">
            <div className="eyebrow">Latest values — {latestYear}</div>
            <div className="m-xscroll" style={{ marginTop: 16 }}>
              <div style={{
                display: 'grid', gridTemplateColumns: '1fr 100px 150px 90px 130px 100px', columnGap: 14,
                alignItems: 'center', padding: '0 0 8px',
                borderBottom: '2px solid var(--line)',
              }}>
                {['Metric', 'Value', 'Unit', 'YoY', 'Trend', 'Confidence'].map((h, i) => (
                  <div key={h} style={{
                    fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)',
                    letterSpacing: '0.06em', textTransform: 'uppercase',
                    textAlign: i === 0 ? 'left' : 'right',
                  }}>{h === 'Confidence' ? <Gloss term="Confidence" /> : h}</div>
                ))}
              </div>
              {metricIds.map(mid => {
                const row = latestObs.find(o => o.metric_id === mid);
                if (!row) return null;
                const change = yoyChange(mid);
                const series = groupObs.filter(o => o.metric_id === mid)
                  .sort((a, b) => a.report_year - b.report_year)
                  .map(o => ({ year: o.report_year, value: o.value }));
                const trend = metricTrendStatus(mid, series);
                return (
                  <div key={mid} style={{
                    display: 'grid', gridTemplateColumns: '1fr 100px 150px 90px 130px 100px', columnGap: 14,
                    alignItems: 'center', padding: '12px 0',
                    borderBottom: '1px solid var(--line)',
                  }}>
                    <div style={{ fontSize: 14, fontWeight: 500 }}><TermedText text={strixMetricName(mid)} /></div>
                    <div style={{ fontFamily: 'var(--mono)', fontSize: 15, fontWeight: 600, textAlign: 'right' }}>
                      {row.value != null ? formatValue(row.value) : <NotReported />}
                    </div>
                    <div style={{ fontSize: 12, color: 'var(--ink-3)', fontFamily: 'var(--mono)', textAlign: 'right' }}>
                      {row.unit ? <Gloss term={row.unit} /> : 'NA'}
                    </div>
                    <div style={{ textAlign: 'right' }}>
                      {change != null ? (() => {
                        const dir = metricDirection(mid);
                        const improving = Math.abs(change) <= 1 ? null : dir === 'lower' ? change < 0 : dir === 'higher' ? change > 0 : null;
                        return (
                        <span style={{
                          fontSize: 12, fontFamily: 'var(--mono)', fontWeight: 600,
                          color: improving === true ? 'var(--moss-deep)' : improving === false ? '#8b4545' : 'var(--ink-3)',
                        }}>
                          {change > 0 ? '↑' : change < 0 ? '↓' : '—'} {Math.abs(change).toFixed(1)}%
                        </span>
                        );
                      })() : (
                        <span style={{ fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)' }}>NA</span>
                      )}
                    </div>
                    <div style={{ display: 'flex', justifyContent: 'flex-end' }}>
                      {trend ? <StatusChip status={trend} /> : <span style={{ fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)' }}>NA</span>}
                    </div>
                    <div style={{ display: 'flex', alignItems: 'center', gap: 6, justifyContent: 'flex-end' }}>
                      <MiniBar value={row.confidence * 100} tone="var(--moss)" />
                      <span style={{ fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)' }}>
                        {Math.round(row.confidence * 100)}
                      </span>
                    </div>
                  </div>
                );
              })}
            </div>
          </div>
        </Reveal>

        {/* Analyst context — forest panel, rotating Trend / Drivers / Outlook */}
        {analysisParas.length > 0 && (() => {
          const kickers = analysisParas.map((_, i) => ['Trend', 'Drivers', 'Outlook'][i] || 'Note');
          const idx = Math.min(activePara, analysisParas.length - 1);
          return (
            <Reveal delay={120}>
              <div style={{
                marginTop: 32, padding: '32px 36px', borderRadius: 16,
                background: '#16240E', border: '1px solid rgba(166,225,94,0.25)',
              }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 22, gap: 16, flexWrap: 'wrap' }}>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                    <Icon name="spark" size={16} color="#A6E15E" />
                    <div className="eyebrow" style={{ color: '#A6E15E' }}>Analyst context</div>
                  </div>
                  <div style={{ display: 'flex', alignItems: 'center', gap: 18 }}>
                    {kickers.map((k, i) => (
                      <button key={k} onClick={() => setActivePara(i)} style={{
                        background: 'none', border: 'none', cursor: 'pointer', padding: '4px 0',
                        fontFamily: 'var(--mono)', fontSize: 11, fontWeight: 600,
                        letterSpacing: '0.14em', textTransform: 'uppercase',
                        color: i === idx ? '#A6E15E' : '#7E8E6D',
                        borderBottom: i === idx ? '2px solid #A6E15E' : '2px solid transparent',
                      }}>
                        ► {k}
                      </button>
                    ))}
                    <button onClick={() => setActivePara((idx + 1) % analysisParas.length)} title="Next"
                      style={{
                        width: 30, height: 30, borderRadius: 999, border: '1px solid rgba(166,225,94,0.4)',
                        background: 'transparent', color: '#A6E15E', cursor: 'pointer',
                        display: 'flex', alignItems: 'center', justifyContent: 'center',
                      }}>
                      <Icon name="arrow-right" size={13} />
                    </button>
                  </div>
                </div>
                <div style={{ overflow: 'hidden' }}>
                  <div style={{
                    display: 'flex',
                    transform: `translateX(-${idx * 100}%)`,
                    transition: 'transform 480ms var(--ease-quiet)',
                  }}>
                    {analysisParas.map((p, i) => (
                      <div key={i} style={{ flex: '0 0 100%', minWidth: '100%', paddingRight: 8 }} aria-hidden={i !== idx}>
                        <p style={{ fontSize: 15, lineHeight: '26px', color: '#C2CDB5', margin: 0 }}>
                          <HighlightFigures text={p} />
                        </p>
                      </div>
                    ))}
                  </div>
                </div>
                <div style={{ marginTop: 16, fontFamily: 'var(--mono)', fontSize: 11, color: '#7E8E6D' }}>
                  {idx + 1} / {analysisParas.length}
                </div>
              </div>
            </Reveal>
          );
        })()}

        {/* Targets */}
        {targets.length > 0 && (
          <Reveal delay={160}>
            <div style={{
              marginTop: 32, padding: '28px 32px', border: '1px solid var(--line)',
              borderRadius: 16, background: 'var(--canvas)',
            }} className="lift">
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 16 }}>
                <div>
                  <div className="eyebrow">Targets — {strixFamilyName(family)}</div>
                  <div style={{ fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)', marginTop: 2 }}>
                    {targets.length} target{targets.length !== 1 ? 's' : ''} · status computed from extracted history
                  </div>
                </div>
                <SectionToggle open={open.targets} onClick={() => toggle('targets')} />
              </div>
              {open.targets && <div style={{ marginTop: 16, display: 'flex', flexDirection: 'column', gap: 16 }}>
                {targets.map((t, i) => {
                  const status = targetStatus(t, companyId);
                  return (
                    <div key={i} onClick={() => jumpToSource(srcKeyTarget(t))} title="View source"
                      style={{ paddingBottom: 16, borderBottom: i < targets.length - 1 ? '1px solid var(--line)' : 'none', cursor: 'pointer' }}>
                      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', gap: 16 }}>
                        <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--ink)', lineHeight: '20px' }}>{t.expressed_as}</div>
                        <StatusChip status={status} />
                      </div>
                      <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 4, fontFamily: 'var(--mono)' }}>
                        {t.target_year ? `Target: ${t.target_year}` : ''}
                        {t.baseline_year ? ` · Baseline: ${t.baseline_year}` : ''}
                        {t.target_value != null ? ` · Goal: ${formatValue(t.target_value)}${t.target_unit ? ' ' + t.target_unit : t.target_kind === 'percentage_reduction' ? '% reduction' : t.target_kind === 'percentage_increase' ? '% increase' : ''}` : ''}
                        {` · ${Math.round(t.confidence * 100)}% conf`}
                      </div>
                    </div>
                  );
                })}
              </div>}
            </div>
          </Reveal>
        )}

        {/* Dropped targets */}
        {dropped.length > 0 && (
          <Reveal delay={180}>
            <div style={{
              marginTop: 24, padding: '28px 32px', border: '1px solid #e8c4c4',
              borderRadius: 14, background: '#fdf6f6',
            }} className="lift">
              <div className="eyebrow" style={{ color: '#8b4545' }}>Silently dropped — {strixFamilyName(family)}</div>
              <p style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 4, marginBottom: 16 }}>
                Targets disclosed in a prior report but absent from the next.
              </p>
              {dropped.map((dt, i) => (
                <div key={i} style={{ paddingBottom: 12, borderBottom: i < dropped.length - 1 ? '1px solid #e8c4c4' : 'none', marginBottom: 12 }}>
                  <div style={{ fontSize: 14, fontWeight: 500, color: 'var(--ink)' }}>{dt.expressed_as}</div>
                  <div style={{ fontSize: 12, color: '#8b4545', marginTop: 4, fontFamily: 'var(--mono)' }}>
                    Last seen: {dt.last_seen_year} · Dropped in: {dt.dropped_in_year}
                    {dt.target_year ? ` · Target year: ${dt.target_year}` : ''}
                  </div>
                </div>
              ))}
            </div>
          </Reveal>
        )}

        {/* Methodology history */}
        {meth.length > 0 && (
          <Reveal delay={200}>
            <div style={{
              marginTop: 32, padding: '28px 32px', border: '1px solid var(--line)',
              borderRadius: 16, background: 'var(--canvas)',
            }} className="lift">
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 16 }}>
                <div>
                  <div className="eyebrow">Methodology history — {strixFamilyName(family)}</div>
                  <p style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 4, marginBottom: 0 }}>
                    How {c.name} has calculated these metrics over time. Changes here affect comparability.
                  </p>
                </div>
                <SectionToggle open={open.meth} onClick={() => toggle('meth')} />
              </div>
              {open.meth && <>
              <div style={{ overflowX: 'auto', marginTop: 20 }}>
                <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
                  <thead>
                    <tr style={{ borderBottom: '2px solid var(--line)' }}>
                      <th style={thStyle}>Year</th>
                      <th style={thStyle}><Gloss term="Boundary" /></th>
                      <th style={thStyle}><Gloss term="Assurance" /></th>
                      {family === 'ghg_emissions' && <th style={thStyle}><Gloss term="GWP set" /></th>}
                      <th style={thStyle}><Gloss term="JVs" /></th>
                      <th style={thStyle}><Gloss term="Contractors" /></th>
                      <th style={thStyle}><Gloss term="Restated" /></th>
                    </tr>
                  </thead>
                  <tbody>
                    {meth.sort((a, b) => b.report_year - a.report_year).map((m, i, arr) => {
                      const prev = arr[i + 1]; // previous reported year (rows sorted newest-first)
                      const changed = (field) => prev && prev[field] != null && m[field] != null && prev[field] !== m[field];
                      return (
                        <tr key={i} style={{ borderBottom: '1px solid var(--line)' }}>
                          <td style={tdStyle}><strong>{m.report_year}</strong></td>
                          <td style={{ ...tdStyle, ...(changed('boundary_basis') ? changeStyle : {}) }}>
                            {m.boundary_basis ? <Gloss term={formatBasis(m.boundary_basis)} /> : <NotReported />}
                          </td>
                          <td style={{ ...tdStyle, ...(changed('assurance_level') ? changeStyle : {}) }}>
                            {m.assurance_level ? <Gloss term={m.assurance_level.replace(/_/g, ' ')} /> : <NotReported />}
                          </td>
                          {family === 'ghg_emissions' && (
                            <td style={{ ...tdStyle, ...(changed('gwp_set') ? changeStyle : {}) }}>
                              {m.gwp_set ? m.gwp_set.toUpperCase() : <NotReported />}
                            </td>
                          )}
                          <td style={{ ...tdStyle, ...(changed('includes_managed_jvs') ? changeStyle : {}) }}>
                            {m.includes_managed_jvs == null ? <NotReported /> : m.includes_managed_jvs ? 'Yes' : 'No'}
                          </td>
                          <td style={{ ...tdStyle, ...(changed('includes_contractors') ? changeStyle : {}) }}>
                            {m.includes_contractors == null ? <NotReported /> : m.includes_contractors ? 'Yes' : 'No'}
                          </td>
                          <td style={tdStyle}>
                            {m.restated_this_year ? (
                              restatements.length > 0 ? (
                                <button
                                  onClick={() => {
                                    setOpen(o => ({ ...o, restate: true }));
                                    setTimeout(() => document.getElementById('restated-figures-section')?.scrollIntoView({ behavior: 'smooth', block: 'start' }), 80);
                                  }}
                                  title="See the restated figures"
                                  style={{
                                    background: 'none', border: 'none', padding: 0, cursor: 'pointer',
                                    color: '#8b4545', fontWeight: 600, fontSize: 13,
                                    textDecoration: 'underline', textDecorationStyle: 'dotted', textUnderlineOffset: 3,
                                  }}>
                                  Yes →
                                </button>
                              ) : <span style={{ color: '#8b4545', fontWeight: 600 }}>Yes</span>
                            ) : 'No'}
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
              <div style={{ marginTop: 12, display: 'flex', alignItems: 'center', gap: 8, fontSize: 11, color: 'var(--ink-3)' }}>
                <span style={{ width: 12, height: 12, borderRadius: 3, background: '#fff8e6', border: '1px solid #ecd9a8', display: 'inline-block' }} />
                Highlighted cells changed from the previous reported year — a comparability flag, not an error.
              </div>
              </>}
            </div>
          </Reveal>
        )}

        {/* Operational events */}
        {events.length > 0 && (
          <Reveal delay={220}>
            <div style={{
              marginTop: 32, padding: '28px 32px', border: '1px solid var(--line)',
              borderRadius: 16, background: 'var(--canvas)',
            }} className="lift">
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 16 }}>
                <div>
                  <div className="eyebrow">Operational events</div>
                  <p style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 4, marginBottom: 0 }}>
                    {events.length} corporate changes that may affect {strixFamilyName(family).toLowerCase()} metrics.
                  </p>
                </div>
                <SectionToggle open={open.events} onClick={() => toggle('events')} />
              </div>
              {open.events && <>
              <div style={{ display: 'flex', flexDirection: 'column', gap: 10, marginTop: 16 }}>
                {(showAllEvents ? events : events.slice(0, 8)).map((ev, i, shown) => (
                  <div key={i} style={{
                    display: 'grid', gridTemplateColumns: '150px 1fr', gap: 16, alignItems: 'baseline',
                    paddingBottom: 10, borderBottom: i < shown.length - 1 ? '1px solid var(--line)' : 'none',
                  }}>
                    <div>
                      <span style={{
                        display: 'inline-block', padding: '3px 10px', borderRadius: 10,
                        border: '1px solid var(--line)', background: 'var(--canvas-2)',
                        fontSize: 11, fontFamily: 'var(--mono)', color: 'var(--ink-2)', lineHeight: '15px',
                        overflowWrap: 'anywhere', maxWidth: '100%',
                      }}>{formatEventKind(ev.event_kind)}</span>
                      {ev.effective_date && (
                        <div style={{ fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)', marginTop: 4 }}>{ev.effective_date}</div>
                      )}
                    </div>
                    <div>
                      <div style={{ fontSize: 13, fontWeight: 500, color: 'var(--ink)' }}>{ev.affected_entity.replace(/_/g, ' ')}</div>
                      {ev.description && <div style={{ fontSize: 12, color: 'var(--ink-3)', marginTop: 2, lineHeight: '16px' }}>{ev.description}</div>}
                    </div>
                  </div>
                ))}
              </div>
              {events.length > 8 && (
                <button onClick={() => setShowAllEvents(v => !v)} style={{
                  marginTop: 14, background: 'none', border: 'none', cursor: 'pointer',
                  fontSize: 12, color: 'var(--moss-deep)', fontFamily: 'var(--mono)', fontWeight: 600,
                  display: 'flex', alignItems: 'center', gap: 4, padding: 0,
                }}>
                  {showAllEvents ? 'Show fewer' : `Show all ${events.length} events`}
                  <Icon name={showAllEvents ? 'chevron-down' : 'chevron-right'} size={12} />
                </button>
              )}
              </>}
            </div>
          </Reveal>
        )}

        {/* Dimension breakdowns — section header, standalone headline panels, then the full table */}
        {breakdownObs.length > 0 && (
          <Reveal delay={240}>
            <div style={{ marginTop: 48 }}>
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', marginBottom: 20, gap: 16, flexWrap: 'wrap' }}>
                <div className="eyebrow">Dimensional breakdowns</div>
                <div style={{ fontSize: 12, color: 'var(--ink-3)', fontFamily: 'var(--mono)' }}>
                  {breakdownObs.length} observations by {breakdownTypes.map(formatDimType).join(', ')} · click an item for its source
                </div>
              </div>

              {/* Headline breakdown charts — dominant metric per dimension, latest year.
                  Alternates donut and bar presentation; every item links to its source row. */}
              {(() => {
                const DIM_ORDER = ['country', 'business_unit', 'asset', 'source_type', 'category'];
                const panels = DIM_ORDER.filter(dt => breakdownTypes.includes(dt)).slice(0, 4).map(dt => {
                  const dtObs = breakdownObs.filter(o => o.dimension_type === dt && o.value != null && o.value > 0);
                  if (!dtObs.length) return null;
                  const dtLatest = Math.max(...dtObs.map(o => o.report_year));
                  const latest = dtObs.filter(o => o.report_year === dtLatest);
                  const byMetric = {};
                  latest.forEach(o => { (byMetric[o.metric_id] = byMetric[o.metric_id] || []).push(o); });
                  const mid = Object.keys(byMetric).sort((a, b) => byMetric[b].length - byMetric[a].length)[0];
                  const rows = byMetric[mid].sort((a, b) => b.value - a.value);
                  return { dt, mid, year: dtLatest, unit: rows[0].unit, rows };
                }).filter(Boolean);
                if (!panels.length) return null;
                const GRID = 'repeating-linear-gradient(0deg, rgba(78,90,65,0.06) 0 1px, transparent 1px 40px), repeating-linear-gradient(90deg, rgba(78,90,65,0.06) 0 1px, transparent 1px 40px)';
                // Two annotated donuts side by side — prefer asset (Scope 1) and category (Scope 3)
                const donutPref = ['asset', 'category', 'country', 'business_unit', 'source_type'];
                const donutPanels = donutPref.map(dt => panels.find(p => p.dt === dt)).filter(Boolean).slice(0, 2);
                for (const p of panels) { if (donutPanels.length >= 2) break; if (!donutPanels.includes(p)) donutPanels.push(p); }
                const mkSegs = (p) => {
                  const total = p.rows.reduce((a, o) => a + o.value, 0);
                  const top = p.rows.slice(0, 5);
                  const other = p.rows.slice(5).reduce((a, o) => a + o.value, 0);
                  const segs = [
                    ...top.map((o, i) => ({ label: (o.dimension_value || 'unknown').replace(/_/g, ' '), value: (o.value / total) * 100, abs: o.value, color: DONUT_GREENS[i % DONUT_GREENS.length], o })),
                    ...(other > 0 ? [{ label: `Remaining (${p.rows.length - 5})`, value: (other / total) * 100, abs: other, color: DONUT_OTHER, o: null }] : []),
                  ];
                  return { total, segs };
                };
                return (
                  <>
                    {/* Full-bleed grid band carrying the two annotated donuts (no card frames) */}
                    <div style={{ width: '100vw', marginLeft: 'calc(50% - 50vw)', background: 'var(--canvas)', backgroundImage: GRID, borderTop: '1px solid var(--line)', borderBottom: '1px solid var(--line)', padding: '40px 0' }}>
                      <div className="site-wrap">
                        <div className="m-1col" style={{ display: 'grid', gridTemplateColumns: donutPanels.length > 1 ? '1fr 1fr' : '1fr', gap: 40 }}>
                          {donutPanels.map((p) => {
                            const { total, segs } = mkSegs(p);
                            return (
                              <div key={p.dt}>
                                <div style={{ fontSize: 14, fontWeight: 600, color: 'var(--ink)', textAlign: 'center' }}>
                                  <TermedText text={strixMetricName(p.mid)} /> by {formatDimType(p.dt)}
                                </div>
                                <div style={{ fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)', marginTop: 2, marginBottom: 6, textAlign: 'center' }}>
                                  {p.year} · <UnitGloss unit={p.unit} /> · click a label for its source
                                </div>
                                <AnnotatedDonut segs={segs} total={total} unit={p.unit} onSeg={(o) => jumpToSource(srcKeyObs(o))} />
                              </div>
                            );
                          })}
                        </div>
                      </div>
                    </div>
                  </>
                );
              })()}

              <div className="lift" style={{ marginTop: 20, padding: '28px 32px', border: '1px solid var(--line)', borderRadius: 16, background: 'var(--canvas)' }}>
                <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 16 }}>
                  <div>
                    <div className="eyebrow">Full breakdown table</div>
                    <div style={{ fontSize: 12, color: 'var(--ink-3)', fontFamily: 'var(--mono)', marginTop: 2 }}>
                      every dimensional observation · {latestYear}
                    </div>
                  </div>
                  <SectionToggle open={showBreakdowns} onClick={() => setShowBreakdowns(!showBreakdowns)} />
                </div>
              {showBreakdowns && (
                <div style={{ marginTop: 20 }}>
                  {breakdownTypes.map(dt => {
                    const dtAll = breakdownObs.filter(o => o.dimension_type === dt);
                    if (!dtAll.length) return null;
                    const dtLatest = Math.max(...dtAll.map(o => o.report_year));
                    const dtObs = dtAll.filter(o => o.report_year === dtLatest);
                    const byDimVal = {};
                    dtObs.forEach(o => {
                      const key = o.dimension_value || 'Unknown';
                      if (!byDimVal[key]) byDimVal[key] = [];
                      byDimVal[key].push(o);
                    });
                    return (
                      <div key={dt} style={{ marginBottom: 24 }}>
                        <div style={{ fontSize: 13, fontWeight: 600, color: 'var(--ink)', marginBottom: 12 }}>
                          By {formatDimType(dt)} — {dtLatest} · {dtObs.length} observations
                        </div>
                        {Object.entries(byDimVal).sort((a, b) => a[0].localeCompare(b[0])).map(([dv, obs]) => (
                          <div key={dv} style={{ marginBottom: 8, paddingLeft: 16, borderLeft: '2px solid var(--line)' }}>
                            <div style={{ fontSize: 12, fontWeight: 600, color: 'var(--ink-2)', textTransform: 'capitalize', marginBottom: 4 }}>
                              {dv.replace(/_/g, ' ')}
                            </div>
                            {obs.map((o, i) => (
                              <div key={i} onClick={() => jumpToSource(srcKeyObs(o))} title="View source"
                                style={{ display: 'flex', justifyContent: 'space-between', gap: 16, fontSize: 12, color: 'var(--ink-3)', padding: '2px 0', cursor: 'pointer' }}>
                                <span>{strixMetricName(o.metric_id)}</span>
                                <span style={{ fontFamily: 'var(--mono)', color: 'var(--ink-2)', whiteSpace: 'nowrap' }}>
                                  {o.value != null
                                    ? <>{formatValue(o.value)} <UnitGloss unit={o.unit} /></>
                                    : o.value_original != null
                                      ? <>{o.value_original} <UnitGloss unit={o.unit_original} /></>
                                      : 'Not reported'}
                                </span>
                              </div>
                            ))}
                          </div>
                        ))}
                      </div>
                    );
                  })}
                </div>
              )}
              </div>
            </div>
          </Reveal>
        )}

        {/* Restated figures */}
        {restatements.length > 0 && (
          <Reveal delay={210}>
            <div id="restated-figures-section" style={{
              marginTop: 32, padding: '28px 32px', border: '1px solid var(--line)',
              borderRadius: 16, background: 'var(--canvas)',
            }} className="lift">
              <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 16 }}>
                <div>
                  <div className="eyebrow"><Gloss term="Restated">Restated figures</Gloss> — {strixFamilyName(family)}</div>
                  <p style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 4, marginBottom: 0 }}>
                    {restatements.length} value{restatements.length !== 1 ? 's' : ''} {c.name} revised after first publishing them. Click a row for its source.
                  </p>
                </div>
                <SectionToggle open={open.restate} onClick={() => toggle('restate')} />
              </div>
              {open.restate && (
                <div style={{ overflowX: 'auto', marginTop: 20 }}>
                  <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
                    <thead>
                      <tr style={{ borderBottom: '2px solid var(--line)' }}>
                        <th style={thStyle}>Metric</th>
                        <th style={thStyle}>Year</th>
                        <th style={thStyle}>Original</th>
                        <th style={thStyle}>Restated</th>
                        <th style={thStyle}>Change</th>
                        <th style={thStyle}>Restated in</th>
                        <th style={thStyle}>Why</th>
                      </tr>
                    </thead>
                    <tbody>
                      {restatements.map((r, i) => {
                        const sameUnit = !r.restated_unit || r.restated_unit === r.unit;
                        const pct = (sameUnit && r.original_value != null && r.restated_value != null && r.original_value !== 0)
                          ? ((r.restated_value - r.original_value) / Math.abs(r.original_value)) * 100
                          : null;
                        const methReason = (meth.find(m => m.report_year === r.restated_in_year) || {}).restatement_reason;
                        const reason = methReason || r.notes
                          || (r.kind ? r.kind.replace(/_/g, ' ').replace(/^./, ch => ch.toUpperCase()) : null);
                        return (
                          <React.Fragment key={i}>
                          <tr
                            onClick={() => jumpToSource(srcKeyObs({ metric_id: r.metric_id, report_year: r.fiscal_year, dimension_type: 'group', dimension_value: '' }))}
                            title="View source"
                            style={{ borderBottom: openReason === i ? 'none' : '1px solid var(--line)', cursor: 'pointer' }}>
                            <td style={{ ...tdStyle, fontWeight: 500, color: 'var(--ink)' }}><TermedText text={strixMetricName(r.metric_id)} /></td>
                            <td style={{ ...tdStyle, fontFamily: 'var(--mono)' }}>{r.fiscal_year}</td>
                            <td style={{ ...tdStyle, fontFamily: 'var(--mono)', whiteSpace: 'nowrap' }}>
                              {r.original_value} <UnitGloss unit={r.unit} />
                            </td>
                            <td style={{ ...tdStyle, fontFamily: 'var(--mono)', whiteSpace: 'nowrap', fontWeight: 600, color: 'var(--ink)' }}>
                              {r.restated_value} <UnitGloss unit={r.restated_unit || r.unit} />
                            </td>
                            <td style={{ ...tdStyle, fontFamily: 'var(--mono)', whiteSpace: 'nowrap' }}>
                              {pct != null ? (
                                <span style={{ fontWeight: 600, color: Math.abs(pct) > 10 ? '#8b4545' : 'var(--ink-2)' }}>
                                  {pct > 0 ? '+' : ''}{pct.toFixed(1)}%
                                </span>
                              ) : !sameUnit ? (
                                <Gloss def="The original and restated figures use different units, so a percentage change would be misleading."
                                  style={{ fontSize: 11, fontStyle: 'italic', color: 'var(--ink-3)' }}>unit changed</Gloss>
                              ) : '—'}
                            </td>
                            <td style={{ ...tdStyle, fontSize: 12, color: 'var(--ink-3)', whiteSpace: 'nowrap' }}
                              title={r.restated_source_doc}>
                              {r.restated_in_year ? `${r.restated_in_year} report` : (r.restated_source_doc || '—')}
                            </td>
                            <td style={{ ...tdStyle, fontSize: 12, maxWidth: 260 }}
                              onClick={(e) => { e.stopPropagation(); if (reason) setOpenReason(openReason === i ? null : i); }}>
                              {reason ? (
                                <span style={{
                                  display: 'inline-flex', alignItems: 'center', gap: 4, cursor: 'pointer',
                                  color: openReason === i ? 'var(--moss-deep)' : 'var(--ink-3)',
                                }}>
                                  <span style={{
                                    display: 'inline-block', maxWidth: 220, overflow: 'hidden',
                                    textOverflow: 'ellipsis', whiteSpace: 'nowrap', verticalAlign: 'bottom',
                                  }}>{reason}</span>
                                  <Icon name={openReason === i ? 'chevron-down' : 'chevron-right'} size={11} style={{ flexShrink: 0 }} />
                                </span>
                              ) : <NotReported />}
                            </td>
                          </tr>
                          {openReason === i && reason && (
                            <tr>
                              <td colSpan={7} style={{ padding: '0 12px 14px', borderBottom: '1px solid var(--line)' }}>
                                <div style={{
                                  padding: '14px 18px', background: 'var(--canvas-2)',
                                  borderLeft: '3px solid var(--moss)', borderRadius: '0 8px 8px 0',
                                }}>
                                  <div style={{
                                    fontFamily: 'var(--mono)', fontSize: 10, fontWeight: 600,
                                    letterSpacing: '0.12em', textTransform: 'uppercase',
                                    color: 'var(--moss-deep)', marginBottom: 6,
                                  }}>
                                    Company&rsquo;s explanation{r.restated_in_year ? ` — ${r.restated_in_year} report` : ''}
                                  </div>
                                  <div style={{ fontSize: 13, lineHeight: '21px', color: 'var(--ink-2)' }}>
                                    {methReason || reason}
                                  </div>
                                </div>
                              </td>
                            </tr>
                          )}
                          </React.Fragment>
                        );
                      })}
                    </tbody>
                  </table>
                </div>
              )}
            </div>
          </Reveal>
        )}

        {/* Source provenance */}
        <Reveal delay={260}>
          <div style={{
            marginTop: 32, padding: '28px 32px', border: '1px solid var(--line)',
            borderRadius: 16, background: 'var(--canvas)',
          }} className="lift">
            <div ref={sourcesHeaderRef} style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', gap: 16 }}>
              <div>
                <div className="eyebrow">Source provenance</div>
                <p style={{ fontSize: 13, color: 'var(--ink-3)', marginTop: 4, marginBottom: 0 }}>
                  Every data point traces back to a cell or page in {c.name}&rsquo;s published reports —{' '}
                  {groupObs.length} group values, {targets.length} targets, {breakdownObs.length} breakdowns.
                </p>
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, flexShrink: 0 }}>
                <CsvDownloadButton
                  getCsv={() => csvForStrixObs([...groupObs, ...breakdownObs])}
                  filename={`${companyId}-${family}-strix-data.csv`}
                  count={groupObs.length + breakdownObs.length}
                  title={`Download ${c.name}'s ${strixFamilyName(family)} data (${(groupObs.length + breakdownObs.length).toLocaleString()} observations) as CSV — original value & unit, normalised value & unit, and exact source (document · sheet · cell)`}
                />
                <SectionToggle open={open.sources} onClick={() => toggle('sources')} />
              </div>
            </div>
            {open.sources && (
              <div style={{ overflowX: 'auto', marginTop: 20 }}>
                <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
                  <thead>
                    <tr style={{ borderBottom: '2px solid var(--line)' }}>
                      <th style={thStyle}>Item</th>
                      <th style={thStyle}>Year</th>
                      <th style={thStyle}>Context</th>
                      <th style={thStyle}>Reported value</th>
                      <th style={thStyle}>Document</th>
                      <th style={thStyle}>Sheet</th>
                      <th style={thStyle}>Cell / Page</th>
                    </tr>
                  </thead>
                  <tbody>
                    {(() => {
                      const obsSort = (a, b) => strixMetricName(a.metric_id).localeCompare(strixMetricName(b.metric_id)) || b.report_year - a.report_year;
                      const rows = [
                        ...[...groupObs].sort(obsSort).map(o => ({
                          key: srcKeyObs(o),
                          item: strixMetricName(o.metric_id),
                          year: o.report_year,
                          context: 'Group total',
                          value: o.value_original != null ? `${o.value_original} ${o.unit_original || ''}` : null,
                          doc: o.source_doc, sheet: o.source_sheet, cell: o.source_cell, page: o.source_page,
                        })),
                        ...targets.map(t => ({
                          key: srcKeyTarget(t),
                          item: t.expressed_as.length > 70 ? t.expressed_as.substring(0, 70) + '…' : t.expressed_as,
                          itemTitle: t.expressed_as,
                          year: t.target_year,
                          context: 'Target',
                          value: t.target_value != null ? `${t.target_value} ${t.target_unit || ''}` : null,
                          doc: t.source_doc, sheet: t.source_sheet, cell: t.source_cell, page: t.source_page,
                        })),
                        ...[...breakdownObs].sort(obsSort).map(o => ({
                          key: srcKeyObs(o),
                          item: strixMetricName(o.metric_id),
                          year: o.report_year,
                          context: formatDimType(o.dimension_type) + ': ' + (o.dimension_value || '').replace(/_/g, ' '),
                          value: o.value_original != null ? `${o.value_original} ${o.unit_original || ''}` : null,
                          doc: o.source_doc, sheet: o.source_sheet, cell: o.source_cell, page: o.source_page,
                        })),
                      ];
                      return rows.map((r, i) => {
                        const hl = highlightSrc && highlightSrc.key === r.key;
                        return (
                          <tr key={i} id={r.key}
                            style={{ borderBottom: '1px solid var(--line)', background: hl ? '#fff8e6' : 'transparent', transition: 'background 400ms var(--ease-quiet)' }}>
                            <td style={{ ...tdStyle, fontWeight: 500, color: 'var(--ink)' }} title={r.itemTitle}>{r.item}</td>
                            <td style={{ ...tdStyle, fontFamily: 'var(--mono)' }}>{r.year ?? '—'}</td>
                            <td style={{ ...tdStyle, fontSize: 12, color: 'var(--ink-3)', textTransform: 'capitalize', maxWidth: 130, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={r.context}>
                              {r.context}
                            </td>
                            <td style={{ ...tdStyle, fontFamily: 'var(--mono)', fontSize: 12, whiteSpace: 'nowrap' }}>
                              {r.value != null ? r.value : <NotReported />}
                            </td>
                            <td style={{ ...tdStyle, fontSize: 12, color: 'var(--ink-3)', maxWidth: 150, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={r.doc}>
                              {r.doc || <NotReported />}
                            </td>
                            <td style={{ ...tdStyle, fontSize: 12, color: 'var(--ink-3)', maxWidth: 110, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }} title={r.sheet}>
                              {r.sheet || '—'}
                            </td>
                            <td style={{ ...tdStyle, fontFamily: 'var(--mono)', fontSize: 12, whiteSpace: 'nowrap' }}>
                              {r.cell || (r.page != null ? `p.${r.page}` : '—')}
                            </td>
                          </tr>
                        );
                      });
                    })()}
                  </tbody>
                </table>
              </div>
            )}
          </div>
        </Reveal>

        {/* Back to top — portalled to <body> so no transformed ancestor can re-anchor the fixed position */}
        {showTop && ReactDOM.createPortal(
          <button onClick={() => window.scrollTo({ top: 0, behavior: 'smooth' })} title="Back to top"
            style={{
              position: 'fixed', bottom: 28, right: 28, zIndex: 900, width: 46, height: 46,
              borderRadius: 999, border: 'none', background: 'var(--ink)', color: 'var(--canvas)',
              cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
              boxShadow: '0 4px 16px rgba(0,0,0,0.22)',
            }}>
            <Icon name="arrow-left" size={18} style={{ transform: 'rotate(90deg)' }} />
          </button>,
          document.body
        )}
      </div>
    </section>
  );
};

const thStyle = { textAlign: 'left', padding: '8px 12px', fontSize: 11, color: 'var(--ink-3)', fontFamily: 'var(--mono)', letterSpacing: '0.06em', textTransform: 'uppercase', fontWeight: 500 };
const tdStyle = { padding: '10px 12px', fontSize: 13, color: 'var(--ink-2)', lineHeight: '18px', verticalAlign: 'top' };
const changeStyle = { background: '#fff8e6', fontWeight: 600, color: 'var(--ink)' };

window.MetricDeepDive = MetricDeepDive;
