// dashboard-hero.jsx — Rotating-greeting hero + KPI strip + dual-axis chart
const { useState: useHS, useEffect: useHE, useMemo: useHM, useRef: useHR } = React;

// ─────────────────────────────────────────────────────────── Greeting helpers
const HYPED_TEMPLATES = [
  ({n,part}) => ({lead:`Good ${part},`, name:`${n}.`,           tail:'Let’s run it.'}),
  ({n})       => ({lead:`${n},`,         name:`let’s do this.`, tail:'Numbers are up.'}),
  ({n})       => ({lead:'You are',       name:`killing it, ${n}.`, tail:'Keep going.'}),
  ({n,part})  => ({lead:`${cap(part)},`, name:`${n}.`,           tail:'You’re on a tear.'}),
  ({n})       => ({lead:`Back at it,`,   name:`${n}.`,           tail:'Catalog is humming.'}),
  ({n})       => ({lead:`Here we go,`,   name:`${n}.`,           tail:'Big numbers today.'}),
  ({n})       => ({lead:`Eyes up,`,      name:`${n}.`,           tail:'Q2 is yours.'}),
  ({n})       => ({lead:`Look at you,`,  name:`${n}.`,           tail:'Streams over a million.'}),
  ({n,part})  => ({lead:`Hey ${n},`,     name:`${part}’s on.`,   tail:'Time to ship.'}),
  ({n})       => ({lead:`On the board,`, name:`${n}.`,           tail:'Up and to the right.'}),
];
function cap(s){ return s.charAt(0).toUpperCase()+s.slice(1); }
function partOfDay() {
  const h = new Date().getHours();
  if (h < 5)  return 'late';
  if (h < 12) return 'morning';
  if (h < 17) return 'afternoon';
  if (h < 21) return 'evening';
  return 'night';
}

// Rotates EVERY visit (page load) — uses a localStorage cursor.
function useRotatingGreeting(name, count, override) {
  return useHM(()=>{
    const part = partOfDay();
    let idx = 0;
    if (typeof override === 'number') {
      idx = ((override % count) + count) % count;
    } else {
      try {
        const raw = localStorage.getItem('astro_greet_idx');
        const cur = raw == null ? -1 : parseInt(raw, 10);
        idx = ((cur + 1) % count + count) % count;
        localStorage.setItem('astro_greet_idx', String(idx));
      } catch { idx = Math.floor(Math.random()*count); }
    }
    const tpl = HYPED_TEMPLATES[idx % HYPED_TEMPLATES.length];
    return { ...tpl({n:name, part}), idx, part };
  }, [name, count, override]);
}

// ─────────────────────────────────────────────────────────── Data
// 30 days of paired earnings ($) and streams (count) — slight correlation, with weekly cadence.
const DAYS_30 = (()=>{
  const base = new Date('2026-04-27'); base.setHours(0,0,0,0);
  const e = [4820,5210,5840,6120,5640,4380,3960, 5210,6420,7180,7640,7110,5320,4880, 6510,7820,8640,9120,8540,6280,5810, 7990,9410,10240,10810,9920,7440,6920, 9210,10580];
  const s = [22.1,24.6,27.0,28.2,26.4,18.9,17.0, 24.2,29.4,32.6,34.8,32.1,22.4,20.7, 30.0,35.8,39.6,41.6,38.9,27.4,24.6, 36.4,42.6,46.6,49.0,44.6,32.1,30.0, 41.8,48.2];
  return e.map((earn,i)=>{
    const d = new Date(base); d.setDate(base.getDate() - (29 - i));
    return { d, earn, streams: s[i] }; // streams in millions
  });
})();
const TOTAL_EARN_30 = DAYS_30.reduce((a,r)=>a+r.earn,0);
const TOTAL_STREAMS_30 = DAYS_30.reduce((a,r)=>a+r.streams,0);

// ─────────────────────────────────────────────────────────── Dual-axis chart
function DualChart({ data, height=280, accent='var(--accent)', variant='editorial' }) {
  const W = 1100, H = height, padL = 64, padR = 64, padT = 24, padB = 36;
  const [hover, setHover] = useHS(null);
  const ref = useHR(null);

  const eMax = Math.ceil(Math.max(...data.map(d=>d.earn))/2000)*2000;
  const sMax = Math.ceil(Math.max(...data.map(d=>d.streams))/10)*10;
  // Inset bar centers so first/last bar bodies don't collide with axes.
  const bw = (W - padL - padR) / data.length * 0.7;
  const xInset = bw/2 + 4;
  const x = (i) => padL + xInset + (i/(data.length-1)) * (W - padL - padR - xInset*2);
  const yE = (v) => padT + (1 - v/eMax) * (H - padT - padB);
  const yS = (v) => padT + (1 - v/sMax) * (H - padT - padB);

  // Earnings — area path (filled bars/area)
  const earnArea = data.map((d,i)=>`${i===0?'M':'L'}${x(i).toFixed(1)} ${yE(d.earn).toFixed(1)}`).join(' ')
    + ` L ${x(data.length-1).toFixed(1)} ${(H-padB).toFixed(1)} L ${padL} ${(H-padB).toFixed(1)} Z`;
  const earnLine = data.map((d,i)=>`${i===0?'M':'L'}${x(i).toFixed(1)} ${yE(d.earn).toFixed(1)}`).join(' ');
  // Streams — line
  const streamsLine = data.map((d,i)=>`${i===0?'M':'L'}${x(i).toFixed(1)} ${yS(d.streams).toFixed(1)}`).join(' ');

  // Y ticks
  const eTicks = [0, eMax*0.25, eMax*0.5, eMax*0.75, eMax];
  const sTicks = [0, sMax*0.25, sMax*0.5, sMax*0.75, sMax];

  const onMove = (ev) => {
    const r = ref.current.getBoundingClientRect();
    const px = (ev.clientX - r.left) * (W / r.width);
    const ratio = (px - padL) / (W - padL - padR);
    const i = Math.max(0, Math.min(data.length-1, Math.round(ratio*(data.length-1))));
    setHover(i);
  };
  const fmtDate = (d) => d.toLocaleDateString('en-US',{month:'short',day:'numeric'});
  const isBars = variant === 'editorial' || variant === 'noir';
  const earnFill = variant === 'noir' ? 'var(--ink)' : (variant==='neon' ? 'transparent' : 'var(--ink)');
  const earnStroke = variant === 'noir' ? 'var(--accent)' : (variant==='neon' ? accent : 'var(--ink)');
  const streamsStroke = variant === 'neon' ? 'var(--ink)' : 'var(--ink)';

  return (
    <div style={{position:'relative',width:'100%'}}>
      <svg ref={ref} viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none"
        onMouseMove={onMove} onMouseLeave={()=>setHover(null)}
        style={{display:'block',width:'100%',height,cursor:'crosshair'}}>

        {/* gridlines */}
        {eTicks.map((v,i)=>(
          <line key={'g'+i} x1={padL} x2={W-padR} y1={yE(v)} y2={yE(v)}
            stroke="var(--rule-soft)" strokeWidth="1" strokeDasharray={i===0?'0':'2 3'}/>
        ))}

        {/* earnings — area or bars */}
        {variant === 'editorial' && (
          <>
            <defs>
              <linearGradient id="earnGradEd" x1="0" x2="0" y1="0" y2="1">
                <stop offset="0%" stopColor={accent} stopOpacity="0.30"/>
                <stop offset="100%" stopColor={accent} stopOpacity="0"/>
              </linearGradient>
            </defs>
            <path d={earnArea} fill="url(#earnGradEd)"/>
            {data.map((d,i)=>{
              const cx = x(i);
              const top = yE(d.earn);
              const isWeekend = d.d.getDay()===0 || d.d.getDay()===6;
              return (
                <rect key={'b'+i} x={cx - bw/2} y={top}
                  width={bw} height={(H-padB) - top}
                  fill={hover===i ? 'var(--ink)' : (isWeekend ? accent : 'var(--ink)')}/>
              );
            })}
            {/* trend line on top */}
            <path d={earnLine} fill="none" stroke="var(--ink)" strokeWidth="1.5" opacity="0.0"/>
          </>
        )}
        {variant === 'noir' && (
          <>
            <path d={earnArea} fill="var(--ink)" opacity="0.92"/>
            <path d={earnLine} fill="none" stroke="var(--accent)" strokeWidth="1.5"/>
          </>
        )}
        {variant === 'neon' && (
          <>
            <defs>
              <linearGradient id="earnGrad" x1="0" x2="0" y1="0" y2="1">
                <stop offset="0%" stopColor={accent} stopOpacity="0.35"/>
                <stop offset="100%" stopColor={accent} stopOpacity="0"/>
              </linearGradient>
            </defs>
            <path d={earnArea} fill="url(#earnGrad)"/>
            <path d={earnLine} fill="none" stroke={accent} strokeWidth="2"/>
            {data.map((d,i)=>(
              <circle key={'p'+i} cx={x(i)} cy={yE(d.earn)} r={hover===i?4:2.2}
                fill="var(--bg)" stroke={accent} strokeWidth="1.5"/>
            ))}
          </>
        )}

        {/* streams — overlay line */}
        <path d={streamsLine} fill="none"
          stroke={variant==='editorial' ? accent : streamsStroke}
          strokeWidth={variant==='editorial' ? 3 : 2}
          strokeDasharray={variant==='editorial' ? '0' : (variant==='noir' ? '0' : '4 3')}/>
        {variant==='editorial' && data.map((d,i)=>(
          <circle key={'sp'+i} cx={x(i)} cy={yS(d.streams)} r={hover===i?4.5:2.5}
            fill="var(--bg)" stroke={accent} strokeWidth="2"/>
        ))}

        {/* Y labels — left = earnings */}
        {eTicks.map((v,i)=>(
          <text key={'el'+i} x={padL-8} y={yE(v)+3} textAnchor="end"
            fontFamily="IBM Plex Mono,monospace" fontSize="10" fill="var(--ink-3)">
            ${v >= 1000 ? (v/1000).toFixed(0)+'K' : v.toFixed(0)}
          </text>
        ))}
        {/* Y labels — right = streams (M) */}
        {sTicks.map((v,i)=>(
          <text key={'sl'+i} x={W-padR+8} y={yS(v)+3} textAnchor="start"
            fontFamily="IBM Plex Mono,monospace" fontSize="10" fill="var(--ink-3)">
            {v.toFixed(0)}M
          </text>
        ))}

        {/* X labels — every 5 days */}
        {data.map((d,i)=> (i%5===0 || i===data.length-1) && (
          <text key={'xl'+i} x={x(i)} y={H - 14} textAnchor="middle"
            fontFamily="IBM Plex Mono,monospace" fontSize="10" fill="var(--ink-3)">
            {fmtDate(d.d).toUpperCase()}
          </text>
        ))}

        {/* hover line + readout */}
        {hover != null && (
          <>
            <line x1={x(hover)} x2={x(hover)} y1={padT} y2={H-padB}
              stroke="var(--ink)" strokeWidth="1" strokeDasharray="3 2"/>
            <circle cx={x(hover)} cy={yE(data[hover].earn)} r="4" fill={accent} stroke="var(--ink)" strokeWidth="1.5"/>
            <circle cx={x(hover)} cy={yS(data[hover].streams)} r="4" fill="var(--bg)" stroke="var(--ink)" strokeWidth="1.5"/>
          </>
        )}
      </svg>

      {/* Axis captions */}
      <div className="ff-mono upper" style={{position:'absolute',left:0,top:4,fontSize:9,color:'var(--ink-3)',letterSpacing:'.08em'}}>$ EARN</div>
      <div className="ff-mono upper" style={{position:'absolute',right:0,top:4,fontSize:9,color:'var(--ink-3)',letterSpacing:'.08em'}}>STREAMS·M</div>

      {/* Tooltip */}
      {hover != null && (
        <div className="ff-mono" style={{position:'absolute',left:`min(calc(${(x(hover)/W)*100}% + 12px), calc(100% - 200px))`,
          top:8,padding:'10px 12px',background:'var(--ink)',color:'var(--bg)',fontSize:11,minWidth:180,
          boxShadow:'0 4px 14px rgba(0,0,0,.18)',pointerEvents:'none'}}>
          <div className="upper" style={{fontSize:9,opacity:.6,letterSpacing:'.1em',marginBottom:6}}>
            {fmtDate(data[hover].d)} · DAY {hover+1}/30
          </div>
          <div style={{display:'flex',justifyContent:'space-between',gap:18,marginBottom:3}}>
            <span style={{opacity:.7}}>Earnings</span>
            <span className="num" style={{fontWeight:600}}>${data[hover].earn.toLocaleString()}</span>
          </div>
          <div style={{display:'flex',justifyContent:'space-between',gap:18}}>
            <span style={{opacity:.7}}>Streams</span>
            <span className="num" style={{fontWeight:600}}>{data[hover].streams.toFixed(2)}M</span>
          </div>
        </div>
      )}
    </div>
  );
}

// ─────────────────────────────────────────────────────────── KPI cards
function KpiCard({ label, value, sub, tone, spark, area, accent, big }) {
  const isAccent = tone === 'accent';
  return (
    <div style={{padding: big ? '20px 18px' : '18px 16px',
      background: isAccent ? 'var(--accent)' : 'transparent',
      color: isAccent ? 'var(--accent-ink)' : 'var(--ink)'}}>
      <div className="ff-mono upper" style={{fontSize:10,fontWeight:600,letterSpacing:'.08em',marginBottom:8,opacity:.85}}>{label}</div>
      <div className="ff-display num heading-swap" style={{fontSize: big?44:30, fontWeight:600, letterSpacing:'-0.04em', lineHeight:1, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis'}}>
        {value}
      </div>
      <div style={{display:'flex',justifyContent:'space-between',alignItems:'flex-end',marginTop:10,gap:10}}>
        <span className="ff-mono" style={{fontSize:10, color: isAccent ? 'var(--accent-ink)' : 'var(--ink-3)', whiteSpace:'nowrap'}}>{sub}</span>
        {spark && <Spark data={spark} w={70} h={20} stroke="currentColor" fill="currentColor" area={area}/>}
      </div>
    </div>
  );
}

// ─────────────────────────────────────────────────────────── Hero
function DashboardHero({ go, variant='editorial', firstName='Paul', greetIndex }) {
  const greet = useRotatingGreeting(firstName, HYPED_TEMPLATES.length, greetIndex);
  const today = useHM(()=>new Date('2026-04-27 09:42'), []);
  const [now, setNow] = useHS(today);
  useHE(()=>{ const id=setInterval(()=>setNow(new Date(today.getTime() + (Date.now()%86400000))), 60000); return ()=>clearInterval(id); },[today]);

  const moMEarn = '+12.4%';
  const yoYEarn = '+8.4%';

  // ───── KPI definitions
  const kpis = [
    { label:'$ QUEUED · Q2',   value:'$248,302',     sub:`${yoYEarn} YoY · run-rate`, spark: sparkRoyalty,                     area:true,  click:()=>go('analytics') },
    { label:'STREAMS / HR',    value:'1.08M',        sub:'14 DSPs · live',            spark: sparkPlays.slice(-22),            area:false, click:()=>go('analytics'), tone:'accent' },
    { label:'ACTIVE LISTENERS',value:'412,884',      sub:'+6.1% WoW',                 spark: sparkPlays.slice(8).map(v=>v*0.4),area:true,  click:()=>go('analytics') },
    { label:'LIFETIME EARNED', value:'$11.42M',      sub:'since 2014',                spark: sparkRoster,                      area:true,  click:()=>go('analytics') },
    { label:'TOP TRACK · NOW', value:'TONIGHT',      sub:'Helado Negro · 41,208/hr',  spark: sparkPlays.slice(-16),            area:false, click:()=>go('catalog') },
  ];

  // ───── Variant containers
  const containerStyle =
    variant === 'noir'      ? { background:'var(--ink)', color:'var(--bg)' } :
    variant === 'neon'      ? { background:'var(--paper)' } :
    /* editorial */           { background:'transparent' };

  const greetingNumberStyle =
    variant === 'noir'  ? { background:'var(--accent)', color:'var(--accent-ink)', padding:'0 .12em' } :
    variant === 'neon'  ? { color:'var(--ink)', borderBottom:'4px solid var(--accent)', paddingBottom:4 } :
    /* editorial */       { color:'var(--ink-3)' };

  // ───── Top masthead strip — catalog pulse
  const masthead = (
    <div style={{borderTop: variant==='noir'?'2px solid var(--bg)':'2px solid var(--rule)',
      borderBottom: variant==='noir'?'1px solid rgba(244,239,230,.18)':'1px solid var(--rule)',
      padding:'8px 0',marginBottom:24,
      display:'flex',justifyContent:'space-between',alignItems:'center',gap:18,flexWrap:'wrap'}}>
      <div className="ff-mono upper" style={{fontSize:11,fontWeight:600,letterSpacing:'.1em', opacity: variant==='noir'?0.85:1, display:'flex',alignItems:'center',gap:14,flexWrap:'wrap'}}>
        <span style={{display:'inline-flex',alignItems:'center',gap:6,whiteSpace:'nowrap'}}>
          <span className="pulse-dot" style={{display:'inline-block',width:7,height:7,background:'var(--accent)'}}/>
          NOW PLAYING · TONIGHT — HELADO NEGRO
        </span>
        <span style={{opacity:.4}}>·</span>
        <span style={{whiteSpace:'nowrap'}}>{(window.CATALOG_STATS?.works?.total || 0).toLocaleString()} WORKS</span>
        <span style={{opacity:.4}}>·</span>
        <span style={{whiteSpace:'nowrap'}}>{(window.CATALOG_STATS?.recordings?.total || 0).toLocaleString()} RECORDINGS</span>
      </div>
      <div className="ff-mono num" style={{fontSize:11,opacity:variant==='noir'?0.6:1, color: variant==='noir'?'var(--bg)':'var(--ink-3)',display:'flex',alignItems:'center',gap:14,flexWrap:'wrap'}}>
        <span style={{whiteSpace:'nowrap'}}>NEW: SOLANGE +3 WORKS</span>
        <span style={{opacity:.4}}>·</span>
        <span style={{whiteSpace:'nowrap'}}>CLAIMS {window.CATALOG_STATS?.claims?.open || 0} OPEN</span>
        <span style={{opacity:.4}}>·</span>
        <span style={{whiteSpace:'nowrap'}}>CWR ACK {((window.CATALOG_STATS?.cwrAckRate || 0)*100).toFixed(1)}%</span>
      </div>
    </div>
  );

  // Pick a per-greeting accent role so the colors rotate too.
  const colorRoles = [
    { lead:'var(--ink-3)',     name:{background:'var(--accent)', color:'var(--accent-ink)', padding:'0 .12em'},                tail:'var(--ink-2)' },
    { lead:'var(--ink-3)',     name:{color:'var(--ink)', borderBottom:'10px solid var(--accent)', paddingBottom:0},             tail:'var(--ink-2)' },
    { lead:'var(--accent-ink)',name:{background:'var(--ink)', color:'var(--accent)', padding:'0 .12em'},                       tail:'var(--ink-2)' },
    { lead:'var(--ok)',        name:{color:'var(--ink)', WebkitTextStroke:'2px var(--ink)', textShadow:'4px 4px 0 var(--accent)'}, tail:'var(--ink-3)' },
    { lead:'var(--ink-2)',     name:{background:'var(--ink)', color:'var(--bg)', padding:'0 .12em'},                            tail:'var(--accent-ink)' },
    { lead:'var(--ink-3)',     name:{color:'var(--accent)', WebkitTextStroke:'1.5px var(--ink)'},                               tail:'var(--ink-2)' },
    { lead:'var(--ink-3)',     name:{background:'var(--accent)', color:'var(--accent-ink)', padding:'0 .12em', transform:'skew(-6deg)', display:'inline-block'}, tail:'var(--ink-2)' },
    { lead:'var(--ink-2)',     name:{color:'var(--accent)', textShadow:'3px 3px 0 var(--ink)'},                                  tail:'var(--ink-3)' },
    { lead:'var(--ink-3)',     name:{color:'var(--ink)', background:'linear-gradient(transparent 60%, var(--accent) 60%)', padding:'0 .08em'}, tail:'var(--ink-2)' },
    { lead:'var(--ink-3)',     name:{color:'var(--accent)', background:'var(--ink)', padding:'0 .12em'},                        tail:'var(--ink-2)' },
  ];
  const role = colorRoles[greet.idx % colorRoles.length];

  // Variant-aware overrides — keep noir/neon distinctive
  const leadColor =
    variant === 'noir' ? 'rgba(244,239,230,.55)' :
    variant === 'neon' ? 'var(--ink-3)' :
    role.lead;
  const tailColor =
    variant === 'noir' ? 'var(--accent)' :
    variant === 'neon' ? 'var(--ink-2)' :
    role.tail;
  const nameStyle =
    variant === 'noir'  ? { background:'var(--accent)', color:'var(--accent-ink)', padding:'0 .12em' } :
    variant === 'neon'  ? { color:'var(--ink)', background:'linear-gradient(transparent 62%, var(--accent) 62%)', padding:'0 .08em' } :
    role.name;

  // ───── Greeting block — same anatomy across variants, different treatments
  const greetingBlock = (
    <div style={{display:'grid', gridTemplateColumns:'1fr', gap:18, marginBottom: 28}}>
      <div>
        <div className="ff-mono upper" style={{fontSize:11, opacity: variant==='noir'?0.55:1, color: variant==='noir'?'var(--bg)':'var(--ink-3)', marginBottom:12, display:'flex', alignItems:'center', gap:10}}>
          <span style={{display:'inline-block', width:10, height:10, background:'var(--accent)'}}/>
          {greet.part === 'morning' ? 'GOOD MORNING' :
           greet.part === 'afternoon' ? 'GOOD AFTERNOON' :
           greet.part === 'evening' ? 'GOOD EVENING' :
           greet.part === 'night' ? 'ON THE NIGHT SHIFT' :
           'EARLY HOURS'} · 04 → 27 / 2026 · {String(greet.idx+1).padStart(2,'0')}/{HYPED_TEMPLATES.length}
        </div>
        <h1 className="heading-swap ff-display" style={{
          fontSize:'clamp(48px,8vw,128px)', lineHeight:0.95, margin:0, fontWeight:700, letterSpacing:'-0.05em'}}>
          <span style={{display:'block', color: leadColor}}>{greet.lead}</span>
          <span style={{display:'inline-block', ...nameStyle}}>{greet.name}</span>
          <span style={{display:'block', fontSize:'0.42em', fontWeight:500, marginTop:14, letterSpacing:'-0.03em', color: tailColor}}>
            {greet.tail}
          </span>
        </h1>
      </div>
    </div>
  );

  // ───── KPI strip — varies per variant
  const kpiStrip = variant === 'editorial' ? (
    <div style={{display:'grid', gridTemplateColumns:'repeat(5,1fr)',
      borderTop:'1px solid var(--rule)', borderBottom:'1px solid var(--rule)'}}>
      {kpis.map((k,i,arr)=>(
        <div key={k.label} onClick={k.click} style={{cursor:'pointer',
          borderRight: i<arr.length-1?'1px solid var(--rule)':'none'}}>
          <KpiCard {...k} accent="var(--accent)"/>
        </div>
      ))}
    </div>
  ) : variant === 'noir' ? (
    <div style={{display:'grid', gridTemplateColumns:'repeat(5,1fr)', gap:1, background:'rgba(244,239,230,.18)',
      border:'1px solid rgba(244,239,230,.18)'}}>
      {kpis.map((k)=>(
        <div key={k.label} onClick={k.click} style={{cursor:'pointer', background:'var(--ink)'}}>
          <KpiCard {...k} tone={k.tone === 'accent' ? 'accent' : 'noir-card'}/>
        </div>
      ))}
    </div>
  ) : (
    /* neon — cards w/ accent border */
    <div style={{display:'grid', gridTemplateColumns:'repeat(5,1fr)', gap:12}}>
      {kpis.map((k,i)=>(
        <div key={k.label} onClick={k.click} style={{cursor:'pointer', background:'var(--bg)',
          border:'1px solid var(--rule)',
          borderTop: i===1 ? '3px solid var(--accent)' : '3px solid var(--ink)',
          padding:0}}>
          <KpiCard {...k}/>
        </div>
      ))}
    </div>
  );

  // ───── Chart caption row
  const chartHeader = (
    <div style={{display:'flex',alignItems:'flex-end',justifyContent:'space-between',gap:24,
      paddingTop: 36, paddingBottom: 18, flexWrap:'wrap',
      borderTop: variant==='neon' ? 'none' : (variant==='noir' ? '1px solid rgba(244,239,230,.18)' : 'none')}}>
      <div>
        <div className="ff-mono upper" style={{fontSize:10, color: variant==='noir'?'rgba(244,239,230,.55)':'var(--ink-3)',marginBottom:8,letterSpacing:'.1em'}}>
          §03 · EARNINGS + STREAMS · LAST 30 DAYS
        </div>
        <div style={{display:'flex',alignItems:'flex-end',gap:32,flexWrap:'wrap'}}>
          <div>
            <div className="ff-display num heading-swap" style={{fontSize:'clamp(36px,4.6vw,64px)',fontWeight:600,letterSpacing:'-0.04em',lineHeight:1}}>
              ${(TOTAL_EARN_30/1000).toFixed(0)}K
            </div>
            <div className="ff-mono upper" style={{fontSize:10, color: variant==='noir'?'rgba(244,239,230,.55)':'var(--ink-3)',marginTop:6,letterSpacing:'.1em'}}>
              ▲ {moMEarn} MoM · ${TOTAL_EARN_30.toLocaleString()} TOTAL
            </div>
          </div>
          <div style={{borderLeft: variant==='noir'?'1px solid rgba(244,239,230,.2)':'1px solid var(--rule-soft)', paddingLeft:24}}>
            <div className="ff-display num heading-swap" style={{fontSize:'clamp(28px,3.6vw,48px)',fontWeight:600,letterSpacing:'-0.04em',lineHeight:1}}>
              {TOTAL_STREAMS_30.toFixed(1)}M
            </div>
            <div className="ff-mono upper" style={{fontSize:10, color: variant==='noir'?'rgba(244,239,230,.55)':'var(--ink-3)',marginTop:6,letterSpacing:'.1em'}}>
              ▲ +14.2% MoM · STREAMS
            </div>
          </div>
        </div>
      </div>
      <div style={{display:'flex',gap:18,alignItems:'center'}}>
        <Legend swatch={variant==='editorial' ? 'var(--ink)' : (variant==='noir' ? 'var(--bg)' : 'var(--accent)')} dark={variant==='noir'}>EARNINGS</Legend>
        <Legend swatch="line" stroke={variant==='editorial' ? 'var(--accent)' : (variant==='noir' ? 'var(--bg)' : 'var(--ink)')} dashed={variant==='neon'} dark={variant==='noir'}>STREAMS</Legend>
        <a onClick={()=>go('analytics')} className="ff-mono upper" style={{
          fontSize:10, padding:'8px 14px',
          background: variant==='noir' ? 'var(--accent)' : 'var(--ink)',
          color: variant==='noir' ? 'var(--accent-ink)' : 'var(--bg)',
          letterSpacing:'.1em', cursor:'pointer'}}>
          Full report →
        </a>
      </div>
    </div>
  );

  return (
    <div style={{...containerStyle,
      ...(variant==='noir' ? { padding:'24px 24px 28px', margin:'0 -24px 0', borderBottom:'2px solid var(--rule)' } : {}),
      ...(variant==='neon' ? { padding:'24px 24px 28px', margin:'0 -24px 0',
        background:'var(--bg-2)',
        borderBottom:'1px solid var(--rule)'} : {})
    }}>
      {masthead}
      {greetingBlock}
      {kpiStrip}
      {chartHeader}
      <div style={{padding:'8px 0 24px',
        background: variant==='noir' ? 'transparent' : 'transparent'}}>
        <DualChart data={DAYS_30} variant={variant} accent="var(--accent)"/>
      </div>
    </div>
  );
}

function Legend({ children, swatch, stroke, dashed, dark }) {
  const color = dark ? 'rgba(244,239,230,.7)' : 'var(--ink-3)';
  return (
    <span className="ff-mono upper" style={{fontSize:10, color, display:'inline-flex',alignItems:'center',gap:8,letterSpacing:'.1em'}}>
      {swatch === 'line' ? (
        <svg width="22" height="8" viewBox="0 0 22 8"><line x1="0" y1="4" x2="22" y2="4"
          stroke={stroke || 'currentColor'} strokeWidth="2"
          strokeDasharray={dashed?'4 3':'0'}/></svg>
      ) : (
        <span style={{display:'inline-block',width:12,height:12,background:swatch}}/>
      )}
      {children}
    </span>
  );
}

Object.assign(window, { DashboardHero, DAYS_30, DualChart });
