/* Cellar + Analytics + About pages */

const { useState: usS, useMemo: usM } = React;

/* ============ CELLAR ============ */
function Cellar({ lang, data }) {
  const [selected, setSelected] = usS(null);
  const inStock = data.cellar.filter(c => c.quantity > 0);
  const thisYear = 2026;
  const groups = {
    now:  inStock.filter(c => +c.beginConsume <= thisYear && +c.endConsume >= thisYear && +c.endConsume < 9000),
    soon: inStock.filter(c => +c.beginConsume > thisYear && +c.beginConsume <= thisYear + 3),
    mid:  inStock.filter(c => +c.beginConsume > thisYear + 3 && +c.beginConsume <= thisYear + 8),
    long: inStock.filter(c => +c.beginConsume > thisYear + 8 || +c.endConsume >= 9000),
  };
  // bottles in groups['now'] but also any past-end (drink immediately) included
  const past = inStock.filter(c => +c.endConsume < thisYear && +c.endConsume < 9000);
  groups.now = [...groups.now, ...past];

  const titles = {
    now:  { en: 'Drinking now',  cn: '现在适饮', sub: { en: 'Open these. They are ready, or already on borrowed time.', cn: '现在就开。已经到点，或者已经过点。' } },
    soon: { en: 'Drinks soon',   cn: '即将适饮', sub: { en: 'Within three years. Patience is almost over.', cn: '三年之内。再等一等就好。' } },
    mid:  { en: 'Mid-term',      cn: '中期窖藏', sub: { en: 'A few years still. Forget for now.', cn: '还需几年。先放着。' } },
    long: { en: 'Long haul',     cn: '长期窖藏', sub: { en: 'Decade or more. For another version of me.', cn: '十年以上。留给以后那个我。' } },
  };

  return (
    <main className="container cellar-page">
      <div style={{display:'grid', gridTemplateColumns:'1fr auto', alignItems:'end', gap:32, paddingBottom:24, borderBottom:'1px solid var(--rule-strong)'}}>
        <div>
          <h1>The cellar.</h1>
          <div className="cn">{inStock.length} 瓶酒，等候时机。 · {inStock.length} bottles, waiting their turn.</div>
        </div>
        <div style={{fontFamily:'var(--mono)',fontSize:11,letterSpacing:'0.16em',color:'var(--muted)',textTransform:'uppercase'}}>
          Total value · ¥{Math.round(inStock.reduce((s,c)=>s+(c.value||0),0)).toLocaleString()}
        </div>
      </div>

      {['now','soon','mid','long'].map(g => groups[g].length > 0 && (
        <section key={g} className="cellar-band">
          <div className="cellar-band-h">
            <div className="cellar-band-h-l">
              <span className="cellar-band-title">{titles[g].en}</span>
              <span className="cellar-band-cn">· {titles[g].cn} — {titles[g].sub[lang==='cn'?'cn':'en']}</span>
            </div>
            <span className="cellar-band-count">{groups[g].length} bottles</span>
          </div>
          <div className="bottle-grid">
            {groups[g].map((b, i) => <BottleCard key={i} bottle={b} lang={lang} onClick={() => setSelected(b)} />)}
          </div>
        </section>
      ))}

      {selected && (
        <CellarModal bottle={selected} allNotes={data.tastingNotes} onClose={() => setSelected(null)} lang={lang} />
      )}
    </main>
  );
}

function BottleCard({ bottle, lang, onClick }) {
  const accentByVarietal = {
    'Sangiovese': 'var(--wine)',
    'Red Bordeaux Blend': 'var(--wine)',
    'Pinot Noir': '#a3354a',
    'Cabernet Sauvignon': '#5a1722',
    'Nebbiolo': '#7d2030',
    'Chardonnay': 'var(--cream)',
    'Trebbiano d\'Abruzzo': 'var(--cream)',
    'Sémillon-Sauvignon Blanc Blend': 'var(--gold)',
  };
  const accent = accentByVarietal[bottle.varietal] || 'var(--wine)';
  return (
    <div className="bottle" role="button" tabIndex={0} onClick={onClick}
         onKeyDown={(e)=>{ if(e.key==='Enter' || e.key===' '){ e.preventDefault(); onClick(); } }}>
      <BottleSVG className="bottle-svg" accent={accent} />
      <div className="bottle-yr">{bottle.vintage}</div>
      <div className="bottle-name">{bottle.wine}</div>
      <div className="bottle-region">{window.fmt.region(bottle.locale, 'en')}</div>
      <div className="bottle-foot">
        <span>{bottle.beginConsume}–{+bottle.endConsume >= 9000 ? '∞' : bottle.endConsume}</span>
        <span className="price">{window.fmt.cny(bottle.value)}</span>
      </div>
    </div>
  );
}

/* ============ CELLAR MODAL ============ */
function CellarModal({ bottle, allNotes, onClose, lang }) {
  // ESC + lock body scroll
  React.useEffect(() => {
    const onKey = (e) => { if (e.key === 'Escape') onClose(); };
    document.addEventListener('keydown', onKey);
    const prevOverflow = document.body.style.overflow;
    document.body.style.overflow = 'hidden';
    return () => {
      document.removeEventListener('keydown', onKey);
      document.body.style.overflow = prevOverflow;
    };
  }, [onClose]);

  const thisYear = 2026;
  const begin = +bottle.beginConsume;
  const end = +bottle.endConsume;
  const age = thisYear - +bottle.vintage;

  // When-to-drink suggestion
  let when;
  if (end < thisYear && end < 9000) {
    when = { en: 'Past peak — open soon, before it slips.', cn: '已过适饮期 —— 尽快开，别再等了。' };
  } else if (begin > thisYear + 5) {
    when = { en: `Hold ${begin - thisYear} more years. Not even close.`, cn: `再等 ${begin - thisYear} 年。还差得远。` };
  } else if (begin > thisYear) {
    when = { en: `${begin - thisYear} more year${begin - thisYear > 1 ? 's' : ''} for the prime window.`, cn: `再等 ${begin - thisYear} 年进入最佳窗口。` };
  } else if (end - thisYear <= 2 && end < 9000) {
    when = { en: 'In the closing window. Open within a year or two.', cn: '正处于尾段。一两年内开掉。' };
  } else {
    when = { en: 'Squarely in window. Open whenever.', cn: '正适饮。随时可开。' };
  }

  // Decant + serve advice (heuristic by varietal × age)
  const v = bottle.varietal || '';
  let how;
  if (bottle.category === 'Sparkling' || /Champagne/i.test(v)) {
    how = { en: 'Serve at 8–10 °C. Tulip glass, not flute. No decant.', cn: '8–10 °C 冰镇。郁金香杯，不要笛形杯。无需醒酒。' };
  } else if (bottle.color === 'White') {
    how = { en: 'Chill to 10–12 °C. Bring out 15 min before. No decant.', cn: '10–12 °C 冰镇。开瓶前 15 分钟取出。无需醒酒。' };
  } else if (age >= 25) {
    how = { en: 'Stand upright 24h. Decant gently — sediment is real. 20–30 min.', cn: '提前 24 小时立瓶。轻柔醒酒 —— 有酒泥。20–30 分钟。' };
  } else if (age >= 12 && /(Bordeaux|Cabernet|Sangiovese|Nebbiolo)/i.test(v)) {
    how = { en: 'Decant 1 hour. 16–18 °C in glass.', cn: '醒酒 1 小时。杯中 16–18 °C 饮用。' };
  } else if (/(Pinot Noir|Nebbiolo)/i.test(v)) {
    how = { en: '30 min in the glass is enough. 14–16 °C.', cn: '杯醒 30 分钟即可。14–16 °C。' };
  } else if (age <= 4 && /(Bordeaux|Cabernet|Sangiovese)/i.test(v)) {
    how = { en: 'Aggressive decant 2+ hours — it needs air.', cn: '强醒 2 小时以上 —— 它需要空气。' };
  } else {
    how = { en: 'Decant 1 hour before serving. 16–18 °C.', cn: '饮前醒酒 1 小时。16–18 °C。' };
  }

  // User's own previous tasting note (if any)
  const myNote = allNotes.find(n => n.wine === bottle.wine && n.vintage === bottle.vintage);

  // Critic database lookup
  const critics = (window.WINE_CRITICS || {})[bottle.wine + '|' + bottle.vintage];
  const appellation = critics?.appellation;
  const blend = critics?.blend;

  const showBoth = lang === 'both';
  const txt = (obj) => showBoth ? null : (lang === 'cn' ? obj.cn : obj.en);

  return (
    <div className="modal-overlay" onClick={onClose} role="dialog" aria-modal="true">
      <div className="modal-card" onClick={(e) => e.stopPropagation()}>
        <button className="modal-close" onClick={onClose} aria-label="Close">×</button>

        <div className="modal-meta">{window.fmt.region(bottle.locale, 'en')}</div>
        <div className="modal-vintage">{bottle.vintage}</div>
        <div className="modal-wine">{bottle.wine}</div>
        <div className="modal-producer">{bottle.producer}</div>

        {(appellation || blend) && (
          <div className="modal-spec">
            {appellation && (
              <div className="modal-spec-row">
                <span className="modal-spec-lbl">Appellation · 产区</span>
                <span className="modal-spec-val">{appellation}</span>
              </div>
            )}
            {blend && blend.length > 0 && (
              <div className="modal-spec-row">
                <span className="modal-spec-lbl">{blend.length === 1 ? 'Grape · 品种' : 'Blend · 混酿'}</span>
                <span className="modal-spec-val">
                  {blend.length === 1 ? (
                    <span>{blend[0].grape}{blend[0].pct < 100 ? ` ${blend[0].pct}%` : ''}</span>
                  ) : (
                    <span className="modal-blend-list">
                      {blend.map((g, i) => (
                        <span key={i} className="modal-blend-item">
                          <span className="modal-blend-grape">{g.grape}</span>
                          <span className="modal-blend-pct">{g.pct}%</span>
                        </span>
                      ))}
                    </span>
                  )}
                </span>
              </div>
            )}
          </div>
        )}

        <div className="modal-grid">
          <div className="modal-stat">
            <div className="modal-stat-lbl">Window · 适饮</div>
            <div className="modal-stat-val">{bottle.beginConsume}–{end >= 9000 ? '∞' : end}</div>
          </div>
          <div className="modal-stat">
            <div className="modal-stat-lbl">Community · 群体</div>
            <div className="modal-stat-val">{bottle.cScore || '—'}<span className="small">/100</span></div>
          </div>
          <div className="modal-stat">
            <div className="modal-stat-lbl">Paid · 入价</div>
            <div className="modal-stat-val">{window.fmt.cny(bottle.price)}</div>
          </div>
          <div className="modal-stat">
            <div className="modal-stat-lbl">Now valued · 估值</div>
            <div className="modal-stat-val">{window.fmt.cny(bottle.value)}</div>
          </div>
        </div>

        <div className="modal-section">
          <div className="modal-section-h">Suggestion · 建议</div>
          <div className="modal-row">
            <span className="modal-row-lbl">When</span>
            <span>
              {showBoth ? <><span>{when.en}</span><span className="modal-row-cn">{when.cn}</span></> : txt(when)}
            </span>
          </div>
          <div className="modal-row">
            <span className="modal-row-lbl">How</span>
            <span>
              {showBoth ? <><span>{how.en}</span><span className="modal-row-cn">{how.cn}</span></> : txt(how)}
            </span>
          </div>
        </div>

        {myNote && (
          <div className="modal-section">
            <div className="modal-section-h">My own note · 我喝过</div>
            <div className="modal-mynote">
              <span className="modal-mynote-date">{window.fmt.longDate(myNote.tastingDate, 'en')}</span>
              {myNote.notes ? <span className="modal-mynote-text">"{myNote.notes}"</span> : <span className="modal-mynote-text" style={{color:'var(--muted)'}}>(No note written.)</span>}
              {myNote.rating > 0 && <span className="modal-mynote-rating">{myNote.rating}/100</span>}
            </div>
          </div>
        )}

        <div className="modal-section">
          <div className="modal-section-h">Critic · 酒评人</div>
          {critics ? (
            <>
              {critics.take && (
                <div className="modal-critic-take">
                  {showBoth ? (
                    <><div>{critics.take.en}</div><div className="modal-row-cn" style={{marginTop:8}}>{critics.take.cn}</div></>
                  ) : (lang === 'cn' ? critics.take.cn : critics.take.en)}
                </div>
              )}
              {critics.scores && critics.scores.length > 0 && (
                <div className="modal-critic-scores">
                  {critics.scores.map((s, i) => (
                    <div key={i} className="modal-critic-score">
                      <span>{s.critic}{s.year ? ` · ${s.year}` : ''}</span>
                      <b>{s.value}/100</b>
                    </div>
                  ))}
                </div>
              )}
            </>
          ) : (
            <div className="modal-critic-empty">
              <span>No curated review yet — the cellar's keeping its secrets.</span>
              <a href={`https://www.cellartracker.com/list.asp?Q=${encodeURIComponent(bottle.vintage + ' ' + bottle.wine)}`} target="_blank" rel="noopener noreferrer">Search CellarTracker →</a>
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

/* ============ ANALYTICS ============ */
function Analytics({ lang, data }) {
  const inStock = data.cellar.filter(c => c.quantity > 0);
  const totalSpend = data.purchases.reduce((s,p) => s + (p.price || 0), 0);
  const totalBottles = data.purchases.reduce((s,p) => s + (p.quantity || 0), 0);

  // Held-time analysis: median days between purchase and consume per wine+vintage
  const heldDays = usM(() => {
    const days = [];
    data.consumed.forEach(c => {
      const purchase = data.purchases.find(p => p.wine === c.wine && p.vintage === c.vintage);
      if (purchase) {
        const dp = window.fmt.parseDate(purchase.date);
        const dc = window.fmt.parseDate(c.date);
        if (dp && dc) days.push((dc - dp) / (1000*60*60*24));
      }
    });
    days.sort((a,b)=>a-b);
    return days;
  }, [data]);
  const median = heldDays.length ? Math.round(heldDays[Math.floor(heldDays.length/2)]) : 0;
  const meanDays = heldDays.length ? Math.round(heldDays.reduce((s,d)=>s+d,0)/heldDays.length) : 0;

  // Region by bottles + spend
  const regions = usM(() => {
    const m = {};
    [...data.cellar.filter(c=>c.quantity>0), ...data.consumed].forEach(r => {
      const key = (r.locale||'').split(',')[0].trim() + ' · ' + ((r.locale||'').split(',')[1]||'').trim();
      if (!m[key]) m[key] = { bottles: 0, spend: 0, name: key };
      m[key].bottles += 1;
      m[key].spend += (r.value || r.price || 0);
    });
    return Object.values(m).sort((a,b)=>b.bottles-a.bottles).slice(0, 10);
  }, [data]);

  // Year distribution
  const yearDist = usM(() => {
    const m = {};
    [...data.cellar.filter(c=>c.quantity>0), ...data.consumed].forEach(r => {
      if (!r.vintage) return;
      m[r.vintage] = (m[r.vintage] || 0) + 1;
    });
    const years = Object.keys(m).map(y => ({ year: y, count: m[y] })).sort((a,b)=> +a.year - +b.year);
    return years;
  }, [data]);

  // Top spend
  const topSpend = usM(() => [...data.consumed].filter(c=>c.value).sort((a,b)=>b.value-a.value).slice(0, 8), [data]);
  // Repeat producers
  const repeats = usM(() => {
    const m = {};
    [...data.consumed, ...data.purchases].forEach(r => {
      if (!r.producer) return;
      m[r.producer] = (m[r.producer] || 0) + 1;
    });
    return Object.entries(m).filter(([,c])=>c>=2).map(([p,c])=>({producer:p,count:c})).sort((a,b)=>b.count-a.count).slice(0, 8);
  }, [data]);

  // Judgment delta - your rating vs community
  const judgment = usM(() => {
    return data.tastingNotes
      .filter(n => n.rating && n.cScore)
      .map(n => ({ ...n, delta: n.rating - n.cScore }))
      .sort((a,b) => Math.abs(b.delta) - Math.abs(a.delta))
      .slice(0, 8);
  }, [data]);

  // Price vs Rating scatter — featured chart
  const scatter = usM(() => {
    const items = [];
    data.tastingNotes.forEach(n => {
      if (!n.rating) return;
      const purchase = data.purchases.find(p => p.wine === n.wine && p.vintage === n.vintage);
      const price = purchase?.price || data.consumed.find(c => c.wine === n.wine && c.vintage === n.vintage)?.price;
      if (!price) return;
      const country = (n.locale || '').split(',')[0].trim();
      items.push({ id: n.id, wine: n.wine, vintage: n.vintage, rating: n.rating, price, country, loved: n.fLikeIt });
    });
    return items;
  }, [data]);

  const COUNTRY_COLOR = {
    'France': '#8b1e2d',
    'Italy': '#c89b4a',
    'United States': '#3a6b8a',
    'China': '#2d6b3a',
    'Spain': '#c44e1f',
  };
  const countriesInScatter = [...new Set(scatter.map(p => p.country))];

  const maxBottles = Math.max(...regions.map(r => r.bottles), 1);
  const maxYearCount = Math.max(...yearDist.map(y => y.count), 1);

  // Scatter plot dimensions
  const sw = 880, sh = 460, sm = { t: 24, r: 32, b: 56, l: 64 };
  const minPrice = Math.min(...scatter.map(p=>p.price), 100);
  const maxPrice = Math.max(...scatter.map(p=>p.price), 1000);
  // log scale for price
  const px = (p) => sm.l + (Math.log10(p) - Math.log10(minPrice)) / (Math.log10(maxPrice) - Math.log10(minPrice)) * (sw - sm.l - sm.r);
  const py = (r) => sm.t + (100 - r) / 18 * (sh - sm.t - sm.b);  // 82-100 range
  const priceTicks = [200, 500, 1000, 2000, 5000, 10000].filter(p => p >= minPrice * 0.9 && p <= maxPrice * 1.1);
  const ratingTicks = [85, 88, 91, 94, 97, 100];

  // Smart observation
  const obs = usM(() => {
    if (!scatter.length) return null;
    const avgPrice = scatter.reduce((s,p) => s+p.price, 0) / scatter.length;
    const cheapHigh = scatter.filter(p => p.price < avgPrice * 0.6 && p.rating >= 92);
    const expensiveLow = scatter.filter(p => p.price > avgPrice * 1.5 && p.rating < 90);
    const sweetSpot = scatter.filter(p => p.price >= 500 && p.price <= 1500 && p.rating >= 91);
    return { avgPrice, cheapHigh, expensiveLow, sweetSpot };
  }, [scatter]);

  return (
    <main className="container an-page">
      <h1>By the numbers.</h1>
      <div className="cn">数据里的我 — 一年的买与喝，到底是什么样子。</div>

      {/* FEATURED CHART — price vs rating */}
      {scatter.length > 0 && (
        <section className="featured-chart">
          <div className="fc-head">
            <div className="fc-eyebrow">
              <span>What I paid · what I felt</span>
              <span className="cn">· 价格与喜爱</span>
            </div>
            <div className="fc-legend">
              {countriesInScatter.map(c => (
                <span key={c} className="fc-legend-item">
                  <span className="fc-dot" style={{background: COUNTRY_COLOR[c] || '#888'}}></span>
                  {c}
                </span>
              ))}
            </div>
          </div>
          <div className="fc-svg-wrap">
            <svg viewBox={`0 0 ${sw} ${sh}`} className="fc-svg" preserveAspectRatio="xMidYMid meet">
              {/* axes */}
              <line x1={sm.l} x2={sw - sm.r} y1={sh - sm.b} y2={sh - sm.b} stroke="var(--rule)" />
              <line x1={sm.l} x2={sm.l} y1={sm.t} y2={sh - sm.b} stroke="var(--rule)" />
              {/* x ticks (price) */}
              {priceTicks.map(p => (
                <g key={p}>
                  <line x1={px(p)} x2={px(p)} y1={sm.t} y2={sh - sm.b} stroke="var(--rule)" strokeDasharray="2 4" opacity="0.5" />
                  <text x={px(p)} y={sh - sm.b + 22} textAnchor="middle" className="fc-tick">¥{p >= 1000 ? (p/1000)+'K' : p}</text>
                </g>
              ))}
              {/* y ticks (rating) */}
              {ratingTicks.map(r => (
                <g key={r}>
                  <line x1={sm.l} x2={sw - sm.r} y1={py(r)} y2={py(r)} stroke="var(--rule)" strokeDasharray="2 4" opacity="0.5" />
                  <text x={sm.l - 12} y={py(r) + 4} textAnchor="end" className="fc-tick">{r}</text>
                </g>
              ))}
              {/* axis labels */}
              <text x={sw/2} y={sh - 6} textAnchor="middle" className="fc-axis-lbl">Price paid (log scale, CNY)</text>
              <text x={16} y={sh/2} textAnchor="middle" transform={`rotate(-90 16 ${sh/2})`} className="fc-axis-lbl">My rating</text>
              {/* points */}
              {scatter.map(p => (
                <a key={p.id} href={`#/note/${p.id}`}>
                  <circle
                    cx={px(p.price)} cy={py(p.rating)}
                    r={p.loved ? 8 : 6}
                    fill={COUNTRY_COLOR[p.country] || '#888'}
                    fillOpacity={p.loved ? 0.95 : 0.7}
                    stroke="var(--paper)"
                    strokeWidth="1.5"
                    className="fc-point">
                    <title>{p.vintage} {p.wine} — ¥{p.price.toLocaleString()} · {p.rating}/100{p.loved ? ' ♡' : ''}</title>
                  </circle>
                </a>
              ))}
            </svg>
          </div>
          {obs && (
            <div className="fc-observation">
              <p className="fc-obs-en">
                Across {scatter.length} bottles I both paid for and rated, the average price was{' '}
                ¥{Math.round(obs.avgPrice).toLocaleString()}. {obs.cheapHigh.length > 0 && (
                  <>{obs.cheapHigh.length} bottles came in under ¥{Math.round(obs.avgPrice*0.6).toLocaleString()}{' '}
                  and still hit 92+ — these are the ones I'd buy again without hesitation.{' '}</>
                )}
                {obs.expensiveLow.length > 0 && (
                  <>{obs.expensiveLow.length} bottle{obs.expensiveLow.length > 1 ? 's' : ''} cost north of{' '}
                  ¥{Math.round(obs.avgPrice*1.5).toLocaleString()} but didn't crack 90 — a quiet reminder that price isn't a promise. </>
                )}
                {obs.sweetSpot.length >= 2 && (
                  <>The sweet spot, for me, sits between ¥500 and ¥1,500 — that's where{' '}
                  {obs.sweetSpot.length} of my favourites live.</>
                )}
              </p>
              <p className="fc-obs-cn">
                {scatter.length} 瓶我自己买、自己评的酒里，均价 ¥{Math.round(obs.avgPrice).toLocaleString()}。
                {obs.cheapHigh.length > 0 && `${obs.cheapHigh.length} 瓶在均价六折以下却打到 92 分以上 — 这些是会再买的。`}
                {obs.expensiveLow.length > 0 && ` ${obs.expensiveLow.length} 瓶花了均价的 1.5 倍以上却没破 90 — 提醒自己价钱不是承诺。`}
                {obs.sweetSpot.length >= 2 && ` 我的甜蜜点在 ¥500–1,500 之间，这里住着 ${obs.sweetSpot.length} 瓶最爱。`}
              </p>
            </div>
          )}
        </section>
      )}

      <div className="kpi-row">
        <div className="kpi">
          <div className="kpi-num">{totalBottles}</div>
          <div className="kpi-lbl">Bottles bought</div>
          <div className="kpi-cn">购入瓶数</div>
        </div>
        <div className="kpi">
          <div className="kpi-num">¥{(totalSpend/1000).toFixed(0)}<span className="unit">K</span></div>
          <div className="kpi-lbl">Total spend</div>
          <div className="kpi-cn">累计花费</div>
        </div>
        <div className="kpi">
          <div className="kpi-num">{median}<span className="unit">DAYS</span></div>
          <div className="kpi-lbl">Median time held</div>
          <div className="kpi-cn">持有时长中位数 — 哎</div>
        </div>
        <div className="kpi">
          <div className="kpi-num">{regions.length}<span className="unit">+</span></div>
          <div className="kpi-lbl">Regions</div>
          <div className="kpi-cn">涉猎产区</div>
        </div>
      </div>

      {/* Held time anecdote */}
      <section className="an-block">
        <div className="an-block-h">
          <div>
            <span className="an-block-title">How long do I actually hold them?</span>
            <span className="an-block-cn">瓶子在我手里活多久？</span>
          </div>
          <span className="an-block-quip">A cellar, in theory.</span>
        </div>
        <div className="lifespan-vis">
          <div className="life-row">
            <div>
              <div className="life-label">Median (purchase → consume)  ·  中位数</div>
              <div className="life-bar"><div className="life-bar-fill" style={{width: `${Math.min(100, median/365*100)}%`}}></div></div>
            </div>
            <div className="life-num">{median}<span style={{fontSize:11,fontFamily:'var(--mono)',fontStyle:'normal',color:'var(--muted)',marginLeft:6}}>days</span></div>
          </div>
          <div className="life-row">
            <div>
              <div className="life-label">Mean  ·  平均</div>
              <div className="life-bar"><div className="life-bar-fill" style={{width: `${Math.min(100, meanDays/365*100)}%`, background:'var(--cream)', opacity:.7}}></div></div>
            </div>
            <div className="life-num">{meanDays}<span style={{fontSize:11,fontFamily:'var(--mono)',fontStyle:'normal',color:'var(--muted)',marginLeft:6}}>days</span></div>
          </div>
        </div>
        <div style={{fontFamily:'var(--serif-en)', fontStyle:'italic', fontSize:18, color:'var(--muted)', marginTop:18, lineHeight:1.5}}>
          The wines spend, on average, about as long in my house as a houseplant before it dies of love.
        </div>
      </section>

      {/* Regions */}
      <section className="an-block">
        <div className="an-block-h">
          <div>
            <span className="an-block-title">Regional map</span>
            <span className="an-block-cn">产区版图</span>
          </div>
          <span className="an-block-quip">By bottles owned + drunk</span>
        </div>
        <div className="region-table">
          {regions.map(r => (
            <div key={r.name} className="region-row">
              <div>
                <div className="region-name">{r.name}</div>
              </div>
              <div className="region-bar"><div className="region-bar-fill" style={{width: `${r.bottles/maxBottles*100}%`}}></div></div>
              <div className="region-bottles">{r.bottles} btl</div>
              <div className="region-spend">¥{Math.round(r.spend).toLocaleString()}</div>
            </div>
          ))}
        </div>
      </section>

      {/* Year distribution */}
      <section className="an-block">
        <div className="an-block-h">
          <div>
            <span className="an-block-title">Vintage spread</span>
            <span className="an-block-cn">年份分布</span>
          </div>
          <span className="an-block-quip">{yearDist[0]?.year} → {yearDist[yearDist.length-1]?.year}</span>
        </div>
        <div className="year-bars" style={{gridTemplateColumns: `repeat(${yearDist.length}, 1fr)`}}>
          {yearDist.map(y => (
            <div key={y.year} className="year-bar" style={{height: `${y.count/maxYearCount*100}%`}} title={`${y.year} — ${y.count} bottles`}>
              {(yearDist.length <= 30 || +y.year % 5 === 0) && <span className="yr-lbl">{y.year.toString().slice(-2)}</span>}
            </div>
          ))}
        </div>
        <div className="year-bars-meta">
          <span>Oldest · {yearDist[0]?.year}</span>
          <span>{yearDist.reduce((s,y)=>s+y.count,0)} bottles total</span>
          <span>Newest · {yearDist[yearDist.length-1]?.year}</span>
        </div>
      </section>

      {/* Top spend + repeat producers */}
      <section className="an-block">
        <div className="an-block-h">
          <div>
            <span className="an-block-title">Heaviest pours · 真爱回购</span>
          </div>
          <span className="an-block-quip">Top spend / repeat producers</span>
        </div>
        <div className="top-list">
          <div>
            <div className="article-col-h">Top 8 by spend · 重磅消费</div>
            {topSpend.map((c, i) => (
              <div key={i} className="top-item">
                <span className={`top-item-rank ${i<3?'gold':''}`}>{(i+1).toString().padStart(2,'0')}</span>
                <span>
                  <span className="top-item-name">{c.vintage} {c.wine}</span>
                  <div className="top-item-meta">{window.fmt.region(c.locale, 'en')}</div>
                </span>
                <span className="top-item-val">¥{Math.round(c.value).toLocaleString()}</span>
              </div>
            ))}
          </div>
          <div>
            <div className="article-col-h">Repeat producers · 真爱酒庄</div>
            {repeats.map((r, i) => (
              <div key={i} className="top-item">
                <span className={`top-item-rank ${i<3?'gold':''}`}>{(i+1).toString().padStart(2,'0')}</span>
                <span><span className="top-item-name">{r.producer}</span></span>
                <span className="top-item-val">×{r.count}</span>
              </div>
            ))}
          </div>
        </div>
      </section>

      {/* Judgment delta */}
      <section className="an-block">
        <div className="an-block-h">
          <div>
            <span className="an-block-title">My ear vs the chorus</span>
            <span className="an-block-cn">个人评分 vs 群体评分</span>
          </div>
          <span className="an-block-quip">Where I disagreed most</span>
        </div>
        <div className="judgment-grid">
          {judgment.map(n => {
            const a = Math.min(n.rating, n.cScore);
            const b = Math.max(n.rating, n.cScore);
            const left = ((a - 84) / 14) * 100;
            const right = ((b - 84) / 14) * 100;
            return (
              <div key={n.id} className="judgment-row">
                <span className="theirs">{n.cScore.toFixed(1)}</span>
                <div className="judgment-track">
                  <div className="axis"></div>
                  <div className="delta-line" style={{left:`${left}%`, width:`${right-left}%`}}></div>
                  <div className="pin them" style={{left:`${((n.cScore-84)/14)*100}%`}}></div>
                  <div className="pin you" style={{left:`${((n.rating-84)/14)*100}%`}}></div>
                </div>
                <span className="yours">{n.rating}</span>
                <span style={{gridColumn:'1/-1', fontFamily:'var(--serif-en)', fontStyle:'italic', fontSize:14, color:'var(--muted)', paddingLeft:80, marginTop:-4}}>
                  {n.vintage} {n.wine} <span style={{fontFamily:'var(--mono)', fontStyle:'normal', fontSize:10, marginLeft:8, color: n.delta>0?'var(--moss)':'var(--wine-fg)'}}>
                    {n.delta>0?'+':''}{n.delta.toFixed(1)}
                  </span>
                </span>
              </div>
            );
          })}
        </div>
        <div style={{fontFamily:'var(--mono)', fontSize:11, letterSpacing:'0.1em', color:'var(--muted)', marginTop:18, display:'flex', gap:24}}>
          <span><span style={{display:'inline-block',width:10,height:10,borderRadius:'50%',background:'var(--wine-fg)',verticalAlign:'middle',marginRight:8}}></span>MY RATING</span>
          <span><span style={{display:'inline-block',width:10,height:10,borderRadius:'50%',background:'var(--cream)',verticalAlign:'middle',marginRight:8,border:'1px solid var(--muted-2)'}}></span>COMMUNITY</span>
        </div>
      </section>
    </main>
  );
}

/* ============ ABOUT ============ */
function About({ lang }) {
  return (
    <main className="container about-page">
      <div className="about-grid">
        <div>
          <image-slot
            id="about-portrait"
            class="img-about-portrait"
            style={{width:'220px',height:'280px',display:'block',marginBottom:'32px'}}
            shape="rect"
            placeholder="Portrait · 一张你的照片或剪影"
          ></image-slot>
          <h1><em>About<br/>this notebook.</em></h1>
          <div className="cn-h">关于这本笔记。</div>
          <div className="creed">
            <div className="creed-h">A few rules of thumb · 几条规矩</div>
            <ul className="creed-list">
              <li>If I'm disappointed, I write disappointed.</li>
              <li>Wine is not a personality trait.</li>
              <li>The best bottle is the one with someone you like across the table.</li>
              <li>Old wine is not automatically good wine.</li>
              <li>Decant. Or don't. The bottle decides.</li>
            </ul>
          </div>
        </div>
        <div>
          <div className="article-col-h"><span>Why this exists</span><span style={{color:'var(--wine-fg)'}}>EN</span></div>
          <div className="about-body-en">
            <p>This is a personal log. Not a magazine, not a database. There is no SEO here. There is no shop. If you found this, you probably know me, and probably already opened something good last weekend.</p>
            <p>I started keeping notes because I kept forgetting which Brunello was the one I loved and which one I had to apologize for. Then it became something else: a way to pay attention. A way to slow down a Tuesday.</p>
            <p>The notes are bilingual when I had the patience to write them that way, and bilingual when I didn't but the translator did. The English half is sometimes blunt; the Chinese half is sometimes long-winded. Both are mine.</p>
            <p>Numbers are kept honestly. The cellar is small. The median time a bottle survives in my house is, frankly, embarrassing. That's a feature.</p>
          </div>

          <div style={{height:32}} />
          <div className="article-col-h"><span>为什么有这个网站</span><span style={{color:'var(--wine-fg)'}}>中</span></div>
          <div className="about-body-cn">
            <p>这是一本私人笔记。不是杂志，不是数据库，也没有什么 SEO。如果你能看到这里，多半是我认识的人，多半上个周末也开了什么好东西。</p>
            <p>开始记笔记，是因为我老是记不清 — 上次让我惊艳的那瓶 Brunello，到底是哪一瓶；让我尴尬不已的，又是哪一瓶。后来它变成了别的：一种留意的方式，一种把周二的晚上放慢的方式。</p>
            <p>有耐心的时候，笔记是中英双语写的；没耐心的时候，是后来翻成双语的。英文那边偶尔很直；中文这边偶尔啰嗦。都是我。</p>
            <p>数字是诚实的。酒柜不大。一瓶酒在我家的中位生存时间，老实讲，挺尴尬的。这是特点不是 bug。</p>
          </div>
        </div>
      </div>
    </main>
  );
}

/* ============ ARTICLES ============ */

// Lightweight markdown-lite → React: ## heading, > quote, - bullet, *italic*
function renderArticleBody(text, lang) {
  const blocks = text.split(/\n\n+/);
  return blocks.map((raw, i) => {
    const block = raw.trim();
    if (!block) return null;

    // ## Heading
    if (block.startsWith('## ')) {
      return <h3 key={i} className="article-h">{block.slice(3)}</h3>;
    }
    // > Block quote
    if (block.startsWith('> ')) {
      // Could have multiple > lines collapsed here, keep simple: each block = 1 quote para
      return <blockquote key={i} className="article-quote">{block.replace(/^>\s?/gm, '')}</blockquote>;
    }
    // - List
    if (block.startsWith('- ')) {
      const items = block.split('\n').filter(l => l.startsWith('- ')).map(l => l.slice(2));
      return (
        <ul key={i} className="article-list">
          {items.map((it, j) => <li key={j}>{renderInline(it)}</li>)}
        </ul>
      );
    }
    // Paragraph
    return <p key={i}>{renderInline(block)}</p>;
  });
}

// Inline emphasis: **bold** and *italic*
function renderInline(text) {
  // tokenize roughly with split
  const out = [];
  let rest = text;
  let key = 0;
  // **bold** first (greedy non-overlapping)
  const re = /(\*\*([^*]+)\*\*|\*([^*\n]+)\*)/g;
  let last = 0;
  let m;
  while ((m = re.exec(text)) !== null) {
    if (m.index > last) out.push(text.slice(last, m.index));
    if (m[2]) out.push(<strong key={key++}>{m[2]}</strong>);
    else if (m[3]) out.push(<em key={key++}>{m[3]}</em>);
    last = m.index + m[0].length;
  }
  if (last < text.length) out.push(text.slice(last));
  return out.length === 0 ? text : out;
}

function ArticlesList({ lang, articles }) {
  return (
    <main className="container articles-page">
      <div className="tn-head">
        <div>
          <h1>{lang === 'cn' ? '札记。' : 'Reading.'}</h1>
          <div className="cn">{lang === 'cn' ? '从酒柜的书架上抄下来的笔记。' : 'Notes from the cellar shelf.'}</div>
        </div>
        <div className="tn-count">{articles.length} {articles.length === 1 ? 'piece' : 'pieces'}</div>
      </div>

      <div className="articles-grid">
        {articles.map((a, i) => (
          <a key={a.slug} href={`#/article/${a.slug}`} className="article-card">
            <div className="article-card-eyebrow">
              {lang === 'cn' ? a.eyebrow.cn : a.eyebrow.en}
              <span style={{margin:'0 8px',color:'var(--muted-2)'}}>·</span>
              <span>{a.readMins} min read</span>
            </div>
            <div className="article-card-title">{lang === 'cn' ? a.title.cn : a.title.en}</div>
            <div className="article-card-sub">{lang === 'cn' ? a.subtitle.cn : a.subtitle.en}</div>
            <div className="article-card-excerpt">{lang === 'cn' ? a.excerpt.cn : a.excerpt.en}</div>
            <div className="article-card-foot">
              <span>{window.fmt.longDate(a.publishDate, lang === 'cn' ? 'cn' : 'en')}</span>
              <span className="article-card-arrow">Read →</span>
            </div>
          </a>
        ))}
        {articles.length === 0 && (
          <div style={{padding:'80px 0', textAlign:'center', color:'var(--muted)', fontFamily:'var(--serif-en)', fontStyle:'italic', fontSize:22}}>
            Nothing on the shelf yet.
          </div>
        )}
      </div>
    </main>
  );
}

function findNotesMentionedInArticle(article, notes) {
  if (!notes || !notes.length) return [];
  const haystack = (article.body?.en || '') + ' ' + (article.body?.cn || '') + ' ' +
                   (article.subtitle?.en || '') + ' ' + (article.subtitle?.cn || '') + ' ' +
                   (article.title?.en || '') + ' ' + (article.title?.cn || '');
  const matches = [];
  for (const n of notes) {
    const candidates = new Set();
    if (n.wine) candidates.add(n.wine);
    if (n.producer) {
      candidates.add(n.producer);
      const stripped = n.producer.replace(/^(Château|Ch\.|Domaine|Tenuta|Castello|Bodegas|Marchese|Marchesi)\s+/i, '');
      if (stripped !== n.producer) candidates.add(stripped);
    }
    (n.wine || '').split(/[\s,]+/).forEach(t => {
      if (t.length >= 5 && /^[A-Z]/.test(t) && !['Château','Brunello','Riserva','Chianti','Cuvée','Grand','Vintage','Reserve'].includes(t)) {
        candidates.add(t);
      }
    });
    if ([...candidates].some(c => haystack.includes(c))) matches.push(n);
  }
  // dedupe by wine|vintage and limit
  const seen = new Set();
  return matches.filter(n => {
    const k = n.wine + '|' + n.vintage;
    if (seen.has(k)) return false;
    seen.add(k);
    return true;
  }).slice(0, 8);
}

function ArticleDetail({ slug, lang, articles, data }) {
  const idx = articles.findIndex(a => a.slug === slug);
  const a = articles[idx];
  if (!a) return <main className="container" style={{padding:'120px 0'}}><div className="display" style={{fontSize:48}}>Article not found.</div></main>;

  const prev = articles[idx - 1];
  const next = articles[idx + 1];
  const mentionedNotes = React.useMemo(
    () => findNotesMentionedInArticle(a, data?.tastingNotes || []),
    [a, data]
  );

  const showBoth = lang === 'both';

  const title    = lang === 'cn' ? a.title.cn    : a.title.en;
  const subtitle = lang === 'cn' ? a.subtitle.cn : a.subtitle.en;
  const eyebrow  = lang === 'cn' ? a.eyebrow.cn  : a.eyebrow.en;
  const body     = lang === 'cn' ? a.body.cn     : a.body.en;

  return (
    <main className="container article-page">
      <a href="#/articles" className="detail-back">← {lang === 'cn' ? '返回札记' : 'Back to reading'}</a>

      <div className="article-head">
        <div className="article-eyebrow">{eyebrow}</div>
        <h1 className="article-title">{title}</h1>
        <div className="article-subtitle">{subtitle}</div>
        <div className="article-meta">
          <span>{window.fmt.longDate(a.publishDate, lang === 'cn' ? 'cn' : 'en')}</span>
          <span style={{margin:'0 12px',color:'var(--muted-2)'}}>·</span>
          <span>{a.readMins} {lang === 'cn' ? '分钟读完' : 'min read'}</span>
        </div>
      </div>

      <image-slot
        id={`article-hero-${a.slug}`}
        class="img-article-hero"
        style={{width:'100%',height:'420px',display:'block',margin:'40px 0 56px'}}
        shape="rect"
        placeholder="Hero image · 文章主图（产区、酒庄或氛围照）"
      ></image-slot>

      {showBoth ? (
        <div className="article-twocol">
          <div className="article-body article-body-en">
            <div className="article-col-h"><span>English</span><span className="lang-badge">EN</span></div>
            {renderArticleBody(a.body.en, 'en')}
          </div>
          <div className="article-body article-body-cn">
            <div className="article-col-h"><span>中文</span><span className="lang-badge">中</span></div>
            {renderArticleBody(a.body.cn, 'cn')}
          </div>
        </div>
      ) : (
        <div className={`article-body ${lang === 'cn' ? 'article-body-cn' : 'article-body-en'}`}>
          {renderArticleBody(body, lang)}
        </div>
      )}

      {mentionedNotes.length > 0 && (
        <section className="article-tasted">
          <div className="section-eyebrow">
            <span>Tasted from this piece</span>
            <span>· 这篇里喝过的瓶子</span>
          </div>
          <div className="article-tasted-grid">
            {mentionedNotes.map(n => (
              <a key={n.id} href={`#/note/${n.id}`} className="article-tasted-card">
                <div className="att-vintage">{n.vintage}</div>
                <div className="att-wine">{n.wine}</div>
                <div className="att-producer">{n.producer}</div>
                <div className="att-foot">
                  <span className="att-rating">{n.rating || '—'}<span className="att-rating-max">/100</span></span>
                  {n.fLikeIt && <span className="att-loved">♡</span>}
                </div>
              </a>
            ))}
          </div>
        </section>
      )}

      {(prev || next) && (
        <nav className="detail-nav">
          {prev ? (
            <a href={`#/article/${prev.slug}`}>
              <span className="detail-nav-lbl">← {lang==='cn'?'上一篇':'Previous'}</span>
              <span className="detail-nav-title">{lang==='cn' ? prev.title.cn : prev.title.en}</span>
            </a>
          ) : <span></span>}
          {next ? (
            <a href={`#/article/${next.slug}`}>
              <span className="detail-nav-lbl">{lang==='cn'?'下一篇':'Next'} →</span>
              <span className="detail-nav-title">{lang==='cn' ? next.title.cn : next.title.en}</span>
            </a>
          ) : <span></span>}
        </nav>
      )}
    </main>
  );
}

window.Cellar = Cellar;
window.Analytics = Analytics;
window.About = About;
window.ArticlesList = ArticlesList;
window.ArticleDetail = ArticleDetail;

/* ============ PRODUCER PAGE ============ */

function slugifyProducer(name) {
  return (name || '')
    .toLowerCase()
    .replace(/[àáâãä]/g, 'a').replace(/[èéêë]/g, 'e')
    .replace(/[ìíîï]/g, 'i').replace(/[òóôõö]/g, 'o')
    .replace(/[ùúûü]/g, 'u').replace(/[ç]/g, 'c').replace(/[ñ]/g, 'n')
    .replace(/&/g, 'and')
    .replace(/[^a-z0-9]+/g, '-')
    .replace(/^-+|-+$/g, '');
}
window.slugifyProducer = slugifyProducer;

function Producer({ slug, lang, data }) {
  // Find the producer by matching slug
  const allProducers = [...new Set([
    ...data.tastingNotes.map(n => n.producer),
    ...data.cellar.map(c => c.producer),
    ...data.consumed.map(c => c.producer),
  ].filter(Boolean))];
  const producer = allProducers.find(p => slugifyProducer(p) === slug);

  if (!producer) {
    return (
      <main className="container" style={{padding:'120px 0'}}>
        <div className="display" style={{fontSize:48}}>Producer not found.</div>
        <a href="#/notes" className="detail-back" style={{marginTop:24,display:'inline-block'}}>← back</a>
      </main>
    );
  }

  const notes = data.tastingNotes
    .filter(n => n.producer === producer)
    .sort((a, b) => {
      const da = window.fmt.parseDate(a.tastingDate)?.getTime() || 0;
      const db = window.fmt.parseDate(b.tastingDate)?.getTime() || 0;
      return db - da;
    });
  const cellarBottles = data.cellar.filter(c => c.producer === producer && c.quantity > 0);
  const consumed = data.consumed.filter(c => c.producer === producer);

  // Stats
  const ratedNotes = notes.filter(n => n.rating);
  const avgRating = ratedNotes.length
    ? (ratedNotes.reduce((s, n) => s + n.rating, 0) / ratedNotes.length)
    : null;
  const lovedCount = notes.filter(n => n.fLikeIt).length;
  const stillInCellar = cellarBottles.reduce((s, b) => s + (b.quantity || 0), 0);
  const totalSpent = consumed.reduce((s, c) => s + (c.price || 0), 0);

  // Region (use first note's locale, or first cellar)
  const refRow = notes[0] || cellarBottles[0] || consumed[0];
  const region = refRow ? window.fmt.region(refRow.locale, 'en') : '';

  // Articles mentioning producer
  const arts = window.WINE_ARTICLES || [];
  const stripped = producer.replace(/^(Château|Ch\.|Domaine|Tenuta|Castello|Bodegas|Marchese|Marchesi)\s+/i, '');
  const relatedArticles = arts.filter(a => {
    const h = (a.body?.en || '') + ' ' + (a.body?.cn || '') + ' ' + (a.title?.en || '');
    return h.includes(producer) || (stripped !== producer && h.includes(stripped));
  });

  return (
    <main className="container producer-page">
      <a href="#/notes" className="detail-back">← {lang === 'cn' ? '返回酒评' : 'Back to notes'}</a>

      <image-slot
        id={`producer-hero-${slug}`}
        class="img-producer-hero"
        style={{width:'100%',height:'320px',display:'block',marginTop:'24px',marginBottom:'40px'}}
        shape="rect"
        placeholder="House / vineyard photo · 酒庄或葡萄园照片"
      ></image-slot>

      <header className="producer-head">
        <div className="producer-eyebrow">
          <span>House</span>
          <span className="cn">· 酒庄</span>
          {region && <><span className="dot">·</span><span>{region}</span></>}
        </div>
        <h1 className="producer-name">{producer}</h1>

        <div className="producer-stats">
          <div className="ps-cell">
            <div className="ps-num">{notes.length}</div>
            <div className="ps-lbl">Notes written</div>
            <div className="ps-cn">已写笔记</div>
          </div>
          <div className="ps-cell">
            <div className="ps-num">{avgRating != null ? avgRating.toFixed(1) : '—'}</div>
            <div className="ps-lbl">Avg my rating</div>
            <div className="ps-cn">平均评分</div>
          </div>
          <div className="ps-cell">
            <div className="ps-num">{stillInCellar}</div>
            <div className="ps-lbl">In the cellar</div>
            <div className="ps-cn">在窖</div>
          </div>
          <div className="ps-cell">
            <div className="ps-num">{lovedCount}<span className="ps-loved">{lovedCount > 0 ? '♡' : ''}</span></div>
            <div className="ps-lbl">Loved bottles</div>
            <div className="ps-cn">喜爱</div>
          </div>
          <div className="ps-cell">
            <div className="ps-num">{totalSpent ? '¥' + (totalSpent/1000).toFixed(1) + 'K' : '—'}</div>
            <div className="ps-lbl">Total invested</div>
            <div className="ps-cn">累计花费</div>
          </div>
        </div>
      </header>

      {notes.length > 0 && (
        <section className="producer-section">
          <div className="section-eyebrow">
            <span>Tasted</span>
            <span>· 已尝</span>
          </div>
          <div className="producer-notes">
            {notes.map(n => (
              <a key={n.id} href={`#/note/${n.id}`} className="prod-note-row">
                <span className="pnr-vintage">{n.vintage}</span>
                <span className="pnr-wine">{n.wine.replace(producer, '').trim() || n.wine}</span>
                <span className="pnr-date">{window.fmt.longDate(n.tastingDate, 'en')}</span>
                <span className="pnr-rating">
                  {n.rating || '—'}
                  {n.fLikeIt && <span className="pnr-heart">♡</span>}
                </span>
              </a>
            ))}
          </div>
        </section>
      )}

      {cellarBottles.length > 0 && (
        <section className="producer-section">
          <div className="section-eyebrow">
            <span>In the cellar</span>
            <span>· 在窖</span>
          </div>
          <div className="producer-notes">
            {cellarBottles.map((b, i) => (
              <div key={i} className="prod-note-row prod-cellar-row">
                <span className="pnr-vintage">{b.vintage}</span>
                <span className="pnr-wine">{b.wine.replace(producer, '').trim() || b.wine}</span>
                <span className="pnr-date">
                  {b.drinkFrom ? `Drink from ${b.drinkFrom}` : ''}
                  {b.drinkTo ? ` · to ${b.drinkTo}` : ''}
                </span>
                <span className="pnr-qty">×{b.quantity}</span>
              </div>
            ))}
          </div>
        </section>
      )}

      {relatedArticles.length > 0 && (
        <section className="related-articles" style={{marginTop:80}}>
          <div className="section-eyebrow">
            <span>Mentioned in</span>
            <span>· 相关札记</span>
          </div>
          <div className="related-articles-grid">
            {relatedArticles.map(a => (
              <a key={a.slug} href={`#/article/${a.slug}`} className="related-article-card">
                <div className="related-article-eyebrow">{lang === 'cn' ? a.eyebrow.cn : a.eyebrow.en} · {a.readMins} min</div>
                <div className="related-article-title">{lang === 'cn' ? a.title.cn : a.title.en}</div>
                <div className="related-article-sub">{lang === 'cn' ? a.subtitle.cn : a.subtitle.en}</div>
                <div className="related-article-arrow">Read →</div>
              </a>
            ))}
          </div>
        </section>
      )}
    </main>
  );
}

window.Producer = Producer;
