import { useState, useEffect, useRef } from "react";

const JM = "'JetBrains Mono',monospace";
const W04 = "rgba(255,255,255,0.04)";
const W06 = "rgba(255,255,255,0.06)";
const W08 = "rgba(255,255,255,0.08)";
const W1  = "rgba(255,255,255,0.1)";
const DEFAULT_WL = ["NVDA","AAPL","MSFT","TSLA","META","AMZN","GOOGL","JPM","SPY","QQQ","AMD","XOM","GLD","PLTR","COIN"];
const TIER_C  = { ULTRA:"#ff3d71", HIGH:"#00e676", MEDIUM:"#ffeb3b", WATCH:"#888" };
const ROLE_I  = { CEO:"CEO", CFO:"CFO", President:"Pres", Director:"Dir", "10% Owner":"10%+", VP:"VP" };
const PRED_C  = { UP:"#00e676", DOWN:"#ff5252", NEUTRAL:"#ffeb3b", VOLATILE:"#ff9100" };
const ACT_C   = { BUY:"#00e676", SELL:"#ff5252", WAIT:"#ffeb3b", AVOID:"#ff5252" };
const DIR_C   = { BULLISH:"#00e676", BEARISH:"#ff5252", NEUTRAL:"#888" };
const BIAS_C  = { Bullish:"#00e676", "Cautiously Bullish":"#69f0ae", Neutral:"#ffeb3b", "Cautiously Bearish":"#ff9100", Bearish:"#ff5252" };
const SECTOR_ETFS = [
  {name:"Technology",etf:"XLK",color:"#38bdf8"},{name:"Healthcare",etf:"XLV",color:"#34d399"},
  {name:"Financials",etf:"XLF",color:"#a78bfa"},{name:"Energy",etf:"XLE",color:"#ff9100"},
  {name:"Consumer Disc.",etf:"XLY",color:"#f472b6"},{name:"Industrials",etf:"XLI",color:"#fbbf24"},
  {name:"Real Estate",etf:"XLRE",color:"#fb923c"},{name:"Materials",etf:"XLB",color:"#a3e635"},
  {name:"Utilities",etf:"XLU",color:"#67e8f9"},{name:"Comm. Services",etf:"XLC",color:"#c084fc"},
];

async function store(k,v){try{localStorage.setItem(k,JSON.stringify(v));}catch(_){}}
async function retrieve(k){try{const r=localStorage.getItem(k);return r?JSON.parse(r):null;}catch(_){return null;}}
async function loadCache(key){return retrieve("iw_cache_"+key);}
async function saveCache(key,val){await store("iw_cache_"+key,{value:val,ts:Date.now()});}

async function callAPI(system,msg,maxTok){
  const apiKey=window.TRADEIQ_API_KEY||"";
  if(!apiKey){throw new Error("Service not configured. Please contact support.");}
  const res=await fetch("https://api.anthropic.com/v1/messages",{
    method:"POST",headers:{"Content-Type":"application/json","x-api-key":apiKey,"anthropic-version":"2023-06-01","anthropic-dangerous-direct-browser-access":"true"},
    body:JSON.stringify({model:"claude-sonnet-4-5",max_tokens:maxTok||4000,system,
      tools:[{type:"web_search_20250305",name:"web_search"}],
      messages:[{role:"user",content:msg}]}),
  });
  if(!res.ok)throw new Error("API error "+res.status);
  const j=await res.json();
  return j.content.filter(b=>b.type==="text").map(b=>b.text).join("");
}

function parseJSON(text){
  if(!text?.trim())throw new Error("Empty response.");
  let t=text.trim().replace(/^\x60{3}(?:json)?\s*/i,"").replace(/\s*\x60{3}\s*$/,"").trim();
  const s=t.indexOf("{"),e=t.lastIndexOf("}");
  if(s<0||e<0)throw new Error("No JSON in response - try again.");
  let raw=t.slice(s,e+1).replace(/,(\s*[}\]])/g,"$1");
  try{return JSON.parse(raw);}catch(_){}
  try{return JSON.parse(raw.replace(/[\u0000-\u001F]+/g," "));}catch(_){}
  try{return JSON.parse(raw.substring(0,raw.lastIndexOf("}")+1));}catch(_){}
  try{
    const clean=raw.replace(/"([^"]*)"\s*:/g,function(_,k){return '"'+k.replace(/[^a-zA-Z0-9_]/g,"_")+'":'});
    return JSON.parse(clean);
  }catch(_){}
  throw new Error("Could not parse response - please try again.");
}

async function fetchPrice(ticker){
  if(!ticker)return null;
  const yUrl="https://query1.finance.yahoo.com/v8/finance/chart/"+ticker+"?interval=1m&range=1d";
  for(const proxy of["https://api.allorigins.win/get?url=","https://corsproxy.io/?"]) {
    try{
      const ctrl=new AbortController();setTimeout(()=>ctrl.abort(),6000);
      const r=await fetch(proxy+encodeURIComponent(yUrl),{signal:ctrl.signal});
      if(!r.ok)continue;
      const j=await r.json();
      const raw=j.contents?JSON.parse(j.contents):j;
      const meta=raw?.chart?.result?.[0]?.meta;
      if(meta?.regularMarketPrice){
        const p=meta.regularMarketPrice,prev=meta.previousClose||meta.chartPreviousClose;
        const chg=prev?(((p-prev)/prev)*100):null;
        return{price:"$"+p.toFixed(2),change:chg!==null?(chg>=0?"+":"")+chg.toFixed(2)+"%":null,raw:p};
      }
    }catch(_){continue;}
  }
  return null;
}

async function fetchTechnicals(ticker){
  if(!ticker)return null;
  const yUrl="https://query1.finance.yahoo.com/v8/finance/chart/"+ticker+"?interval=1d&range=6mo";
  for(var pi=0;pi<2;pi++){
    var proxy=pi===0?"https://api.allorigins.win/get?url=":"https://corsproxy.io/?";
    try{
      var ctrl=new AbortController();
      setTimeout(function(){ctrl.abort();},8000);
      var r=await fetch(proxy+encodeURIComponent(yUrl),{signal:ctrl.signal});
      if(!r.ok)continue;
      var j=await r.json();
      var raw=j.contents?JSON.parse(j.contents):j;
      var result=raw&&raw.chart&&raw.chart.result&&raw.chart.result[0];
      if(!result)continue;
      var q=result.indicators&&result.indicators.quote&&result.indicators.quote[0];
      if(!q)continue;
      var closes=q.close||[];
      var volumes=q.volume||[];
      var vc=closes.filter(function(c){return c!=null;});
      var vv=volumes.filter(function(v){return v!=null;});
      if(vc.length<50)continue;
      var ma50=vc.slice(-50).reduce(function(a,b){return a+b;},0)/50;
      var ma200=vc.length>=200?vc.slice(-200).reduce(function(a,b){return a+b;},0)/200:null;
      var gains=0,losses=0,last15=vc.slice(-15);
      for(var i=1;i<last15.length;i++){var d=last15[i]-last15[i-1];if(d>0)gains+=d;else losses+=Math.abs(d);}
      var avgG=gains/14,avgL=losses/14;
      var rsi=avgL===0?100:100-(100/(1+(avgG/avgL)));
      var avgVol=vv.length>30?vv.slice(-31,-1).reduce(function(a,b){return a+b;},0)/30:0;
      var todayVol=vv[vv.length-1]||0;
      var relVol=avgVol>0?todayVol/avgVol:null;
      var price=result.meta&&result.meta.regularMarketPrice;
      return{
        rsi:rsi.toFixed(1),
        ma50:"$"+ma50.toFixed(2),
        ma200:ma200?"$"+ma200.toFixed(2):null,
        aboveMa50:price>ma50,
        aboveMa200:ma200?price>ma200:null,
        relVolume:relVol?relVol.toFixed(2)+"x":null,
        avgVolume:avgVol>0?(avgVol/1e6).toFixed(1)+"M":null,
        todayVolume:todayVol>0?(todayVol/1e6).toFixed(1)+"M":null,
      };
    }catch(err){continue;}
  }
  return null;
}


async function fetchInsiderTrades(ticker,days){
  if(!ticker)return null;
  var fd=days==="7d"?7:days==="30d"?30:90;
  var url="https://openinsider.com/screener?s="+ticker+"&fd="+fd+"&xs=1&vl=50000&action=getdata";
  for(var pi=0;pi<2;pi++){
    var proxy=pi===0?"https://api.allorigins.win/get?url=":"https://corsproxy.io/?";
    try{
      var ctrl=new AbortController();
      setTimeout(function(){ctrl.abort();},8000);
      var r=await fetch(proxy+encodeURIComponent(url),{signal:ctrl.signal});
      if(!r.ok)continue;
      var j=await r.json();
      var html=j.contents||"";
      if(typeof html!=="string"||html.length<200)continue;
      var rows=html.match(/<tr[^>]*>[\s\S]*?<\/tr>/gi)||[];
      var trades=[];
      for(var ri=0;ri<rows.length;ri++){
        var cells=rows[ri].match(/<td[^>]*>[\s\S]*?<\/td>/gi)||[];
        if(cells.length<12)continue;
        var txt=function(c){return c.replace(/<[^>]+>/g,"").replace(/&amp;/g,"&").replace(/&#39;/g,"'").trim();};
        if(txt(cells[6])!=="P")continue;
        var val=parseFloat(txt(cells[11]).replace(/[$,]/g,""))||0;
        if(val<50000)continue;
        trades.push({
          ticker:ticker.toUpperCase(),
          insider_name:txt(cells[4]),
          insider_title:txt(cells[5]),
          transaction_date:txt(cells[1]),
          transaction_type:"P",
          price_per_share:parseFloat(txt(cells[7]).replace(/[$,]/g,""))||0,
          total_value:val,
          is_10b51:false,
          source:"REAL_SEC",
        });
      }
      if(trades.length>0)return trades;
    }catch(err){continue;}
  }
  return null;
}


function fmtMoney(n){if(!n)return"--";if(n>=1e9)return"$"+(n/1e9).toFixed(1)+"B";if(n>=1e6)return"$"+(n/1e6).toFixed(1)+"M";if(n>=1e3)return"$"+(n/1e3).toFixed(0)+"K";return"$"+n;}
function ago(ts){if(!ts)return"";const s=Math.floor((Date.now()-ts)/1000);if(s<60)return s+"s ago";if(s<3600)return Math.floor(s/60)+"m ago";if(s<86400)return Math.floor(s/3600)+"h ago";return Math.floor(s/86400)+"d ago";}

function Bars({color}){const c=color||"#00e676";return(<div style={{display:"flex",gap:"3px",alignItems:"flex-end",height:"20px"}}>{[0.4,0.7,1,0.6,0.9].map((h,i)=>(<div key={i} style={{width:"4px",height:(h*20)+"px",background:c,borderRadius:"2px",animation:"pulse 1.2s ease infinite",animationDelay:(i*0.15)+"s"}}/>))}</div>);}
function ErrBox({msg}){return(<div style={{padding:"12px 16px",background:"rgba(255,82,82,0.08)",border:"1px solid rgba(255,82,82,0.25)",borderRadius:"7px",color:"#ff5252",fontSize:"12px",marginBottom:"12px"}}>{msg}</div>);}
function TierBadge({tier}){const c=TIER_C[tier]||"#888";return(<span style={{padding:"2px 7px",background:c+"20",border:"1px solid "+c+"50",borderRadius:"4px",color:c,fontFamily:JM,fontSize:"9px",fontWeight:"800",letterSpacing:"1px"}}>{tier}</span>);}

function LivePrice({ticker,large}){
  const [lp,setLp]=useState(null);
  const [loading,setLoading]=useState(false);
  useEffect(()=>{
    if(!ticker)return;
    setLoading(true);
    fetchPrice(ticker).then(r=>{setLp(r);setLoading(false);}).catch(()=>setLoading(false));
  },[ticker]);
  const fs=large?"18px":"12px";
  if(loading)return <span style={{fontFamily:JM,fontSize:fs,color:"#555"}}>...</span>;
  if(!lp)return null;
  const cc=lp.change?.startsWith("+")||lp.change?.startsWith("-")?lp.change.startsWith("+")?""+"#00e676":"#ff5252":"#888";
  return(<span style={{fontFamily:JM,fontSize:fs,fontWeight:"700"}}><span style={{color:"#fff"}}>{lp.price}</span>{lp.change&&<span style={{color:cc,marginLeft:"5px",fontSize:large?"13px":"10px"}}>{lp.change}</span>}</span>);
}

function AccessCodeModal({onSuccess}){
  const [input,setInput]=React.useState("");
  const [error,setError]=React.useState(false);
  const CODES=["BETA2025","TRADEIQ1","TRADEIQ2","TRADEIQ3","TRADEIQ4","TRADEIQ5","OWNER"];
  function check(){
    if(CODES.includes(input.toUpperCase().trim())){
      try{localStorage.setItem("tiq_access",input.toUpperCase().trim());}catch(_){}
      onSuccess();
    } else {
      setError(true);
      setTimeout(function(){setError(false);},2000);
    }
  }
  return(
    <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.97)",zIndex:10000,display:"flex",alignItems:"center",justifyContent:"center",padding:"20px"}}>
      <div style={{background:"#0d1117",border:"1px solid rgba(255,145,0,0.2)",borderRadius:"14px",maxWidth:"420px",width:"100%",padding:"40px",textAlign:"center"}}>
        <div style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"20px",fontWeight:"800",color:"#ff9100",letterSpacing:"3px",marginBottom:"8px"}}>TRADEIQ</div>
        <div style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"10px",color:"#555",letterSpacing:"3px",marginBottom:"32px"}}>AI MARKET INTELLIGENCE</div>
        <div style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"11px",color:"#888",letterSpacing:"2px",marginBottom:"16px"}}>ENTER ACCESS CODE</div>
        <input
          value={input}
          onChange={function(e){setInput(e.target.value);}}
          onKeyDown={function(e){if(e.key==="Enter")check();}}
          placeholder="Access code..."
          style={{width:"100%",padding:"14px 16px",background:"rgba(255,255,255,0.04)",
            border:"1px solid "+(error?"rgba(255,82,82,0.5)":"rgba(255,255,255,0.1)"),
            borderRadius:"6px",color:"#fff",fontFamily:"'JetBrains Mono',monospace",
            fontSize:"14px",letterSpacing:"2px",textAlign:"center",marginBottom:"12px",
            outline:"none"}}
          autoFocus
        />
        {error&&<div style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"10px",color:"#ff5252",marginBottom:"12px",letterSpacing:"1px"}}>INVALID CODE -- TRY AGAIN</div>}
        <button onClick={check}
          style={{width:"100%",padding:"14px",background:"#ff9100",border:"none",
            borderRadius:"6px",color:"#000",fontFamily:"'JetBrains Mono',monospace",
            fontSize:"12px",fontWeight:"800",cursor:"pointer",letterSpacing:"2px",marginBottom:"24px"}}>
          ENTER
        </button>
        <div style={{fontSize:"12px",color:"#444",lineHeight:"1.7"}}>
          {"Don't have an access code? "}
          <a href="#" style={{color:"#ff9100",textDecoration:"none"}}>Request early access</a>
        </div>
      </div>
    </div>
  );
}

function DisclaimerModal({onAccept}){
  return(
    <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.95)",zIndex:9999,display:"flex",alignItems:"center",justifyContent:"center",padding:"20px"}}>
      <div style={{background:"#0d1117",border:"1px solid rgba(255,235,59,0.3)",borderRadius:"14px",maxWidth:"580px",width:"100%",padding:"32px"}}>
        <div style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"14px",fontWeight:"800",color:"#ffeb3b",letterSpacing:"2px",marginBottom:"6px"}}>TRADEIQ</div>
        <div style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"10px",fontWeight:"700",color:"#888",letterSpacing:"2px",marginBottom:"20px"}}>IMPORTANT LEGAL DISCLAIMER</div>
        <div style={{fontSize:"13px",fontWeight:"500",color:"#d8d8d8",lineHeight:"1.8",marginBottom:"20px"}}>
          <strong style={{color:"#fff"}}>TRADEIQ is for informational and educational purposes only.</strong><br/><br/>
          This tool does <strong style={{color:"#ffeb3b"}}>NOT</strong> constitute financial advice, investment advice, or any other type of advice. Nothing on this platform should be construed as a recommendation to buy, sell, or hold any security or financial instrument.<br/><br/>
          <strong style={{color:"#fff"}}>AI-generated analysis may be inaccurate, incomplete, or outdated.</strong> Insider trade data, news analysis, and stock scores are generated by artificial intelligence and may not reflect real-time or accurate market conditions.<br/><br/>
          <strong style={{color:"#fff"}}>Trading involves substantial risk of loss.</strong> Past signals and analysis do <strong style={{color:"#ffeb3b"}}>NOT</strong> guarantee future results. You may lose some or all of your invested capital.<br/><br/>
          <strong style={{color:"#fff"}}>Always conduct your own research</strong> and consult a qualified, licensed financial advisor before making any investment decisions. TRADEIQ is <strong style={{color:"#ffeb3b"}}>NOT</strong> registered as an investment advisor, broker-dealer, or financial institution.
        </div>
        <button onClick={onAccept} style={{width:"100%",padding:"14px",background:"rgba(0,230,118,0.1)",border:"1px solid rgba(0,230,118,0.4)",borderRadius:"8px",color:"#00e676",fontFamily:"'JetBrains Mono',monospace",fontSize:"12px",fontWeight:"800",cursor:"pointer",letterSpacing:"1px"}}>
          I UNDERSTAND AND AGREE -- CONTINUE TO TRADEIQ
        </button>
      </div>
    </div>
  );
}

/* -- WATCHLIST MANAGER ------------------------------------- */

function WatchlistModal({list,onSave,onClose}){
  const [input,setInput]=useState((list||[]).join(", "));
  function save(){
    const tickers=input.toUpperCase().split(/[\s,]+/).map(t=>t.trim()).filter(t=>/^[A-Z]{1,5}$/.test(t));
    onSave(tickers);onClose();
  }
  return(
    <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.85)",zIndex:9999,display:"flex",alignItems:"center",justifyContent:"center",padding:"20px"}}>
      <div style={{background:"#0d1117",border:"1px solid rgba(0,230,118,0.3)",borderRadius:"12px",padding:"28px",maxWidth:"500px",width:"100%"}}>
        <div style={{fontFamily:JM,fontSize:"11px",fontWeight:"800",color:"#00e676",letterSpacing:"2px",marginBottom:"16px"}}>EDIT WATCHLIST</div>
        <textarea value={input} onChange={e=>setInput(e.target.value)} rows={4}
          style={{width:"100%",padding:"10px",background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.12)",borderRadius:"6px",color:"#fff",fontFamily:JM,fontSize:"12px",resize:"vertical",marginBottom:"14px",boxSizing:"border-box"}}
          placeholder="AAPL, TSLA, NVDA..."/>
        <div style={{display:"flex",gap:"10px"}}>
          <button onClick={save} style={{flex:1,padding:"10px",background:"rgba(0,230,118,0.1)",border:"1px solid rgba(0,230,118,0.3)",borderRadius:"6px",color:"#00e676",fontFamily:JM,fontSize:"11px",fontWeight:"700",cursor:"pointer"}}>SAVE</button>
          <button onClick={onClose} style={{padding:"10px 20px",background:"transparent",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"6px",color:"#888",fontFamily:JM,fontSize:"11px",fontWeight:"700",cursor:"pointer"}}>CANCEL</button>
        </div>
      </div>
    </div>
  );
}
/* -- PROMPTS ----------------------------------------------- */
const ANALYSIS_SYS = `You are an unbiased senior market analyst. Return ONLY valid raw JSON. CRITICAL: Do NOT default to bullish. PRICE RULE: The current live price is in the user message - use it for ALL entry/target/stop levels within 1-2% for intraday. SHORT SETUP RULE: When overall_bias is Bearish - set direction to "SHORT" on all setups, entry near current price or breakdown level, target BELOW current price, stop ABOVE entry. When overall_bias is Bullish - set direction to "LONG", entry near current price or breakout, target ABOVE, stop BELOW. Neutral - use most likely direction. If technicals are weak, macro is negative, or fundamentals deteriorating - return Bearish honestly.

SCORING 0-100 per factor:
- Technical: trend, pattern quality, key levels, indicator confluence
- Momentum: price rate-of-change vs sector(40%) + volume vs 30d avg(40%) + relative strength(20%)
- Catalyst: 0 if none, 90+ if major catalyst
- Insider: 90+ if CEO/CFO open market buy >$1M last 30 days, 70+ if cluster 3+ buying, 50 if none, 20 if selling
- Sentiment: news tone + analyst consensus + options flow
- Fundamental: revenue growth, earnings trend, valuation vs peers
- Macro: rate environment, sector tailwinds/headwinds

CONVICTION per timeframe:
- Intraday: Technical(45%)+Momentum(25%)+Catalyst(20%)+Macro(5%)+Sentiment(5%)
- Short Term: Technical(35%)+Momentum(20%)+Catalyst(20%)+Sentiment(10%)+Fundamental(10%)+Macro(5%)
- Medium Term: Technical(25%)+Fundamental(25%)+Momentum(15%)+Sentiment(15%)+Catalyst(10%)+Macro(10%)
- Long Term: Fundamental(40%)+Macro(20%)+Sentiment(20%)+Momentum(10%)+Technical(5%)+Catalyst(5%)

OVERALL SCORE: Technical(20%)+Momentum(20%)+Catalyst(15%)+Fundamental(20%)+Macro(15%)+Sentiment(10%)

THRESHOLDS: 90+=Exceptional, 80-89=Strong, 70-79=Moderate, 60-69=Weak, below 60=skip_reason required, leave entry/target/stop blank.

VOLUME: relative_volume>2x boost Momentum +10pts. <0.5x reduce -15pts and add key_risk about low volume.

EARNINGS: Search next earnings date. Within 5 days set earnings_warning. Within 2 days skip short_term setup.

POSITION SIZING: overall_score 85+/SPY risk-on/no earnings=Full Size(2%). 70-84 or SPY risk-off=Half Size(1%). 60-69 or earnings within 5d=Quarter Size(0.5%). Below 60 or SPY down 2%+=Avoid.

INTRADAY NEWS: If catalyst score 70+: wait 9:45am candle, gap fill or resistance as target, gap support or MA as stop, notes include 2pm exit and chase warning if gap 8%+.

TRADE SETUP PRICE RULES - MANDATORY:
The user message contains CURRENT LIVE PRICE. Use it as BASE for ALL entry/target/stop.
LONG SETUPS (Bullish): entry=live*1.001, intraday target=live*1.015, intraday stop=live*0.990. Short term target=live*1.04, stop=live*0.97. Swing target=live*1.08, stop=live*0.95. Medium target=live*1.15, stop=live*0.93. Long target=live*1.25, stop=live*0.90.
SHORT SETUPS (Bearish): entry=live*0.999, intraday target=live*0.985, intraday stop=live*1.010. Short term target=live*0.96, stop=live*1.03. Swing target=live*0.92, stop=live*1.05. Medium target=live*0.85, stop=live*1.07. Long target=live*0.75, stop=live*1.10.
ADJUST levels to nearest key support/resistance. Widen stops 20% if earnings within 5 days or VIX above 25.
R:R MINIMUMS: Intraday 1.5:1, Short Term 2:1, Medium Term 3:1, Long Term 4:1. Always show entry/target/stop. If below minimum set skip_reason as caution warning only.

Return this exact JSON:
{"ticker":"","company_name":"","asset_type":"","sector":"","overall_bias":"Bullish","overall_score":76,"confidence":"High","bias_summary":"","scores":{"technical":{"score":65,"label":"Bullish","summary":""},"momentum":{"score":70,"label":"Strong","summary":""},"catalyst":{"score":50,"label":"Neutral","detail":""},"fundamental":{"score":70,"label":"Bullish","summary":""},"macro":{"score":50,"label":"Neutral","summary":""},"sentiment":{"score":60,"label":"Bullish","summary":""}},"technical_details":{"trend":"","chart_pattern":"","key_levels":{"support":"","resistance":""},"indicators":[{"name":"RSI","value":"","signal":"Bullish"},{"name":"MACD","value":"","signal":"Neutral"},{"name":"50 MA","value":"","signal":"Bullish"}]},"fundamental_details":{"market_cap":"","pe_ratio":"","forward_pe":"","revenue_growth":"","earnings_trend":"","next_catalyst":""},"macro_details":{"rate_environment":"","sector_tailwinds":[""],"sector_headwinds":[""]},"earnings_date":"","earnings_warning":"","analyst_targets":{"consensus":"","target_low":"","target_high":"","target_avg":"","upside":"","num_analysts":0},"position_size":"","position_size_reason":"","bull_case":["","",""],"bear_case":["","",""],"key_risks":["",""],"trade_setups":{"intraday":{"conviction_score":84,"timeframe":"Intraday (Today)","direction":"LONG","entry":"","target":"","stop":"","risk_reward":"","notes":"","skip_reason":""},"short_term":{"conviction_score":78,"timeframe":"2-5 Days","entry":"","target":"","stop":"","risk_reward":"","notes":"","skip_reason":""},"medium_term":{"conviction_score":71,"timeframe":"1-4 Weeks","entry":"","target":"","stop":"","risk_reward":"","notes":"","skip_reason":""},"long_term":{"conviction_score":65,"timeframe":"1-6 Months","entry":"","target":"","stop":"","risk_reward":"","notes":"","skip_reason":""}}}`;


const NEWS_SYS=`You are an unbiased news-driven trading analyst. Search for ALL recent news - both positive AND negative. CRITICAL: Do NOT default to bullish predictions. Be honest and objective.

SEARCH FOR ALL OF THE FOLLOWING:
1. COMPANY NEWS: earnings beats/misses, guidance raised/lowered, product launches, CEO changes, layoffs, lawsuits, FDA decisions, contract wins/losses, analyst upgrades/downgrades
2. SECTOR NEWS: sector rotation, industry headwinds/tailwinds, competitor moves, regulatory changes
3. MACRO NEWS - DIRECT IMPACT: Fed rate decisions, CPI/PCE/PPI inflation data, NFP jobs report, jobless claims, GDP, retail sales, ISM Manufacturing/Services, consumer confidence, Michigan sentiment
4. MACRO NEWS - INDIRECT IMPACT: oil price moves (>2% matters), dollar/DXY strength or weakness, China economy/PMI/property crisis, geopolitical tensions, wars, sanctions, strait closures, trade tariffs, Treasury yield moves (10yr), VIX level
5. MARKET SENTIMENT: VIX spikes, sector rotation, institutional selling, short interest changes

If NEGATIVE news dominates - return SHORT/Bearish. If POSITIVE news dominates - return LONG/Bullish. If mixed - return NEUTRAL.

VOLUME CONFIRMATION: Search current volume vs 30-day average. Adjust conviction_score DOWN 15pts if relative_volume < 0.5x. Boost UP 10pts if relative_volume > 2x.

EARNINGS CHECK: Search next earnings date. If within 5 days set earnings_warning.

BEST TIMEFRAME: Recommend single best timeframe based on catalyst_type:
- Earnings Beat/Miss: "Short Term (2-5 days)"
- FDA Approval/Rejection: "Daily (Today)"
- M&A/Buyout: "Swing (1-4 weeks)"
- Analyst Upgrade/Downgrade: "Short Term (2-5 days)"
- Macro/Fed/CPI: "Swing (1-4 weeks)"
- Geopolitical: "Daily (Today)"
- Product Launch: "Short Term (2-5 days)"

CONVICTION SCORE: conviction_score 0-100 = catalyst_strength(40%) + confidence(35%) + news_quality(25%). news_quality: 90 if 3+ HIGH impact items, 70 if 1-2 HIGH, 50 if MEDIUM only, 30 if LOW only.

POSITION SIZING:
- Full Size (2% risk): conviction 90+, SPY risk-on, volume 2x+, no earnings within 5 days
- Half Size (1% risk): conviction 70-89, OR SPY risk-off, OR low volume
- Quarter Size (0.5% risk): conviction 60-69, OR earnings within 5 days
- Avoid: conviction below 60, OR SPY down 2%+

PREDICTION SUMMARY: 2-3 sentences with specific catalyst magnitude, volume confirmation, key risk, expected move. Be specific with actual numbers - no generic statements.

Return ONLY raw JSON (no markdown):
{"ticker":"","company_name":"","prediction":"UP","confidence":72,"conviction_score":81,"catalyst_strength":85,"expected_move":"+2.5%","prediction_summary":"","trade_action":"BUY","catalyst_type":"Earnings","news_items":[{"headline":"","source":"","hours_ago":2,"impact":"HIGH","sentiment":"Bullish"},{"headline":"","source":"","hours_ago":4,"impact":"HIGH","sentiment":"Bullish"},{"headline":"","source":"","hours_ago":6,"impact":"MEDIUM","sentiment":"Neutral"}],"avoid_if":"","position_size":"","position_size_reason":"","volume_context":{"current_volume":"","avg_volume":"","relative_volume":"","volume_signal":""},"earnings_date":"","earnings_warning":"","best_timeframe":"Short Term (2-5 days)","best_timeframe_reason":""}`;

const CATALYST_SYS="You are a real-time market catalyst scanner. Search the web RIGHT NOW for the most significant news events TODAY across all major US stocks and ETFs. Large-cap only ($10B+ market cap, volume >1M/day). All sectors: Technology, Healthcare, Energy, Materials/Gold, Financials, Consumer, Industrials, Utilities, and major ETFs (SPY, QQQ, GLD, USO, XLK, XLV, XLE, XLF, XBI). Exclude penny stocks and stocks under $5. Return ONLY stocks with conviction score 90+. SCORING FORMULA - calculate score 0-100 using same formula as manual analysis: catalyst_strength(40%) + confidence(35%) + news_quality(25%). catalyst_strength: 90+ if major catalyst (earnings beat/miss, FDA decision, M&A), 70 if moderate news, 50 if minor. confidence: how certain is the directional move. news_quality: 90 if 3+ major sources confirm, 70 if 1-2 sources, 50 if single source. Only return stocks where calculated score is 90+. Return ONLY a raw JSON array with double-quoted keys: example: [{\"ticker\":\"NVDA\",\"company_name\":\"NVIDIA\",\"sector\":\"Technology\",\"score\":95,\"direction\":\"LONG\",\"catalyst\":\"Earnings beat\",\"catalyst_type\":\"Earnings\",\"expected_move\":\"+5%\",\"why_now\":\"Gap up on volume\"}]. direction: LONG=bullish, SHORT=bearish. Max 10 results sorted by score descending.";




const SCREENER_SYS=`You are a technical momentum screener. Analyze each stock for technical setup quality RIGHT NOW. Return ONLY raw JSON array (no markdown):
[{"ticker":"","company_name":"","sector":"Technology","score":88,"direction":"LONG","setup_type":"Breakout","signal":"Breaking above 50-day MA on 2x average volume","why_now":"Strong momentum with institutional buying detected","confidence":"HIGH"}]
Score 0-100 using: technical pattern quality (40pts) + momentum vs sector (30pts) + volume confirmation (20pts) + catalyst present (10pts).
Direction: LONG=bullish setup, SHORT=bearish setup. Return only stocks scoring 80+. Do NOT include entry, target, stop or R:R.`;

const CONGRESS_SYS=`You are a financial data assistant. Search housestockwatcher.com and senatestockwatcher.com for recent US Congress stock trades. Return ONLY raw JSON array (no markdown):
[{"representative":"","ticker":"","transaction_type":"Purchase","amount":"$15,001-$50,000","transaction_date":"","asset_description":""}]`;

/* -- INSIDER SCAN ------------------------------------------- */
const INSIDER_SYS=`You are an expert insider trading analyst. Search SEC EDGAR Form 4 filings and OpenInsider.com for recent insider PURCHASES only. Ignore sales.

CONVICTION SCORING - score each trade 0-100:
- Transaction size >$1M: +35pts | $500K-$1M: +25pts | $100K-$500K: +15pts | below $100K: +5pts
- Role: CEO/CFO: +25pts | 10%+ shareholder: +20pts | Director: +15pts | VP/Other: +5pts
- Ownership change >5%: +15pts | 2-5%: +10pts | below 2%: +5pts
- First time buyer (never bought before): +10pts bonus
- Buying during price decline >10%: +10pts bonus
- Cluster (3+ insiders same stock same week): +15pts bonus

10b5-1 FILTER: Flag ALL 10b5-1 plan purchases with is_10b51:true. These are pre-scheduled automatic purchases with NO conviction signal. Prioritize open market purchases (is_10b51:false) only.

CONVICTION TIERS: 85+=ULTRA | 70-84=HIGH | 55-69=MEDIUM | below 55=WATCH

IGNORE: Purchases below $50,000. Option exercises. RSU/stock grants. Sales of any kind.

Return ONLY raw JSON (no markdown):
{"trades":[{"ticker":"","company_name":"","sector":"","insider_name":"","insider_title":"","transaction_date":"","shares":10000,"price_per_share":45.20,"total_value":452000,"transaction_type":"P","ownership_change_pct":2.1,"is_10b51":false,"conviction_score":78,"conviction_tier":"HIGH","first_time_buyer":false,"buying_dip":false,"signal_summary":""}],"cluster_alerts":[{"ticker":"","company_name":"","total_insiders":3,"total_value":1500000,"date_range":"","strength_label":"STRONG","conviction_score":88}],"strong_clusters":[]}`;

function getImportance(trade){
  var score=trade.score||0;
  var val=trade.total_value||0;
  var title=(trade.insider_title||"").toUpperCase();
  var isCEO=title.includes("CEO")||title.includes("PRESIDENT")||title.includes("CFO");
  if(score>=80||val>=1000000||isCEO)return{label:"HIGH",color:"#ff5252",bg:"rgba(255,82,82,0.08)"};
  if(score>=60||val>=200000)return{label:"MEDIUM",color:"#ffeb3b",bg:"rgba(255,235,59,0.08)"};
  return{label:"WATCH",color:"#555",bg:"rgba(255,255,255,0.03)"};
}

function getSummary(trade){
  var val=trade.total_value||0;
  var title=(trade.insider_title||"Unknown").split("/").join(" ");
  var valStr=val>=1000000?"$"+(val/1000000).toFixed(1)+"M":"$"+(val/1000).toFixed(0)+"K";
  var is10b5=trade.is_10b51?"Pre-scheduled 10b5-1 plan - lower conviction signal.":"Open market purchase - genuine conviction signal.";
  var size=val>=1000000?"Large purchase signals strong conviction.":val>=200000?"Meaningful purchase for this role.":"Routine-sized purchase.";
  return title+" purchased "+valStr+" on the open market. "+size+" "+is10b5+(trade.signal_summary?" "+trade.signal_summary:"");
}

function calcScore(trade){
  let s=0;
  const title=(trade.insider_title||"").toUpperCase();
  if(title.includes("CEO")||title.includes("PRESIDENT"))s+=30;
  else if(title.includes("CFO")||title.includes("CHIEF"))s+=25;
  else if(title.includes("DIRECTOR"))s+=15;
  else s+=10;
  const v=trade.total_value||0;
  if(v>=1000000)s+=30;else if(v>=500000)s+=22;else if(v>=250000)s+=15;else if(v>=100000)s+=8;else s+=3;
  if(!trade.is_10b51)s+=10;
  const chg=trade.ownership_change_pct||0;
  if(chg>=10)s+=15;else if(chg>=5)s+=8;else if(chg>=2)s+=4;
  return Math.min(99,Math.round(s));
}

function getTier(score){if(score>=80)return"ULTRA";if(score>=65)return"HIGH";if(score>=45)return"MEDIUM";return"WATCH";}

function ClusterCard({cluster,onAnalyze}){
  const str=cluster.strength_label==="STRONG";
  const c=str?"#ff3d71":"#ffeb3b";
  return(
    <div style={{padding:"14px 16px",background:c+"08",border:"1px solid "+c+"30",borderRadius:"8px",display:"flex",justifyContent:"space-between",alignItems:"center",gap:"12px",flexWrap:"wrap"}}>
      <div>
        <div style={{display:"flex",alignItems:"center",gap:"8px",marginBottom:"4px"}}>
          <span style={{fontFamily:JM,fontSize:"15px",fontWeight:"800",color:"#fff"}}>{cluster.ticker}</span>
          <span style={{fontSize:"9px",fontWeight:"800",padding:"2px 6px",borderRadius:"3px",color:c,background:c+"15"}}>{cluster.strength_label}</span>
        </div>
        <div style={{fontSize:"11px",color:"#888"}}>{cluster.company_name}</div>
        <div style={{fontSize:"10px",color:"#555",marginTop:"3px"}}>{cluster.total_insiders+" insiders . "+fmtMoney(cluster.total_value)+" total"}</div>
      </div>
      {onAnalyze&&<button onClick={()=>onAnalyze(cluster.ticker)} style={{padding:"6px 14px",background:"rgba(56,189,248,0.08)",border:"1px solid rgba(56,189,248,0.25)",borderRadius:"5px",color:"#38bdf8",fontFamily:JM,fontSize:"10px",fontWeight:"700",cursor:"pointer"}}>ANALYZE</button>}
    </div>
  );
}

function DrillPanel({trade,onClose}){
  const [loading,setLoading]=useState(false);
  const [data,setData]=useState(null);
  const [error,setError]=useState(null);
  async function run(){
    setLoading(true);setError(null);
    try{
      const msg="Analyze this insider trade: "+trade.insider_name+" ("+trade.insider_title+") at "+trade.company_name+" ("+trade.ticker+") bought "+(trade.shares||0).toLocaleString()+" shares at $"+trade.price_per_share+" = $"+((trade.total_value||0)/1e6).toFixed(2)+"M on "+trade.transaction_date+(trade.is_10b51?" [10b5-1 PLAN - pre-scheduled]":" [OPEN MARKET PURCHASE]")+(trade.ownership_change_pct?" Ownership change: "+trade.ownership_change_pct+"%":"")+". Search for company news, fundamentals, and why this insider bought now. Return ONLY valid JSON: {\"conviction_tier\":\"HIGH\",\"thesis\":\"\",\"why_now\":\"\",\"historical_pattern\":\"\",\"catalysts\":[\"\"],\"trade_setup\":{\"entry_zone\":\"\",\"target_1\":\"\",\"target_2\":\"\",\"stop_loss\":\"\",\"timeframe\":\"\",\"risk_reward\":\"\"},\"risks\":[\"\"],\"verdict\":\"Buy\",\"verdict_reason\":\"\"}";
      const DRILL_SYS="You are an expert insider trading analyst. Analyze this specific insider trade deeply. CRITICAL: Do NOT default to bullish - if the company has weak fundamentals or the trade is routine/small, say so honestly. Search for: (1) Why this insider is buying NOW - what do they know? (2) Company fundamentals and recent news, (3) Historical pattern - has this insider bought before and what happened?, (4) Current stock technical setup, (5) Whether this is a genuine conviction buy or routine/scheduled purchase. CONVICTION SCORING: CEO/CFO open market buy >$1M during dip = ULTRA. Small director buy or 10b5-1 = LOW. Return ONLY valid JSON.";
      setData(parseJSON(await callAPI(DRILL_SYS,msg)));
    }catch(e){setError(e.message);}
    finally{setLoading(false);}
  }
  const VC={  "Strong Buy":"#00e676",Buy:"#69f0ae",Watch:"#ffeb3b",Pass:"#ff5252"};
  return(
    <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.85)",zIndex:1000,display:"flex",alignItems:"center",justifyContent:"center",padding:"20px"}} onClick={onClose}>
      <div style={{background:"#0d1117",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"12px",maxWidth:"620px",width:"100%",maxHeight:"85vh",overflow:"auto",padding:"28px"}} onClick={e=>e.stopPropagation()}>
        <div style={{display:"flex",justifyContent:"space-between",marginBottom:"20px"}}>
          <div>
            <div style={{display:"flex",alignItems:"center",gap:"10px",marginBottom:"4px"}}>
              <span style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"22px",fontWeight:"700",color:"#fff"}}>{trade.ticker}</span>
              <TierBadge tier={trade.conviction_tier}/>
              {trade.is_cluster&&<span style={{fontSize:"11px",color:"#ff3d71",background:"rgba(255,61,113,0.1)",padding:"2px 8px",borderRadius:"3px"}}>{"CLUSTER x"+trade.cluster_count}</span>}
            </div>
            <div style={{color:"#ccc",fontSize:"13px"}}>{trade.company_name}</div>
          </div>
          <button onClick={onClose} style={{background:"none",border:"none",color:"#bbb",cursor:"pointer",fontSize:"20px",fontWeight:"700"}}>{"X"}</button>
        </div>
        {onAnalyze&&trade&&(
          <button onClick={function(){onAnalyze(trade.ticker);onClose();}}
            style={{width:"100%",padding:"8px",background:"rgba(56,189,248,0.1)",
              border:"1px solid rgba(56,189,248,0.3)",borderRadius:"6px",
              color:"#38bdf8",fontFamily:JM,fontSize:"10px",fontWeight:"800",
              cursor:"pointer",marginBottom:"10px",letterSpacing:"1px"}}>
            ANALYZE IN STOCK ANALYSIS -
          </button>
        )}
        <div style={{display:"grid",gridTemplateColumns:"1fr 1fr 1fr",gap:"10px",marginBottom:"16px"}}>
          {[["Insider",(ROLE_I[trade.insider_title]||"")+" "+trade.insider_name],["Role",trade.insider_title],["Total",fmtMoney(trade.total_value)],["Shares",(trade.shares||0).toLocaleString()],["Price","$"+trade.price_per_share],["Date",trade.transaction_date]].map(([k,v])=>(
            <div key={k} style={{background:"rgba(255,255,255,0.03)",borderRadius:"6px",padding:"10px"}}>
              <div style={{fontSize:"10px",color:"#bbb",marginBottom:"4px"}}>{k}</div>
              <div style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"12px",color:"#ddd"}}>{v}</div>
            </div>
          ))}
        </div>
        <div style={{fontSize:"13px",color:"#ddd",lineHeight:"1.7",marginBottom:"16px",padding:"12px",background:"rgba(255,255,255,0.02)",borderRadius:"6px",borderLeft:"2px solid #333"}}>{trade.why_notable}</div>
        {!data&&!loading&&<button onClick={run} style={{width:"100%",padding:"14px",background:"transparent",border:"1px solid #00e676",borderRadius:"8px",color:"#00e676",fontFamily:"'JetBrains Mono',monospace",fontSize:"13px",cursor:"pointer"}}>GENERATE TRADE THESIS</button>}
        {loading&&<div style={{textAlign:"center",padding:"24px"}}><div style={{display:"flex",justifyContent:"center",marginBottom:"8px"}}><Bars color="#00e676"/></div><div style={{color:"#00e676",fontFamily:"'JetBrains Mono',monospace",fontSize:"11px"}}>Analyzing...</div></div>}
        {error&&<ErrBox msg={error} onRetry={run}/>}
        {data&&(
          <div style={{display:"flex",flexDirection:"column",gap:"14px"}}>
            <div style={{display:"flex",alignItems:"center",gap:"12px",padding:"14px",background:(VC[data.verdict]||"#fff")+"15",borderRadius:"8px",border:"1px solid "+(VC[data.verdict]||"#fff")+"33"}}>
              <span style={{fontSize:"18px",fontWeight:"800",color:VC[data.verdict]||"#fff"}}>{data.verdict}</span>
              <span style={{fontSize:"13px",color:"#bbb",lineHeight:"1.5"}}>{data.verdict_reason}</span>
            </div>
            <div><div style={{fontSize:"10px",color:"#bbb",letterSpacing:"2px",marginBottom:"6px"}}>THESIS</div><div style={{fontSize:"13px",color:"#ccc",lineHeight:"1.8"}}>{data.thesis}</div></div>
            {data.trade_setup&&(
              <div style={{background:"rgba(0,230,118,0.04)",border:"1px solid rgba(0,230,118,0.15)",borderRadius:"8px",padding:"16px"}}>
                <div style={{fontSize:"10px",color:"#00e676",letterSpacing:"2px",marginBottom:"12px"}}>TRADE SETUP</div>
                <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"10px"}}>
                  {[["Entry Zone",data.trade_setup.entry_zone],["Target 1",data.trade_setup.target_1],["Target 2",data.trade_setup.target_2],["Stop Loss",data.trade_setup.stop_loss],["Timeframe",data.trade_setup.timeframe],["R/R",data.trade_setup.risk_reward]].map(([k,v])=>(
                    <div key={k}><div style={{fontSize:"10px",color:"#bbb",marginBottom:"2px"}}>{k}</div><div style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"13px",color:"#fff"}}>{v||"--"}</div></div>
                  ))}
                </div>
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

/* -- INSIDER SCAN ------------------------------------------ */

function ConvBar({score,tier}){const c=TIER_C[tier]||"#888";return(<div style={{display:"flex",alignItems:"center",gap:"8px"}}><div style={{width:"60px",height:"4px",background:"rgba(255,255,255,0.08)",borderRadius:"2px",overflow:"hidden"}}><div style={{width:score+"%",height:"100%",background:"linear-gradient(90deg,"+c+"88,"+c+")",borderRadius:"2px"}}/></div><span style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"11px",color:c}}>{score}</span></div>);}


function SinceInsiderBuy({ticker,buyPrice}) {
  const [pct,setPct]=useState(null);
  useEffect(()=>{
    const bp=parseFloat(buyPrice);
    if(!ticker||!bp||bp<=0)return;
    fetchPrice(ticker).then(lp=>{
      if(lp?.raw){const p=((lp.raw-bp)/bp)*100;setPct(p);}
    });
  },[ticker,buyPrice]);
  if(pct===null)return <span style={{fontSize:"10px",color:"#bbb"}}>--</span>;
  const c=pct>=5?"#00e676":pct>=0?"#69f0ae":pct>=-5?"#ff9100":"#ff5252";
  return <span style={{fontFamily:"'JetBrains Mono',monospace",fontSize:"12px",fontWeight:"800",color:c,background:c+"15",border:"1px solid "+c+"44",padding:"2px 7px",borderRadius:"4px"}}>{(pct>=0?"+":"")+pct.toFixed(1)+"%"}</span>;
}

/* -- UI ATOMS ---------------------------------------------- */
function fmtMoney(n){if(!n)return"--";if(n>=1e6)return"$"+(n/1e6).toFixed(2)+"M";if(n>=1e3)return"$"+(n/1e3).toFixed(0)+"K";return"$"+n;}

function InsiderScan({onAnalyze,watchlist}){
  const [loading,setLoading]=useState(false);
  const [scanData,setScanData]=useState(null);
  const [error,setError]=useState(null);
  const [status,setStatus]=useState("");
  const [cacheTs,setCacheTs]=useState(null);
  const [minValue,setMinValue]=useState(50000);
  const [tierFilter,setTierFilter]=useState("ALL");
  const [dateRange,setDateRange]=useState("7d");
  const [showSells,setShowSells]=useState(false);
  const [drillTrade,setDrillTrade]=useState(null);

  useEffect(()=>{
    loadCache("insider").then(c=>{if(c?.value){setScanData(c.value);setCacheTs(c.ts);}});
  },[]);

  async function scan(force){
    const SCAN_CACHE_MS=7*24*60*60*1000;
    if(!force&&cacheTs&&(Date.now()-cacheTs)<SCAN_CACHE_MS){
      if(!scanData){
        loadCache("insider").then(function(c){if(c&&c.value)setScanData(c.value);});
      }
      return;
    }
    setLoading(true);setError(null);setScanData(null);
    try{
      var wl=(watchlist&&watchlist.length>0?watchlist:DEFAULT_WL).slice(0,20).join(",");
      var today=new Date().toLocaleDateString("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric"});
      setStatus("Searching insider trades...");
      var text=await callAPI(INSIDER_SYS,"Today is "+today+". Find the 15 most significant insider PURCHASES (open market only, above $50K) in the last "+dateRange+" for these stocks: "+wl+". Focus on CEO, CFO, Director level purchases. Include cluster analysis where multiple insiders buy same stock. Return ONLY valid JSON starting with { and ending with }. Use double-quoted keys. No markdown.",8000);
      var parsed=parseJSON(text);
      if(parsed.trades){
        parsed.trades=parsed.trades.map(function(t){return Object.assign({},t,{score:t.conviction_score||calcScore(t),tier:t.conviction_tier||getTier(calcScore(t)),transaction_type:t.transaction_type||"P"});});
        if(!parsed.cluster_alerts)parsed.cluster_alerts=[];
        if(!parsed.strong_clusters)parsed.strong_clusters=[];
      }
      setScanData(parsed);saveCache("insider",parsed);setCacheTs(Date.now());
    }catch(e){setError(e.message);}
    setLoading(false);setStatus("");
  }

  const FILTERS=[{label:"$50K+",value:50000},{label:"$100K+",value:100000},{label:"$250K+",value:250000},{label:"$500K+",value:500000},{label:"$1M+",value:1000000}];
  const TIERS=["ALL","ULTRA","HIGH","MEDIUM","WATCH"];
  const filtered=(scanData?.trades||[]).filter(t=>(t.total_value||0)>=minValue&&(tierFilter==="ALL"||t.tier===tierFilter||(t.conviction_tier&&t.conviction_tier===tierFilter))&&(showSells||(t.transaction_type||"P")!=="S"&&(t.transaction_type||"P")!=="S"));

  return(
    <div>
      <div style={{display:"flex",alignItems:"center",gap:"10px",marginBottom:"12px",flexWrap:"wrap"}}>
        <button onClick={scan} disabled={loading} style={{padding:"12px 24px",background:"transparent",border:"1px solid #00e676",borderRadius:"7px",color:"#00e676",fontFamily:JM,fontSize:"12px",fontWeight:"800",cursor:loading?"not-allowed":"pointer",opacity:loading?0.7:1,letterSpacing:"1px"}}>
          {loading?<span style={{display:"flex",alignItems:"center",gap:"8px"}}><Bars color="#00e676"/>{status||"SCANNING..."}</span>:"SCAN INSIDER BUYS"}
        </button>
        <div style={{display:"flex",gap:"4px"}}>
          {["7d","30d","90d"].map(d=>(
            <button key={d} onClick={()=>setDateRange(d)} style={{padding:"5px 10px",background:dateRange===d?"rgba(0,230,118,0.1)":"transparent",border:"1px solid "+(dateRange===d?"rgba(0,230,118,0.4)":"rgba(255,255,255,0.08)"),borderRadius:"4px",color:dateRange===d?"#00e676":"#555",fontFamily:JM,fontSize:"9px",fontWeight:"700",cursor:"pointer"}}>{d}</button>
          ))}
        </div>
        <div style={{display:"flex",gap:"4px"}}>
          {["BUYS","ALL"].map(function(f){
            var isBuy=f==="BUYS";
            var active=isBuy?!showSells:showSells;
            return(
              <button key={f} onClick={function(){setShowSells(f==="ALL");}}
                style={{padding:"5px 10px",
                  background:active?"rgba(0,230,118,0.1)":"transparent",
                  border:"1px solid "+(active?"rgba(0,230,118,0.4)":"rgba(255,255,255,0.08)"),
                  borderRadius:"4px",color:active?"#00e676":"#555",
                  fontFamily:JM,fontSize:"9px",fontWeight:"700",cursor:"pointer"}}>
                {f}
              </button>
            );
          })}
        </div>
        {cacheTs&&!loading&&(
          <div style={{display:"flex",alignItems:"center",gap:"8px",marginLeft:"auto"}}>
            <span style={{fontFamily:JM,fontSize:"8px",fontWeight:"800",letterSpacing:"1px",
              color:scanData&&scanData.data_source==="REAL_SEC"?"#00e676":"#555"}}>
              {scanData&&scanData.data_source==="REAL_SEC"?"LIVE SEC DATA":"AI SEARCH"}
            </span>
            <span style={{fontSize:"10px",color:"#ddd"}}>{ago(cacheTs)}</span>
            <button onClick={function(){scan(true);}}
              style={{padding:"2px 8px",background:"transparent",border:"1px solid rgba(255,255,255,0.1)",
                borderRadius:"3px",color:"#ddd",fontFamily:JM,fontSize:"9px",cursor:"pointer"}}>
              REFRESH
            </button>
          </div>
        )}
      </div>

      <div style={{display:"flex",gap:"6px",marginBottom:"10px",flexWrap:"wrap"}}>
        {FILTERS.map(f=>(
          <button key={f.value} onClick={()=>setMinValue(f.value)} style={{padding:"5px 10px",background:minValue===f.value?"rgba(0,230,118,0.08)":"transparent",border:"1px solid "+(minValue===f.value?"rgba(0,230,118,0.3)":"rgba(255,255,255,0.07)"),borderRadius:"4px",color:minValue===f.value?"#00e676":"#555",fontFamily:JM,fontSize:"9px",fontWeight:"700",cursor:"pointer"}}>{f.label}</button>
        ))}
        {TIERS.map(t=>(
          <button key={t} onClick={()=>setTierFilter(t)} style={{padding:"5px 10px",background:tierFilter===t?"rgba(0,230,118,0.08)":"transparent",border:"1px solid "+(tierFilter===t?"rgba(0,230,118,0.3)":"rgba(255,255,255,0.07)"),borderRadius:"4px",color:tierFilter===t?"#00e676":"#555",fontFamily:JM,fontSize:"9px",fontWeight:"700",cursor:"pointer"}}>{t==="ALL"?"ALL TIERS":t}</button>
        ))}
      </div>

      {error&&<ErrBox msg={error}/>}

      {scanData?.strong_clusters?.length>0&&(
        <div style={{marginBottom:"16px"}}>
          <div style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:"#ff3d71",letterSpacing:"2px",marginBottom:"8px"}}>STRONG CLUSTERS</div>
          <div style={{display:"flex",flexDirection:"column",gap:"8px"}}>
            {scanData.strong_clusters.map((c,i)=><ClusterCard key={c.ticker+i} cluster={c} onAnalyze={onAnalyze}/>)}
          </div>
        </div>
      )}

      {scanData&&filtered.length===0&&!loading&&(
        <div style={{textAlign:"center",padding:"30px 20px",border:"1px dashed rgba(255,255,255,0.08)",borderRadius:"10px"}}>
          <div style={{fontFamily:JM,fontSize:"11px",color:"#ddd",marginBottom:"6px"}}>NO RESULTS FOUND</div>
          <div style={{fontSize:"12px",color:"#ccc"}}>{"No insider purchases match current filters. Try changing date range, lowering min value, or click REFRESH."}</div>
        </div>
      )}
      {filtered.length>0&&(
        <div style={{display:"flex",flexDirection:"column",gap:"12px"}}>
          {(function(){
            var sectors={};
            filtered.forEach(function(t){
              var s=t.sector||"Other";
              if(!sectors[s])sectors[s]={trades:[],total:0};
              sectors[s].trades.push(t);
              sectors[s].total+=(t.total_value||0);
            });
            var sorted=Object.keys(sectors).sort(function(a,b){return sectors[b].total-sectors[a].total;});
            return sorted.map(function(sector){
              var grp=sectors[sector];
              return(
                <div key={sector}>
                  <div style={{display:"flex",alignItems:"center",gap:"8px",marginBottom:"6px",paddingBottom:"6px",borderBottom:"1px solid rgba(255,255,255,0.06)"}}>
                    <span style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:"#a78bfa",letterSpacing:"1px"}}>{sector.toUpperCase()}</span>
                    <span style={{fontSize:"9px",color:"#ddd"}}>{grp.trades.length+" trade"+(grp.trades.length>1?"s":"")}</span>
                    <span style={{fontFamily:JM,fontSize:"9px",color:"#00e676",marginLeft:"auto"}}>{"$"+(grp.total/1e6).toFixed(1)+"M total"}</span>
                  </div>
                  <div style={{display:"flex",flexDirection:"column",gap:"8px"}}>
                    {grp.trades.map(function(trade,idx){
            const isBuy=trade.transaction_type!=="S";
            const tc=isBuy?"#00e676":"#ff5252";
            const score=trade.score||calcScore(trade);
            const tier=trade.tier||getTier(score);
            return(
              <div key={trade.ticker+idx} style={{padding:"16px",background:W04,border:"1px solid "+W08,borderRadius:"10px"}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",flexWrap:"wrap",gap:"8px",marginBottom:"8px"}}>
                  <div style={{display:"flex",alignItems:"center",gap:"10px",flexWrap:"wrap"}}>
                    <span style={{fontFamily:JM,fontSize:"18px",fontWeight:"800",color:"#fff"}}>{trade.ticker}</span>
                    <TierBadge tier={tier}/>
                    <span style={{fontSize:"9px",fontWeight:"800",padding:"2px 6px",borderRadius:"3px",color:tc,background:tc+"15"}}>{isBuy?"BUY":"SELL"}</span>
                    <ConvBar score={trade.score} tier={tier}/>
                    <LivePrice ticker={trade.ticker}/>
                  </div>
                  <div style={{textAlign:"right"}}>
                    <div style={{fontFamily:JM,fontSize:"20px",fontWeight:"800",color:"#00e676"}}>{score}</div>
                    <div style={{fontSize:"9px",color:"#ddd"}}>SCORE</div>
                  </div>
                </div>
                <div style={{fontSize:"12px",color:"#ccc",marginBottom:"6px"}}>{(ROLE_I[trade.insider_title]||"Insider")+" "+trade.insider_name+" . "+trade.insider_title}</div>
                <div style={{display:"flex",gap:"16px",flexWrap:"wrap",fontSize:"11px"}}>
                  <span style={{color:"#00e676",fontWeight:"600"}}>{fmtMoney(trade.total_value)}</span>
                  <span style={{color:"#ddd"}}>{"$"+trade.price_per_share+" x "+(trade.shares||0).toLocaleString()+" sh"}</span>
                  <span style={{color:"#ddd"}}>{trade.transaction_date}</span>
                  <span style={{fontSize:"10px",color:"#ddd"}}>{"Since buy: "}</span>
                  <SinceInsiderBuy ticker={trade.ticker} buyPrice={trade.price_per_share}/>
                  {trade.signal_summary&&(
                    <div style={{fontSize:"12px",color:"#ddd",lineHeight:"1.6",marginTop:"6px",fontWeight:"600",
                      paddingTop:"6px",borderTop:"1px solid rgba(255,255,255,0.08)"}}>
                      {trade.signal_summary}
                    </div>
                  )}
                  <div style={{marginTop:"10px",padding:"10px",background:getImportance(trade).bg,
                    border:"1px solid rgba(255,255,255,0.06)",borderRadius:"6px"}}>
                    <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"6px"}}>
                      <span style={{fontFamily:JM,fontSize:"9px",color:"#ddd",letterSpacing:"1px"}}>WHY IT MATTERS</span>
                      <span style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",
                        padding:"2px 7px",borderRadius:"3px",
                        color:getImportance(trade).color,
                        background:"rgba(0,0,0,0.3)"}}>
                        {getImportance(trade).label}
                      </span>
                    </div>
                    <div style={{fontSize:"12px",color:"#ddd",lineHeight:"1.6",fontWeight:"600"}}>
                      {getSummary(trade)}
                    </div>
                  </div>
                  {trade.is_10b51&&<span style={{color:"#ccc",fontSize:"9px",padding:"1px 5px",background:"rgba(255,255,255,0.05)",borderRadius:"3px"}}>10b5-1</span>}
                </div>
                {onAnalyze&&(
                  <button onClick={()=>onAnalyze(trade.ticker)} style={{marginTop:"10px",padding:"6px 14px",background:"rgba(56,189,248,0.08)",border:"1px solid rgba(56,189,248,0.25)",borderRadius:"5px",color:"#38bdf8",fontFamily:JM,fontSize:"10px",fontWeight:"700",cursor:"pointer"}}>DEEP ANALYSIS</button>
                )}
              </div>
            );
                    })}
                  </div>
                </div>
              );
            });
          })()}
        </div>
      )}

      {!loading&&!scanData&&(
        <div style={{textAlign:"center",padding:"50px 20px",border:"1px dashed rgba(0,230,118,0.15)",borderRadius:"12px"}}>
          <div style={{fontFamily:JM,fontSize:"11px",color:"#00e676",letterSpacing:"2px",marginBottom:"8px"}}>PRESS SCAN TO FIND INSIDER BUYS</div>
          <div style={{fontSize:"12px",color:"#ccc"}}>{"Click SCAN INSIDER BUYS to find significant insider purchases across your watchlist. Each trade is scored by role, transaction size and conviction level -- with a WHY IT MATTERS summary on every card."}</div>
        </div>
      )}
    </div>
  );
}
/* -- STOCK ANALYSIS ----------------------------------------- */
function StockAnalysis({initialTicker,watchlist,onAnalyze}){
  const [ticker,setTicker]=useState(initialTicker||"");
  const [loading,setLoading]=useState(false);
  const [data,setData]=useState(null);
  const [error,setError]=useState(null);
    const [cacheTs,setCacheTs]=useState(null);
  const [livePrice,setLivePrice]=useState(null); const [activeTab,setActiveTab]=useState("overview");
  const [spyData,setSpyData]=useState(null);

  useEffect(()=>{
    fetchPrice("SPY").then(r=>setSpyData(r)).catch(()=>{});
    var symToLoad=initialTicker||(typeof localStorage!=="undefined"?localStorage.getItem("sa_last_ticker"):null);
    if(symToLoad){
      setTicker(symToLoad);
      loadCache("analysis_"+symToLoad.toUpperCase()).then(function(c){
        if(c&&c.value&&c.ts&&(Date.now()-c.ts)<7*24*60*60*1000){
          setData(c.value);setCacheTs(c.ts);
        } else if(initialTicker){
          runAnalysis(initialTicker);
        }
      }).catch(function(){if(initialTicker)runAnalysis(initialTicker);});
    }
  },[initialTicker]);

  async function runAnalysis(t,force){
    const sym=(t||ticker).toUpperCase().trim();
    if(!sym)return;
    const CACHE_MS=7*24*60*60*1000;
    if(!force&&data&&cacheTs&&(Date.now()-cacheTs)<CACHE_MS&&data.ticker===sym){
      return;
    }
    setLoading(true);setError(null);
    const today=new Date().toLocaleDateString("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric"});
    try{
      const lp=await fetchPrice(sym).catch(function(){return null;});
      const tech=await fetchTechnicals(sym).catch(function(){return null;});
      const fetchTime=new Date().toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",timeZone:"America/New_York"});
      const priceCtx=lp?"LIVE PRICE ALERT: "+sym+" is trading at "+lp.price+" RIGHT NOW as of "+fetchTime+" EST ("+lp.change+" today). MANDATORY INTRADAY RULE: Intraday entry price MUST be between $"+(Math.round(parseFloat(lp.raw||lp.price.replace("$",""))*0.98*100)/100)+" and $"+(Math.round(parseFloat(lp.raw||lp.price.replace("$",""))*1.02*100)/100)+". Any intraday entry outside this range is WRONG. Base all entry/target/stop on "+lp.price+". ":"";
      const techCtx=tech?"VERIFIED TECHNICAL DATA from Yahoo Finance - USE THESE EXACT VALUES: RSI(14)="+tech.rsi+(parseFloat(tech.rsi)>70?" (OVERBOUGHT)":parseFloat(tech.rsi)<30?" (OVERSOLD)":"")+", 50MA="+tech.ma50+" (price "+(tech.aboveMa50?"ABOVE":"BELOW")+"),"+(tech.ma200?" 200MA="+tech.ma200+" (price "+(tech.aboveMa200?"ABOVE":"BELOW")+"),":"")+(" Volume="+tech.todayVolume+" vs 30d avg="+tech.avgVolume+" ("+tech.relVolume+")")+" . ":"";
      const spyCtx=spyData?"Current market: SPY "+spyData.price+" "+spyData.change+". ":"";
      const text=await callAPI(ANALYSIS_SYS,priceCtx+techCtx+spyCtx+"Today is "+today+". Analyze "+sym+". Search for ALL of the following: (1) Current price action, 50MA and 200MA position, recent chart pattern, (2) Today volume vs 30-day average volume, (3) Recent news last 7 days: earnings, analyst upgrades/downgrades, FDA decisions, M&A, guidance changes, (4) RSI, MACD, key support and resistance levels, (5) P/E, forward P/E, revenue growth, next earnings date, analyst price targets, (6) Sector ETF performance today and sector rotation, (7) Insider buying or selling last 30 days. (8) Analyst consensus, average price target, upside%. (9) MACRO EVENTS TODAY - search all of these: Fed/FOMC decisions or speeches, CPI/PCE/PPI inflation data, NFP jobs report (first Friday of month at 8:30am EST), jobless claims (every Thursday 8:30am EST), GDP, retail sales, ISM Manufacturing/Services, consumer confidence, Michigan sentiment. (10) SCHEDULED REPORTS - if ANY major report releases TODAY or TOMORROW: skip intraday setup, reduce conviction 10-15pts, max Half Size, add note saying wait until after data release. (11) VIX level today - if above 25 widen stops 20% and reduce all conviction 10pts, if above 30 skip intraday and max Quarter Size. (12) DOLLAR (DXY) move today - if up or down more than 0.5% note direct impact on "+sym+" especially if multinational or commodity stock. (13) Treasury yields - 10yr move today, rising yields hurt growth/tech, falling yields help. (14) GEOPOLITICAL events today - wars, sanctions, strait closures, elections, trade disputes, tariffs - note direct and indirect impact on "+sym+". (15) OIL price move today - if more than 2% note sector impact. (16) CHINA economy news - PMI, property crisis, trade data - note supply chain or demand impact on "+sym+". For ALL macro findings - adjust macro score, conviction scores per timeframe, position sizing and add specific notes to affected trade setups. Return JSON.",8000);
      const parsed=parseJSON(text);
      setData(parsed);
      saveCache("analysis_"+sym,parsed);
      setCacheTs(Date.now());
      try{localStorage.setItem("sa_last_ticker",sym);}catch(_){}
    }catch(e){
      if(e.message&&(e.message.includes("No JSON")||e.message.includes("parse")||e.message.includes("Could not"))){
        try{
          await new Promise(function(r){setTimeout(r,2000);});
          const text2=await callAPI(ANALYSIS_SYS,"Today is "+today+". Analyze "+sym+" comprehensively. Return JSON.",8000);
          const parsed2=parseJSON(text2);
          setData(parsed2);saveCache("analysis_"+sym,parsed2);setCacheTs(Date.now());
        }catch(e2){setError(e2.message);}
      } else {setError(e.message);}
    }
    setLoading(false);
  }

  const SETUPS=[
    {key:"intraday",    color:"#fbbf24", label:"TODAY",        hint:"Intraday"},
    {key:"short_term",  color:"#ff9100", label:"SHORT TERM",  hint:"1-5 days"},
    {key:"swing",       color:"#a78bfa", label:"SWING",        hint:"1-4 weeks"},
    {key:"medium_term", color:"#38bdf8", label:"MED TERM",     hint:"1-3 months"},
    {key:"long_term",   color:"#00e676", label:"LONG TERM",    hint:"6-12 months"},
  ];

  return(
    <div>
      <div style={{display:"flex",gap:"10px",marginBottom:"16px",flexWrap:"wrap"}}>
        <input value={ticker} onChange={e=>{setTicker(e.target.value.toUpperCase());setTickerPrice(null);}}
          onKeyDown={e=>e.key==="Enter"&&runAnalysis(ticker,true)}
          placeholder="Enter ticker..." maxLength={5}
          style={{flex:1,minWidth:"140px",padding:"10px 14px",background:W06,border:"1px solid "+W1,borderRadius:"7px",color:"#fff",fontFamily:JM,fontSize:"14px",outline:"none"}}/>
        <button onClick={()=>runAnalysis(ticker,true)} disabled={loading||!ticker}
          style={{padding:"10px 24px",background:"transparent",border:"1px solid #38bdf8",borderRadius:"7px",color:"#38bdf8",fontFamily:JM,fontSize:"12px",fontWeight:"800",cursor:"pointer",opacity:loading?0.6:1}}>
          {loading?<span style={{display:"flex",alignItems:"center",gap:"8px"}}><Bars color="#38bdf8"/>ANALYZING...</span>:"ANALYZE"}
        </button>
        {spyData&&<div style={{display:"flex",alignItems:"center",gap:"6px",padding:"8px 12px",background:W04,border:"1px solid "+W08,borderRadius:"6px"}}>
          <span style={{fontFamily:JM,fontSize:"9px",color:"#ddd"}}>SPY</span>
          <span style={{fontFamily:JM,fontSize:"11px",color:"#fff"}}>{spyData.price}</span>
          <span style={{fontFamily:JM,fontSize:"10px",color:spyData.change?.startsWith("+")?""+"#00e676":"#ff5252"}}>{spyData.change}</span>
        </div>}
      </div>

      {error&&<ErrBox msg={error}/>}
      {loading&&data&&(
        <div style={{textAlign:"center",padding:"6px 12px",background:"rgba(56,189,248,0.06)",
          border:"1px solid rgba(56,189,248,0.15)",borderRadius:"6px",marginBottom:"10px",
          display:"flex",alignItems:"center",justifyContent:"center",gap:"8px"}}>
          <Bars color="#38bdf8"/>
          <span style={{fontFamily:JM,fontSize:"9px",color:"#38bdf8",letterSpacing:"1px"}}>REFRESHING ANALYSIS...</span>
        </div>
      )}
      {data&&(
        <div>
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",flexWrap:"wrap",gap:"12px",marginBottom:"20px"}}>
            <div>
              <div style={{display:"flex",alignItems:"center",gap:"12px",marginBottom:"6px",flexWrap:"wrap"}}>
                <span style={{fontFamily:JM,fontSize:"28px",fontWeight:"800",color:"#fff"}}>{data.ticker}</span>
                <span style={{fontFamily:JM,fontSize:"16px",color:BIAS_C[data.overall_bias]||"#888"}}>{data.overall_bias}</span>
                {livePrice&&(
                  <span style={{fontFamily:JM,fontSize:"10px",fontWeight:"700",
                    color:"#38bdf8",background:"rgba(56,189,248,0.08)",
                    border:"1px solid rgba(56,189,248,0.2)",
                    padding:"2px 8px",borderRadius:"3px",marginLeft:"8px"}}>
                    {"Live: "+livePrice.price+" "+livePrice.change+" @ "+livePrice.time+" EST"}
                  </span>
                )}
                {data.overall_score&&(
                  <div style={{display:"flex",alignItems:"center",gap:"6px"}}>
                    <div style={{width:"80px",height:"5px",background:"rgba(255,255,255,0.06)",borderRadius:"3px"}}>
                      <div style={{width:Math.min(data.overall_score,100)+"%",height:"100%",borderRadius:"3px",
                        background:data.overall_score>=80?"#00e676":data.overall_score>=70?"#ffeb3b":"#ff5252"}}/>
                    </div>
                    <span style={{fontFamily:JM,fontSize:"12px",fontWeight:"800",
                      color:data.overall_score>=80?"#00e676":data.overall_score>=70?"#ffeb3b":"#ff5252"}}>
                      {data.overall_score+"/100"}
                    </span>
                    <span style={{fontSize:"9px",color:"#ddd"}}>SETUP SCORE</span>
                  </div>
                )}
                <LivePrice ticker={data.ticker} large/>
              </div>
              <div style={{fontSize:"13px",color:"#ccc"}}>{data.company_name}</div>
              {data.bias_summary&&(
                <div style={{marginTop:"10px",paddingLeft:"10px",
                  borderLeft:"3px solid "+(BIAS_C[data.overall_bias]||"#555"),
                  maxWidth:"520px"}}>
                  <div style={{fontSize:"13px",color:"#bbb",lineHeight:"1.6",fontStyle:"normal",fontWeight:"600"}}>{data.bias_summary}</div>
                </div>
              )}
              {data.earnings_warning&&(
                <div style={{display:"flex",gap:"8px",alignItems:"flex-start",marginTop:"10px",padding:"10px 12px",background:"rgba(251,191,36,0.06)",border:"1px solid rgba(251,191,36,0.3)",borderRadius:"6px",maxWidth:"500px"}}>
                  <span style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:"#fbbf24",flexShrink:0,marginTop:"1px"}}>EARNINGS</span>
                  <div>
                    {data.earnings_date&&<div style={{fontFamily:JM,fontSize:"11px",color:"#fbbf24",marginBottom:"3px"}}>{data.earnings_date}</div>}
                    <div style={{fontSize:"11px",color:"#d4a017",lineHeight:"1.5"}}>{data.earnings_warning}</div>
                  </div>
                </div>
              )}
            </div>
            {data.fundamental_details?.next_catalyst&&(
              <div style={{display:"flex",gap:"8px",alignItems:"center",marginTop:"10px",padding:"8px 12px",
                background:"rgba(167,139,250,0.06)",border:"1px solid rgba(167,139,250,0.25)",borderRadius:"6px",maxWidth:"500px"}}>
                <span style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:"#a78bfa",flexShrink:0}}>NEXT CATALYST</span>
                <span style={{fontSize:"11px",color:"#c4b5fd",lineHeight:"1.5"}}>{data.fundamental_details.next_catalyst}</span>
              </div>
            )}
            {data.analyst_targets?.consensus&&(
              <div style={{display:"flex",gap:"8px",alignItems:"flex-start",marginTop:"10px",padding:"10px 12px",
                background:"rgba(56,189,248,0.06)",border:"1px solid rgba(56,189,248,0.2)",borderRadius:"6px",maxWidth:"500px"}}>
                <span style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:"#38bdf8",flexShrink:0,marginTop:"1px"}}>ANALYSTS</span>
                <div style={{display:"flex",flexWrap:"wrap",gap:"10px",alignItems:"center"}}>
                  <span style={{fontFamily:JM,fontSize:"13px",fontWeight:"800",
                    color:data.analyst_targets.consensus==="Buy"?"#00e676":data.analyst_targets.consensus==="Sell"?"#ff5252":"#ffeb3b"}}>
                    {data.analyst_targets.consensus}
                  </span>
                  {data.analyst_targets.num_analysts>0&&<span style={{fontSize:"10px",color:"#ddd"}}>{"("+data.analyst_targets.num_analysts+" analysts)"}</span>}
                  {data.analyst_targets.target_avg&&<span style={{fontFamily:JM,fontSize:"11px",color:"#fff"}}>{"Avg "+data.analyst_targets.target_avg}</span>}
                  {data.analyst_targets.target_low&&data.analyst_targets.target_high&&(
                    <span style={{fontSize:"10px",color:"#ddd"}}>{data.analyst_targets.target_low+" - "+data.analyst_targets.target_high}</span>
                  )}
                  {data.analyst_targets.upside&&(
                    <span style={{fontFamily:JM,fontSize:"11px",fontWeight:"800",
                      color:data.analyst_targets.upside.startsWith("+")?"#00e676":"#ff5252"}}>
                      {data.analyst_targets.upside+" upside"}
                    </span>
                  )}
                </div>
              </div>
            )}
            {cacheTs&&(
              <div style={{display:"flex",alignItems:"center",gap:"8px"}}>
                <span style={{fontSize:"10px",
                  color:(Date.now()-cacheTs)<1800000?"#00e676":(Date.now()-cacheTs)<7200000?"#ffeb3b":"#ff9100"}}>
                  {(Date.now()-cacheTs)>7200000?"Analyzed "+ago(cacheTs)+" - consider refreshing":"Analyzed "+ago(cacheTs)}
                </span>
                <button onClick={function(){setCacheTs(null);runAnalysis(ticker);}}
                  style={{padding:"2px 8px",background:"transparent",border:"1px solid rgba(255,255,255,0.15)",
                    borderRadius:"4px",color:"#ccc",fontFamily:JM,fontSize:"9px",cursor:"pointer"}}>
                  REFRESH
                </button>
              </div>
            )}
          </div>

          {data.ticker&&(
            <div style={{marginBottom:"16px",borderRadius:"8px",border:"1px solid rgba(56,189,248,0.2)",overflow:"hidden"}}>
              <div style={{background:"rgba(56,189,248,0.04)",padding:"12px 14px",display:"flex",alignItems:"center",justifyContent:"space-between",flexWrap:"wrap",gap:"8px"}}>
                <div>
                  <div style={{fontFamily:JM,fontSize:"9px",color:"#38bdf8",letterSpacing:"2px",marginBottom:"4px"}}>CHART</div>
                  <div style={{fontSize:"11px",color:"#ccc"}}>{"View "+data.ticker+" chart with technical indicators on TradingView"}</div>
                </div>
                <div style={{display:"flex",gap:"8px",flexWrap:"wrap"}}>
                  <a href={"https://www.tradingview.com/chart/?symbol="+data.ticker} target="_blank" rel="noreferrer"
                    style={{padding:"7px 14px",background:"rgba(56,189,248,0.1)",border:"1px solid rgba(56,189,248,0.3)",
                      borderRadius:"5px",color:"#38bdf8",fontFamily:JM,fontSize:"9px",fontWeight:"800",
                      cursor:"pointer",textDecoration:"none",letterSpacing:"1px"}}>
                    OPEN CHART
                  </a>

                </div>
              </div>
            </div>
          )}
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(150px,1fr))",gap:"10px",marginBottom:"20px"}}>
            {[
              {l:"Technical",  v:data.scores?.technical?.score,  c:"#38bdf8", s:data.scores?.technical?.summary||data.scores?.technical?.label},
              {l:"Momentum",   v:data.scores?.momentum?.score,   c:"#ff9100", s:data.scores?.momentum?.summary||data.scores?.momentum?.label},
              {l:"Catalyst",   v:data.scores?.catalyst?.score,   c:"#fbbf24", s:data.scores?.catalyst?.detail||data.scores?.catalyst?.label},
              {l:"Fundamental",v:data.scores?.fundamental?.score,c:"#00e676", s:data.scores?.fundamental?.summary||data.scores?.fundamental?.label},
              {l:"Macro",      v:data.scores?.macro?.score,      c:"#a78bfa", s:data.scores?.macro?.summary||data.scores?.macro?.label},
              {l:"Sentiment",  v:data.scores?.sentiment?.score,  c:"#38bdf8", s:data.scores?.sentiment?.summary||data.scores?.sentiment?.label},
            ].map(function(item){
              return(
                <div key={item.l} style={{padding:"12px",background:W04,border:"1px solid "+W08,borderRadius:"8px"}}>
                  <div style={{fontFamily:JM,fontSize:"9px",color:"#ddd",letterSpacing:"2px",marginBottom:"6px"}}>{item.l.toUpperCase()}</div>
                  <div style={{fontFamily:JM,fontSize:"22px",fontWeight:"800",color:item.v>=60?item.c:item.v>=45?"#ffeb3b":"#ff5252",marginBottom:"4px"}}>{item.v||"--"}</div>
                  {item.s&&<div style={{fontSize:"9px",color:"#bbb",lineHeight:"1.4",fontStyle:"normal",fontWeight:"600"}}>{item.s}</div>}
                </div>
              );
            })}
          </div>

          {data.key_risks&&data.key_risks.filter(function(r){return r;}).length>0&&(
            <div style={{marginBottom:"16px",padding:"12px 14px",background:"rgba(255,82,82,0.04)",border:"1px solid rgba(255,82,82,0.15)",borderRadius:"8px"}}>
              <div style={{fontFamily:JM,fontSize:"9px",color:"#ff5252",letterSpacing:"2px",marginBottom:"8px"}}>KEY RISKS</div>
              {data.key_risks.map(function(risk,i){
                return risk?<div key={i} style={{display:"flex",gap:"8px",marginBottom:"6px",alignItems:"flex-start"}}>
                  <span style={{color:"#ff5252",fontSize:"12px",flexShrink:0,marginTop:"1px"}}>!</span>
                  <span style={{fontSize:"11px",color:"#cc4444",lineHeight:"1.5"}}>{risk}</span>
                </div>:null;
              })}
            </div>
          )}
          <div style={{marginBottom:"20px"}}>
            <div style={{fontFamily:JM,fontSize:"9px",color:"#ddd",letterSpacing:"2px",marginBottom:"10px"}}>TRADE SETUPS</div>
              {onAnalyze&&data.ticker&&(
                <button onClick={function(){onAnalyze(data.ticker);}}
                  style={{width:"100%",padding:"12px",marginBottom:"12px",
                    background:"rgba(56,189,248,0.08)",
                    border:"2px solid rgba(56,189,248,0.35)",
                    borderRadius:"7px",color:"#38bdf8",fontFamily:JM,
                    fontSize:"11px",fontWeight:"800",cursor:"pointer",
                    letterSpacing:"1px",display:"flex",alignItems:"center",
                    justifyContent:"center",gap:"8px"}}>
                  {"DEEP ANALYSIS IN STOCK ANALYSIS ->"}
                </button>
              )}
              {data.position_size&&(
                <div style={{display:"flex",alignItems:"flex-start",gap:"8px",padding:"10px 12px",
                  background:data.position_size==="Full Size (2% risk)"?"rgba(0,230,118,0.06)":
                             data.position_size==="Half Size (1% risk)"?"rgba(255,235,59,0.06)":
                             data.position_size==="Quarter Size (0.5% risk)"?"rgba(255,145,0,0.06)":"rgba(255,82,82,0.06)",
                  border:"1px solid "+(data.position_size==="Full Size (2% risk)"?"rgba(0,230,118,0.25)":
                                       data.position_size==="Half Size (1% risk)"?"rgba(255,235,59,0.25)":
                                       data.position_size==="Quarter Size (0.5% risk)"?"rgba(255,145,0,0.25)":"rgba(255,82,82,0.25)"),
                  borderRadius:"7px",marginBottom:"10px"}}>
                  <div style={{flexShrink:0}}>
                    <div style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",letterSpacing:"1px",marginBottom:"3px",
                      color:data.position_size==="Full Size (2% risk)"?"#00e676":
                            data.position_size==="Half Size (1% risk)"?"#ffeb3b":
                            data.position_size==="Quarter Size (0.5% risk)"?"#ff9100":"#ff5252"}}>
                      POSITION SIZE
                    </div>
                    <div style={{fontFamily:JM,fontSize:"13px",fontWeight:"800",color:"#fff"}}>{data.position_size}</div>
                  </div>
                  {data.position_size_reason&&<div style={{fontSize:"11px",color:"#ccc",lineHeight:"1.5",paddingTop:"2px"}}>{data.position_size_reason}</div>}
                </div>
              )}
              {data.position_size&&(
                <div style={{display:"flex",alignItems:"flex-start",gap:"8px",padding:"10px 12px",
                  background:data.position_size==="Full Size (2% risk)"?"rgba(0,230,118,0.06)":
                             data.position_size==="Half Size (1% risk)"?"rgba(255,235,59,0.06)":
                             data.position_size==="Quarter Size (0.5% risk)"?"rgba(255,145,0,0.06)":"rgba(255,82,82,0.06)",
                  border:"1px solid "+(data.position_size==="Full Size (2% risk)"?"rgba(0,230,118,0.25)":
                                       data.position_size==="Half Size (1% risk)"?"rgba(255,235,59,0.25)":
                                       data.position_size==="Quarter Size (0.5% risk)"?"rgba(255,145,0,0.25)":"rgba(255,82,82,0.25)"),
                  borderRadius:"7px",marginBottom:"10px"}}>
                  <div style={{flexShrink:0}}>
                    <div style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",letterSpacing:"1px",marginBottom:"3px",
                      color:data.position_size==="Full Size (2% risk)"?"#00e676":
                            data.position_size==="Half Size (1% risk)"?"#ffeb3b":
                            data.position_size==="Quarter Size (0.5% risk)"?"#ff9100":"#ff5252"}}>POSITION SIZE</div>
                    <div style={{fontFamily:JM,fontSize:"13px",fontWeight:"800",color:"#fff"}}>{data.position_size}</div>
                  </div>
                  {data.position_size_reason&&<div style={{fontSize:"11px",color:"#ccc",lineHeight:"1.5",paddingTop:"2px"}}>{data.position_size_reason}</div>}
                </div>
              )}
          {data.best_timeframe&&(
                <div style={{display:"flex",alignItems:"flex-start",gap:"8px",padding:"10px 12px",
                  background:"rgba(167,139,250,0.06)",border:"1px solid rgba(167,139,250,0.25)",
                  borderRadius:"7px",marginBottom:"12px"}}>
                  <div style={{flexShrink:0}}>
                    <div style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:"#a78bfa",letterSpacing:"1px",marginBottom:"3px"}}>BEST TIMEFRAME</div>
                    <div style={{fontFamily:JM,fontSize:"13px",fontWeight:"800",color:"#fff"}}>{data.best_timeframe}</div>
                  </div>
                  {data.best_timeframe_reason&&<div style={{fontSize:"11px",color:"#ccc",lineHeight:"1.5",paddingTop:"2px"}}>{data.best_timeframe_reason}</div>}
                </div>
              )}
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(180px,1fr))",gap:"10px"}}>
              {SETUPS.map(({key,color,label,hint})=>{
                const s=data.trade_setups?.[key];
                if(!s)return null;
                if(key==="intraday"){
                  var sess=getMarketSession();
                  if(sess==="AFTER HOURS"||sess==="OVERNIGHT"||sess==="WEEKEND")return null;
                }
                return(
                  <div key={key} style={{padding:"14px",background:color+"08",border:"1px solid "+color+"30",borderRadius:"8px"}}>
                    <div style={{display:"flex",justifyContent:"space-between",alignItems:"center",marginBottom:"8px"}}>
                      <div style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:color}}>{label}</div>
                      <div style={{fontFamily:JM,fontSize:"9px",color:color,background:color+"20",padding:"2px 7px",borderRadius:"3px"}}>{(s.timeframe&&s.timeframe!=="?")?s.timeframe:hint}</div>
                    </div>
                    {s.direction&&(
                      <div style={{display:"flex",alignItems:"center",gap:"6px",marginBottom:"6px"}}>
                        <span style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",
                          padding:"2px 8px",borderRadius:"3px",letterSpacing:"1px",
                          background:s.direction==="SHORT"?"rgba(255,82,82,0.12)":"rgba(0,230,118,0.12)",
                          border:"1px solid "+(s.direction==="SHORT"?"rgba(255,82,82,0.3)":"rgba(0,230,118,0.3)"),
                          color:s.direction==="SHORT"?"#ff5252":"#00e676"}}>
                          {s.direction==="SHORT"?"SHORT SELL":"LONG BUY"}
                        </span>
                      </div>
                    )}
                    {s.conviction_score&&(
                      <div style={{display:"flex",alignItems:"center",gap:"6px",marginBottom:"8px"}}>
                        <div style={{flex:1,height:"4px",background:"rgba(255,255,255,0.06)",borderRadius:"2px"}}>
                          <div style={{width:Math.min(s.conviction_score,100)+"%",height:"100%",borderRadius:"2px",
                            background:s.conviction_score>=80?color:s.conviction_score>=70?"#ffeb3b":"#ff5252"}}/>
                        </div>
                        <span style={{fontFamily:JM,fontSize:"11px",fontWeight:"800",
                          color:s.conviction_score>=80?color:s.conviction_score>=70?"#ffeb3b":"#ff5252"}}>
                          {s.conviction_score+"/100"}
                        </span>
                      </div>
                    )}
                    <div style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:color,marginBottom:"8px",display:"none"}}>{label+" "+label}</div>
                    {[["ENTRY",s.entry,"#fff"],[s.direction==="SHORT"?"TARGET (SHORT)":"TARGET",s.target,s.direction==="SHORT"?"#ff5252":"#00e676"],["STOP",s.stop,s.direction==="SHORT"?"#00e676":"#ff5252"]].map(([k,v,c])=>v&&(
                      <div key={k} style={{display:"flex",justifyContent:"space-between",marginBottom:"4px"}}>
                        <span style={{fontSize:"9px",color:"#ddd"}}>{k}</span>
                        <span style={{fontFamily:JM,fontSize:"11px",fontWeight:"700",color:c}}>{v}</span>
                      </div>
                    ))}
                    {s.risk_reward&&(
                      <div style={{display:"flex",justifyContent:"space-between",marginTop:"6px",paddingTop:"6px",borderTop:"1px solid rgba(255,255,255,0.06)"}}>
                        <span style={{fontSize:"9px",color:"#ddd"}}>R:R</span>
                        <span style={{fontFamily:JM,fontSize:"11px",fontWeight:"800",
                          color:parseFloat(s.risk_reward)>=3?"#00e676":parseFloat(s.risk_reward)>=2?"#ffeb3b":"#ff5252"}}>
                          {s.risk_reward}
                        </span>
                      </div>
                    )}
                    {s.expected_move&&<div style={{marginTop:"6px",fontFamily:JM,fontSize:"11px",color:color}}>{s.expected_move}</div>}
                    {s.notes&&(
                      <div style={{marginTop:"8px",paddingTop:"8px",borderTop:"1px solid rgba(255,255,255,0.06)"}}>
                        <div style={{fontSize:"10px",color:"#ccc",lineHeight:"1.6",fontWeight:"600"}}>{s.notes}</div>
                      </div>
                    )}
                    {s.skip_reason&&(
                      <div style={{marginTop:"6px",padding:"6px 8px",background:"rgba(255,235,59,0.06)",
                        border:"1px solid rgba(255,235,59,0.2)",borderRadius:"4px",
                        display:"flex",gap:"6px",alignItems:"flex-start"}}>
                        <span style={{fontFamily:JM,fontSize:"9px",color:"#ffeb3b",flexShrink:0}}>!</span>
                        <span style={{fontSize:"10px",color:"#ffeb3b",lineHeight:"1.4"}}>{s.skip_reason}</span>
                      </div>
                    )}
                  </div>
                );
              })}
            </div>
          </div>

          {data.volume_context&&data.volume_context.relative_volume&&(
            <div style={{marginTop:"14px",padding:"10px 14px",background:W04,border:"1px solid "+W08,borderRadius:"8px"}}>
              <div style={{display:"flex",alignItems:"center",gap:"10px",flexWrap:"wrap"}}>
                <div style={{fontFamily:JM,fontSize:"9px",color:"#ddd",letterSpacing:"2px"}}>VOLUME</div>
                <span style={{fontFamily:JM,fontSize:"13px",fontWeight:"800",
                  color:parseFloat(data.volume_context.relative_volume)>=2?"#00e676":
                        parseFloat(data.volume_context.relative_volume)>=0.8?"#ffeb3b":"#ff5252"}}>
                  {data.volume_context.relative_volume+"x avg"}
                </span>
                {data.volume_context.current_volume&&<span style={{fontSize:"11px",color:"#ccc"}}>{data.volume_context.current_volume+" shares"}</span>}
                {data.volume_context.volume_signal&&<span style={{fontSize:"11px",color:"#bbb",fontStyle:"normal",fontWeight:"600"}}>{data.volume_context.volume_signal}</span>}
              </div>
            </div>
          )}
          {data.news_items&&data.news_items.length>0&&(
            <div style={{marginTop:"14px"}}>
              <div style={{fontFamily:JM,fontSize:"9px",color:"#ddd",letterSpacing:"2px",marginBottom:"8px"}}>NEWS DRIVING THIS PREDICTION</div>
              <div style={{display:"flex",flexDirection:"column",gap:"6px"}}>
                {data.news_items.map(function(item,i){
                  var ic=item.impact==="HIGH"?"#ff5252":item.impact==="MEDIUM"?"#ffeb3b":"#555";
                  var sc=item.sentiment==="Bullish"||item.sentiment==="Positive"?"#00e676":
                         item.sentiment==="Bearish"||item.sentiment==="Negative"?"#ff5252":"#888";
                  return(
                    <div key={i} style={{padding:"10px 12px",background:W04,border:"1px solid "+W08,borderRadius:"7px"}}>
                      <div style={{display:"flex",alignItems:"center",gap:"6px",marginBottom:"4px",flexWrap:"wrap"}}>
                        <span style={{fontSize:"9px",fontWeight:"800",padding:"1px 6px",borderRadius:"3px",
                          color:ic,background:ic+"15"}}>{item.impact||"LOW"}</span>
                        <span style={{fontSize:"9px",fontWeight:"700",color:sc}}>{item.sentiment}</span>
                        {item.hours_ago>0&&<span style={{fontSize:"9px",color:"#ddd"}}>{item.hours_ago+"h ago"}</span>}
                        {item.source&&<span style={{fontSize:"9px",color:"#ddd",fontStyle:"normal",fontWeight:"600"}}>{item.source}</span>}
                      </div>
                      <div style={{fontSize:"11px",color:"#ccc",lineHeight:"1.5"}}>{item.headline}</div>
                    </div>
                  );
                })}
              </div>
            </div>
          )}

          {(data.technical_details||data.fundamental_details||data.macro_details)&&(
            <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(200px,1fr))",gap:"10px",marginBottom:"16px"}}>
              {data.technical_details&&(
                <div style={{padding:"12px",background:W04,border:"1px solid "+W08,borderRadius:"8px"}}>
                  <div style={{fontFamily:JM,fontSize:"9px",color:"#38bdf8",letterSpacing:"2px",marginBottom:"8px"}}>TECHNICAL</div>
                  {data.technical_details.trend&&<div style={{fontSize:"11px",color:"#ccc",marginBottom:"4px"}}><span style={{color:"#ddd",fontSize:"9px"}}>Trend: </span>{data.technical_details.trend}</div>}
                  {data.technical_details.chart_pattern&&<div style={{fontSize:"11px",color:"#ccc",marginBottom:"4px"}}><span style={{color:"#ddd",fontSize:"9px"}}>Pattern: </span>{data.technical_details.chart_pattern}</div>}
                  {data.technical_details.key_levels&&(
                    <div style={{fontSize:"11px",color:"#ccc",marginBottom:"4px"}}>
                      <span style={{color:"#ddd",fontSize:"9px"}}>Support: </span><span style={{color:"#00e676"}}>{data.technical_details.key_levels.support}</span>
                      <span style={{color:"#ddd",fontSize:"9px",marginLeft:"8px"}}>Resist: </span><span style={{color:"#ff5252"}}>{data.technical_details.key_levels.resistance}</span>
                    </div>
                  )}
                  {data.technical_details.indicators&&data.technical_details.indicators.map(function(ind,i){
                    return <div key={i} style={{display:"flex",justifyContent:"space-between",marginTop:"3px"}}>
                      <span style={{fontSize:"9px",color:"#ddd"}}>{ind.name}</span>
                      <span style={{fontSize:"9px",fontWeight:"800",color:ind.signal==="Bullish"?"#00e676":ind.signal==="Bearish"?"#ff5252":"#ffeb3b"}}>{ind.value} {ind.signal}</span>
                    </div>;
                  })}
                </div>
              )}
              {data.fundamental_details&&(
                <div style={{padding:"12px",background:W04,border:"1px solid "+W08,borderRadius:"8px"}}>
                  <div style={{fontFamily:JM,fontSize:"9px",color:"#00e676",letterSpacing:"2px",marginBottom:"8px"}}>FUNDAMENTAL</div>
                  {[["Market Cap",data.fundamental_details.market_cap],["P/E Ratio",data.fundamental_details.pe_ratio],["Fwd P/E",data.fundamental_details.forward_pe],["Rev Growth",data.fundamental_details.revenue_growth],["Earnings",data.fundamental_details.earnings_trend],["Next Catalyst",data.fundamental_details.next_catalyst]].map(function(row,i){
                    return row[1]?<div key={i} style={{display:"flex",justifyContent:"space-between",marginBottom:"3px"}}>
                      <span style={{fontSize:"9px",color:"#ddd"}}>{row[0]}</span>
                      <span style={{fontSize:"9px",color:"#ccc",fontWeight:"700",maxWidth:"120px",textAlign:"right"}}>{row[1]}</span>
                    </div>:null;
                  })}
                </div>
              )}
              {data.macro_details&&(
                <div style={{padding:"12px",background:W04,border:"1px solid "+W08,borderRadius:"8px"}}>
                  <div style={{fontFamily:JM,fontSize:"9px",color:"#a78bfa",letterSpacing:"2px",marginBottom:"8px"}}>MACRO</div>
                  {data.macro_details.rate_environment&&<div style={{fontSize:"11px",color:"#ccc",marginBottom:"6px"}}><span style={{color:"#ddd",fontSize:"9px"}}>Rates: </span>{data.macro_details.rate_environment}</div>}
                  {data.macro_details.sector_tailwinds?.length>0&&<div style={{marginBottom:"4px"}}><div style={{fontSize:"9px",color:"#ddd",marginBottom:"2px"}}>TAILWINDS</div>{data.macro_details.sector_tailwinds.map(function(t,i){return t?<div key={i} style={{fontSize:"10px",color:"#00e676",lineHeight:"1.5"}}>{t}</div>:null;})}</div>}
                  {data.macro_details.sector_headwinds?.length>0&&<div><div style={{fontSize:"9px",color:"#ddd",marginBottom:"2px"}}>HEADWINDS</div>{data.macro_details.sector_headwinds.map(function(h,i){return h?<div key={i} style={{fontSize:"10px",color:"#ff5252",lineHeight:"1.5"}}>{h}</div>:null;})}</div>}
                </div>
              )}
            </div>
          )}
          <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"14px"}}>
            {data.bull_case?.length>0&&(
              <div style={{padding:"14px",background:"rgba(0,230,118,0.04)",border:"1px solid rgba(0,230,118,0.15)",borderRadius:"8px"}}>
                <div style={{fontFamily:JM,fontSize:"9px",color:"#00e676",letterSpacing:"2px",marginBottom:"10px"}}>BULL CASE</div>
                {data.bull_case.map((b,i)=>b&&<div key={i} style={{fontSize:"11px",color:"#ccc",marginBottom:"6px",paddingLeft:"10px",borderLeft:"2px solid rgba(0,230,118,0.3)"}}>{b}</div>)}
              </div>
            )}
            {data.bear_case?.length>0&&(
              <div style={{padding:"14px",background:"rgba(255,82,82,0.04)",border:"1px solid rgba(255,82,82,0.15)",borderRadius:"8px"}}>
                <div style={{fontFamily:JM,fontSize:"9px",color:"#ff5252",letterSpacing:"2px",marginBottom:"10px"}}>BEAR CASE</div>
                {data.bear_case.map((b,i)=>b&&<div key={i} style={{fontSize:"11px",color:"#ccc",marginBottom:"6px",paddingLeft:"10px",borderLeft:"2px solid rgba(255,82,82,0.3)"}}>{b}</div>)}
              </div>
            )}
          </div>
        </div>
      )}

      {!loading&&!data&&(
        <div style={{textAlign:"center",padding:"50px 20px",border:"1px dashed rgba(56,189,248,0.15)",borderRadius:"12px"}}>
          <div style={{fontFamily:JM,fontSize:"11px",color:"#38bdf8",letterSpacing:"2px",marginBottom:"8px"}}>ENTER A TICKER TO ANALYZE</div>
          <div style={{fontSize:"12px",color:"#ccc"}}>{"AI-powered technical + fundamental + macro analysis with 4-timeframe trade setups"}</div>
        </div>
      )}
    </div>
  );
}
/* -- NEWS PREDICTOR ----------------------------------------- */
function getMarketSession(){
  var now=new Date();
  var est=new Date(now.toLocaleString("en-US",{timeZone:"America/New_York"}));
  var h=est.getHours(),m=est.getMinutes(),day=est.getDay();
  if(day===0||day===6)return "WEEKEND";
  var mins=h*60+m;
  if(mins>=240&&mins<570)return "PRE-MARKET";
  if(mins>=570&&mins<960)return "MARKET OPEN";
  if(mins>=960&&mins<1200)return "AFTER HOURS";
  return "OVERNIGHT";
}

function NewsPredictor({onAnalyze}){
  const [ticker,setTicker]=useState("");
  const [loading,setLoading]=useState(false);
  const [data,setData]=useState(null);
  const [error,setError]=useState(null);
  const [scanLoading,setScanLoading]=useState(false);
  const [scanResults,setScanResults]=useState([]);
  const [scanError,setScanError]=useState(null);
  const [scanTs,setScanTs]=useState(null);
  const [scanDirFilter,setScanDirFilter]=useState("ALL");
  const resultRef=useRef(null);
  const [loadingStep,setLoadingStep]=useState(0);
  const [tickerPrice,setTickerPrice]=useState(null);
  const [priceInfo,setPriceInfo]=useState(null);
  const [cacheTs,setCacheTs]=useState(null);

  useEffect(()=>{
    loadCache("news").then(c=>{if(c?.value){setData(c.value);setCacheTs(c.ts);var lt=typeof localStorage!=="undefined"?localStorage.getItem("np_last_ticker"):null;if(lt)setTicker(lt);}});
    loadCache("catalyst_scan").then(c=>{if(c?.value){setScanResults(c.value.results||[]);setScanTs(c.ts);}});
  },[]);

  async function predict(force){
    const sym=ticker.toUpperCase().trim();
    if(!sym)return;
    const CACHE_MS=7*24*60*60*1000;
    if(!force&&data&&cacheTs&&(Date.now()-cacheTs)<CACHE_MS&&data.ticker&&data.ticker.toUpperCase()===sym){
      return;
    }
    setLoading(true);setError(null);setData(null);setLoadingStep(1);
    try{
      const today=new Date().toLocaleDateString("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric"});
      const [lp,spy]=await Promise.all([
        fetchPrice(sym).catch(function(){return null;}),
        fetchPrice("SPY").catch(function(){return null;})
      ]);
      const fetchTime=new Date().toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",timeZone:"America/New_York"});
      setPriceInfo(lp?{price:lp.price,change:lp.change,time:fetchTime,success:true}:{time:fetchTime,success:false});
      const priceCtx=lp?"IMPORTANT: Current live price of "+sym+" is "+lp.price+" ("+lp.change+" today). Base ALL entry/target/stop levels on this exact current price. ":"";
      setLoadingStep(2);
      const spyCtx=spy?"MARKET CONTEXT: SPY (S&P 500) is currently "+spy.price+" ("+spy.change+" today). "+(parseFloat(spy.change)>=-0.3&&parseFloat(spy.change)<=0.3?"Market is FLAT/NEUTRAL today.":parseFloat(spy.change)>0.3?"Market is in RISK-ON mode today - bullish tailwind.":parseFloat(spy.change)<=-2?"Market is in SELL-OFF mode - avoid new LONG positions unless very high conviction.":"Market is in RISK-OFF mode - reduce conviction on LONG setups, tighten stops.")+" Factor this into conviction_score and trade setups. ":"";
      setLoadingStep(3);
      const text=await callAPI(NEWS_SYS,priceCtx+spyCtx+"Today is "+today+". Search for the MOST RECENT news about "+sym+" from today and last 24 hours. Include ALL news - positive AND negative. Check: (1) earnings, analyst upgrades/downgrades, FDA decisions, M&A, guidance changes, (2) sector headwinds/tailwinds, AI concerns, competition, (3) MACRO EVENTS TODAY: Fed/FOMC decisions or speeches, CPI/PCE inflation data, NFP jobs report (first Friday of month), jobless claims (every Thursday), GDP, retail sales, ISM, consumer confidence, (4) SCHEDULED REPORTS: if major report releases TODAY flag it - reduce conviction 10-15pts and warn about volatility, (5) VIX level - if above 25 flag elevated market fear, (6) DOLLAR (DXY) move today - note impact on "+sym+" if multinational or commodity, (7) Treasury yield moves - rising hurts growth/tech, (8) GEOPOLITICAL events: wars, sanctions, strait closures, elections, tariffs, trade disputes, (9) OIL price move today, (10) CHINA news - PMI, trade data, property crisis. Do NOT default to bullish - be objective. Return JSON.",6000);
      const parsed=parseJSON(text);
      setLoadingStep(0);
      setData(parsed);
      setTimeout(function(){if(resultRef.current)resultRef.current.scrollIntoView({behavior:"smooth",block:"start"});},100);
      saveCache("news",parsed);setCacheTs(Date.now());try{localStorage.setItem("np_last_ticker",sym);}catch(_){}
    }catch(e){
      if(e.message&&(e.message.includes("No JSON")||e.message.includes("parse")||e.message.includes("Could not"))){
        try{
          await new Promise(function(r){setTimeout(r,2000);});
          const text2=await callAPI(NEWS_SYS,"Today is "+new Date().toLocaleDateString("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric"})+". Analyze news catalyst for "+sym+". Return JSON only.",8000);
          setData(parseJSON(text2));
        }catch(e2){setError(e2.message);}
      } else {setError(e.message);}
    }finally{setLoading(false);setLoadingStep(0);}
  }

  const pc=PRED_C[data?.prediction]||"#888";
  const ac=ACT_C[data?.trade_action]||"#888";

  async function scanMarket(){
    setScanLoading(true);setScanError(null);
    try{
      const today=new Date().toLocaleDateString("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric"});
      const spyR=await fetchPrice("SPY").catch(function(){return null;});
      const spyCtx=spyR?"Current market: SPY "+spyR.price+" "+spyR.change+(parseFloat(spyR.change)<-2?" (RISK-OFF - flag all LONG signals with high market risk, prioritize SHORT catalysts)":parseFloat(spyR.change)>1?" (RISK-ON)":"")+" . ":"";
      const text=await callAPI(CATALYST_SYS,spyCtx+"Today is "+today+". Find top news catalysts NOW. Return JSON only.",8000);
      var arr=[];
      try{
        var t=text.trim().replace(/^\x60{3}(?:json)?[^\x60]*\x60{3}$/,"").trim();
        var s=t.indexOf("["),e=t.lastIndexOf("]");
        if(s>-1&&e>-1){
          var raw=t.slice(s,e+1);
          raw=raw.replace(/,([\s]*[\]\}])/g,"$1");
          raw=raw.replace(/([{,]\s*)([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g,'$1"$2":');
          try{arr=JSON.parse(raw);}catch(_){
            try{arr=JSON.parse(raw.replace(/[\u0000-\u001F]+/g," "));}catch(_){}
          }
        }
      }catch(_){}
      const filtered=arr.filter(function(r){return(r.score||0)>=90;}).slice(0,10);
      setScanResults(filtered);
      setScanTs(Date.now());
      saveCache("catalyst_scan",{results:filtered});
    }catch(err){setScanError(err.message);}
    setScanLoading(false);
  }

  return(
    <div>
      <div style={{display:"flex",gap:"10px",marginBottom:"16px",flexWrap:"wrap"}}>
        <input value={ticker} onChange={e=>{setTicker(e.target.value.toUpperCase());if(typeof setTickerPrice!=="undefined")setTickerPrice(null);}}
          onKeyDown={e=>e.key==="Enter"&&predict()}
          placeholder="Enter ticker..."
          style={{flex:1,minWidth:"140px",padding:"10px 14px",background:W06,border:"1px solid "+W1,borderRadius:"7px",color:"#fff",fontFamily:JM,fontSize:"14px",outline:"none"}}/>
        {tickerPrice&&!data&&(
          <div style={{display:"flex",flexDirection:"column",alignItems:"center",padding:"4px 10px",background:W04,border:"1px solid "+W08,borderRadius:"7px",minWidth:"70px"}}>
            <span style={{fontFamily:JM,fontSize:"12px",fontWeight:"800",color:"#fff"}}>{tickerPrice.price}</span>
            <span style={{fontFamily:JM,fontSize:"10px",color:tickerPrice.change&&tickerPrice.change.startsWith("+")?"#00e676":"#ff5252"}}>{tickerPrice.change}</span>
          </div>
        )}
        <button onClick={predict} disabled={loading||!ticker}
          style={{padding:"10px 24px",background:"transparent",border:"1px solid #ff9100",borderRadius:"7px",color:"#ff9100",fontFamily:JM,fontSize:"12px",fontWeight:"800",cursor:"pointer",opacity:loading?0.6:1}}>
          {loading?<span style={{display:"flex",alignItems:"center",gap:"8px"}}><Bars color="#ff9100"/>
                  <span>{loadingStep===1?"Fetching live price...":loadingStep===2?"Checking market conditions...":loadingStep===3?"Searching news and analyzing catalyst...":"Analyzing..."}</span>
                </span>:"PREDICT"}
        </button>
      </div>

      {error&&<ErrBox msg={error}/>}

      <div style={{marginBottom:"14px"}}>
        <button onClick={function(){scanMarket();}} disabled={scanLoading}
          style={{width:"100%",padding:"11px",background:"transparent",
            border:"1px solid rgba(255,145,0,0.4)",borderRadius:"7px",
            color:"#ff9100",fontFamily:JM,fontSize:"11px",fontWeight:"800",
            cursor:scanLoading?"not-allowed":"pointer",letterSpacing:"1px"}}>
          {scanLoading?"SCANNING ALL SECTORS...":"SCAN FOR CATALYSTS"}
        </button>
        {scanError&&<ErrBox msg={scanError}/>}
        {scanResults.length>0&&(
          <div style={{marginTop:"12px"}}>
            <div style={{fontFamily:JM,fontSize:"9px",color:"#ddd",letterSpacing:"2px",marginBottom:"8px"}}>{"TOP CATALYSTS - "+scanResults.length+" RESULTS"}
                  {scanTs&&<span style={{fontFamily:JM,fontSize:"9px",color:"#ddd",marginLeft:"8px"}}>{"Scanned "+ago(scanTs)}</span>}</div>
            <div style={{display:"flex",flexDirection:"column",gap:"8px"}}>
              {scanResults.filter(function(r){return scanDirFilter==="ALL"||r.direction===scanDirFilter;}).map(function(r,i){
                var dc=r.direction==="LONG"?"#00e676":"#ff5252";
                var sc=r.score>=97?"#ff3d71":r.score>=93?"#ff9100":"#a78bfa";
                return(
                  <div key={r.ticker+i} style={{padding:"12px",background:"rgba(255,145,0,0.04)",border:"1px solid rgba(255,145,0,0.15)",borderRadius:"8px"}}>
                    <div style={{display:"flex",alignItems:"center",gap:"8px",flexWrap:"wrap",marginBottom:"6px"}}>
                      <span style={{fontFamily:JM,fontSize:"16px",fontWeight:"800",color:"#fff"}}>{r.ticker}</span>
                      <span style={{fontSize:"9px",fontWeight:"800",padding:"2px 6px",borderRadius:"3px",color:dc,background:dc+"15"}}>{r.direction}</span>
                      {r.sector&&<span style={{fontSize:"9px",padding:"2px 6px",borderRadius:"3px",color:"#ccc",background:"rgba(255,255,255,0.06)",border:"1px solid rgba(255,255,255,0.1)"}}>{r.sector}</span>}
                      {r.catalyst_type&&<span style={{fontSize:"9px",fontWeight:"800",padding:"2px 6px",borderRadius:"3px",
                        color:r.catalyst_type==="Earnings"?"#fbbf24":
                              r.catalyst_type==="FDA"?"#34d399":
                              r.catalyst_type==="M&A"?"#a78bfa":
                              r.catalyst_type==="Macro"?"#38bdf8":
                              r.catalyst_type==="Geopolitical"?"#ff9100":"#888",
                        background:r.catalyst_type==="Earnings"?"rgba(251,191,36,0.1)":
                                   r.catalyst_type==="FDA"?"rgba(52,211,153,0.1)":
                                   r.catalyst_type==="M&A"?"rgba(167,139,250,0.1)":
                                   r.catalyst_type==="Macro"?"rgba(56,189,248,0.1)":
                                   r.catalyst_type==="Geopolitical"?"rgba(255,145,0,0.1)":"rgba(255,255,255,0.06)",
                        border:"1px solid "+(r.catalyst_type==="Earnings"?"rgba(251,191,36,0.3)":
                                             r.catalyst_type==="FDA"?"rgba(52,211,153,0.3)":
                                             r.catalyst_type==="M&A"?"rgba(167,139,250,0.3)":
                                             r.catalyst_type==="Macro"?"rgba(56,189,248,0.3)":
                                             r.catalyst_type==="Geopolitical"?"rgba(255,145,0,0.3)":"rgba(255,255,255,0.1)")
                      }}>{r.catalyst_type.toUpperCase()}</span>}
                      {(function(){
                        var session=getMarketSession();
                        var sc=session==="MARKET OPEN"?"#00e676":session==="PRE-MARKET"?"#fbbf24":session==="AFTER HOURS"?"#a78bfa":"#555";
                        var bg=session==="MARKET OPEN"?"rgba(0,230,118,0.1)":session==="PRE-MARKET"?"rgba(251,191,36,0.1)":session==="AFTER HOURS"?"rgba(167,139,250,0.1)":"rgba(255,255,255,0.06)";
                        return <span style={{fontSize:"9px",fontWeight:"800",padding:"2px 6px",borderRadius:"3px",color:sc,background:bg,border:"1px solid "+sc+"44"}}>{session}</span>;
                      })()}
                      <span style={{fontFamily:JM,fontSize:"12px",fontWeight:"800",color:sc}}>{r.score+"/100"}</span>
                      {r.expected_move&&<span style={{fontFamily:JM,fontSize:"12px",fontWeight:"800",
                        color:r.expected_move.startsWith("+")?"#00e676":"#ff5252",
                        background:r.expected_move.startsWith("+")?"rgba(0,230,118,0.1)":"rgba(255,82,82,0.1)",
                        padding:"2px 8px",borderRadius:"3px"}}>{r.expected_move}</span>}
                    </div>
                    <div style={{fontSize:"11px",color:"#ccc",marginBottom:"4px"}}>{r.company_name}</div>
                    {r.catalyst&&<div style={{fontSize:"11px",color:"#ccc",lineHeight:"1.5",marginBottom:"6px"}}>{r.catalyst}</div>}
                    <button onClick={function(){setTicker(r.ticker);predict();}}
                      style={{padding:"5px 14px",background:"rgba(255,145,0,0.1)",
                        border:"1px solid rgba(255,145,0,0.3)",borderRadius:"4px",
                        color:"#ff9100",fontFamily:JM,fontSize:"9px",fontWeight:"800",cursor:"pointer"}}>
                      FULL ANALYSIS
                    </button>
                  </div>
                );
              })}
            </div>
          </div>
        )}
      </div>

      {data&&(
        <div ref={resultRef}>
          <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",flexWrap:"wrap",gap:"16px",marginBottom:"20px",padding:"20px",background:pc+"08",border:"1px solid "+pc+"30",borderRadius:"10px"}}>
            <div>
              <div style={{display:"flex",alignItems:"center",gap:"12px",marginBottom:"8px",flexWrap:"wrap"}}>
                <span style={{fontFamily:JM,fontSize:"36px",fontWeight:"800",color:pc}}>{data.prediction}</span>
                <span style={{fontFamily:JM,fontSize:"20px",color:"#fff"}}>{data.expected_move}</span>
              </div>
              <div style={{fontFamily:JM,fontSize:"11px",color:pc}}>{data.ticker+" . "+data.company_name}</div>
              {cacheTs&&(
                <div style={{display:"flex",alignItems:"center",gap:"8px",marginTop:"4px"}}>
                  <span style={{fontSize:"10px",
                    color:(Date.now()-cacheTs)<3600000?"#00e676":(Date.now()-cacheTs)<86400000?"#ffeb3b":"#ff9100"}}>
                    {"Analyzed "+ago(cacheTs)}
                  </span>
                  <button onClick={function(){setData(null);setCacheTs(null);predict(true);}}
                    style={{padding:"2px 8px",background:"transparent",border:"1px solid rgba(255,255,255,0.1)",
                      borderRadius:"3px",color:"#ddd",fontFamily:JM,fontSize:"9px",cursor:"pointer"}}>
                    REFRESH
                  </button>
                </div>
              )}
              {onAnalyze&&data.ticker&&(
                <button onClick={function(){onAnalyze(data.ticker);}}
                  style={{padding:"4px 12px",marginTop:"4px",
                    background:"rgba(56,189,248,0.1)",
                    border:"1px solid rgba(56,189,248,0.3)",
                    borderRadius:"4px",color:"#38bdf8",fontFamily:JM,
                    fontSize:"9px",fontWeight:"800",cursor:"pointer",
                    letterSpacing:"1px"}}>
                  {"ANALYZE IN STOCK ANALYSIS ->"}
                </button>
              )}
              {data.ticker&&(
                <a href={"https://www.tradingview.com/chart/?symbol="+data.ticker} target="_blank" rel="noreferrer"
                  style={{display:"inline-block",marginTop:"6px",padding:"5px 14px",
                    background:"rgba(56,189,248,0.08)",border:"1px solid rgba(56,189,248,0.25)",
                    borderRadius:"4px",color:"#38bdf8",fontFamily:JM,fontSize:"9px",
                    fontWeight:"800",cursor:"pointer",textDecoration:"none",letterSpacing:"1px"}}>
                  OPEN CHART
                </a>
              )}
              {priceInfo&&(
                <div style={{display:"flex",alignItems:"center",gap:"6px",marginTop:"4px",marginBottom:"2px"}}>
                  {priceInfo.success
                    ?<>
                      <span style={{fontFamily:JM,fontSize:"13px",fontWeight:"800",color:"#fff"}}>{priceInfo.price}</span>
                      <span style={{fontFamily:JM,fontSize:"11px",color:priceInfo.change&&priceInfo.change.startsWith("+")?"#00e676":"#ff5252"}}>{priceInfo.change}</span>
                      <span style={{fontSize:"9px",color:"#ddd"}}>{"as of "+priceInfo.time+" EST"}</span>
                    </>
                    :<span style={{fontSize:"10px",color:"#ddd",fontStyle:"normal",fontWeight:"600"}}>{"Live price unavailable - analysis based on recent data ("+priceInfo.time+" EST)"}</span>
                  }
                </div>
              )}
              {data.catalyst_type&&(
                <div style={{display:"inline-flex",alignItems:"center",gap:"6px",marginTop:"8px",marginBottom:"4px"}}>
                  <span style={{fontSize:"9px",fontWeight:"800",padding:"3px 10px",borderRadius:"4px",letterSpacing:"1px",
                    color:data.catalyst_type==="Earnings"?"#fbbf24":
                          data.catalyst_type==="FDA"?"#34d399":
                          data.catalyst_type==="M&A"?"#a78bfa":
                          data.catalyst_type==="Macro"?"#38bdf8":
                          data.catalyst_type==="Geopolitical"?"#ff9100":"#888",
                    background:data.catalyst_type==="Earnings"?"rgba(251,191,36,0.1)":
                               data.catalyst_type==="FDA"?"rgba(52,211,153,0.1)":
                               data.catalyst_type==="M&A"?"rgba(167,139,250,0.1)":
                               data.catalyst_type==="Macro"?"rgba(56,189,248,0.1)":
                               data.catalyst_type==="Geopolitical"?"rgba(255,145,0,0.1)":"rgba(255,255,255,0.06)",
                    border:"1px solid "+(data.catalyst_type==="Earnings"?"rgba(251,191,36,0.3)":
                                         data.catalyst_type==="FDA"?"rgba(52,211,153,0.3)":
                                         data.catalyst_type==="M&A"?"rgba(167,139,250,0.3)":
                                         data.catalyst_type==="Macro"?"rgba(56,189,248,0.3)":
                                         data.catalyst_type==="Geopolitical"?"rgba(255,145,0,0.3)":"rgba(255,255,255,0.1)")
                  }}>{data.catalyst_type.toUpperCase()}</span>
                </div>
              )}
              {data.catalyst_strength&&(
                <div style={{display:"flex",alignItems:"center",gap:"8px",marginTop:"6px",marginBottom:"4px"}}>
                  <span style={{fontSize:"9px",color:"#ddd",whiteSpace:"nowrap"}}>CATALYST STRENGTH</span>
                  <div style={{flex:1,height:"5px",background:"rgba(255,255,255,0.06)",borderRadius:"3px",maxWidth:"150px"}}>
                    <div style={{width:Math.min(data.catalyst_strength,100)+"%",height:"100%",borderRadius:"3px",
                      background:data.catalyst_strength>=80?"#00e676":data.catalyst_strength>=60?"#ffeb3b":"#ff5252"}}/>
                  </div>
                  <span style={{fontFamily:JM,fontSize:"10px",fontWeight:"800",
                    color:data.catalyst_strength>=80?"#00e676":data.catalyst_strength>=60?"#ffeb3b":"#ff5252"}}>
                    {data.catalyst_strength+"/100"}
                  </span>
                </div>
              )}
              {data.prediction_summary&&<div style={{fontSize:"13px",color:"#ccc",marginTop:"4px",maxWidth:"500px"}}>{data.prediction_summary}</div>}
            {data.avoid_if&&<div style={{display:"flex",gap:"8px",alignItems:"flex-start",marginTop:"10px",padding:"8px 12px",background:"rgba(255,82,82,0.06)",border:"1px solid rgba(255,82,82,0.2)",borderRadius:"6px",maxWidth:"500px"}}>
              <span style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:"#ff5252",flexShrink:0,marginTop:"1px"}}>AVOID IF</span>
              <span style={{fontSize:"11px",color:"#ff5252",lineHeight:"1.5"}}>{data.avoid_if}</span>
            </div>}
            {data.earnings_warning&&(
              <div style={{display:"flex",gap:"8px",alignItems:"flex-start",marginTop:"10px",padding:"10px 12px",background:"rgba(251,191,36,0.06)",border:"1px solid rgba(251,191,36,0.3)",borderRadius:"6px",maxWidth:"500px"}}>
                <span style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:"#fbbf24",flexShrink:0,marginTop:"1px"}}>EARNINGS</span>
                <div>
                  {data.earnings_date&&<div style={{fontFamily:JM,fontSize:"11px",color:"#fbbf24",marginBottom:"3px"}}>{data.earnings_date}</div>}
                  <div style={{fontSize:"11px",color:"#d4a017",lineHeight:"1.5"}}>{data.earnings_warning}</div>
                </div>
              </div>
            )}
            </div>
            <div style={{display:"flex",flexDirection:"column",alignItems:"flex-end",gap:"10px"}}>
              <div style={{textAlign:"center"}}>
                <div style={{fontFamily:JM,fontSize:"28px",fontWeight:"800",color:pc}}>{(data.confidence||0)+"%"}</div>
                <div style={{fontSize:"9px",color:"#ddd",letterSpacing:"1px"}}>CONFIDENCE</div>
              </div>
              {data.conviction_score&&(
                <div style={{display:"flex",flexDirection:"column",alignItems:"center",padding:"6px 14px",background:W04,border:"1px solid "+W08,borderRadius:"8px"}}>
                  <div style={{display:"flex",alignItems:"center",gap:"6px",marginBottom:"4px"}}>
                    <div style={{width:"60px",height:"4px",background:"rgba(255,255,255,0.06)",borderRadius:"2px"}}>
                      <div style={{width:Math.min(data.conviction_score,100)+"%",height:"100%",borderRadius:"2px",
                        background:data.conviction_score>=80?pc:data.conviction_score>=70?"#ffeb3b":"#ff5252"}}/>
                    </div>
                    <span style={{fontFamily:JM,fontSize:"14px",fontWeight:"800",
                      color:data.conviction_score>=80?pc:data.conviction_score>=70?"#ffeb3b":"#ff5252"}}>
                      {data.conviction_score+"/100"}
                    </span>
                  </div>
                  <div style={{fontSize:"9px",color:"#ddd",letterSpacing:"1px"}}>CONVICTION</div>
                </div>
              )}
              {data.catalyst_strength&&(
                <div style={{display:"flex",flexDirection:"column",alignItems:"center",padding:"6px 14px",background:W04,border:"1px solid "+W08,borderRadius:"8px"}}>
                  <div style={{display:"flex",alignItems:"center",gap:"6px",marginBottom:"4px"}}>
                    <div style={{width:"60px",height:"4px",background:"rgba(255,255,255,0.06)",borderRadius:"2px"}}>
                      <div style={{width:Math.min(data.catalyst_strength,100)+"%",height:"100%",borderRadius:"2px",
                        background:data.catalyst_strength>=80?"#ff9100":data.catalyst_strength>=60?"#ffeb3b":"#555"}}/>
                    </div>
                    <span style={{fontFamily:JM,fontSize:"14px",fontWeight:"800",
                      color:data.catalyst_strength>=80?"#ff9100":data.catalyst_strength>=60?"#ffeb3b":"#555"}}>
                      {data.catalyst_strength+"/100"}
                    </span>
                  </div>
                  <div style={{fontSize:"9px",color:"#ddd",letterSpacing:"1px"}}>CATALYST</div>
                </div>
              )}
              <div style={{padding:"6px 14px",background:ac+"15",border:"1px solid "+ac+"33",borderRadius:"4px",fontFamily:JM,fontSize:"13px",fontWeight:"800",color:ac}}>{data.trade_action}</div>
            </div>
          </div>

          {data.volume_context&&data.volume_context.relative_volume&&(
            <div style={{marginTop:"14px",padding:"10px 14px",background:W04,border:"1px solid "+W08,borderRadius:"8px"}}>
              <div style={{display:"flex",alignItems:"center",gap:"10px",flexWrap:"wrap"}}>
                <div style={{fontFamily:JM,fontSize:"9px",color:"#ddd",letterSpacing:"2px"}}>VOLUME</div>
                <span style={{fontFamily:JM,fontSize:"13px",fontWeight:"800",
                  color:parseFloat(data.volume_context.relative_volume)>=2?"#00e676":
                        parseFloat(data.volume_context.relative_volume)>=0.8?"#ffeb3b":"#ff5252"}}>
                  {data.volume_context.relative_volume+"x avg"}
                </span>
                {data.volume_context.current_volume&&<span style={{fontSize:"11px",color:"#ccc"}}>{data.volume_context.current_volume}</span>}
                {data.volume_context.volume_signal&&<span style={{fontSize:"11px",color:"#bbb",fontStyle:"normal",fontWeight:"600"}}>{data.volume_context.volume_signal}</span>}
              </div>
            </div>
          )}
          {data.news_items?.length>0&&(
            <div style={{marginBottom:"16px"}}>
              <div style={{fontFamily:JM,fontSize:"9px",color:"#ddd",letterSpacing:"2px",marginBottom:"10px"}}>NEWS DRIVING PREDICTION</div>
              <div style={{display:"flex",flexDirection:"column",gap:"8px"}}>
                {data.news_items.slice(0,4).map((n,i)=>(
                  <div key={i} style={{padding:"12px 14px",background:W04,border:"1px solid "+W08,borderRadius:"7px"}}>
                    <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"8px"}}>
                      <div style={{fontSize:"12px",color:"#ddd",flex:1}}>{n.headline}</div>
                      <div style={{display:"flex",gap:"5px",flexShrink:0}}>
                        <span style={{fontSize:"9px",color:"#ddd"}}>{n.source}</span>
                        {n.hours_ago!=null&&<span style={{fontSize:"9px",color:"#ddd"}}>{n.hours_ago+"h ago"}</span>}
                      </div>
                    </div>
                  </div>
                ))}
              </div>
            </div>
          )}

          
          {onAnalyze&&data&&data.ticker&&(
            <button onClick={function(){onAnalyze(data.ticker);}}
              style={{width:"100%",padding:"14px",marginTop:"12px",
                background:"rgba(56,189,248,0.08)",
                border:"2px solid rgba(56,189,248,0.35)",
                borderRadius:"8px",color:"#38bdf8",fontFamily:JM,
                fontSize:"12px",fontWeight:"800",cursor:"pointer",
                letterSpacing:"1px",display:"flex",alignItems:"center",
                justifyContent:"center",gap:"8px"}}>
              {"DEEP ANALYSIS IN STOCK ANALYSIS ->"}
            </button>
          )}
        </div>
      )}

      {!loading&&!data&&(
        <div style={{textAlign:"center",padding:"50px 20px",border:"1px dashed rgba(255,145,0,0.15)",borderRadius:"12px"}}>
          <div style={{fontFamily:JM,fontSize:"11px",color:"#ff9100",letterSpacing:"2px",marginBottom:"8px"}}>ENTER A TICKER TO PREDICT</div>
          <div style={{fontSize:"12px",color:"#ccc"}}>{"Enter any ticker to get an AI-powered news catalyst score, conviction rating, and best timeframe recommendation. Or click SCAN FOR CATALYSTS to find top opportunities across the market right now."}</div>
        </div>
      )}
    </div>
  );
}

/* -- DAILY SCREENER ----------------------------------------- */
function DailyScreener({onAnalyze,watchlist}){
  const TOP50=[
    "SPY","QQQ","IWM","DIA",
    "NVDA","AAPL","MSFT","META","GOOGL","AMZN","TSLA","AMD","AVGO","CRM","NFLX","ORCL","ADBE","QCOM","TXN","MU","PLTR","COIN",
    "JPM","GS","MS","BAC","V","MA","BLK","SCHW","AXP",
    "LLY","UNH","JNJ","ABBV","MRK","PFE","AMGN","GILD",
    "XOM","CVX","COP","SLB","OXY",
    "CAT","BA","GE","RTX","HON","UPS",
    "WMT","COST","MCD","NKE","SBUX","HD","TGT",
    "GLD","NEM","FCX","BHP",
    "UBER","SHOP","ABNB","DASH",
  ];
  const [loading,setLoading]=useState(false);
  const [results,setResults]=useState([]);
  const [error,setError]=useState(null);
  const [status,setStatus]=useState("");
  const [scanned,setScanned]=useState(0);
  const [cacheTs,setCacheTs]=useState(null);
  const [selected,setSelected]=useState(new Set());
  const [batchSize,setBatchSize]=useState(5);
  const [mode,setMode]=useState("top50");
  const [dirFilter,setDirFilter]=useState("ALL");

  useEffect(()=>{ loadCache("screener").then(c=>{if(c?.value){setResults(c.value);setCacheTs(c.ts);setScanned(c.value.length);}});  },[]);

  async function scan(){
    setLoading(true);setError(null);setStatus("Scanning market for top setups...");
    try{
      const today=new Date().toLocaleDateString("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric"});
      const tickers=mode==="watchlist"&&watchlist&&watchlist.length>0?watchlist:TOP50;
      const wl=tickers.join(",");
      const prompt="Today is "+today+". Find the top "+batchSize+" highest-scoring stock trade setups right now from this list: "+wl+". Include both LONG and SHORT setups. Return JSON array.";
      const text=await callAPI(SCREENER_SYS,prompt,5000);
      const cleaned=text.trim().replace(/^\x60{3}(?:json)?\s*/i,"").replace(/\s*\x60{3}\s*$/,"").trim();
      const s=cleaned.indexOf("["),e=cleaned.lastIndexOf("]");
      if(s<0||e<0)throw new Error("No array in response");
      const arr=JSON.parse(cleaned.slice(s,e+1));
      setResults(arr);setScanned(arr.length);
      saveCache("screener",arr);setCacheTs(Date.now());
    }catch(e){setError(e.message);}
    setLoading(false);setStatus("");
  }

  function toggleTicker(t){
    setSelected(prev=>{
      const next=new Set(prev);
      if(next.has(t))next.delete(t);
      else if(next.size<batchSize)next.add(t);
      return next;
    });
  }

  const scoreColor=s=>s>=90?"#ff3d71":s>=80?"#00e676":s>=70?"#ffeb3b":"#888";

  return(
    <div>
      <div style={{display:"flex",flexWrap:"wrap",gap:"5px",padding:"10px",background:W04,border:"1px solid "+W08,borderRadius:"8px",marginBottom:"12px"}}>
        {TOP50.map(function(t){
          return(
            <span key={t} style={{padding:"4px 10px",background:"rgba(167,139,250,0.06)",border:"1px solid rgba(167,139,250,0.15)",borderRadius:"4px",color:"#a78bfa",fontFamily:JM,fontSize:"10px",fontWeight:"700"}}>{t}</span>
          );
        })}
      </div>

      <div style={{display:"flex",gap:"8px",marginBottom:"12px",flexWrap:"wrap",alignItems:"center"}}>
        <button onClick={scan} disabled={loading}
          style={{padding:"10px 20px",background:"transparent",border:"1px solid #a78bfa",borderRadius:"7px",color:"#a78bfa",fontFamily:JM,fontSize:"12px",fontWeight:"800",cursor:"pointer",opacity:loading?0.6:1}}>
          {loading?<span style={{display:"flex",alignItems:"center",gap:"8px"}}><Bars color="#a78bfa"/>{status||"SCANNING..."}</span>:"RUN SCAN"}
        </button>
        {["top50","watchlist"].map(m=>(
          <button key={m} onClick={()=>setMode(m)} style={{padding:"6px 12px",background:mode===m?"rgba(167,139,250,0.1)":"transparent",border:"1px solid "+(mode===m?"rgba(167,139,250,0.4)":"rgba(255,255,255,0.08)"),borderRadius:"5px",color:mode===m?"#a78bfa":"#555",fontFamily:JM,fontSize:"10px",fontWeight:"700",cursor:"pointer"}}>{m==="top50"?"TOP 50":"WATCHLIST"}</button>
        ))}
        {[5,10].map(n=>(
          <button key={n} onClick={()=>setBatchSize(n)} style={{padding:"6px 12px",background:batchSize===n?"rgba(167,139,250,0.1)":"transparent",border:"1px solid "+(batchSize===n?"rgba(167,139,250,0.4)":"rgba(255,255,255,0.08)"),borderRadius:"5px",color:batchSize===n?"#a78bfa":"#555",fontFamily:JM,fontSize:"10px",fontWeight:"700",cursor:"pointer"}}>{"PICK "+n}</button>
        ))}
        {cacheTs&&!loading&&<span style={{fontSize:"10px",color:"#ddd",marginLeft:"auto"}}>{ago(cacheTs)}</span>}
      </div>

      {error&&<ErrBox msg={error}/>}

      {results.length>0&&(
        <div>
          <div style={{display:"flex",gap:"6px",marginBottom:"10px"}}>
            {["ALL","LONG","SHORT"].map(function(f){
              return(
                <button key={f} onClick={function(){setDirFilter(f);}}
                  style={{padding:"5px 16px",
                    background:dirFilter===f?(f==="LONG"?"rgba(0,230,118,0.15)":f==="SHORT"?"rgba(255,82,82,0.15)":"rgba(167,139,250,0.15)"):"transparent",
                    border:"1px solid "+(dirFilter===f?(f==="LONG"?"rgba(0,230,118,0.5)":f==="SHORT"?"rgba(255,82,82,0.5)":"rgba(167,139,250,0.5)"):"rgba(255,255,255,0.1)"),
                    borderRadius:"5px",color:dirFilter===f?(f==="LONG"?"#00e676":f==="SHORT"?"#ff5252":"#a78bfa"):"#555",
                    fontFamily:JM,fontSize:"10px",fontWeight:"800",cursor:"pointer"}}>
                  {f}
                </button>
              );
            })}
          </div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(120px,1fr))",gap:"8px",marginBottom:"16px"}}>
            {[["SETUPS",results.length,"#a78bfa"],["LONG",results.filter(r=>r.direction==="LONG").length,"#00e676"],["SHORT",results.filter(r=>r.direction==="SHORT").length,"#ff5252"],["SELECTED",selected.size+"/"+batchSize,"#ffeb3b"]].map(([l,v,c])=>(
              <div key={l} style={{padding:"10px",background:W04,border:"1px solid "+W08,borderRadius:"7px"}}>
                <div style={{fontFamily:JM,fontSize:"9px",color:"#ddd",letterSpacing:"2px",marginBottom:"4px"}}>{l}</div>
                <div style={{fontFamily:JM,fontSize:"16px",fontWeight:"800",color:c}}>{v}</div>
              </div>
            ))}
          </div>
          <div style={{display:"flex",flexDirection:"column",gap:"8px"}}>
            {results.filter(function(r){return dirFilter==="ALL"||r.direction===dirFilter;}).map(r=>{
              const sc=scoreColor(r.score);
              const dc=r.direction==="LONG"?"#00e676":"#ff5252";
              const isSel=selected.has(r.ticker);
              const isFull=selected.size>=batchSize&&!isSel;
              return(
                <div key={r.ticker} onClick={()=>!isFull&&toggleTicker(r.ticker)}
                  style={{padding:"14px 16px",background:isSel?"rgba(167,139,250,0.08)":W04,border:"1px solid "+(isSel?"rgba(167,139,250,0.4)":W08),borderRadius:"9px",cursor:isFull?"not-allowed":"pointer",opacity:isFull?0.5:1,transition:"all 0.15s"}}>
                  <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",flexWrap:"wrap",gap:"8px"}}>
                    <div>
                      <div style={{display:"flex",alignItems:"center",gap:"8px",marginBottom:"4px",flexWrap:"wrap"}}>
                        <span style={{fontFamily:JM,fontSize:"16px",fontWeight:"800",color:"#fff"}}>{r.ticker}</span>
                        <span style={{fontSize:"9px",fontWeight:"800",padding:"2px 6px",borderRadius:"3px",color:dc,background:dc+"15"}}>{r.direction}</span>
                        {r.sector&&<span style={{fontSize:"9px",fontWeight:"700",padding:"2px 6px",borderRadius:"3px",color:"#ccc",background:"rgba(255,255,255,0.06)",border:"1px solid rgba(255,255,255,0.1)"}}>{r.sector}</span>}
                        <span style={{fontFamily:JM,fontSize:"12px",color:sc}}>{"Score: "+r.score}</span>
                        {isSel&&<span style={{fontSize:"9px",color:"#a78bfa"}}>? SELECTED</span>}
                      </div>
                      <div style={{fontSize:"11px",color:"#ccc"}}>{r.company_name}</div>
                    </div>
                    <div style={{textAlign:"right"}}>
                      <div style={{fontFamily:JM,fontSize:"14px",fontWeight:"700",color:sc}}>{r.expected_move}</div>
                      <div style={{fontSize:"10px",color:"#ddd"}}>{r.timeframe}</div>
                    </div>
                  </div>
                  {r.setup_type&&<span style={{fontSize:"9px",fontWeight:"700",padding:"2px 8px",borderRadius:"3px",color:"#fbbf24",background:"rgba(251,191,36,0.1)",border:"1px solid rgba(251,191,36,0.25)",display:"inline-block",marginTop:"6px"}}>{r.setup_type}</span>}
                  {r.signal&&<div style={{fontSize:"11px",color:"#ccc",marginTop:"6px",lineHeight:"1.5"}}>{r.signal}</div>}
                  {r.why_now&&<div style={{fontSize:"11px",color:"#bbb",marginTop:"4px",fontStyle:"normal",fontWeight:"600"}}>{r.why_now}</div>}
                  {onAnalyze&&<button onClick={e=>{e.stopPropagation();onAnalyze(r.ticker);}} style={{marginTop:"8px",padding:"5px 12px",background:"rgba(56,189,248,0.08)",border:"1px solid rgba(56,189,248,0.2)",borderRadius:"4px",color:"#38bdf8",fontFamily:JM,fontSize:"9px",fontWeight:"700",cursor:"pointer"}}>DEEP ANALYSIS</button>}
                </div>
              );
            })}
          </div>
        </div>
      )}

      {!loading&&results.length===0&&(
        <div style={{textAlign:"center",padding:"50px 20px",border:"1px dashed rgba(167,139,250,0.15)",borderRadius:"12px"}}>
          <div style={{fontFamily:JM,fontSize:"11px",color:"#2a1f40",letterSpacing:"2px",marginBottom:"8px"}}>PRESS RUN SCAN TO FIND TOP SETUPS</div>
          <div style={{fontSize:"12px",color:"#1a1530"}}>{"AI scans for high-conviction LONG and SHORT setups scored 70+"}</div>
        </div>
      )}
    </div>
  );
}
/* -- SECTOR HEATMAP ----------------------------------------- */
function SectorHeatmap(){
  const [data,setData]=useState([]);
  const [loading,setLoading]=useState(false);
  const [aiCtx,setAiCtx]=useState(null);
  const [error,setError]=useState(null);
  const [cacheTs,setCacheTs]=useState(null);

  useEffect(()=>{
    loadCache("sector").then(c=>{if(c?.value){setData(c.value.prices||[]);setAiCtx(c.value.ai||null);setCacheTs(c.ts);}});
    loadPrices();
  },[]);

  async function loadPrices(){
    setLoading(true);
    const results=await Promise.all(SECTOR_ETFS.map(async s=>{
      const p=await fetchPrice(s.etf).catch(()=>null);
      return{...s,price:p?.price,change:p?.change,raw:p?.raw,changeNum:p?.change?parseFloat(p.change):null};
    }));
    setData(results);
    setLoading(false);
    setCacheTs(Date.now());
  }

  async function getAiContext(){
    setLoading(true);setError(null);
    try{
      const ctx=data.filter(d=>d.changeNum!=null).map(d=>d.name+": "+d.change).join(", ");
      const today=new Date().toLocaleDateString("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric"});
      const text=await callAPI("You are a sector rotation analyst. Analyze sector performance and provide brief insights. Return ONLY raw JSON: {\"themes\":[{\"theme\":\"\",\"sectors\":[\"\"],\"insight\":\"\"}],\"rotation\":\"\",\"opportunities\":\"\"}",
        "Today is "+today+". Sector performance: "+ctx+". Identify 3 rotation themes and opportunities.",2000);
      const parsed=parseJSON(text);
      setAiCtx(parsed);
      saveCache("sector",{prices:data,ai:parsed});
      setCacheTs(Date.now());
    }catch(e){setError(e.message);}
    setLoading(false);
  }

  return(
    <div>
      <div style={{display:"flex",gap:"8px",marginBottom:"16px",flexWrap:"wrap",alignItems:"center"}}>
        <button onClick={loadPrices} disabled={loading}
          style={{padding:"8px 16px",background:"transparent",border:"1px solid #34d399",borderRadius:"6px",color:"#34d399",fontFamily:JM,fontSize:"11px",fontWeight:"700",cursor:"pointer"}}>REFRESH PRICES</button>
        <button onClick={getAiContext} disabled={loading}
          style={{padding:"8px 16px",background:"transparent",border:"1px solid rgba(52,211,153,0.4)",borderRadius:"6px",color:"#34d399",fontFamily:JM,fontSize:"11px",fontWeight:"700",cursor:"pointer"}}>GET AI CONTEXT</button>
        {cacheTs&&<span style={{fontSize:"10px",color:"#ddd",marginLeft:"auto"}}>{ago(cacheTs)}</span>}
      </div>
      {error&&<ErrBox msg={error}/>}
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fill,minmax(160px,1fr))",gap:"8px",marginBottom:"20px"}}>
        {(data.length?data:SECTOR_ETFS).map(s=>{
          const chg=s.changeNum;
          const bg=chg==null?"rgba(255,255,255,0.02)":chg>1?"rgba(0,230,118,0.12)":chg>0?"rgba(0,230,118,0.05)":chg<-1?"rgba(255,82,82,0.12)":"rgba(255,82,82,0.05)";
          const col=chg==null?"#555":chg>0?"#00e676":"#ff5252";
          return(
            <div key={s.etf} style={{padding:"14px",background:bg,border:"1px solid "+(chg==null?W08:chg>0?"rgba(0,230,118,0.2)":"rgba(255,82,82,0.2)"),borderRadius:"8px"}}>
              <div style={{fontFamily:JM,fontSize:"10px",color:"#ddd",marginBottom:"4px"}}>{s.etf}</div>
              <div style={{fontSize:"12px",fontWeight:"600",color:"#fff",marginBottom:"6px"}}>{s.name}</div>
              {s.price&&<div style={{fontFamily:JM,fontSize:"16px",fontWeight:"800",color:"#fff"}}>{s.price}</div>}
              {s.change&&<div style={{fontFamily:JM,fontSize:"12px",color:col}}>{s.change}</div>}
              {!s.price&&<div style={{fontSize:"11px",color:"#ccc"}}>Loading...</div>}
            </div>
          );
        })}
      </div>
      {aiCtx&&(
        <div style={{padding:"16px",background:W04,border:"1px solid "+W08,borderRadius:"10px"}}>
          <div style={{fontFamily:JM,fontSize:"9px",color:"#34d399",letterSpacing:"2px",marginBottom:"12px"}}>AI SECTOR ANALYSIS</div>
          {aiCtx.rotation&&<div style={{fontSize:"12px",color:"#ccc",marginBottom:"10px"}}>{aiCtx.rotation}</div>}
          {aiCtx.themes?.map((t,i)=>(
            <div key={i} style={{marginBottom:"10px",paddingLeft:"12px",borderLeft:"2px solid rgba(52,211,153,0.3)"}}>
              <div style={{fontFamily:JM,fontSize:"10px",fontWeight:"700",color:"#34d399",marginBottom:"3px"}}>{t.theme}</div>
              <div style={{fontSize:"11px",color:"#ddd"}}>{t.insight}</div>
            </div>
          ))}
          {aiCtx.opportunities&&<div style={{marginTop:"10px",fontSize:"12px",color:"#ccc"}}>{aiCtx.opportunities}</div>}
        </div>
      )}
    </div>
  );
}

/* -- CONGRESS TRADES --------------------------------------- */
const PARTY_C={Democrat:"#38bdf8",Republican:"#ff5252",Independent:"#a78bfa"};
const COMMITTEE_MAP={Tuberville:"Armed Services",Rubio:"Intelligence",Warner:"Intelligence",Manchin:"Energy",Cantwell:"Energy",Thune:"Commerce",Khanna:"Armed Services",Pelosi:"Financial Svcs",Schiff:"Intelligence"};
function getParty(name){if(!name)return null;const n=name.toUpperCase();if(n.includes("(D)"))return"Democrat";if(n.includes("(R)"))return"Republican";if(n.includes("(I)"))return"Independent";return null;}
function getCommittee(name){if(!name)return null;const last=name.replace(/\(.\)/,"").trim().split(/\s+/).pop();return COMMITTEE_MAP[last]||null;}

function CongressTrades(){
  const [loading,setLoading]=useState(false);
  const [trades,setTrades]=useState([]);
  const [error,setError]=useState(null);
  const [cacheTs,setCacheTs]=useState(null);
  const [filter,setFilter]=useState("ALL");

  useEffect(()=>{ loadCache("congress").then(c=>{if(c?.value){setTrades(c.value);setCacheTs(c.ts);}}); },[]);

  async function scan(){
    setLoading(true);setError(null);
    try{
      const today=new Date().toLocaleDateString("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric"});
      const text=await callAPI(CONGRESS_SYS,"Today is "+today+". Search housestockwatcher.com and senatestockwatcher.com for the 25 most recent congressional stock trades from 2024-2025. Return JSON array only.",4000);
      const cleaned=text.trim().replace(/^\x60{3}(?:json)?\s*/i,"").replace(/\s*\x60{3}\s*$/,"").trim();
      const s=cleaned.indexOf("["),e=cleaned.lastIndexOf("]");
      if(s<0||e<0)throw new Error("No data found");
      const arr=JSON.parse(cleaned.slice(s,e+1));
      setTrades(arr);saveCache("congress",arr);setCacheTs(Date.now());
    }catch(e){setError(e.message);}
    setLoading(false);
  }

  const filtered=trades.filter(t=>filter==="ALL"||(filter==="BUY"?t.transaction_type?.toUpperCase().includes("PURCH"):t.transaction_type?.toUpperCase().includes("SALE")));

  return(
    <div>
      <div style={{display:"flex",gap:"8px",marginBottom:"14px",flexWrap:"wrap",alignItems:"center"}}>
        <button onClick={scan} disabled={loading}
          style={{padding:"10px 20px",background:"transparent",border:"1px solid #f59e0b",borderRadius:"7px",color:"#f59e0b",fontFamily:JM,fontSize:"12px",fontWeight:"700",cursor:"pointer",opacity:loading?0.6:1}}>
          {loading?<span style={{display:"flex",alignItems:"center",gap:"8px"}}><Bars color="#f59e0b"/>FETCHING...</span>:"FETCH CONGRESS TRADES"}
        </button>
        {["ALL","BUY","SELL"].map(f=>(
          <button key={f} onClick={()=>setFilter(f)} style={{padding:"6px 12px",background:filter===f?"rgba(245,158,11,0.1)":"transparent",border:"1px solid "+(filter===f?"rgba(245,158,11,0.4)":"rgba(255,255,255,0.08)"),borderRadius:"5px",color:filter===f?"#f59e0b":"#555",fontFamily:JM,fontSize:"10px",fontWeight:"700",cursor:"pointer"}}>{f}</button>
        ))}
        {cacheTs&&!loading&&<span style={{fontSize:"10px",color:"#ddd",marginLeft:"auto"}}>{ago(cacheTs)}</span>}
      </div>
      {error&&<ErrBox msg={error}/>}
      {filtered.length>0&&(
        <div style={{display:"flex",flexDirection:"column",gap:"8px"}}>
          {filtered.map((t,i)=>{
            const isBuy=t.transaction_type?.toUpperCase().includes("PURCH")||t.transaction_type?.toUpperCase().includes("BUY");
            const tc=isBuy?"#00e676":"#ff5252";
            const party=getParty(t.representative);
            const pc=party?PARTY_C[party]:"#888";
            const committee=getCommittee(t.representative);
            return(
              <div key={i} style={{padding:"14px 16px",background:W04,border:"1px solid "+W08,borderRadius:"9px"}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",flexWrap:"wrap",gap:"8px"}}>
                  <div>
                    <div style={{display:"flex",alignItems:"center",gap:"8px",marginBottom:"4px",flexWrap:"wrap"}}>
                      <span style={{fontFamily:JM,fontSize:"15px",fontWeight:"800",color:"#fff"}}>{t.ticker||"N/A"}</span>
                      <span style={{fontSize:"9px",fontWeight:"800",padding:"2px 6px",borderRadius:"3px",color:tc,background:tc+"15"}}>{isBuy?"BUY":"SELL"}</span>
                      {party&&<span style={{fontSize:"9px",fontWeight:"700",padding:"2px 5px",borderRadius:"3px",color:pc,background:pc+"15"}}>{party}</span>}
                      {committee&&<span style={{fontSize:"9px",padding:"2px 5px",borderRadius:"3px",color:"#a78bfa",background:"rgba(167,139,250,0.1)"}}>{committee}</span>}
                    </div>
                    <div style={{fontSize:"11px",color:"#ccc"}}>{t.representative}</div>
                    {t.asset_description&&<div style={{fontSize:"10px",color:"#ddd",marginTop:"2px"}}>{t.asset_description}</div>}
                  </div>
                  <div style={{textAlign:"right"}}>
                    <div style={{fontFamily:JM,fontSize:"12px",fontWeight:"700",color:tc}}>{t.amount||"--"}</div>
                    <div style={{fontSize:"10px",color:"#ddd",marginTop:"2px"}}>{t.transaction_date||"--"}</div>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}
      {!loading&&trades.length===0&&(
        <div style={{textAlign:"center",padding:"40px",border:"1px dashed rgba(245,158,11,0.15)",borderRadius:"10px"}}>
          <div style={{fontFamily:JM,fontSize:"11px",color:"#2a2000",letterSpacing:"2px",marginBottom:"8px"}}>PRESS FETCH TO LOAD CONGRESSIONAL TRADES</div>
          <div style={{fontSize:"12px",color:"#1a1500"}}>{"Required to be disclosed within 45 days by the STOCK Act"}</div>
        </div>
      )}
    </div>
  );
}
/* -- PRICE ALERTS ------------------------------------------- */
const ALERT_TYPES=[{key:"price_above",label:"Price Above",color:"#00e676"},{key:"price_below",label:"Price Below",color:"#ff5252"},{key:"pct_gain",label:"% Gain From Entry",color:"#00e676"},{key:"pct_drop",label:"% Drop From Entry",color:"#ff5252"},{key:"insider_buy",label:"New Insider Buy",color:"#f59e0b"},{key:"cluster",label:"Cluster Alert",color:"#ff3d71"}];

function AlertsTab(){
  const [alerts,setAlerts]=useState([]);
  const [loaded,setLoaded]=useState(false);
  const [showCreate,setShowCreate]=useState(false);

  useEffect(()=>{ retrieve("iw_alerts_v1").then(d=>{if(d)setAlerts(d);setLoaded(true);}); },[]);
  useEffect(()=>{ if(!loaded)return; store("iw_alerts_v1",alerts); },[alerts]);

  function saveAlert(a){ setAlerts(prev=>[{...a,id:Date.now()+"_"+Math.random().toString(36).slice(2),createdAt:Date.now(),active:true},...prev]); setShowCreate(false); }
  function deleteAlert(id){ setAlerts(prev=>prev.filter(a=>a.id!==id)); }
  function toggleAlert(id){ setAlerts(prev=>prev.map(a=>a.id===id?{...a,active:!a.active}:a)); }

  return(
    <div>
      <div style={{display:"flex",gap:"8px",marginBottom:"16px",alignItems:"center"}}>
        <button onClick={()=>setShowCreate(!showCreate)}
          style={{padding:"10px 20px",background:"rgba(244,63,94,0.08)",border:"1px solid rgba(244,63,94,0.3)",borderRadius:"7px",color:"#f43f5e",fontFamily:JM,fontSize:"12px",fontWeight:"700",cursor:"pointer"}}>
          {showCreate?"CANCEL":"+ CREATE ALERT"}
        </button>
        <span style={{fontSize:"11px",color:"#ddd"}}>{alerts.filter(a=>a.active).length+" active alerts"}</span>
      </div>

      {showCreate&&<CreateAlertModal onSave={saveAlert} onClose={()=>setShowCreate(false)}/>}

      {alerts.length>0&&(
        <div style={{display:"flex",flexDirection:"column",gap:"8px"}}>
          {alerts.map(alert=>{
            const t=ALERT_TYPES.find(x=>x.key===alert.type)||{color:"#ccc",label:alert.type};
            return(
              <div key={alert.id} style={{padding:"14px 16px",background:alert.active?W04:"rgba(255,255,255,0.01)",border:"1px solid "+(alert.active?W08:"rgba(255,255,255,0.04)"),borderRadius:"9px",opacity:alert.active?1:0.5}}>
                <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",gap:"8px"}}>
                  <div>
                    <div style={{display:"flex",alignItems:"center",gap:"8px",marginBottom:"4px"}}>
                      <span style={{fontFamily:JM,fontSize:"14px",fontWeight:"800",color:"#fff"}}>{alert.ticker}</span>
                      <span style={{fontSize:"9px",fontWeight:"800",padding:"2px 6px",borderRadius:"3px",color:t.color,background:t.color+"15"}}>{t.label}</span>
                    </div>
                    <div style={{fontSize:"11px",color:"#ccc"}}>{alert.threshold?"At $"+alert.threshold:alert.pct?alert.pct+"%":""}</div>
                    <div style={{fontSize:"9px",color:"#ddd",marginTop:"2px"}}>{"Created "+new Date(alert.createdAt).toLocaleDateString()}</div>
                  </div>
                  <div style={{display:"flex",gap:"6px"}}>
                    <button onClick={()=>toggleAlert(alert.id)} style={{padding:"4px 10px",background:"transparent",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"4px",color:alert.active?"#00e676":"#555",fontFamily:JM,fontSize:"9px",cursor:"pointer"}}>{alert.active?"ON":"OFF"}</button>
                    <button onClick={()=>deleteAlert(alert.id)} style={{padding:"4px 10px",background:"transparent",border:"1px solid rgba(255,82,82,0.2)",borderRadius:"4px",color:"#ddd",fontFamily:JM,fontSize:"9px",cursor:"pointer"}}>DEL</button>
                  </div>
                </div>
              </div>
            );
          })}
        </div>
      )}

      {loaded&&alerts.length===0&&(
        <div style={{textAlign:"center",padding:"40px",border:"1px dashed rgba(244,63,94,0.15)",borderRadius:"10px"}}>
          <div style={{fontFamily:JM,fontSize:"11px",color:"#2a0a12",letterSpacing:"2px",marginBottom:"8px"}}>NO ALERTS SET</div>
          <div style={{fontSize:"12px",color:"#1a0810"}}>{"Set price alerts and insider buy triggers"}</div>
        </div>
      )}
    </div>
  );
}

function CreateAlertModal({onSave,onClose}){
  const [ticker,setTicker]=useState("");
  const [type,setType]=useState("price_above");
  const [threshold,setThreshold]=useState("");
  const [pct,setPct]=useState("");
  const [email,setEmail]=useState("");

  function save(){
    if(!ticker)return;
    onSave({ticker:ticker.toUpperCase(),type,threshold:threshold?parseFloat(threshold):null,pct:pct?parseFloat(pct):null,email});
  }

  const needsThreshold=type==="price_above"||type==="price_below";
  const needsPct=type==="pct_gain"||type==="pct_drop";

  return(
    <div style={{background:"rgba(244,63,94,0.04)",border:"1px solid rgba(244,63,94,0.2)",borderRadius:"10px",padding:"16px",marginBottom:"16px"}}>
      <div style={{fontFamily:JM,fontSize:"10px",fontWeight:"800",color:"#f43f5e",letterSpacing:"2px",marginBottom:"14px"}}>CREATE ALERT</div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(120px,1fr))",gap:"8px",marginBottom:"10px"}}>
        <input value={ticker} onChange={e=>setTicker(e.target.value.toUpperCase())} placeholder="TICKER"
          style={{padding:"8px 10px",background:W06,border:"1px solid rgba(244,63,94,0.3)",borderRadius:"5px",color:"#fff",fontFamily:JM,fontSize:"13px",outline:"none"}}/>
        <select value={type} onChange={e=>setType(e.target.value)}
          style={{padding:"8px 10px",background:W06,border:"1px solid "+W1,borderRadius:"5px",color:"#fff",fontFamily:JM,fontSize:"11px"}}>
          {ALERT_TYPES.map(t=><option key={t.key} value={t.key}>{t.label}</option>)}
        </select>
        {needsThreshold&&<input value={threshold} onChange={e=>setThreshold(e.target.value)} placeholder="Price $" type="number"
          style={{padding:"8px 10px",background:W06,border:"1px solid "+W1,borderRadius:"5px",color:"#fff",fontFamily:JM,fontSize:"13px",outline:"none"}}/>}
        {needsPct&&<input value={pct} onChange={e=>setPct(e.target.value)} placeholder="%" type="number"
          style={{padding:"8px 10px",background:W06,border:"1px solid "+W1,borderRadius:"5px",color:"#fff",fontFamily:JM,fontSize:"13px",outline:"none"}}/>}
        <input value={email} onChange={e=>setEmail(e.target.value)} placeholder="Email (optional)"
          style={{padding:"8px 10px",background:W06,border:"1px solid "+W1,borderRadius:"5px",color:"#fff",fontFamily:JM,fontSize:"12px",outline:"none"}}/>
      </div>
      <button onClick={save} style={{padding:"8px 20px",background:"rgba(244,63,94,0.1)",border:"1px solid rgba(244,63,94,0.3)",borderRadius:"6px",color:"#f43f5e",fontFamily:JM,fontSize:"11px",fontWeight:"700",cursor:"pointer"}}>CREATE ALERT</button>
    </div>
  );
}

/* -- TRADE JOURNAL ------------------------------------------ */
const SIGNAL_SOURCES=["Insider Scan","News Predictor","Daily Screener","Stock Analysis","Congress Trades","Manual"];
const TRADE_STATUS=["OPEN","CLOSED","CANCELLED"];

function TradeJournal(){
  const [trades,setTrades]=useState([]);
  const [showForm,setShowForm]=useState(false);
  const [editId,setEditId]=useState(null);
  const [filter,setFilter]=useState("ALL");
  const [form,setForm]=useState({ticker:"",direction:"LONG",source:"Manual",entryDate:new Date().toISOString().split("T")[0],entryPrice:"",shares:"",stopPrice:"",targetPrice:"",notes:"",status:"OPEN",exitDate:"",exitPrice:""});

  useEffect(()=>{ retrieve("iw_journal_v1").then(d=>{if(d)setTrades(d);}); },[]);

  function save(next){setTrades(next);store("iw_journal_v1",next);}
  function resetForm(){setForm({ticker:"",direction:"LONG",source:"Manual",entryDate:new Date().toISOString().split("T")[0],entryPrice:"",shares:"",stopPrice:"",targetPrice:"",notes:"",status:"OPEN",exitDate:"",exitPrice:""});}

  function submit(){
    const ep=parseFloat(form.entryPrice),sh=parseInt(form.shares);
    if(!form.ticker||!ep||!sh)return;
    const xp=parseFloat(form.exitPrice)||null,st=parseFloat(form.stopPrice)||null;
    const pnl=xp&&form.status==="CLOSED"?(xp-ep)*sh*(form.direction==="SHORT"?-1:1):null;
    const pnlPct=xp&&form.status==="CLOSED"?((xp-ep)/ep)*100*(form.direction==="SHORT"?-1:1):null;
    const riskPS=st?Math.abs(ep-st):null;
    const rMult=pnl!=null&&riskPS?pnl/(riskPS*sh):null;
    const rec={...form,id:editId||(Date.now()+"_"+Math.random().toString(36).slice(2)),ticker:form.ticker.toUpperCase().trim(),entryPrice:ep,shares:sh,stopPrice:st,targetPrice:parseFloat(form.targetPrice)||null,exitPrice:xp,pnl,pnlPct,rMultiple:rMult,updatedAt:Date.now(),createdAt:editId?(trades.find(t=>t.id===editId)?.createdAt||Date.now()):Date.now()};
    save(editId?trades.map(t=>t.id===editId?rec:t):[rec,...trades]);
    setShowForm(false);setEditId(null);resetForm();
  }

  const closed=trades.filter(t=>t.status==="CLOSED");
  const open=trades.filter(t=>t.status==="OPEN");
  const winners=closed.filter(t=>(t.pnl||0)>0);
  const totalPnl=closed.reduce((a,t)=>a+(t.pnl||0),0);
  const winRate=closed.length>0?Math.round(winners.length/closed.length*100):null;
  const avgWin=winners.length>0?winners.reduce((a,t)=>a+(t.pnl||0),0)/winners.length:0;
  const losers=closed.filter(t=>(t.pnl||0)<0);
  const avgLoss=losers.length>0?Math.abs(losers.reduce((a,t)=>a+(t.pnl||0),0)/losers.length):0;
  const pf=avgLoss>0?(avgWin/avgLoss).toFixed(2):null;
  const pc=n=>n>0?"#00e676":n<0?"#ff5252":"#888";
  const dc=d=>d==="LONG"?"#00e676":"#ff5252";
  const visible=trades.filter(t=>filter==="ALL"||t.status===filter).sort((a,b)=>b.createdAt-a.createdAt);

  const inp=(key,type,ph,col)=>(
    <input type={type||"text"} value={form[key]} onChange={e=>setForm(f=>({...f,[key]:type==="text"?e.target.value.toUpperCase():e.target.value}))} placeholder={ph||""}
      style={{width:"100%",padding:"8px 10px",background:col?"rgba(232,121,249,0.06)":W06,border:"1px solid "+(col||W1),borderRadius:"5px",color:"#fff",fontFamily:JM,fontSize:"13px",outline:"none",boxSizing:"border-box"}}/>
  );

  return(
    <div>
      <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(120px,1fr))",gap:"10px",marginBottom:"20px"}}>
        {[["TOTAL P&L",closed.length?"$"+totalPnl.toFixed(0):"--",pc(totalPnl)],["WIN RATE",winRate!=null?winRate+"%":"--",winRate>=55?"#00e676":winRate>=45?"#ffeb3b":"#ff5252"],["OPEN",open.length,"#38bdf8"],["CLOSED",closed.length,"#888"],["PROFIT FACTOR",pf||"--",parseFloat(pf)>=1.5?"#00e676":parseFloat(pf)>=1?"#ffeb3b":"#ff5252"]].map(([l,v,c])=>(
          <div key={l} style={{background:W04,border:"1px solid "+W08,borderRadius:"8px",padding:"12px"}}>
            <div style={{fontFamily:JM,fontSize:"9px",fontWeight:"700",color:"#ddd",letterSpacing:"2px",marginBottom:"6px"}}>{l}</div>
            <div style={{fontFamily:JM,fontSize:"18px",fontWeight:"800",color:c}}>{v}</div>
          </div>
        ))}
      </div>

      <div style={{display:"flex",gap:"8px",marginBottom:"14px",flexWrap:"wrap",alignItems:"center"}}>
        <button onClick={()=>{setShowForm(!showForm);setEditId(null);resetForm();}} style={{padding:"8px 16px",background:"rgba(232,121,249,0.08)",border:"1px solid rgba(232,121,249,0.3)",borderRadius:"6px",color:"#e879f9",fontFamily:JM,fontSize:"11px",fontWeight:"700",cursor:"pointer"}}>{showForm&&!editId?"CANCEL":"+ LOG TRADE"}</button>
        {["ALL","OPEN","CLOSED","CANCELLED"].map(f=>(
          <button key={f} onClick={()=>setFilter(f)} style={{padding:"6px 12px",background:filter===f?"rgba(232,121,249,0.1)":"transparent",border:"1px solid "+(filter===f?"rgba(232,121,249,0.4)":W08),borderRadius:"5px",color:filter===f?"#e879f9":"#555",fontFamily:JM,fontSize:"10px",fontWeight:"700",cursor:"pointer"}}>{f}</button>
        ))}
      </div>

      {showForm&&(
        <div style={{background:"rgba(232,121,249,0.04)",border:"1px solid rgba(232,121,249,0.2)",borderRadius:"10px",padding:"16px",marginBottom:"16px"}}>
          <div style={{fontFamily:JM,fontSize:"10px",fontWeight:"800",color:"#e879f9",letterSpacing:"2px",marginBottom:"12px"}}>{editId?"EDIT TRADE":"LOG NEW TRADE"}</div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(120px,1fr))",gap:"8px",marginBottom:"10px"}}>
            {inp("ticker","text","TICKER","rgba(232,121,249,0.1)")}
            <select value={form.direction} onChange={e=>setForm(f=>({...f,direction:e.target.value}))} style={{padding:"8px 10px",background:W06,border:"1px solid "+W1,borderRadius:"5px",color:"#fff",fontFamily:JM,fontSize:"13px"}}>
              {["LONG","SHORT"].map(d=><option key={d} value={d}>{d}</option>)}
            </select>
            <select value={form.source} onChange={e=>setForm(f=>({...f,source:e.target.value}))} style={{padding:"8px 10px",background:W06,border:"1px solid "+W1,borderRadius:"5px",color:"#fff",fontFamily:JM,fontSize:"13px"}}>
              {SIGNAL_SOURCES.map(s=><option key={s} value={s}>{s}</option>)}
            </select>
            <select value={form.status} onChange={e=>setForm(f=>({...f,status:e.target.value}))} style={{padding:"8px 10px",background:W06,border:"1px solid "+W1,borderRadius:"5px",color:"#fff",fontFamily:JM,fontSize:"13px"}}>
              {TRADE_STATUS.map(s=><option key={s} value={s}>{s}</option>)}
            </select>
          </div>
          <div style={{display:"grid",gridTemplateColumns:"repeat(auto-fit,minmax(120px,1fr))",gap:"8px",marginBottom:"10px"}}>
            {inp("entryDate","date")}
            {inp("entryPrice","number","Entry $")}
            {inp("shares","number","Shares")}
            {inp("stopPrice","number","Stop $")}
            {inp("targetPrice","number","Target $")}
            {form.status!=="OPEN"&&inp("exitDate","date")}
            {form.status!=="OPEN"&&inp("exitPrice","number","Exit $")}
          </div>
          <button onClick={submit} style={{padding:"8px 20px",background:"rgba(232,121,249,0.1)",border:"1px solid rgba(232,121,249,0.4)",borderRadius:"6px",color:"#e879f9",fontFamily:JM,fontSize:"12px",fontWeight:"700",cursor:"pointer"}}>{editId?"SAVE CHANGES":"ADD TRADE"}</button>
        </div>
      )}

      {visible.length>0&&(
        <div style={{display:"flex",flexDirection:"column",gap:"10px"}}>
          {visible.map(t=>(
            <div key={t.id} style={{background:W04,border:"1px solid "+W08,borderRadius:"10px",padding:"16px"}}>
              <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",flexWrap:"wrap",gap:"8px",marginBottom:"8px"}}>
                <div style={{display:"flex",alignItems:"center",gap:"8px",flexWrap:"wrap"}}>
                  <span style={{fontFamily:JM,fontSize:"16px",fontWeight:"800",color:"#fff"}}>{t.ticker}</span>
                  <span style={{fontSize:"9px",fontWeight:"800",padding:"2px 6px",borderRadius:"3px",color:dc(t.direction),background:dc(t.direction)+"15"}}>{t.direction}</span>
                  <span style={{fontSize:"9px",padding:"2px 6px",borderRadius:"3px",color:t.status==="OPEN"?"#38bdf8":"#888",background:W04}}>{t.status}</span>
                  {t.source&&<span style={{fontSize:"9px",color:"#ddd"}}>{t.source}</span>}
                </div>
                <div style={{display:"flex",gap:"6px"}}>
                  <button onClick={()=>{setEditId(t.id);setForm({...t,exitDate:t.exitDate||""});setShowForm(true);}} style={{padding:"3px 10px",background:"transparent",border:"1px solid "+W1,borderRadius:"4px",color:"#ccc",fontSize:"10px",fontFamily:JM,cursor:"pointer"}}>EDIT</button>
                  <button onClick={()=>save(trades.filter(x=>x.id!==t.id))} style={{padding:"3px 10px",background:"transparent",border:"1px solid rgba(255,82,82,0.2)",borderRadius:"4px",color:"#ddd",fontSize:"10px",fontFamily:JM,cursor:"pointer"}}>DEL</button>
                </div>
              </div>
              <div style={{display:"flex",gap:"16px",flexWrap:"wrap",fontSize:"11px",color:"#ccc"}}>
                {t.entryPrice&&<span>{"$"+t.entryPrice}</span>}
                {t.shares&&<span>{t.shares+" sh"}</span>}
                {t.stopPrice&&<span style={{color:"#ff5252"}}>{"Stop $"+t.stopPrice}</span>}
                {t.targetPrice&&<span style={{color:"#00e676"}}>{"Target $"+t.targetPrice}</span>}
                {t.entryDate&&<span>{t.entryDate}</span>}
              </div>
              {t.pnl!=null&&(
                <div style={{marginTop:"8px",display:"flex",gap:"12px",alignItems:"center"}}>
                  <div style={{fontFamily:JM,fontSize:"18px",fontWeight:"800",color:pc(t.pnl)}}>{(t.pnl>=0?"+":"")+"$"+Math.abs(t.pnl).toFixed(0)}</div>
                  {t.pnlPct!=null&&<div style={{fontSize:"11px",color:pc(t.pnl)}}>{(t.pnlPct>=0?"+":"")+t.pnlPct.toFixed(1)+"%"}</div>}
                  {t.rMultiple!=null&&<div style={{fontFamily:JM,fontSize:"11px",color:pc(t.pnl)}}>{(t.rMultiple>=0?"+":"")+t.rMultiple.toFixed(2)+"R"}</div>}
                </div>
              )}
              {t.notes&&<div style={{marginTop:"6px",fontSize:"11px",color:"#ddd",fontStyle:"normal",fontWeight:"600"}}>{t.notes}</div>}
            </div>
          ))}
        </div>
      )}

      {visible.length===0&&(
        <div style={{textAlign:"center",padding:"40px",border:"1px dashed rgba(232,121,249,0.15)",borderRadius:"10px"}}>
          <div style={{fontFamily:JM,fontSize:"11px",color:"#2a1530",letterSpacing:"2px"}}>NO TRADES LOGGED YET</div>
          <div style={{fontSize:"12px",color:"#1a0d20",marginTop:"8px"}}>{"Press + LOG TRADE to record your first trade"}</div>
        </div>
      )}
    </div>
  );
}
/* -- MACRO CALENDAR ----------------------------------------- */
function MacroCalendar(){
  const JM="'JetBrains Mono',monospace";
  const [events,setEvents]=React.useState([]);
  const [loading,setLoading]=React.useState(false);
  const [selectedEvent,setSelectedEvent]=React.useState(null);
  const [analysis,setAnalysis]=React.useState(null);
  const [analysisLoading,setAnalysisLoading]=React.useState(false);
  const [currentDate,setCurrentDate]=React.useState(new Date());
  const [cacheTs,setCacheTs]=React.useState(null);

  const IMPACT_COLOR={high:"#ff5252",medium:"#ffeb3b",low:"#00e676",holiday:"#555"};
  const IMPACT_BG={high:"rgba(255,82,82,0.08)",medium:"rgba(255,235,59,0.08)",low:"rgba(0,230,118,0.08)",holiday:"rgba(255,255,255,0.02)"};

  // Known recurring 2025 economic events - always show immediately
  var RECURRING=[
    // APRIL 2026
    {date:"2026-04-01",time:"10:00am ET",event:"ISM Manufacturing PMI",impact:"medium",country:"US",forecast:"49.5",previous:"49.8"},
    {date:"2026-04-02",time:"8:30am ET",event:"Jobless Claims",impact:"medium",country:"US",forecast:"225K",previous:"220K"},
    {date:"2026-04-03",time:"8:30am ET",event:"Non-Farm Payrolls (NFP)",impact:"high",country:"US",forecast:"185K",previous:"151K"},
    {date:"2026-04-03",time:"8:30am ET",event:"Unemployment Rate",impact:"high",country:"US",forecast:"4.1%",previous:"4.1%"},
    {date:"2026-04-07",time:"10:00am ET",event:"ISM Services PMI",impact:"medium",country:"US",forecast:"51.0",previous:"50.8"},
    {date:"2026-04-09",time:"8:30am ET",event:"Jobless Claims",impact:"medium",country:"US",forecast:"225K",previous:"225K"},
    {date:"2026-04-10",time:"8:30am ET",event:"CPI Inflation Report",impact:"high",country:"US",forecast:"2.5%",previous:"2.8%"},
    {date:"2026-04-14",time:"8:30am ET",event:"PPI Producer Prices",impact:"medium",country:"US",forecast:"2.2%",previous:"2.7%"},
    {date:"2026-04-15",time:"8:30am ET",event:"Retail Sales",impact:"medium",country:"US",forecast:"0.3%",previous:"0.2%"},
    {date:"2026-04-16",time:"8:30am ET",event:"Jobless Claims",impact:"medium",country:"US",forecast:"225K",previous:"223K"},
    {date:"2026-04-16",time:"8:30am ET",event:"Housing Starts",impact:"medium",country:"US",forecast:"1.35M",previous:"1.30M"},
    {date:"2026-04-22",time:"10:00am ET",event:"Consumer Confidence",impact:"medium",country:"US",forecast:"88.0",previous:"92.9"},
    {date:"2026-04-23",time:"8:30am ET",event:"Jobless Claims",impact:"medium",country:"US",forecast:"225K",previous:"225K"},
    {date:"2026-04-24",time:"8:30am ET",event:"PCE Price Index",impact:"high",country:"US",forecast:"2.3%",previous:"2.5%"},
    {date:"2026-04-29",time:"10:00am ET",event:"Consumer Confidence CB",impact:"medium",country:"US",forecast:"88.0",previous:"92.9"},
    {date:"2026-04-29",time:"2:00pm ET",event:"FOMC Meeting Begins",impact:"high",country:"US",forecast:"",previous:""},
    {date:"2026-04-30",time:"8:30am ET",event:"GDP Growth Rate Q1 2026",impact:"high",country:"US",forecast:"1.2%",previous:"2.4%"},
    {date:"2026-04-30",time:"2:00pm ET",event:"FOMC Interest Rate Decision",impact:"high",country:"US",forecast:"4.25-4.50%",previous:"4.25-4.50%"},
    {date:"2026-04-30",time:"2:30pm ET",event:"Fed Powell Press Conference",impact:"high",country:"US",forecast:"",previous:""},
    // MAY 2026
    {date:"2026-05-01",time:"8:30am ET",event:"Jobless Claims",impact:"medium",country:"US",forecast:"225K",previous:"225K"},
    {date:"2026-05-01",time:"10:00am ET",event:"ISM Manufacturing PMI",impact:"medium",country:"US",forecast:"49.5",previous:"49.5"},
    {date:"2026-05-05",time:"10:00am ET",event:"ISM Services PMI",impact:"medium",country:"US",forecast:"51.0",previous:"51.0"},
    {date:"2026-05-07",time:"8:30am ET",event:"Jobless Claims",impact:"medium",country:"US",forecast:"225K",previous:"225K"},
    {date:"2026-05-08",time:"8:30am ET",event:"Non-Farm Payrolls (NFP)",impact:"high",country:"US",forecast:"180K",previous:"185K"},
    {date:"2026-05-13",time:"8:30am ET",event:"CPI Inflation Report",impact:"high",country:"US",forecast:"2.4%",previous:"2.5%"},
    {date:"2026-05-14",time:"8:30am ET",event:"PPI Producer Prices",impact:"medium",country:"US",forecast:"2.1%",previous:"2.2%"},
    {date:"2026-05-15",time:"8:30am ET",event:"Retail Sales",impact:"medium",country:"US",forecast:"0.3%",previous:"0.3%"},
    {date:"2026-05-21",time:"8:30am ET",event:"Jobless Claims",impact:"medium",country:"US",forecast:"225K",previous:"225K"},
    {date:"2026-05-28",time:"8:30am ET",event:"PCE Price Index",impact:"high",country:"US",forecast:"2.2%",previous:"2.3%"},
    // JUNE 2026
    {date:"2026-06-05",time:"8:30am ET",event:"Non-Farm Payrolls (NFP)",impact:"high",country:"US",forecast:"178K",previous:"180K"},
    {date:"2026-06-10",time:"8:30am ET",event:"CPI Inflation Report",impact:"high",country:"US",forecast:"2.3%",previous:"2.4%"},
    {date:"2026-06-17",time:"2:00pm ET",event:"FOMC Interest Rate Decision",impact:"high",country:"US",forecast:"4.00-4.25%",previous:"4.25-4.50%"},
    {date:"2026-06-17",time:"2:30pm ET",event:"Fed Powell Press Conference",impact:"high",country:"US",forecast:"",previous:""},
    {date:"2026-06-25",time:"8:30am ET",event:"PCE Price Index",impact:"high",country:"US",forecast:"2.1%",previous:"2.2%"},
    {date:"2026-06-25",time:"8:30am ET",event:"GDP Growth Rate Q1 Final",impact:"high",country:"US",forecast:"1.2%",previous:"1.2%"},
  ];

  React.useEffect(function(){
    // Show recurring events immediately
    setEvents(RECURRING);
    // Then try to load real data
    loadCalendar();
  },[currentDate]);

  async function loadCalendar(){
    setLoading(true);
    try{
      var url="https://nfs.faireconomy.media/ff_calendar_thisweek.json";
      var nextUrl="https://nfs.faireconomy.media/ff_calendar_nextweek.json";
      var allEvents=[];
      var proxy="https://api.allorigins.win/get?url=";
      try{
        var ctrl=new AbortController();
        setTimeout(function(){ctrl.abort();},5000);
        var r=await fetch(proxy+encodeURIComponent(url),{signal:ctrl.signal});
        if(r.ok){
          var j=await r.json();
          var data=j.contents?JSON.parse(j.contents):j;
          if(Array.isArray(data))allEvents=allEvents.concat(data);
        }
      }catch(_){}
      try{
        var ctrl2=new AbortController();
        setTimeout(function(){ctrl2.abort();},5000);
        var r2=await fetch(proxy+encodeURIComponent(nextUrl),{signal:ctrl2.signal});
        if(r2.ok){
          var j2=await r2.json();
          var d2=j2.contents?JSON.parse(j2.contents):j2;
          if(Array.isArray(d2))allEvents=allEvents.concat(d2);
        }
      }catch(_){}
      if(allEvents.length>0){
        setEvents(RECURRING.concat(allEvents));setCacheTs(Date.now());
      } else {
        await loadAICalendar();
      }
    }catch(e){await loadAICalendar();}
    setLoading(false);
  }

  async function loadAICalendar(){
    try{
      const today=new Date().toLocaleDateString("en-US",{weekday:"long",year:"numeric",month:"long",day:"numeric"});
      const text=await callAPI("You are an economic calendar expert. Return ONLY valid JSON array.",
        "Today is "+today+". List the most important US and global economic events for this week and next 2 weeks. Include: NFP jobs report, CPI, PCE, Fed meetings, GDP, retail sales, jobless claims, ISM, consumer confidence, earnings (major companies), OPEC meetings, G7/G20 summits. Return JSON array: [{date:'YYYY-MM-DD',time:'8:30am ET',currency:'USD',event:'Non-Farm Payrolls',impact:'high',forecast:'180K',previous:'175K',country:'US'}]. No markdown.",
        4000);
      var t=text.trim();
      var s=t.indexOf("["),e=t.lastIndexOf("]");
      if(s>-1&&e>-1){
        var parsed=JSON.parse(t.slice(s,e+1));
        setEvents(RECURRING.concat(parsed));setCacheTs(Date.now());
      }
    }catch(_){}
  }

  async function analyzeEvent(evt){
    setSelectedEvent(evt);setAnalysis(null);setAnalysisLoading(true);
    await new Promise(function(r){setTimeout(r,50);});
    try{
      const text=await callAPI(
        "You are a macro analyst. Return ONLY valid JSON. Be specific and actionable.",
        "Analyze: "+evt.event+" on "+evt.date+". Previous: "+(evt.previous||"N/A")+", Forecast: "+(evt.forecast||"N/A")+". Return JSON: {event_name:'',what_it_measures:'',beat_scenario:{market_reaction:'',sectors_up:[],sectors_down:[],trading_tip:''},miss_scenario:{market_reaction:'',sectors_up:[],sectors_down:[],trading_tip:''},before_event_strategy:'',sensitive_tickers:[{ticker:'',reason:'',beat_impact:'',miss_impact:''}]}",
        3000
      );
      const parsed=parseJSON(text);
      setAnalysis(parsed);
    }catch(e){setAnalysis({event_name:evt.event,error:e.message});}
    setAnalysisLoading(false);
  }

  // Build calendar grid
  const year=currentDate.getFullYear();
  const month=currentDate.getMonth();
  const firstDay=new Date(year,month,1).getDay();
  const daysInMonth=new Date(year,month+1,0).getDate();
  const monthName=currentDate.toLocaleDateString("en-US",{month:"long",year:"numeric"});

  function getEventsForDay(day){
    const dateStr=year+"-"+String(month+1).padStart(2,"0")+"-"+String(day).padStart(2,"0");
    return events.filter(function(e){
      var d=e.date||"";
      return d.startsWith(dateStr)||d===dateStr;
    });
  }

  function prevMonth(){var d=new Date(currentDate);d.setMonth(d.getMonth()-1);setCurrentDate(d);}
  function nextMonth(){var d=new Date(currentDate);d.setMonth(d.getMonth()+1);setCurrentDate(d);}

  const today=new Date();
  const isToday=function(day){return today.getFullYear()===year&&today.getMonth()===month&&today.getDate()===day;};

  return(
    <div style={{padding:"0",width:"100%",overflowX:"hidden",boxSizing:"border-box"}}>
      {/* Header */}
      <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:"16px",flexWrap:"wrap",gap:"8px"}}>
        <div>
          <div style={{fontFamily:JM,fontSize:"10px",color:"#a78bfa",letterSpacing:"3px",marginBottom:"4px"}}>MACRO CALENDAR</div>
          <div style={{fontSize:"22px",fontWeight:"800"}}>{monthName}</div>
        </div>
        <div style={{display:"flex",gap:"8px",alignItems:"center"}}>
          <div style={{display:"flex",gap:"12px",fontSize:"11px",fontFamily:JM}}>
            {[["HIGH","#ff5252"],["MEDIUM","#ffeb3b"],["LOW","#00e676"]].map(function([l,c]){return(
              <span key={l} style={{display:"flex",alignItems:"center",gap:"4px"}}>
                <span style={{width:"8px",height:"8px",borderRadius:"2px",background:c,display:"inline-block"}}></span>
                <span style={{color:"#888"}}>{l}</span>
              </span>
            );})}
          </div>
          <button onClick={prevMonth} style={{padding:"6px 12px",background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"4px",color:"#fff",cursor:"pointer",fontFamily:JM,fontSize:"11px"}}>{"<"}</button>
          <button onClick={nextMonth} style={{padding:"6px 12px",background:"rgba(255,255,255,0.05)",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"4px",color:"#fff",cursor:"pointer",fontFamily:JM,fontSize:"11px"}}>{">"}</button>
          <button onClick={function(){setEvents([]);loadCalendar();}} style={{padding:"6px 12px",background:"rgba(167,139,250,0.1)",border:"1px solid rgba(167,139,250,0.3)",borderRadius:"4px",color:"#a78bfa",cursor:"pointer",fontFamily:JM,fontSize:"9px",fontWeight:"800",letterSpacing:"1px"}}>REFRESH</button>
        </div>
      </div>

      {loading&&(
        <div style={{textAlign:"center",padding:"40px",color:"#888",fontFamily:JM,fontSize:"12px"}}>
          LOADING ECONOMIC CALENDAR...
        </div>
      )}

      {!loading&&(
        <div>
          {/* Day headers */}
          <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:"1px",marginBottom:"1px"}}>
            {["SUN","MON","TUE","WED","THU","FRI","SAT"].map(function(d){return(
              <div key={d} style={{fontFamily:JM,fontSize:"9px",fontWeight:"800",color:"#555",textAlign:"center",padding:"8px 0",letterSpacing:"1px"}}>{d}</div>
            );})}
          </div>

          {/* Calendar grid */}
          <div style={{display:"grid",gridTemplateColumns:"repeat(7,1fr)",gap:"1px"}}>
            {/* Empty cells */}
            {Array.from({length:firstDay}).map(function(_,i){
              return <div key={"e"+i} style={{background:"rgba(255,255,255,0.01)",borderRadius:"6px",minHeight:"70px"}}></div>;
            })}

            {/* Day cells */}
            {Array.from({length:daysInMonth}).map(function(_,i){
              var day=i+1;
              var dayEvents=getEventsForDay(day);
              var hasHigh=dayEvents.some(function(e){return(e.impact||"").toLowerCase()==="high";});
              var isWknd=function(){var d=new Date(year,month,day);return d.getDay()===0||d.getDay()===6;}();
              return(
                <div key={day} style={{
                  background:isToday(day)?"rgba(167,139,250,0.08)":isWknd?"rgba(255,255,255,0.01)":"rgba(255,255,255,0.03)",
                  border:isToday(day)?"1px solid rgba(167,139,250,0.3)":"1px solid rgba(255,255,255,0.04)",
                  borderRadius:"4px",minHeight:"70px",padding:"4px",position:"relative"}}>
                  <div style={{fontFamily:JM,fontSize:"11px",fontWeight:"800",
                    color:isToday(day)?"#a78bfa":isWknd?"#333":"#888",
                    marginBottom:"4px",display:"flex",justifyContent:"space-between",alignItems:"center"}}>
                    <span>{day}</span>
                    {hasHigh&&<span style={{width:"6px",height:"6px",borderRadius:"50%",background:"#ff5252",display:"inline-block"}}></span>}
                  </div>
                  <div style={{display:"flex",flexDirection:"column",gap:"2px"}}>
                    {dayEvents.slice(0,3).map(function(evt,ei){
                      var imp=(evt.impact||"low").toLowerCase();
                      return(
                        <div key={ei} onClick={function(){analyzeEvent(evt);}}
                          style={{padding:"2px 4px",borderRadius:"3px",
                            background:IMPACT_BG[imp]||"rgba(255,255,255,0.03)",
                            border:"1px solid "+(imp==="high"?"rgba(255,82,82,0.2)":imp==="medium"?"rgba(255,235,59,0.2)":"rgba(0,230,118,0.1)"),
                            cursor:"pointer",transition:"all 0.15s"}}
                          onMouseEnter={function(e){e.currentTarget.style.opacity="0.8";}}
                          onMouseLeave={function(e){e.currentTarget.style.opacity="1";}}>
                          <div style={{fontFamily:JM,fontSize:"8px",fontWeight:"800",
                            color:IMPACT_COLOR[imp]||"#888",
                            whiteSpace:"nowrap",overflow:"hidden",textOverflow:"ellipsis",maxWidth:"100%"}}>
                            {evt.event||evt.name||"Event"}
                          </div>
                          {evt.time&&<div style={{fontFamily:JM,fontSize:"7px",color:"#555"}}>{evt.time}</div>}
                        </div>
                      );
                    })}
                    {dayEvents.length>3&&(
                      <div style={{fontFamily:JM,fontSize:"8px",color:"#555",paddingLeft:"4px"}}>+{dayEvents.length-3} more</div>
                    )}
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {/* Event Analysis Panel */}
      {selectedEvent&&(
        <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.85)",zIndex:9000,display:"flex",alignItems:"center",justifyContent:"center",padding:"20px"}}
          onClick={function(e){if(e.target===e.currentTarget){setSelectedEvent(null);setAnalysis(null);}}}>
          <div style={{background:"#0d1117",border:"1px solid rgba(167,139,250,0.2)",borderRadius:"14px",maxWidth:"680px",width:"100%",maxHeight:"85vh",overflowY:"auto",padding:"28px"}}>
            <div style={{display:"flex",justifyContent:"space-between",alignItems:"flex-start",marginBottom:"20px"}}>
              <div>
                <div style={{fontFamily:JM,fontSize:"10px",color:"#a78bfa",letterSpacing:"2px",marginBottom:"6px"}}>MACRO EVENT ANALYSIS</div>
                <div style={{fontSize:"20px",fontWeight:"800"}}>{selectedEvent.event||selectedEvent.name}</div>
                <div style={{fontFamily:JM,fontSize:"11px",color:"#888",marginTop:"4px"}}>
                  {selectedEvent.date}{selectedEvent.time?" at "+selectedEvent.time:""}{selectedEvent.country?" -- "+selectedEvent.country:""}
                </div>
                <div style={{display:"flex",gap:"12px",marginTop:"8px",flexWrap:"wrap"}}>
                  {selectedEvent.forecast&&<span style={{fontFamily:JM,fontSize:"10px",color:"#38bdf8"}}>{"Forecast: "+selectedEvent.forecast}</span>}
                  {selectedEvent.previous&&<span style={{fontFamily:JM,fontSize:"10px",color:"#888"}}>{"Previous: "+selectedEvent.previous}</span>}
                </div>
              </div>
              <button onClick={function(){setSelectedEvent(null);setAnalysis(null);}}
                style={{background:"transparent",border:"1px solid rgba(255,255,255,0.1)",borderRadius:"4px",color:"#888",padding:"6px 12px",cursor:"pointer",fontFamily:JM,fontSize:"11px"}}>
                CLOSE
              </button>
            </div>

            {analysisLoading&&(
              <div style={{textAlign:"center",padding:"40px",color:"#888",fontFamily:JM,fontSize:"11px",letterSpacing:"2px"}}>
                ANALYZING MARKET IMPACT...
              </div>
            )}

            {analysis&&!analysisLoading&&(
              <div style={{display:"flex",flexDirection:"column",gap:"16px"}}>
                {analysis.error&&<div style={{color:"#ff5252",fontFamily:JM,fontSize:"11px"}}>{analysis.error}</div>}

                {analysis.what_it_measures&&(
                  <div style={{padding:"14px",background:"rgba(255,255,255,0.03)",borderRadius:"8px",border:"1px solid rgba(255,255,255,0.06)"}}>
                    <div style={{fontFamily:JM,fontSize:"9px",color:"#a78bfa",letterSpacing:"2px",marginBottom:"8px"}}>WHAT IT MEASURES</div>
                    <div style={{fontSize:"13px",color:"#ddd",lineHeight:"1.7",fontWeight:"600"}}>{analysis.what_it_measures}</div>
                  </div>
                )}

                <div style={{display:"grid",gridTemplateColumns:"1fr 1fr",gap:"12px"}}>
                  {analysis.beat_scenario&&(
                    <div style={{padding:"14px",background:"rgba(0,230,118,0.04)",border:"1px solid rgba(0,230,118,0.15)",borderRadius:"8px"}}>
                      <div style={{fontFamily:JM,fontSize:"9px",color:"#00e676",letterSpacing:"2px",marginBottom:"8px"}}>IF BEATS FORECAST</div>
                      <div style={{fontSize:"12px",color:"#ddd",lineHeight:"1.6",fontWeight:"600",marginBottom:"8px"}}>{analysis.beat_scenario.market_reaction}</div>
                      {analysis.beat_scenario.sectors_up&&analysis.beat_scenario.sectors_up.length>0&&(
                        <div style={{marginBottom:"6px"}}>
                          <span style={{fontFamily:JM,fontSize:"9px",color:"#00e676"}}>BENEFITS: </span>
                          <span style={{fontSize:"11px",color:"#bbb"}}>{analysis.beat_scenario.sectors_up.join(", ")}</span>
                        </div>
                      )}
                      {analysis.beat_scenario.sectors_down&&analysis.beat_scenario.sectors_down.length>0&&(
                        <div style={{marginBottom:"6px"}}>
                          <span style={{fontFamily:JM,fontSize:"9px",color:"#ff5252"}}>HURTS: </span>
                          <span style={{fontSize:"11px",color:"#bbb"}}>{analysis.beat_scenario.sectors_down.join(", ")}</span>
                        </div>
                      )}
                      {analysis.beat_scenario.trading_tip&&(
                        <div style={{marginTop:"8px",padding:"8px",background:"rgba(0,230,118,0.06)",borderRadius:"4px",fontSize:"11px",color:"#00e676",fontWeight:"600"}}>{analysis.beat_scenario.trading_tip}</div>
                      )}
                    </div>
                  )}
                  {analysis.miss_scenario&&(
                    <div style={{padding:"14px",background:"rgba(255,82,82,0.04)",border:"1px solid rgba(255,82,82,0.15)",borderRadius:"8px"}}>
                      <div style={{fontFamily:JM,fontSize:"9px",color:"#ff5252",letterSpacing:"2px",marginBottom:"8px"}}>IF MISSES FORECAST</div>
                      <div style={{fontSize:"12px",color:"#ddd",lineHeight:"1.6",fontWeight:"600",marginBottom:"8px"}}>{analysis.miss_scenario.market_reaction}</div>
                      {analysis.miss_scenario.sectors_up&&analysis.miss_scenario.sectors_up.length>0&&(
                        <div style={{marginBottom:"6px"}}>
                          <span style={{fontFamily:JM,fontSize:"9px",color:"#00e676"}}>BENEFITS: </span>
                          <span style={{fontSize:"11px",color:"#bbb"}}>{analysis.miss_scenario.sectors_up.join(", ")}</span>
                        </div>
                      )}
                      {analysis.miss_scenario.sectors_down&&analysis.miss_scenario.sectors_down.length>0&&(
                        <div style={{marginBottom:"6px"}}>
                          <span style={{fontFamily:JM,fontSize:"9px",color:"#ff5252"}}>HURTS: </span>
                          <span style={{fontSize:"11px",color:"#bbb"}}>{analysis.miss_scenario.sectors_down.join(", ")}</span>
                        </div>
                      )}
                      {analysis.miss_scenario.trading_tip&&(
                        <div style={{marginTop:"8px",padding:"8px",background:"rgba(255,82,82,0.06)",borderRadius:"4px",fontSize:"11px",color:"#ff5252",fontWeight:"600"}}>{analysis.miss_scenario.trading_tip}</div>
                      )}
                    </div>
                  )}
                </div>

                {analysis.before_event_strategy&&(
                  <div style={{padding:"14px",background:"rgba(255,235,59,0.04)",border:"1px solid rgba(255,235,59,0.15)",borderRadius:"8px"}}>
                    <div style={{fontFamily:JM,fontSize:"9px",color:"#ffeb3b",letterSpacing:"2px",marginBottom:"8px"}}>TRADING STRATEGY</div>
                    <div style={{fontSize:"13px",color:"#ddd",lineHeight:"1.7",fontWeight:"600"}}>{analysis.before_event_strategy}</div>
                  </div>
                )}

                {analysis.sensitive_tickers&&analysis.sensitive_tickers.length>0&&(
                  <div style={{padding:"14px",background:"rgba(56,189,248,0.04)",border:"1px solid rgba(56,189,248,0.12)",borderRadius:"8px"}}>
                    <div style={{fontFamily:JM,fontSize:"9px",color:"#38bdf8",letterSpacing:"2px",marginBottom:"10px"}}>SENSITIVE STOCKS</div>
                    <div style={{display:"flex",flexDirection:"column",gap:"8px"}}>
                      {analysis.sensitive_tickers.map(function(t,i){return(
                        <div key={i} style={{display:"flex",gap:"12px",alignItems:"flex-start",padding:"8px",background:"rgba(255,255,255,0.03)",borderRadius:"6px"}}>
                          <span style={{fontFamily:JM,fontSize:"12px",fontWeight:"800",color:"#38bdf8",minWidth:"50px"}}>{t.ticker}</span>
                          <div style={{flex:1}}>
                            <div style={{fontSize:"11px",color:"#ddd",marginBottom:"4px",fontWeight:"600"}}>{t.reason}</div>
                            <div style={{display:"flex",gap:"12px"}}>
                              {t.beat_impact&&<span style={{fontFamily:JM,fontSize:"9px",color:"#00e676"}}>{"BEAT: "+t.beat_impact}</span>}
                              {t.miss_impact&&<span style={{fontFamily:JM,fontSize:"9px",color:"#ff5252"}}>{"MISS: "+t.miss_impact}</span>}
                            </div>
                          </div>
                        </div>
                      );})}
                    </div>
                  </div>
                )}
              </div>
            )}


          </div>
        </div>
      )}
    </div>
  );
}


/* -- MARKET REGIME BANNER ----------------------------------- */
function MarketRegimeBanner(){
  const [data,setData]=useState(null);
  useEffect(()=>{
    async function load(){
      try{
        const [spy,vix]=await Promise.allSettled([fetchPrice("SPY"),fetchPrice("^VIX")]);
        const s=spy.status==="fulfilled"?spy.value:null;
        const v=vix.status==="fulfilled"?vix.value:null;
        const sc=s?.change?parseFloat(s.change):null;
        const vr=v?.raw||null;
        let regime="NEUTRAL",col="#ffeb3b";
        if(sc!==null&&vr!==null){if(sc>=0.5&&vr<20){regime="RISK-ON";col="#00e676";}else if(sc<=-1||vr>=25){regime="RISK-OFF";col="#ff5252";}else if(sc>=0){regime="NEUTRAL+";col="#69f0ae";}}
        setData({spy:s,vix:v,regime,col});
      }catch(_){}
    }
    load();
    const iv=setInterval(load,5*60*1000);
    return()=>clearInterval(iv);
  },[]);
  if(!data)return null;
  const uc=c=>c?.change?.startsWith("+")?""+"#00e676":c?.change?.startsWith("-")?"#ff5252":"#888";
  return(
    <div style={{background:"rgba(0,0,0,0.4)",borderBottom:"1px solid "+W06,padding:"5px 20px",display:"flex",alignItems:"center",gap:"16px",flexWrap:"wrap",justifyContent:"space-between"}}>
      <div style={{display:"flex",alignItems:"center",gap:"16px",flexWrap:"wrap"}}>
        {data.spy&&<div style={{display:"flex",alignItems:"center",gap:"5px"}}><span style={{fontFamily:JM,fontSize:"10px",color:"#aaa"}}>SPY</span><span style={{fontFamily:JM,fontSize:"11px",color:"#fff"}}>{data.spy.price}</span><span style={{fontFamily:JM,fontSize:"10px",color:uc(data.spy)}}>{data.spy.change}</span></div>}
        {data.vix&&<div style={{display:"flex",alignItems:"center",gap:"5px"}}><span style={{fontFamily:JM,fontSize:"10px",color:"#aaa"}}>VIX</span><span style={{fontFamily:JM,fontSize:"11px",color:data.vix.raw>=25?"#ff5252":data.vix.raw>=18?"#ffeb3b":"#00e676"}}>{data.vix.price}</span></div>}
      </div>
      <div style={{display:"flex",alignItems:"center",gap:"6px"}}>
        <div style={{width:"6px",height:"6px",borderRadius:"50%",background:data.col,flexShrink:0}}/>
        {data.spy&&(
          <span style={{fontFamily:JM,fontSize:"10px",color:"#888"}}>{"SPY"}</span>
        )}
        {data.spy&&(
          <span style={{fontFamily:JM,fontSize:"11px",fontWeight:"700",color:"#fff"}}>{data.spy.price}</span>
        )}
        {data.spy&&(
          <span style={{fontFamily:JM,fontSize:"10px",color:data.spy.change?.startsWith("+")?"#00e676":"#ff5252"}}>{data.spy.change}</span>
        )}
        <span style={{fontFamily:JM,fontSize:"10px",fontWeight:"800",color:data.col,letterSpacing:"1px"}}>{data.regime}</span>
      </div>
    </div>
  );
}

/* -- APP ---------------------------------------------------- */
export default function App(){
  const [tab,setTab]=useState("news");
  const [analysisTicker,setAnalysisTicker]=useState("");
  const [showAccess,setShowAccess]=useState(false);
  const [showDisclaimer,setShowDisclaimer]=useState(false);
  const [showWatchlist,setShowWatchlist]=useState(false);
  const [watchlist,setWatchlist]=useState(DEFAULT_WL);

  useEffect(()=>{
    try{
      var ac=localStorage.getItem("tiq_access");
      if(!ac){setShowAccess(true);return;}
    }catch(_){setShowAccess(true);return;}
    retrieve("iw_disclaimer_v1").then(r=>{if(!r)setShowDisclaimer(true);});
    retrieve("iw_watchlist_v1").then(r=>{if(r&&Array.isArray(r))setWatchlist(r);});
  },[]);

  function acceptAccess(){
    setShowAccess(false);
    retrieve("iw_disclaimer_v1").then(r=>{if(!r)setShowDisclaimer(true);});
    retrieve("iw_watchlist_v1").then(r=>{if(r&&Array.isArray(r))setWatchlist(r);});
  }
  function acceptDisclaimer(){store("iw_disclaimer_v1","accepted");setShowDisclaimer(false);}
  function saveWatchlist(list){setWatchlist(list);store("iw_watchlist_v1",list);}
  function goAnalyze(ticker){setAnalysisTicker(ticker);setTab("analysis");}

  const TABS=[
    ["news","NEWS PREDICTOR","#ff9100","rgba(255,145,0,0.15)"],
    ["analysis","STOCK ANALYSIS","#38bdf8","rgba(56,189,248,0.15)"],
    ["insider","INSIDER SCAN","#00e676","rgba(0,230,118,0.15)"],
    ["calendar","MACRO CALENDAR","#a78bfa","rgba(167,139,250,0.15)"],
  ];

  const TAB_DESC={
    insider:{subtitle:"THE SMART MONEY SIGNAL",title:"Track insiders buying with their own money",desc:"CEOs and directors file Form 4 within 2 days. Large open-market purchases signal strong conviction.",color:"#00e676"},
    screener:{subtitle:"DAILY TRADE SCREENER",title:"Ready-to-trade setups scored 70+",desc:"AI scans for high-conviction LONG and SHORT setups with entry, target, and stop loss.",color:"#a78bfa"},
    analysis:{subtitle:"DEEP STOCK ANALYSIS",title:"AI-powered technical + fundamental analysis",desc:"Comprehensive analysis combining technicals, fundamentals, macro factors, and live price data.",color:"#38bdf8"},
    heatmap:{subtitle:"SECTOR INTELLIGENCE",title:"Where is smart money flowing?",desc:"Real-time sector ETF prices with AI rotation context and themes.",color:"#34d399"},
    calendar:{subtitle:"ECONOMIC CALENDAR",title:"Know what moves markets before it happens",desc:"Monthly view of high-impact economic events. Click any event for AI analysis of beat/miss scenarios and which stocks are most affected.",color:"#a78bfa"},
    news:{subtitle:"NEWS PREDICTION ENGINE",title:"Will it go UP or DOWN?",desc:"AI-powered news catalyst scoring with conviction rating and best timeframe recommendation.",color:"#ff9100"},
    alerts:{subtitle:"SMART ALERT ENGINE",title:"Never miss a signal",desc:"Set price alerts and insider buy triggers. Get notified instantly.",color:"#f43f5e"},
    congress:{subtitle:"FOLLOW THE MONEY",title:"What is Congress buying and selling?",desc:"Track real stock trades by U.S. Senators and Representatives -- required within 45 days by the STOCK Act.",color:"#f59e0b"},
    journal:{subtitle:"MY TRADE JOURNAL",title:"Log, track and review every trade",desc:"Log trades from any tab. Track P&L, R-multiples, and discover which signal sources work best for you.",color:"#e879f9"},
  };

  const td=TAB_DESC[tab]||TAB_DESC.insider;

  return(
    <div style={{minHeight:"100vh",background:"#080c0a",fontFamily:"'DM Sans',sans-serif",color:"#e0e0e0",overflowX:"hidden",maxWidth:"100vw"}}>
      {showAccess&&<AccessCodeModal onSuccess={acceptAccess}/>}
      {!showAccess&&showDisclaimer&&<DisclaimerModal onAccept={()=>{store("iw_disclaimer_v1","accepted");setShowDisclaimer(false);}}/> }
      <style>{`
        @import url('https://fonts.googleapis.com/css2?family=DM+Sans:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700;800&display=swap');
        *{box-sizing:border-box;margin:0;padding:0;}
        ::-webkit-scrollbar{width:4px;} ::-webkit-scrollbar-thumb{background:#1e2e22;border-radius:2px;}
        @keyframes pulse{0%,100%{opacity:1}50%{opacity:0.3}}
        @keyframes glow{0%,100%{box-shadow:0 0 6px rgba(0,230,118,0.3)}50%{box-shadow:0 0 14px rgba(0,230,118,0.6)}}
      `}</style>

      {showDisclaimer&&(
        <div style={{position:"fixed",inset:0,background:"rgba(0,0,0,0.92)",zIndex:9999,display:"flex",alignItems:"center",justifyContent:"center",padding:"20px"}}>
          <div style={{background:"#0d1117",border:"1px solid rgba(0,230,118,0.3)",borderRadius:"12px",padding:"32px",maxWidth:"500px",width:"100%"}}>
            <div style={{fontFamily:JM,fontSize:"14px",fontWeight:"800",color:"#00e676",letterSpacing:"2px",marginBottom:"16px"}}>TRADEIQ -- DISCLAIMER</div>
            <div style={{fontSize:"13px",color:"#888",lineHeight:"1.8",marginBottom:"24px"}}>{"This tool is for informational and educational purposes only. Nothing here constitutes financial advice. Past performance does not guarantee future results. Always do your own research."}</div>
            <button onClick={acceptDisclaimer} style={{width:"100%",padding:"12px",background:"rgba(0,230,118,0.1)",border:"1px solid rgba(0,230,118,0.4)",borderRadius:"7px",color:"#00e676",fontFamily:JM,fontSize:"12px",fontWeight:"800",cursor:"pointer",letterSpacing:"1px"}}>I UNDERSTAND -- START USING TRADEIQ</button>
          </div>
        </div>
      )}

      {showWatchlist&&<WatchlistModal list={watchlist} onSave={saveWatchlist} onClose={()=>setShowWatchlist(false)}/>}

      <MarketRegimeBanner/>

      <div style={{borderBottom:"1px solid rgba(0,230,118,0.15)",background:"rgba(0,0,0,0.4)"}}>
        <div style={{padding:"0 20px",display:"flex",alignItems:"center",justifyContent:"space-between"}}>
          <div style={{display:"flex",alignItems:"center",gap:"10px",padding:"12px 0"}}>
            <div style={{fontFamily:JM,fontSize:"14px",fontWeight:"700",color:"#00e676",letterSpacing:"2px"}}>TRADEIQ</div>
            <div style={{fontSize:"9px",color:"#2e5035",letterSpacing:"2px"}}>AI MARKET INTELLIGENCE</div>
          </div>
          <div style={{display:"flex",alignItems:"center",gap:"8px"}}>
            <div style={{width:"6px",height:"6px",borderRadius:"50%",background:"#00e676",animation:"glow 2s ease infinite"}}/>
            <button onClick={()=>setShowWatchlist(true)} style={{padding:"4px 10px",background:"rgba(0,230,118,0.06)",border:"1px solid rgba(0,230,118,0.2)",borderRadius:"5px",color:"#2e5035",fontFamily:JM,fontSize:"9px",fontWeight:"700",cursor:"pointer"}}>{"WL ("+watchlist.length+")"}</button>
          </div>
        </div>
        <div style={{display:"flex",borderTop:"1px solid "+W04}}>
          {TABS.map(([id,label,activeColor,activeBg])=>(
            <button key={id} onClick={()=>setTab(id)} style={{flex:1,padding:"10px 2px",background:tab===id?activeBg:"transparent",fontFamily:JM,fontSize:"8px",fontWeight:"800",color:tab===id?activeColor:"#555",cursor:"pointer",border:"none",borderBottom:tab===id?"3px solid "+activeColor:"3px solid transparent",textAlign:"center",lineHeight:"1.4",whiteSpace:"pre-line"}}>{label.replace(" ","\n")}</button>
          ))}
        </div>
      </div>

      <div style={{maxWidth:"1100px",margin:"0 auto",padding:"28px 20px",overflowX:"hidden",boxSizing:"border-box"}}>
        <div style={{marginBottom:"28px"}}>
          <div style={{fontSize:"11px",color:td.color,letterSpacing:"4px",textTransform:"uppercase",marginBottom:"8px",fontFamily:JM}}>{td.subtitle}</div>
          <h1 style={{fontSize:"clamp(18px,3vw,28px)",fontWeight:"700",color:"#f0f0f0",lineHeight:"1.2",marginBottom:"8px"}}>{td.title}</h1>
          <p style={{color:"#4a5a52",fontSize:"13px",lineHeight:"1.7"}}>{td.desc}</p>
        </div>
        {tab==="insider"  &&<InsiderScan onAnalyze={goAnalyze} watchlist={watchlist}/>}
        {tab==="calendar" &&<MacroCalendar/>}
        {tab==="screener" &&<DailyScreener onAnalyze={goAnalyze} watchlist={watchlist}/>}
        {tab==="analysis" &&<StockAnalysis key={analysisTicker} initialTicker={analysisTicker} watchlist={watchlist} onAnalyze={goAnalyze}/>}
        {tab==="heatmap"  &&<SectorHeatmap/>}
        {tab==="news"     &&<NewsPredictor onAnalyze={goAnalyze}/>}
        {tab==="alerts"   &&<AlertsTab/>}
        {tab==="congress" &&<CongressTrades/>}
        {tab==="journal"  &&<TradeJournal/>}
      </div>
    </div>
  );
}
