// Dashboard.jsx — Main dashboard page
// Design source: v2/New_design/Easylife Comparison.html + easylife-desktop.jsx
const { useState: useDashState, useEffect: useDashEffect, useRef: useDashRef } = React;

function dashDemo() {
  return window.EASYLIFE_DEMO?.enabled ? window.EASYLIFE_DEMO : null;
}
function dashNormCategory(value) {
  const v = String(value || '').toLowerCase();
  if (v === 'work') return 'Work';
  if (v === 'personal') return 'Personal';
  return value;
}

// ── Analog Clock ─────────────────────────────────────────────────
function DashAnalogClock({ size = 52 }) {
  const [now, setNow] = useDashState(() => new Date());
  useDashEffect(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const s = now.getSeconds(), m = now.getMinutes() + s/60, h = (now.getHours()%12) + m/60;
  const cx = size/2, cy = size/2, r = size/2 - 2;
  const pt = (a, len) => ({
    x: cx + len * Math.sin(a * Math.PI/180),
    y: cy - len * Math.cos(a * Math.PI/180),
  });
  const isLight = document.documentElement.getAttribute('data-theme') === 'light';
  const clr = {
    face: isLight ? 'rgba(26,24,22,0.07)' : 'rgba(255,255,255,0.04)',
    ring: isLight ? 'rgba(26,24,22,0.25)' : 'rgba(255,255,255,0.20)',
    tick: isLight ? 'rgba(26,24,22,0.30)' : 'rgba(255,255,255,0.25)',
    hour: isLight ? 'rgba(26,24,22,0.88)' : 'rgba(255,255,255,0.92)',
    min:  isLight ? 'rgba(26,24,22,0.72)' : 'rgba(255,255,255,0.85)',
    dot:  isLight ? 'rgba(26,24,22,0.85)' : 'rgba(255,255,255,0.90)',
  };
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
      <circle cx={cx} cy={cy} r={r} fill={clr.face} stroke={clr.ring} strokeWidth="1.5" />
      {Array.from({length:12},(_,i) => {
        const a = i/12*360; const p1 = pt(a,r-2); const p2 = pt(a,r-6);
        return <line key={i} x1={p1.x} y1={p1.y} x2={p2.x} y2={p2.y} stroke={clr.tick} strokeWidth="1.5" strokeLinecap="round"/>;
      })}
      {(()=>{ const p = pt(h/12*360, r*0.5); return <line x1={cx} y1={cy} x2={p.x} y2={p.y} stroke={clr.hour} strokeWidth="2.5" strokeLinecap="round"/>; })()}
      {(()=>{ const p = pt(m/60*360, r*0.7);  return <line x1={cx} y1={cy} x2={p.x} y2={p.y} stroke={clr.min}  strokeWidth="1.8" strokeLinecap="round"/>; })()}
      {(()=>{ const p = pt(s/60*360, r*0.76); return <line x1={cx} y1={cy} x2={p.x} y2={p.y} stroke="rgba(251,191,36,0.9)" strokeWidth="1" strokeLinecap="round"/>; })()}
      <circle cx={cx} cy={cy} r="2.5" fill={clr.dot} />
    </svg>
  );
}

// ── Week Dots ────────────────────────────────────────────────────
function DashWeekDots() {
  const today = new Date();
  const dow = today.getDay();
  const todayIdx = dow === 0 ? 6 : dow - 1;
  const labels = ['M','T','O','T','F','L','S'];
  return (
    <div style={{display:'flex',flexDirection:'column',alignItems:'center',gap:5}}>
      <div style={{display:'flex',gap:9,alignItems:'flex-end'}}>
        {labels.map((d,i) => {
          const isCur = i===todayIdx, isPast = i<todayIdx;
          const bg = !isPast && !isCur ? 'rgba(148,163,184,0.15)' : isCur ? 'rgba(148,163,184,0.2)' : 'var(--accent)';
          return (
            <div key={i} style={{display:'flex',flexDirection:'column',alignItems:'center',gap:3}}>
              {isCur && <div style={{fontSize:8,color:'var(--accent)',lineHeight:1}}>▼</div>}
              <div style={{
                width:13,height:13,borderRadius:'50%',background:bg,
                transform:isCur?'scale(1.2)':'scale(1)',
                boxShadow:isCur?'0 0 6px rgba(0,212,170,0.4)':'none',
              }}/>
            </div>
          );
        })}
      </div>
      <div style={{display:'flex',gap:9}}>
        {labels.map((d,i) => (
          <div key={i} style={{width:13,textAlign:'center',fontSize:9,color:'var(--mut)',fontWeight:600}}>{d}</div>
        ))}
      </div>
    </div>
  );
}

// ── Metric Ring ──────────────────────────────────────────────────
function DashMetricRing({ icon, value, total, label, color }) {
  const pct = total ? value/total : 0;
  const r = 16, circ = 2*Math.PI*r;
  return (
    <div style={{display:'flex',alignItems:'center',gap:10}}>
      <div style={{width:40,height:40,position:'relative',flexShrink:0}}>
        <svg width="40" height="40" style={{transform:'rotate(-90deg)'}}>
          <circle cx="20" cy="20" r={r} fill="none" stroke="rgba(148,163,184,0.15)" strokeWidth="3"/>
          <circle cx="20" cy="20" r={r} fill="none" stroke={color} strokeWidth="3" strokeLinecap="round"
            strokeDasharray={circ} strokeDashoffset={circ*(1-pct)}
            style={{transition:'stroke-dashoffset 0.5s ease'}}/>
        </svg>
        <div style={{position:'absolute',inset:0,display:'flex',alignItems:'center',justifyContent:'center',fontSize:13,color:'var(--pri)'}}>{icon}</div>
      </div>
      <div>
        <div style={{fontSize:17,fontWeight:700,color:'var(--pri)',lineHeight:1}}>
          {value}<span style={{fontSize:11,color:'var(--sec)',fontWeight:500}}>/{total}</span>
        </div>
        <div style={{fontSize:11,color:'var(--sec)',marginTop:2}}>{label}</div>
      </div>
    </div>
  );
}

// ── Panel card ───────────────────────────────────────────────────
function DashPanel({ title, badge, action, children, style = {} }) {
  return (
    <div style={{
      background:'var(--surface)',border:'1px solid var(--surface-b)',
      borderRadius:20,display:'flex',flexDirection:'column',
      overflow:'hidden',backdropFilter:'blur(20px)',...style,
    }}>
      <div style={{
        padding:'13px 16px 10px',borderBottom:'1px solid var(--surface-b)',
        display:'flex',alignItems:'center',justifyContent:'space-between',flexShrink:0,
      }}>
        <div style={{display:'flex',alignItems:'center',gap:9}}>
          <span style={{fontSize:10,fontWeight:700,color:'var(--sec)',textTransform:'uppercase',letterSpacing:'1.2px'}}>{title}</span>
          {badge !== undefined && <span style={{fontSize:11,color:'var(--mut)',fontWeight:600}}>{badge}</span>}
        </div>
        {action}
      </div>
      <div style={{flex:1,overflowY:'auto',padding:'8px 13px 12px',scrollbarWidth:'thin',scrollbarColor:'var(--bdr) transparent'}}>
        {children}
      </div>
    </div>
  );
}

// ── Task Row (for panels) ────────────────────────────────────────
function DashTaskRow({ task, onToggle }) {
  return (
    <div className="dash-panel-row"
      onContextMenu={e => window.openFocusMenu && window.openFocusMenu(e, { id: task.id, text: task.title || '', type: 'todo' })}
      onMouseEnter={e=>e.currentTarget.style.background='rgba(255,255,255,0.04)'}
      onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
      <button
        className={`dash-panel-check${task.completed?' chk':''}`}
        onClick={() => onToggle(task.id, task.completed)}
      >
        {task.completed && (
          <svg width="10" height="10" viewBox="0 0 10 10" fill="none">
            <path d="M2 5l2 2 4-4" stroke="#000" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        )}
      </button>
      <span className={`dash-panel-text${task.completed?' done':''}`}>
        {task.title || '(uten tittel)'}
      </span>
    </div>
  );
}

// ── Routine Row (circle indicator) ──────────────────────────────
function DashRoutineRow({ routine, onToggle, onEdit }) {
  return (
    <div className="dash-panel-row"
      onContextMenu={e => window.openFocusMenu && window.openFocusMenu(e, { id: routine.id, text: routine.name || routine.text || '', type: 'routine' })}
      onMouseEnter={e=>e.currentTarget.style.background='rgba(255,255,255,0.04)'}
      onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
      <button
        className={`dash-panel-circle${routine.completed?' chk':''}`}
        onClick={() => onToggle(routine.id, routine.completed)}
      >
        {routine.completed && (
          <svg width="11" height="11" viewBox="0 0 11 11" fill="none">
            <path d="M2 5.5l2.5 2.5 4.5-4.5" stroke="#000" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
          </svg>
        )}
      </button>
      <span
        className={`dash-panel-text${routine.completed?' done':''}`}
        style={{flex:1, cursor: onEdit ? 'pointer' : 'default'}}
        onClick={() => onEdit && onEdit(routine)}
      >
        {routine.name || routine.text}
      </span>
      {routine.streak > 0 && (
        <span style={{fontSize:11,fontWeight:700,color:'var(--accent)',opacity:routine.completed?0.3:0.7,flexShrink:0}}>
          +{routine.streak}d
        </span>
      )}
    </div>
  );
}

// ── Focus Widget ─────────────────────────────────────────────────
function DashFocusWidget() {
  const dur = 25;
  const [secs, setSecs] = useDashState(dur * 60);
  const [running, setRunning] = useDashState(false);
  const [sessions, setSessions] = useDashState(0);

  useDashEffect(() => {
    if (!running) return;
    const id = setInterval(() => {
      setSecs(s => {
        if (s <= 0) { setRunning(false); setSessions(c=>c+1); return dur*60; }
        return s-1;
      });
    }, 1000);
    return () => clearInterval(id);
  }, [running]);

  // Sync running state globally
  useDashEffect(() => {
    window.__dashFocusRunning = running;
    window.dispatchEvent(new CustomEvent('dashfocus-change', { detail: { running } }));
  }, [running]);

  // Listen for external focusmode-start / focusmode-stop events
  useDashEffect(() => {
    function onStart() { setRunning(true); }
    function onStop() { setRunning(false); }
    window.addEventListener('focusmode-start', onStart);
    window.addEventListener('focusmode-stop', onStop);
    return () => {
      window.removeEventListener('focusmode-start', onStart);
      window.removeEventListener('focusmode-stop', onStop);
    };
  }, []);

  const mm = String(Math.floor(secs/60)).padStart(2,'0');
  const ss = String(secs%60).padStart(2,'0');
  const pct = (dur*60 - secs) / (dur*60);
  const R = 34, circ = 2*Math.PI*R;

  return (
    <DashPanel title="Focus">
      <div style={{display:'flex',flexDirection:'column',alignItems:'center',gap:12,padding:'4px 0 2px'}}>
        <div style={{position:'relative',width:80,height:80}}>
          <svg width="80" height="80" style={{transform:'rotate(-90deg)'}}>
            <circle cx="40" cy="40" r={R} fill="none" stroke="rgba(148,163,184,0.15)" strokeWidth="4"/>
            <circle cx="40" cy="40" r={R} fill="none"
              stroke={running?'var(--accent)':'rgba(0,212,170,0.35)'}
              strokeWidth="4" strokeLinecap="round"
              strokeDasharray={circ} strokeDashoffset={circ*(1-pct)}
              style={{transition:'stroke-dashoffset 1s linear, stroke 0.4s'}}/>
          </svg>
          <div style={{position:'absolute',inset:0,display:'flex',alignItems:'center',justifyContent:'center'}}>
            <span style={{fontSize:18,fontWeight:700,color:'var(--pri)',letterSpacing:'-0.04em'}}>{mm}:{ss}</span>
          </div>
        </div>
        <button onClick={() => setRunning(v=>!v)} style={{
          padding:'7px 24px',borderRadius:10,border:'none',
          background:running?'rgba(239,68,68,0.12)':'var(--accent)',
          color:running?'#ef4444':'#000',
          fontFamily:'var(--font)',fontSize:12,fontWeight:700,cursor:'pointer',transition:'all 0.2s',
        }}>{running?'Pause':'Start'}</button>
        <div style={{display:'flex',gap:20}}>
          {[
            {l:'Sesjoner',v:String(sessions)},
            {l:'Total',v:sessions>0?`${dur*sessions}m`:'0m'},
          ].map((s,i) => (
            <div key={i} style={{textAlign:'center'}}>
              <div style={{fontSize:16,fontWeight:700,color:'var(--pri)',lineHeight:1}}>{s.v}</div>
              <div style={{fontSize:10,color:'var(--mut)',marginTop:3}}>{s.l}</div>
            </div>
          ))}
        </div>
      </div>
    </DashPanel>
  );
}

// ── Tracker Row ──────────────────────────────────────────────────
function DashTrackerRow({ icon, label, value, onChange }) {
  const pct = value ? (value-1)/9*100 : 0;
  const ref = useDashRef(null);
  const dragging = useDashRef(false);
  function update(e) {
    if (!ref.current) return;
    const rc = ref.current.getBoundingClientRect();
    onChange(Math.round(Math.max(0,Math.min(1,(e.clientX-rc.left)/rc.width))*9)+1);
  }
  useDashEffect(() => {
    const up = () => { dragging.current = false; };
    const mv = e => { if (dragging.current) update(e); };
    document.addEventListener('mouseup', up);
    document.addEventListener('mousemove', mv);
    return () => { document.removeEventListener('mouseup', up); document.removeEventListener('mousemove', mv); };
  }, []);
  return (
    <div style={{display:'flex',alignItems:'center',gap:9}}>
      <span style={{fontSize:15,flexShrink:0}}>{icon}</span>
      <span style={{fontSize:12,color:'var(--sec)',fontWeight:600,flex:1,minWidth:0}}>{label}</span>
      {value != null && <span style={{fontSize:12,fontWeight:800,color:'var(--accent)',minWidth:18,textAlign:'right'}}>{value}</span>}
      <div ref={ref} onMouseDown={e=>{dragging.current=true;update(e);}} style={{
        width:72,height:20,borderRadius:6,background:'rgba(255,255,255,0.06)',
        border:'1px solid var(--bdr)',position:'relative',cursor:'pointer',overflow:'hidden',flexShrink:0,
      }}>
        {value != null ? (
          <>
            <div style={{position:'absolute',left:0,top:0,bottom:0,width:pct+'%',background:'rgba(0,212,170,0.2)'}}/>
            <div style={{position:'absolute',top:'50%',left:pct+'%',transform:'translate(-50%,-50%)',width:12,height:12,borderRadius:'50%',background:'var(--accent)',boxShadow:'0 0 6px rgba(0,212,170,0.6)'}}/>
          </>
        ) : (
          <span style={{position:'absolute',inset:0,display:'flex',alignItems:'center',justifyContent:'center',fontSize:9,color:'var(--mut)',fontWeight:600}}>Set</span>
        )}
      </div>
    </div>
  );
}

function DashTrackersWidget() {
  const [sleep, setSleep] = useDashState(null);
  const [energy, setEnergy] = useDashState(null);
  const [water, setWater] = useDashState(null);
  const [steps, setSteps] = useDashState(null);
  return (
    <DashPanel title="Trackers">
      <div style={{display:'flex',flexDirection:'column',gap:11,padding:'3px 0'}}>
        <DashTrackerRow icon="🌙" label="Sleep"  value={sleep}  onChange={setSleep}  />
        <DashTrackerRow icon="⚡" label="Energy" value={energy} onChange={setEnergy} />
        <DashTrackerRow icon="💧" label="Water"  value={water}  onChange={setWater}  />
        <DashTrackerRow icon="🏃" label="Steps"  value={steps}  onChange={setSteps}  />
      </div>
    </DashPanel>
  );
}

// ── Mood Widget ──────────────────────────────────────────────────
function DashMoodWidget() {
  const [mood, setMood] = useDashState(null);
  const moods = [{e:'😔',l:'Sad'},{e:'😕',l:'Down'},{e:'😐',l:'OK'},{e:'🙂',l:'Good'},{e:'😄',l:'Great'}];
  return (
    <DashPanel title="Mood">
      <div style={{display:'flex',justifyContent:'space-between',gap:2,padding:'3px 0'}}>
        {moods.map((m,i) => {
          const sel = mood===i;
          return (
            <button key={i} onClick={() => setMood(sel?null:i)} style={{
              flex:1,display:'flex',flexDirection:'column',alignItems:'center',gap:4,
              background:sel?'var(--accent-d)':'rgba(255,255,255,0.03)',
              border:'none',cursor:'pointer',padding:'8px 2px',borderRadius:10,
              fontFamily:'var(--font)',transition:'transform 0.18s cubic-bezier(0.34,1.56,0.64,1)',
              transform:sel?'scale(1.08)':'scale(1)',
            }}>
              <span style={{fontSize:20,lineHeight:1,filter:mood==null?'grayscale(0.4) opacity(0.7)':sel?'none':'grayscale(1) opacity(0.25)'}}>{m.e}</span>
              <span style={{fontSize:8,fontWeight:600,color:sel?'var(--accent)':'var(--mut)'}}>{m.l}</span>
            </button>
          );
        })}
      </div>
    </DashPanel>
  );
}

// ── Big Wins Widget ──────────────────────────────────────────────
function DashBigWinsWidget({ wins }) {
  return (
    <DashPanel title="Big Wins">
      <div style={{display:'flex',flexDirection:'column',gap:4}}>
        {wins.length === 0 && (
          <p style={{fontSize:12,color:'var(--mut)',fontStyle:'italic',padding:'6px 0'}}>Ingen big wins ennå</p>
        )}
        {wins.slice(0,4).map((w,i) => (
          <div key={w.id||i}
            onContextMenu={e => window.openFocusMenu && window.openFocusMenu(e, { id: w.id, text: w.title || '', type: 'bigwin' })}
            style={{
            display:'flex',alignItems:'flex-start',gap:8,
            padding:'8px 10px',borderRadius:9,
            background:'rgba(255,255,255,0.02)',border:'1px solid rgba(255,255,255,0.04)',
          }}>
            <span style={{fontSize:12,color:'var(--amber-ink)',flexShrink:0,marginTop:1}}>★</span>
            <span style={{fontSize:12,color:'var(--sec)',lineHeight:1.5}}>{w.title}</span>
          </div>
        ))}
        <button style={{
          marginTop:2,padding:'7px 10px',borderRadius:9,border:'1px dashed var(--bdr)',
          background:'transparent',color:'var(--mut)',cursor:'pointer',
          fontFamily:'var(--font)',fontSize:11,fontWeight:600,display:'flex',alignItems:'center',gap:5,
          transition:'border-color 0.15s',
        }}
        onMouseEnter={e=>e.currentTarget.style.borderColor='var(--accent-bd)'}
        onMouseLeave={e=>e.currentTarget.style.borderColor='var(--bdr)'}>
          <span style={{fontSize:14,lineHeight:1}}>+</span> Add win
        </button>
      </div>
    </DashPanel>
  );
}

// ── Deadlines Widget ─────────────────────────────────────────────
function DashDeadlinesWidget({ deadlines }) {
  function getDays(due) {
    if (!due) return null;
    const d = new Date(due), now = new Date();
    now.setHours(0,0,0,0);
    return Math.round((d - now) / (1000*60*60*24));
  }
  return (
    <DashPanel title="Deadlines">
      <div style={{display:'flex',flexDirection:'column',gap:5}}>
        {deadlines.length === 0 && (
          <p style={{fontSize:12,color:'var(--mut)',fontStyle:'italic',padding:'6px 0'}}>Ingen deadlines</p>
        )}
        {deadlines.slice(0,5).map((d,i) => {
          const days = getDays(d.due_at);
          const col = days<=3?'var(--red-ink,#ef4444)':days<=7?'var(--amber-ink,#fbbf24)':'var(--today-green,#22c55e)';
          const dateStr = d.due_at ? new Date(d.due_at).toLocaleDateString('no-NO',{day:'numeric',month:'short'}) : '';
          const pillBg = days<=3?'rgba(239,68,68,0.12)':days<=7?'rgba(251,191,36,0.12)':'rgba(52,211,153,0.1)';
          return (
            <div key={d.id||i}
              onContextMenu={e => window.openFocusMenu && window.openFocusMenu(e, { id: d.id, text: d.title || '', type: 'deadline' })}
              style={{
              display:'flex',alignItems:'center',justifyContent:'space-between',
              padding:'9px 10px',borderRadius:9,
              background:'rgba(255,255,255,0.02)',border:'1px solid rgba(255,255,255,0.04)',
            }}>
              <div style={{display:'flex',alignItems:'center',gap:8,minWidth:0}}>
                <div style={{width:8,height:8,borderRadius:'50%',flexShrink:0,background:col}}/>
                <span style={{fontSize:12,color:'var(--pri)',fontWeight:500,overflow:'hidden',textOverflow:'ellipsis',whiteSpace:'nowrap'}}>{d.title}</span>
              </div>
              <div style={{display:'flex',alignItems:'center',gap:7,flexShrink:0}}>
                <span style={{fontSize:11,color:'var(--sec)'}}>{dateStr}</span>
                {days !== null && (
                  <span style={{fontSize:9,fontWeight:700,padding:'2px 7px',borderRadius:20,background:pillBg,color:col}}>{days}d</span>
                )}
              </div>
            </div>
          );
        })}
      </div>
    </DashPanel>
  );
}

// ── Favorites Widget ─────────────────────────────────────────────
function DashFavoritesWidget() {
  const favs = [
    {label:'Journal',icon:'📓',hash:'#/journal'},
    {label:'Focus',  icon:'🎯',hash:'#/tasks'},
    {label:'Mål',    icon:'◎', hash:'#/goals'},
    {label:'Balanse',icon:'⚖️',hash:'#/balance'},
    {label:'Mindmap',icon:'🧠',hash:'#/prompts'},
    {label:'Notater',icon:'📝',hash:'#/notes'},
  ];
  return (
    <DashPanel title="Favorites">
      <div style={{display:'grid',gridTemplateColumns:'repeat(3,1fr)',gap:5}}>
        {favs.map((f,i) => (
          <a key={i} href={f.hash} style={{
            display:'flex',flexDirection:'column',alignItems:'center',gap:5,
            padding:'9px 4px',borderRadius:10,
            background:'rgba(255,255,255,0.02)',border:'1px solid rgba(255,255,255,0.04)',
            cursor:'pointer',fontFamily:'var(--font)',transition:'background 0.15s,border-color 0.15s',
            textDecoration:'none',
          }}
          onMouseEnter={e=>{e.currentTarget.style.background='rgba(0,212,170,0.08)';e.currentTarget.style.borderColor='rgba(0,212,170,0.2)';}}
          onMouseLeave={e=>{e.currentTarget.style.background='rgba(255,255,255,0.02)';e.currentTarget.style.borderColor='rgba(255,255,255,0.04)';}}>
            <span style={{fontSize:17}}>{f.icon}</span>
            <span style={{fontSize:9,fontWeight:600,color:'var(--sec)',letterSpacing:'0.3px'}}>{f.label}</span>
          </a>
        ))}
      </div>
    </DashPanel>
  );
}

// ── Pro Mode Header Widget ───────────────────────────────────────
function DashHeaderWidget({ stats }) {
  const [now, setNow] = useDashState(() => new Date());
  useDashEffect(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);
  const hh = String(now.getHours()).padStart(2,'0');
  const mm = String(now.getMinutes()).padStart(2,'0');
  const dateStr = now.toLocaleDateString('no-NO', {weekday:'long',day:'numeric',month:'long',year:'numeric'});
  const sep = <div style={{width:1,height:44,background:'var(--surface-b)',flexShrink:0}}/>;

  return (
    <div style={{
      display:'flex',alignItems:'center',gap:18,flexWrap:'nowrap',
      background:'var(--surface)',border:'1px solid var(--surface-b)',
      borderRadius:20,padding:'13px 22px',
      backdropFilter:'blur(28px)',flexShrink:0,
    }}>
      {/* Clock */}
      <div style={{display:'flex',alignItems:'center',gap:12,flexShrink:0}}>
        <DashAnalogClock size={52} />
        <div>
          <div style={{fontSize:24,fontWeight:600,color:'var(--pri)',letterSpacing:'-0.04em',lineHeight:1}}>{hh}:{mm}</div>
          <div style={{fontSize:11,color:'var(--sec)',marginTop:4,fontWeight:500,textTransform:'capitalize'}}>{dateStr}</div>
        </div>
      </div>
      {sep}
      {/* Weather placeholder */}
      <div style={{display:'flex',alignItems:'center',gap:10,flexShrink:0}}>
        <span style={{fontSize:26,filter:'drop-shadow(0 2px 8px rgba(0,0,0,0.4))'}}>⛅</span>
        <div>
          <div style={{fontSize:18,fontWeight:700,color:'var(--pri)',lineHeight:1}}>14°C</div>
          <div style={{fontSize:11,color:'var(--sec)',marginTop:3}}>Delvis overskyet · Oslo</div>
        </div>
      </div>
      {sep}
      <div style={{flexShrink:0}}>
        <DashWeekDots />
      </div>
      {sep}
      {/* Metric rings */}
      <div style={{display:'flex',gap:18,alignItems:'center',flexShrink:0,marginLeft:'auto'}}>
        <DashMetricRing icon="✓" value={stats.tasksCompleted} total={stats.tasksTotal} label="Tasks" color="#38bdf8"/>
        <DashMetricRing icon="◎" value={stats.goalsCompleted} total={stats.goalsTotal} label="Goals" color="#a78bfa"/>
        <DashMetricRing icon="○" value={stats.routinesCompleted} total={stats.routinesTotal} label="Routines" color="#34d399"/>
      </div>
    </div>
  );
}

// ── Pro Mode Dashboard ───────────────────────────────────────────
function ProDashboard({ tasks, routines, bigWins, deadlines, loading, onToggleTask, onToggleRoutine, onAddTask, onAddRoutine, onEditRoutine }) {
  const [filter] = useWpFilter();
  const [addText, setAddText] = useDashState('');

  const todayStr = new Date().toISOString().slice(0, 10);
  const fTasks = tasks.filter(t => {
    const c = String(t.category || '').toLowerCase();
    if (c && c !== 'none' && dashNormCategory(c) !== filter) return false;
    return String(t.due_at || t.due_date || '').slice(0, 10) === todayStr;
  });
  const fRoutines = routines.filter(r => {
    const cat = dashNormCategory(r.work_personal_category || r.category);
    return !cat || cat === filter;
  });

  const stats = {
    tasksCompleted:   fTasks.filter(t=>t.completed).length,
    tasksTotal:       fTasks.length,
    routinesCompleted: fRoutines.filter(r=>r.completed).length,
    routinesTotal:    fRoutines.length,
    goalsCompleted: 3, goalsTotal: 7,
  };

  function handleAddTask(e) {
    e.preventDefault();
    if (!addText.trim()) return;
    onAddTask(addText.trim(), filter);
    setAddText('');
  }

  return (
    <div className="dash-pro-layout">
      <DashHeaderWidget stats={stats} />

      <div className="dash-pro-grid">
        {/* Left column */}
        <div className="dash-pro-col">
          <DashBigWinsWidget wins={bigWins} />
          <DashDeadlinesWidget deadlines={deadlines} />
          <DashFavoritesWidget />
        </div>

        {/* Center columns */}
        <div className="dash-pro-center">
          <DashPanel title="Today's tasks" badge={`${stats.tasksCompleted}/${stats.tasksTotal}`}
            style={{flex:1,overflow:'hidden'}}>
            <form onSubmit={handleAddTask} style={{marginBottom:8,display:'flex',gap:6}}>
              <input value={addText} onChange={e=>setAddText(e.target.value)}
                placeholder="Quick add..."
                style={{
                  flex:1,padding:'8px 11px',borderRadius:8,
                  border:'1px solid var(--bdr)',
                  background:'rgba(255,255,255,0.04)',color:'var(--pri)',
                  fontFamily:'var(--font)',fontSize:12,outline:'none',
                }}
                onFocus={e=>e.target.style.borderColor='var(--accent-bd)'}
                onBlur={e=>e.target.style.borderColor='var(--bdr)'}
              />
              <button type="submit" style={{
                padding:'8px 13px',borderRadius:8,border:'none',
                background:addText.trim()?'var(--accent)':'rgba(255,255,255,0.06)',
                color:addText.trim()?'#000':'var(--mut)',
                cursor:'pointer',fontFamily:'var(--font)',fontSize:12,fontWeight:700,transition:'all 0.15s',
              }}>Add</button>
            </form>
            {loading ? (
              <div style={{padding:'14px',textAlign:'center',color:'var(--mut)',fontSize:12}}>Laster…</div>
            ) : fTasks.length === 0 ? (
              <p style={{color:'var(--mut)',fontSize:13,textAlign:'center',padding:'18px 0',fontStyle:'italic'}}>Ingen oppgaver</p>
            ) : (
              fTasks.map(task => <DashTaskRow key={task.id} task={task} onToggle={onToggleTask}/>)
            )}
          </DashPanel>

          <DashPanel
            title="Routines"
            badge={`${stats.routinesCompleted}/${stats.routinesTotal}`}
            action={onAddRoutine && (
              <button
                type="button"
                onClick={onAddRoutine}
                title="Ny rutine"
                style={{
                  width: 24, height: 24, borderRadius: 6, padding: 0,
                  border: '1px solid var(--surface-b)', background: 'rgba(255,255,255,0.04)',
                  color: 'var(--sec)', cursor: 'pointer', fontSize: 14, lineHeight: 1,
                  display: 'flex', alignItems: 'center', justifyContent: 'center',
                }}
              >+</button>
            )}
            style={{flex:1,overflow:'hidden'}}>
            {loading ? (
              <div style={{padding:'14px',textAlign:'center',color:'var(--mut)',fontSize:12}}>Laster…</div>
            ) : fRoutines.length === 0 ? (
              <p style={{color:'var(--mut)',fontSize:13,textAlign:'center',padding:'18px 0',fontStyle:'italic'}}>Ingen rutiner</p>
            ) : (
              fRoutines.map(r => <DashRoutineRow key={r.id} routine={r} onToggle={onToggleRoutine} onEdit={onEditRoutine}/>)
            )}
          </DashPanel>
        </div>

        {/* Right column */}
        <div className="dash-pro-col">
          <DashFocusWidget />
          <DashTrackersWidget />
          <DashMoodWidget />
        </div>
      </div>
    </div>
  );
}

// ── Easy Mode Dashboard ──────────────────────────────────────────
function NoteSwitcher({ notes, currentId, onPick, onCreate }) {
  const [open, setOpen] = useDashState(false);
  const ref = useDashRef(null);

  useDashEffect(() => {
    if (!open) return;
    function onDoc(e) { if (ref.current && !ref.current.contains(e.target)) setOpen(false); }
    function onKey(e) { if (e.key === 'Escape') setOpen(false); }
    document.addEventListener('mousedown', onDoc);
    document.addEventListener('keydown', onKey);
    return () => { document.removeEventListener('mousedown', onDoc); document.removeEventListener('keydown', onKey); };
  }, [open]);

  const favs = notes.filter(n => n.is_favorite);
  const rest = notes.filter(n => !n.is_favorite);
  const previewText = n => {
    const raw = n.heading || n.content || 'Tomt notat';
    try {
      const doc = new DOMParser().parseFromString(raw, 'text/html');
      return (doc.body.textContent || '').replace(/\s+/g, ' ').trim().slice(0, 60);
    } catch(e) {
      return raw.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim().slice(0, 60);
    }
  };

  return (
    <div ref={ref} style={{ position: 'relative', flexShrink: 0 }}>
      <button
        type="button"
        onClick={() => setOpen(o => !o)}
        title="Bytt notat"
        style={{
          width: 26, height: 26, borderRadius: 8, padding: 0,
          border: '1px solid var(--surface-b)', background: 'transparent',
          color: 'var(--sec)', cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
        }}
      >
        <i className="ti ti-chevron-down" style={{ fontSize: 14 }}></i>
      </button>
      {open && (
        <div
          style={{
            position: 'absolute', top: 30, right: 0, zIndex: 50,
            minWidth: 240, maxWidth: 320,
            background: 'var(--bg-card)', border: '1px solid var(--bdr)',
            borderRadius: 12, padding: 6,
            boxShadow: '0 12px 40px rgba(0,0,0,0.35)',
            backdropFilter: 'blur(20px)',
          }}
        >
          {favs.length > 0 && (
            <>
              <div style={{ fontSize: 9, fontWeight: 700, color: 'var(--accent)', letterSpacing: '1.2px', textTransform: 'uppercase', padding: '6px 9px 4px' }}>
                Favoritter
              </div>
              {favs.map(n => (
                <button key={n.id} type="button" onClick={() => { onPick(n.id); setOpen(false); }} className="dash-note-row" style={noteRowStyle(n.id === currentId)}>
                  <i className="ti ti-star-filled" style={{ fontSize: 11, color: 'var(--amber-ink, #f59e0b)', flexShrink: 0 }}></i>
                  <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1 }}>{previewText(n)}</span>
                  {(n.last_opened_at || n.updated_at || n.created_at) ? (
                    <span style={{fontSize:9,color:'var(--mut)',flexShrink:0,marginLeft:'auto'}}>{
                      new Date(n.last_opened_at || n.updated_at || n.created_at).toLocaleDateString('no-NO',{day:'numeric',month:'short'})
                    }</span>
                  ) : null}
                </button>
              ))}
              {rest.length > 0 && <hr style={{ border: 'none', borderTop: '1px solid var(--surface-b)', margin: '4px 0' }} />}
            </>
          )}
          {rest.length > 0 && (
            <>
              <div style={{ fontSize: 9, fontWeight: 700, color: 'var(--sec)', letterSpacing: '1.2px', textTransform: 'uppercase', padding: '6px 9px 4px' }}>
                Siste
              </div>
              {rest.map(n => (
                <button key={n.id} type="button" onClick={() => { onPick(n.id); setOpen(false); }} className="dash-note-row" style={noteRowStyle(n.id === currentId)}>
                  <i className="ti ti-note" style={{ fontSize: 11, color: 'var(--mut)', flexShrink: 0 }}></i>
                  <span style={{ overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', flex: 1 }}>{previewText(n)}</span>
                  {(n.last_opened_at || n.updated_at || n.created_at) ? (
                    <span style={{fontSize:9,color:'var(--mut)',flexShrink:0,marginLeft:'auto'}}>{
                      new Date(n.last_opened_at || n.updated_at || n.created_at).toLocaleDateString('no-NO',{day:'numeric',month:'short'})
                    }</span>
                  ) : null}
                </button>
              ))}
            </>
          )}
          {notes.length === 0 && (
            <div style={{ padding: '10px 9px', fontSize: 11, color: 'var(--mut)', fontStyle: 'italic' }}>Ingen notater ennå</div>
          )}
          <hr style={{ border: 'none', borderTop: '1px solid var(--surface-b)', margin: '4px 0' }} />
          <button type="button" onClick={() => { onCreate(); setOpen(false); }} className="dash-note-row" style={{ ...noteRowStyle(false), color: 'var(--accent)' }}>
            <i className="ti ti-plus" style={{ fontSize: 11, flexShrink: 0 }}></i>
            <span>Nytt notat</span>
          </button>
        </div>
      )}
    </div>
  );
}

function noteRowStyle(active) {
  return {
    display: 'flex', alignItems: 'center', gap: 8,
    width: '100%', textAlign: 'left',
    padding: '7px 9px', borderRadius: 8,
    border: 'none', background: active ? 'var(--accent-d)' : 'transparent',
    color: active ? 'var(--accent)' : 'var(--pri)',
    fontFamily: 'inherit', fontSize: 12, fontWeight: 500,
    cursor: 'pointer',
  };
}

// ── Dashboard Note Rich-Text Editor ──────────────────────────────
function DashNoteEditor({ note, noteId, onNoteChange }) {
  const editorRef = useDashRef(null);
  const [editing, setEditing] = useDashState(false);
  const saveTimerRef = useDashRef(null);

  // Sync innerHTML when the active note changes
  useDashEffect(() => {
    if (editorRef.current) {
      editorRef.current.innerHTML = note || '';
    }
  }, [noteId]);

  function flushSave() {
    if (!editorRef.current) return;
    const html = editorRef.current.innerHTML;
    if (saveTimerRef.current) { clearTimeout(saveTimerRef.current); saveTimerRef.current = null; }
    onNoteChange(html);
  }

  function scheduleSave() {
    if (!editorRef.current) return;
    const html = editorRef.current.innerHTML;
    if (saveTimerRef.current) clearTimeout(saveTimerRef.current);
    saveTimerRef.current = setTimeout(() => onNoteChange(html), 1200);
  }

  function handleInput() {
    scheduleSave();
  }

  function handleFocus() {
    try { document.execCommand('defaultParagraphSeparator', false, 'br'); } catch(e) {}
    setEditing(true);
  }

  function handleBlur() {
    setEditing(false);
    flushSave();
  }

  function handlePaste(e) {
    e.preventDefault();
    const text = e.clipboardData?.getData('text/plain');
    if (typeof text === 'string') {
      const html = text
        .replace(/&/g, '&amp;')
        .replace(/</g, '&lt;')
        .replace(/>/g, '&gt;')
        .replace(/\r\n|\r|\n/g, '<br>');
      document.execCommand('insertHTML', false, html);
    }
  }

  function applyFormat(fmt) {
    if (!editorRef.current) return;
    editorRef.current.focus();
    try {
      if (fmt === 'bold') document.execCommand('bold', false);
      else if (fmt === 'italic') document.execCommand('italic', false);
      else if (fmt === 'bullet') document.execCommand('insertUnorderedList', false);
      else if (fmt === 'numbered') document.execCommand('insertOrderedList', false);
    } catch(e) {}
    scheduleSave();
  }

  const fmtBtnStyle = {
    width: 26, height: 26, borderRadius: 6, padding: 0,
    border: '1px solid var(--surface-b)', background: 'transparent',
    color: 'var(--sec)', cursor: 'pointer',
    display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
    fontFamily: 'var(--font)', fontSize: 12,
  };

  return (
    <div style={{ flex:1, display:'flex', flexDirection:'column', minHeight:0 }}>
      <div style={{
        display: 'flex', gap: 3, padding: '0 0 8px',
        borderBottom: editing ? '1px solid var(--surface-b)' : '1px solid transparent',
        marginBottom: 8, flexShrink: 0, transition: 'border-color 0.15s',
      }}>
        <button type="button" title="Fet" onMouseDown={e=>e.preventDefault()} onClick={()=>applyFormat('bold')} style={fmtBtnStyle}>
          <strong style={{fontWeight:700,fontSize:12}}>B</strong>
        </button>
        <button type="button" title="Kursiv" onMouseDown={e=>e.preventDefault()} onClick={()=>applyFormat('italic')} style={fmtBtnStyle}>
          <em style={{fontStyle:'italic',fontSize:12}}>I</em>
        </button>
        <button type="button" title="Punktliste" onMouseDown={e=>e.preventDefault()} onClick={()=>applyFormat('bullet')} style={fmtBtnStyle}>
          <svg viewBox="0 0 24 24" aria-hidden="true" style={{width:13,height:13,fill:'none',stroke:'currentColor',strokeWidth:2,strokeLinecap:'round'}}>
            <circle cx="4" cy="6" r="1.5" fill="currentColor"/>
            <circle cx="4" cy="12" r="1.5" fill="currentColor"/>
            <circle cx="4" cy="18" r="1.5" fill="currentColor"/>
            <line x1="9" y1="6" x2="20" y2="6"/>
            <line x1="9" y1="12" x2="20" y2="12"/>
            <line x1="9" y1="18" x2="20" y2="18"/>
          </svg>
        </button>
        <button type="button" title="Nummerert liste" onMouseDown={e=>e.preventDefault()} onClick={()=>applyFormat('numbered')} style={fmtBtnStyle}>
          <svg viewBox="0 0 24 24" aria-hidden="true" style={{width:13,height:13,fill:'none',stroke:'currentColor',strokeWidth:2,strokeLinecap:'round'}}>
            <text x="2" y="8" style={{fontSize:'6px',fill:'currentColor',stroke:'none'}} aria-hidden="true">1.</text>
            <text x="2" y="14" style={{fontSize:'6px',fill:'currentColor',stroke:'none'}} aria-hidden="true">2.</text>
            <text x="2" y="20" style={{fontSize:'6px',fill:'currentColor',stroke:'none'}} aria-hidden="true">3.</text>
            <line x1="10" y1="6" x2="20" y2="6"/>
            <line x1="10" y1="12" x2="20" y2="12"/>
            <line x1="10" y1="18" x2="20" y2="18"/>
          </svg>
        </button>
      </div>
      <div
        ref={editorRef}
        contentEditable="true"
        suppressContentEditableWarning={true}
        className="dash-note-editor"
        onInput={handleInput}
        onFocus={handleFocus}
        onBlur={handleBlur}
        onPaste={handlePaste}
        data-placeholder="Skriv noe her…"
        style={{
          flex:1, outline:'none', minHeight:0,
          fontFamily:'var(--font)', fontSize:14, color:'var(--pri)',
          lineHeight:1.6, overflowY:'auto',
        }}
      />
    </div>
  );
}

function EasyDashboard({ tasks, routines, note, notes, currentNoteId, isFavorite, loadingTasks, loadingNote, onToggleTask, onToggleRoutine, onNoteChange, onPickNote, onCreateNote, onToggleFavorite, onAddRoutine, onEditRoutine }) {
  const [filter] = useWpFilter();

  const todayStr = new Date().toISOString().slice(0, 10);
  const fTasks = tasks.filter(t => {
    const c = String(t.category || '').toLowerCase();
    if (c && c !== 'none' && dashNormCategory(c) !== filter) return false;
    return String(t.due_at || t.due_date || '').slice(0, 10) === todayStr;
  });
  const fRoutines = routines.filter(r => {
    const cat = dashNormCategory(r.work_personal_category || r.category);
    return !cat || cat === filter;
  });

  const colStyle = {
    flex:1,display:'flex',flexDirection:'column',overflow:'hidden',
    background:'var(--surface)',border:'1px solid var(--surface-b)',
    borderRadius:18,backdropFilter:'blur(20px)',
  };
  const colHead = {
    padding:'13px 16px 10px',borderBottom:'1px solid var(--surface-b)',
    display:'flex',alignItems:'center',justifyContent:'space-between',flexShrink:0,
  };

  const [now] = useDashState(() => new Date());
  const dateStr = now.toLocaleDateString('no-NO', {weekday:'long',day:'numeric',month:'long'});

  const [trackersOpen, setTrackersOpen] = useDashState(false);
  const trackersRef = useDashRef(null);

  useDashEffect(() => {
    if (!trackersOpen) return;
    function onDoc(e) {
      if (trackersRef.current && !trackersRef.current.contains(e.target)) setTrackersOpen(false);
    }
    function onKey(e) { if (e.key === 'Escape') setTrackersOpen(false); }
    document.addEventListener('mousedown', onDoc);
    document.addEventListener('keydown', onKey);
    return () => { document.removeEventListener('mousedown', onDoc); document.removeEventListener('keydown', onKey); };
  }, [trackersOpen]);

  return (
    <div className="dash-easy-layout">
      {/* Heading */}
      <div style={{textAlign:'center',paddingBottom:4}}>
        <h1 style={{fontSize:52,fontWeight:800,color:'var(--pri)',letterSpacing:'-2px',lineHeight:1,margin:0}}>Today</h1>
        <p style={{fontSize:14,color:'var(--sec)',marginTop:6,fontWeight:500,textTransform:'capitalize'}}>{dateStr}</p>
      </div>

      {/* Weather row */}
      <div style={{display:'flex',alignItems:'center',gap:16,flexWrap:'wrap',justifyContent:'center',position:'relative'}}>
        {/* Trackers button */}
        <div ref={trackersRef} style={{position:'relative'}}>
          <button
            onClick={() => setTrackersOpen(v=>!v)}
            style={{
              display:'inline-flex',alignItems:'center',gap:6,
              padding:'7px 14px',borderRadius:10,
              border:'1px solid var(--surface-b)',background:'rgba(255,255,255,0.05)',
              color:'var(--sec)',cursor:'pointer',fontFamily:'var(--font)',
              fontSize:11,fontWeight:700,transition:'all .15s',
            }}
            title="Trackers"
          >
            <i className="ti ti-chart-bar" style={{fontSize:13}}></i>
            Trackers
          </button>
          {trackersOpen && (
            <div style={{
              position:'absolute',top:'calc(100% + 8px)',left:0,
              zIndex:200,width:280,
              background:'var(--bg-card)',border:'1px solid var(--bdr)',
              borderRadius:16,padding:12,
              boxShadow:'0 16px 48px rgba(0,0,0,0.4)',
              backdropFilter:'blur(20px)',
            }}>
              <DashTrackersWidget />
            </div>
          )}
        </div>
        {/* Weather info */}
        <div style={{display:'flex',alignItems:'center',gap:10}}>
          <span style={{fontSize:26}}>⛅</span>
          <div>
            <div style={{fontSize:17,fontWeight:700,color:'var(--pri)',lineHeight:1}}>14°C</div>
            <div style={{fontSize:11,color:'var(--sec)',marginTop:2}}>Delvis overskyet · Oslo</div>
          </div>
        </div>
      </div>

      {/* 3-column grid */}
      <div style={{flex:1,display:'flex',gap:14,overflow:'hidden',minHeight:0}}>
        {/* Todo */}
        <div style={colStyle}>
          <div style={colHead}>
            <span style={{fontSize:10,fontWeight:700,color:'var(--sec)',textTransform:'uppercase',letterSpacing:'1.2px'}}>Dagens oppgaver</span>
            <span style={{fontSize:11,color:'var(--mut)'}}>{fTasks.filter(t=>t.completed).length}/{fTasks.length}</span>
          </div>
          <div style={{flex:1,overflowY:'auto',padding:'6px 11px 12px'}}>
            {loadingTasks ? (
              <div style={{padding:'16px',textAlign:'center',color:'var(--mut)',fontSize:12}}>Laster…</div>
            ) : fTasks.length === 0 ? (
              <div style={{padding:'22px 0',textAlign:'center'}}>
                <i className="ti ti-circle-check" style={{fontSize:24,color:'var(--accent)',opacity:.4,display:'block',marginBottom:6}}/>
                <p style={{fontSize:12,color:'var(--mut)',fontStyle:'italic'}}>Ingen oppgaver i dag</p>
              </div>
            ) : (
              fTasks.map(t => <DashTaskRow key={t.id} task={t} onToggle={onToggleTask}/>)
            )}
          </div>
        </div>

        {/* Routines */}
        <div style={colStyle}>
          <div style={colHead}>
            <span style={{fontSize:10,fontWeight:700,color:'var(--sec)',textTransform:'uppercase',letterSpacing:'1.2px'}}>Rutiner</span>
            <div style={{display:'flex',alignItems:'center',gap:8}}>
              <span style={{fontSize:11,color:'var(--mut)'}}>{fRoutines.filter(r=>r.completed).length}/{fRoutines.length}</span>
              {onAddRoutine && (
                <button
                  type="button"
                  onClick={onAddRoutine}
                  title="Ny rutine"
                  style={{
                    width:26,height:26,borderRadius:8,padding:0,
                    border:'1px solid var(--surface-b)',background:'transparent',
                    color:'var(--sec)',cursor:'pointer',fontSize:15,lineHeight:1,
                    display:'flex',alignItems:'center',justifyContent:'center',
                  }}
                >+</button>
              )}
            </div>
          </div>
          <div style={{flex:1,overflowY:'auto',padding:'6px 11px 12px'}}>
            {loadingTasks ? (
              <div style={{padding:'16px',textAlign:'center',color:'var(--mut)',fontSize:12}}>Laster…</div>
            ) : fRoutines.length === 0 ? (
              <p style={{fontSize:12,color:'var(--mut)',fontStyle:'italic',padding:'18px 0',textAlign:'center'}}>Ingen rutiner</p>
            ) : (
              fRoutines.map(r => <DashRoutineRow key={r.id} routine={r} onToggle={onToggleRoutine} onEdit={onEditRoutine}/>)
            )}
          </div>
        </div>

        {/* Quick Note */}
        <div style={colStyle}>
          <div style={colHead}>
            <span style={{fontSize:10,fontWeight:700,color:'var(--sec)',textTransform:'uppercase',letterSpacing:'1.2px'}}>Hurtignotat</span>
            <div style={{display:'flex',alignItems:'center',gap:6}}>
              {currentNoteId && (
                <button
                  type="button"
                  onClick={() => onToggleFavorite && onToggleFavorite()}
                  title={isFavorite ? 'Fjern favoritt' : 'Marker som favoritt'}
                  style={{
                    width:26,height:26,borderRadius:8,padding:0,
                    border:'1px solid var(--surface-b)',background:'transparent',
                    color: isFavorite ? 'var(--amber-ink, #f59e0b)' : 'var(--mut)',
                    cursor:'pointer',display:'flex',alignItems:'center',justifyContent:'center',
                  }}
                >
                  <i className={`ti ${isFavorite ? 'ti-star-filled' : 'ti-star'}`} style={{fontSize:13}}></i>
                </button>
              )}
              <NoteSwitcher
                notes={notes || []}
                currentId={currentNoteId}
                onPick={onPickNote}
                onCreate={onCreateNote}
              />
            </div>
          </div>
          <div style={{flex:1,padding:'10px 13px 13px',display:'flex',flexDirection:'column',minHeight:0}}>
            {loadingNote ? (
              <div style={{padding:'16px',textAlign:'center',color:'var(--mut)',fontSize:12}}>Laster…</div>
            ) : (
              <DashNoteEditor note={note} noteId={currentNoteId} onNoteChange={onNoteChange} />
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Mobile Dashboard Components ──────────────────────────────────
const { useState: useMobState, useEffect: useMobEffect, useRef: useMobRef } = React;

function MobTodoItem({ task, isCompleting, onToggle }) {
  return (
    <div className={`el-item${isCompleting ? ' el-completing' : ''}${task.completed ? ' el-completed' : ''}`}>
      <button className="el-checkbox" onClick={() => onToggle(task.id, task.completed)}>
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
          <rect x="2.5" y="2.5" width="19" height="19" rx="5" className="el-cb-box" />
          <rect x="2.5" y="2.5" width="19" height="19" rx="5" className="el-cb-fill" />
          <path d="M7 12.5l3.5 3.5L17 9" className="el-cb-check" />
        </svg>
      </button>
      <span className="el-item-text">{task.title || '(uten tittel)'}</span>
    </div>
  );
}

function MobRoutineItem({ routine, isCompleting, onToggle, onEdit }) {
  return (
    <div className={`el-item${isCompleting ? ' el-completing' : ''}${routine.completed ? ' el-completed' : ''}`}>
      <button className="el-circle" onClick={() => onToggle(routine.id, routine.completed)}>
        <svg width="24" height="24" viewBox="0 0 24 24" fill="none">
          <circle cx="12" cy="12" r="9.5" className="el-cr-ring" />
          <circle cx="12" cy="12" r="9.5" className="el-cr-fill" />
          <path d="M8 12.5l2.5 2.5L16 10" className="el-cr-check" />
        </svg>
      </button>
      <span
        className="el-item-text"
        style={{flex:1, cursor: onEdit ? 'pointer' : 'default'}}
        onClick={() => onEdit && onEdit(routine)}
      >
        {routine.name || routine.text || '(uten navn)'}
      </span>
      {routine.streak > 0 && (
        <span style={{fontSize:11,fontWeight:700,color:'var(--accent)',opacity:routine.completed?0.3:0.7,flexShrink:0}}>
          {routine.streak}d
        </span>
      )}
    </div>
  );
}

function MobLogo({ size = 60, onClick }) {
  const inset2 = Math.round(size * 0.22);
  const svgSz = Math.round(size * 0.36);
  return (
    <div onClick={onClick} style={{
      width:size,height:size,borderRadius:'50%',position:'relative',
      cursor:'pointer',flexShrink:0,
      boxShadow:'0 0 18px 6px rgba(0,212,170,0.35),0 0 40px 14px rgba(0,212,170,0.15)',
    }}>
      <div style={{
        position:'absolute',inset:0,borderRadius:'50%',
        background:'conic-gradient(from 0deg,var(--accent),#004d3a,var(--accent-c),#001a44,var(--accent))',
        animation:'logoSpin 4s linear infinite',
        filter:'blur(2px)',zIndex:1,
      }} />
      <div style={{
        position:'absolute',inset:inset2,borderRadius:'50%',
        background:'radial-gradient(circle at 35% 35%,#0e1e35,#060a14)',
        zIndex:2,
      }} />
      <div style={{position:'absolute',inset:0,display:'flex',alignItems:'center',justifyContent:'center',zIndex:3}}>
        <svg width={svgSz} height={svgSz} viewBox="0 0 20 20" fill="none">
          <path d="M4 10.5l4.5 4.5L16 6" stroke="#00e676" strokeWidth="2.8" strokeLinecap="round" strokeLinejoin="round"
            style={{filter:'drop-shadow(0 0 3px rgba(0,230,118,0.5))'}} />
        </svg>
      </div>
    </div>
  );
}

// Menu items — circular ring around center logo (matches New_design)
const MOB_MENU_ICON = { width: 26, height: 26, display: 'block' };
const MOB_MENU_ITEMS = [
  { label: 'Mindmap',  hash: '#/prompts',  icon: <svg style={MOB_MENU_ICON} viewBox="0 0 26 26" fill="none" stroke="currentColor" strokeWidth="1.6"><circle cx="13" cy="13" r="2" fill="currentColor"/><circle cx="13" cy="5" r="1.5" fill="currentColor"/><circle cx="19" cy="13" r="1.5" fill="currentColor"/><circle cx="13" cy="21" r="1.5" fill="currentColor"/><circle cx="7" cy="13" r="1.5" fill="currentColor"/><line x1="13" y1="6.5" x2="13" y2="11"/><line x1="17.5" y1="14" x2="12" y2="14"/><line x1="13" y1="15.5" x2="13" y2="20"/><line x1="8.5" y1="12" x2="14" y2="12"/></svg> },
  { label: 'Mål',      hash: '#/goals',    icon: <svg style={MOB_MENU_ICON} viewBox="0 0 26 26" fill="none" stroke="currentColor" strokeWidth="1.6"><circle cx="13" cy="13" r="10"/><circle cx="13" cy="13" r="6"/><circle cx="13" cy="13" r="2" fill="currentColor"/></svg> },
  { label: 'Oppgaver', hash: '#/tasks',    icon: <svg style={MOB_MENU_ICON} viewBox="0 0 26 26" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M5 9l3 3L19 5"/><path d="M5 16l3 3L19 12"/></svg> },
  { label: 'Rutiner',  hash: '#/routines', icon: <svg style={MOB_MENU_ICON} viewBox="0 0 26 26" fill="none" stroke="currentColor" strokeWidth="1.6"><circle cx="13" cy="13" r="10"/><path d="M13 7v6l4 2"/></svg> },
  { label: 'Fokus',    hash: '#/tasks',    icon: <svg style={MOB_MENU_ICON} viewBox="0 0 26 26" fill="none" stroke="currentColor" strokeWidth="1.6"><circle cx="13" cy="13" r="10"/><path d="M13 8v10M8 13h10"/></svg> },
  { label: 'Journal',  hash: '#/journal',  icon: <svg style={MOB_MENU_ICON} viewBox="0 0 26 26" fill="none" stroke="currentColor" strokeWidth="1.6"><rect x="4" y="3" width="18" height="20" rx="2"/><line x1="8" y1="7" x2="18" y2="7"/><line x1="8" y1="12" x2="18" y2="12"/><line x1="8" y1="17" x2="14" y2="17"/></svg> },
  { label: 'Balanse',  hash: '#/balance',  icon: <svg style={MOB_MENU_ICON} viewBox="0 0 26 26" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M4 16h18"/><path d="M7 16l3-6h-6l3 6z"/><path d="M19 16l-3-6h6l-3 6z"/><path d="M13 3v13"/></svg> },
  { label: 'Notater',  hash: '#/notes',    icon: <svg style={MOB_MENU_ICON} viewBox="0 0 26 26" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M6 4h14a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2z"/><path d="M9 10h8M9 15h8"/></svg> },
  { label: 'Prompts',  hash: '#/prompts',  icon: <svg style={MOB_MENU_ICON} viewBox="0 0 26 26" fill="none" stroke="currentColor" strokeWidth="1.6"><path d="M5 13c0-4.4 3.6-8 8-8s8 3.6 8 8-3.6 8-8 8H4l1-7z"/></svg> },
];

function MobMenuOverlay({ isOpen, onClose }) {
  const [show, setShow] = useMobState(false);
  const [animIn, setAnimIn] = useMobState(false);

  useMobEffect(() => {
    if (isOpen) {
      setShow(true);
      requestAnimationFrame(() => requestAnimationFrame(() => setAnimIn(true)));
    } else {
      setAnimIn(false);
      const t = setTimeout(() => setShow(false), 550);
      return () => clearTimeout(t);
    }
  }, [isOpen]);

  if (!show) return null;

  function handleClick(hash) {
    window.location.hash = hash;
    onClose();
  }

  return (
    <div className={`mob-menu-overlay${animIn ? ' mob-menu-open' : ''}`} onClick={onClose}>
      <div className="mob-menu-bg" />
      <div className="mob-menu-aurora" />

      {/* Floating orbs */}
      <div className="mob-menu-orb" style={{ width:320, height:320, top:'-8%', left:'-15%', background:'radial-gradient(circle, rgba(0,212,170,0.13), transparent 68%)', '--orb-dur':'10s', '--orb-tx':'35px', '--orb-ty':'25px' }} />
      <div className="mob-menu-orb" style={{ width:260, height:260, bottom:'0%', right:'-8%', background:'radial-gradient(circle, rgba(0,180,216,0.11), transparent 68%)', '--orb-dur':'13s', '--orb-tx':'-25px', '--orb-ty':'-35px' }} />
      <div className="mob-menu-orb" style={{ width:180, height:180, top:'55%', left:'10%', background:'radial-gradient(circle, rgba(0,212,170,0.07), transparent 68%)', '--orb-dur':'8s', '--orb-tx':'15px', '--orb-ty':'-20px' }} />

      {/* Concentric rings */}
      {[100, 148, 200, 260].map((r, i) => (
        <div key={r} className="mob-menu-ring" style={{
          width: r * 2, height: r * 2,
          border: `1px solid rgba(0,212,170,${0.1 - i * 0.02})`,
          '--ring-dur': `${5 + i * 1.5}s`,
          '--ring-op-a': 0.1 - i * 0.02,
          '--ring-op-b': 0.04 - i * 0.008,
        }} />
      ))}

      {/* Center radial glow */}
      <div style={{
        position:'absolute', left:'50%', top:'50%',
        transform:'translate(-50%, -50%)',
        width:280, height:280, borderRadius:'50%', pointerEvents:'none',
        background:'radial-gradient(circle, rgba(0,212,170,0.09) 0%, transparent 65%)',
      }} />

      <div className="mob-menu-dots" />
      <div className="mob-menu-vignette" />

      {/* Menu grid — logo at center, tiles in ring */}
      <div className="mob-menu-grid" onClick={e => e.stopPropagation()}>
        {/* Center logo */}
        <div style={{
          position:'absolute', left:'50%', top:'50%',
          transform:'translate(-50%, -50%)',
          opacity: animIn ? 1 : 0,
          transition: 'opacity 0.4s 0.2s, transform 0.5s 0.2s cubic-bezier(0.25,1,0.5,1)',
          zIndex: 10,
        }}>
          <MobLogo size={80} onClick={onClose} />
        </div>

        {/* Ring tiles */}
        {MOB_MENU_ITEMS.map((tile, i) => {
          const delay = 80 + i * 45;
          return (
            <button key={tile.label} className="mob-menu-tile" onClick={() => handleClick(tile.hash)} style={{
              opacity: animIn ? 1 : 0,
              transition: animIn
                ? `opacity 0.4s ${delay}ms, transform 0.4s ${delay}ms cubic-bezier(0.25,1,0.5,1)`
                : 'opacity 0.15s, transform 0.15s',
            }}>
              <div className="mob-menu-tile-card" style={{ color: 'var(--accent, #00d4aa)' }}>
                {tile.icon}
              </div>
              <span style={{ fontSize: 10, fontWeight: 600, color: 'rgba(255,255,255,0.55)', letterSpacing: '0.3px' }}>{tile.label}</span>
            </button>
          );
        })}
      </div>
    </div>
  );
}

function MobAddSheet({ isOpen, onAdd, onClose, filter }) {
  const [text, setText] = useMobState('');
  const [cat, setCat] = useMobState(filter);
  const inputRef = useMobRef(null);

  useMobEffect(() => {
    if (isOpen) {
      setCat(filter);
      setTimeout(() => inputRef.current?.focus(), 350);
    } else setText('');
  }, [isOpen]);

  function handleSubmit(e) {
    e.preventDefault();
    if (!text.trim()) return;
    onAdd(text.trim(), cat);
    setText('');
    onClose();
  }

  return (
    <>
      {isOpen && (
        <div style={{position:'fixed',inset:0,zIndex:149,cursor:'pointer'}} onClick={onClose} />
      )}
      <div className={`mob-add-sheet${isOpen ? ' mob-add-open' : ''}`}>
        <div className="mob-add-handle" />
        {/* Category toggle */}
        <div style={{display:'flex',gap:6,marginBottom:8,justifyContent:'center'}}>
          {['Work','Personal'].map(c => (
            <button
              key={c}
              type="button"
              onClick={() => setCat(c)}
              style={{
                padding:'5px 14px',borderRadius:999,border:'none',
                background:cat===c?'var(--accent)':'rgba(255,255,255,0.08)',
                color:cat===c?'#000':'rgba(255,255,255,0.5)',
                fontFamily:'var(--font)',fontSize:11,fontWeight:700,
                cursor:'pointer',transition:'all .15s',
              }}
            >{c}</button>
          ))}
        </div>
        <form onSubmit={handleSubmit} style={{display:'flex',gap:8}}>
          <input ref={inputRef} value={text} onChange={e => setText(e.target.value)}
            placeholder="Legg til oppgave…"
            className="mob-add-input"
          />
          <button type="submit" className="mob-add-submit" style={{
            background:text.trim() ? 'var(--accent)' : 'rgba(255,255,255,0.08)',
            color:text.trim() ? '#000' : 'rgba(255,255,255,0.3)',
          }}>
            <svg width="18" height="18" viewBox="0 0 18 18" fill="none">
              <path d="M9 14V4M4 8l5-5 5 5" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          </button>
        </form>
      </div>
    </>
  );
}

function MobileDashboard({ tasks, routines, loading, onToggleTask, onToggleRoutine, onAddTask, onAddRoutine, onEditRoutine }) {
  const [filter] = useWpFilter();
  const [menuOpen, setMenuOpen] = useMobState(false);
  const [addOpen, setAddOpen] = useMobState(false);
  const [fading, setFading] = useMobState(false);
  const [completingIds, setCompletingIds] = useMobState(() => new Set());
  const lastFilterRef = useMobRef(filter);

  // Cross-fade when the (now global) filter changes elsewhere
  useMobEffect(() => {
    if (lastFilterRef.current === filter) return;
    lastFilterRef.current = filter;
    setFading(true);
    const t = setTimeout(() => setFading(false), 230);
    return () => clearTimeout(t);
  }, [filter]);

  // Lock body scroll + hide top nav while the mobile dashboard is mounted
  useMobEffect(() => {
    document.body.classList.add('mob-dash-active');
    return () => document.body.classList.remove('mob-dash-active');
  }, []);

  const now = new Date();
  const dateStr = now.toLocaleDateString('no-NO', {weekday:'long',day:'numeric',month:'long'});

  const mobTodayStr = new Date().toISOString().slice(0, 10);
  const fTasks = tasks
    .filter(t => {
      const c = String(t.category || '').toLowerCase();
      if (c && c !== 'none' && dashNormCategory(c) !== filter) return false;
      return String(t.due_at || t.due_date || '').slice(0, 10) === mobTodayStr;
    })
    .sort((a, b) => (a.completed ? 1 : 0) - (b.completed ? 1 : 0));

  const fRoutines = routines
    .filter(r => { const cat = dashNormCategory(r.work_personal_category || r.category); return !cat || cat === filter; })
    .sort((a, b) => (a.completed ? 1 : 0) - (b.completed ? 1 : 0));

  function handleToggleTask(id, completed) {
    if (!completed) {
      setCompletingIds(prev => new Set([...prev, id]));
      setTimeout(() => {
        onToggleTask(id, completed);
        setCompletingIds(prev => { const n = new Set(prev); n.delete(id); return n; });
      }, 480);
    } else {
      onToggleTask(id, completed);
    }
  }

  function handleToggleRoutine(id, completed) {
    if (!completed) {
      setCompletingIds(prev => new Set([...prev, id]));
      setTimeout(() => {
        onToggleRoutine(id, completed);
        setCompletingIds(prev => { const n = new Set(prev); n.delete(id); return n; });
      }, 480);
    } else {
      onToggleRoutine(id, completed);
    }
  }

  return (
    <div className="mob-dash">
      {/* Header */}
      <div className="el-header">
        <div>
          <h1 className="el-title">TODAY</h1>
          <p className="el-date" style={{textTransform:'capitalize'}}>{dateStr}</p>
        </div>
      </div>

      {/* Main scrollable content */}
      <div className="el-main">
        {/* Tasks section */}
        <div className="el-section">
          <div className="el-section-head">
            <h2 className="el-section-label">Todo</h2>
            <span className="el-section-count">{fTasks.filter(t=>t.completed).length}/{fTasks.length}</span>
          </div>
          <div className={`el-section-scroll${fading ? ' el-fading' : ''}`}>
            {loading ? (
              <p className="el-empty">Laster…</p>
            ) : fTasks.length === 0 ? (
              <p className="el-empty">Ingen oppgaver for {filter}</p>
            ) : (
              fTasks.map(t => (
                <MobTodoItem key={t.id} task={t}
                  isCompleting={completingIds.has(t.id)}
                  onToggle={handleToggleTask} />
              ))
            )}
          </div>
        </div>

        <div className="el-divider" />

        {/* Routines section */}
        <div className="el-section">
          <div className="el-section-head">
            <h2 className="el-section-label">Rutiner</h2>
            <div style={{display:'flex',alignItems:'center',gap:8}}>
              <span className="el-section-count">{fRoutines.filter(r=>r.completed).length}/{fRoutines.length}</span>
              {onAddRoutine && (
                <button
                  type="button"
                  onClick={onAddRoutine}
                  title="Ny rutine"
                  style={{
                    width:26,height:26,borderRadius:8,padding:0,
                    border:'1px solid rgba(255,255,255,0.1)',background:'rgba(255,255,255,0.04)',
                    color:'var(--sec)',cursor:'pointer',fontSize:15,lineHeight:1,
                    display:'flex',alignItems:'center',justifyContent:'center',
                  }}
                >+</button>
              )}
            </div>
          </div>
          <div className={`el-section-scroll${fading ? ' el-fading' : ''}`}>
            {loading ? (
              <p className="el-empty">Laster…</p>
            ) : fRoutines.length === 0 ? (
              <p className="el-empty">Ingen rutiner for {filter}</p>
            ) : (
              fRoutines.map(r => (
                <MobRoutineItem key={r.id} routine={r}
                  isCompleting={completingIds.has(r.id)}
                  onToggle={handleToggleRoutine}
                  onEdit={onEditRoutine} />
              ))
            )}
          </div>
        </div>
      </div>

      {/* Bottom bar */}
      <div className="mob-bottom-bar">
        <button className="mob-icon-btn" onClick={() => setAddOpen(v => !v)} title="Legg til oppgave">
          <svg width="20" height="20" viewBox="0 0 22 22" fill="none">
            <line x1="11" y1="3" x2="11" y2="19" stroke="var(--accent)" strokeWidth="2.2" strokeLinecap="round"/>
            <line x1="3" y1="11" x2="19" y2="11" stroke="var(--accent)" strokeWidth="2.2" strokeLinecap="round"/>
          </svg>
        </button>

        <MobLogo size={64} onClick={() => setMenuOpen(true)} />

        <button className="mob-icon-btn" onClick={() => { window.location.hash = '#/tasks'; }} title="Alle oppgaver">
          <svg width="20" height="20" viewBox="0 0 22 22" fill="none" stroke="var(--accent)" strokeWidth="2" strokeLinecap="round">
            <path d="M4 7h14M4 12h14M4 17h14"/>
          </svg>
        </button>
      </div>

      {/* Overlays */}
      <MobMenuOverlay isOpen={menuOpen} onClose={() => setMenuOpen(false)} />
      <MobAddSheet isOpen={addOpen} onAdd={onAddTask} onClose={() => setAddOpen(false)} filter={filter} />
    </div>
  );
}

// ── Root Dashboard ───────────────────────────────────────────────
function Dashboard({ uiMode, onToggleMode }) {
  const [isMobile, setIsMobile] = useDashState(() => window.matchMedia('(max-width: 640px)').matches);
  const [tasks, setTasks] = useDashState([]);
  const [routines, setRoutines] = useDashState([]);
  const [bigWins, setBigWins] = useDashState([]);
  const [deadlines, setDeadlines] = useDashState([]);
  const [note, setNote] = useDashState('');
  const [noteId, setNoteId] = useDashState(null);
  const [notes, setNotes] = useDashState([]);
  const [isFavorite, setIsFavorite] = useDashState(false);
  const [loadingTasks, setLoadingTasks] = useDashState(true);
  const [loadingNote, setLoadingNote] = useDashState(true);
  const [editRoutine, setEditRoutine] = useDashState(null);
  const [editTask, setEditTask] = useDashState(null);
  const noteSaveRef = useDashRef(null);

  useDashEffect(() => {
    const mq = window.matchMedia('(max-width: 640px)');
    const handler = e => setIsMobile(e.matches);
    mq.addEventListener('change', handler);
    return () => mq.removeEventListener('change', handler);
  }, []);

  useDashEffect(() => {
    function onEditItem(e) {
      const { item: it } = e.detail || {};
      if (!it) return;
      if (it.type === 'routine') {
        setRoutines(prev => {
          const r = prev.find(r => r.id === it.id);
          if (r) setEditRoutine(r);
          return prev;
        });
      } else {
        setTasks(prev => {
          const t = prev.find(t => t.id === it.id);
          if (t) setEditTask(t);
          return prev;
        });
      }
    }
    window.addEventListener('el-edit-item', onEditItem);
    return () => window.removeEventListener('el-edit-item', onEditItem);
  }, []);

  useDashEffect(() => {
    async function loadTasks() {
      try {
        const todayStr = new Date().toISOString().slice(0, 10);

        // Fetch today's tasks (both completed and incomplete) to mirror Tasks page "Today" view
        const { data, error } = await supabaseClient
          .from('todo_tasks')
          .select('id, name, completed_at, category, due_date, is_big_win, position')
          .eq('due_date', todayStr)
          .order('position', { ascending: true })
          .order('created_at', { ascending: false });
        if (error) throw error;
        const demo = dashDemo();
        const mapped = (data || []).map(t => ({
          ...t,
          title: t.name,
          completed: !!t.completed_at,
          due_at: t.due_date,
        }));
        const sourceTasks = mapped.length ? mapped : (demo?.tasks || []);
        setTasks(sourceTasks);

        // Big wins fetched separately (not limited to today)
        const { data: bwData } = await supabaseClient
          .from('todo_tasks')
          .select('id, name, completed_at, category, due_date, is_big_win, position')
          .eq('is_big_win', true)
          .is('completed_at', null)
          .order('position', { ascending: true })
          .limit(10);
        const mappedBw = (bwData || []).map(t => ({ ...t, title: t.name, completed: !!t.completed_at, due_at: t.due_date }));
        setBigWins(mappedBw.length ? mappedBw : (demo?.tasks || []).filter(t => t.is_big_win));

        const { data: dlData } = await supabaseClient
          .from('todo_tasks')
          .select('id, name, due_date, category')
          .is('completed_at', null)
          .not('due_date', 'is', null)
          .order('due_date', { ascending: true })
          .limit(5);
        const mappedDl = (dlData || []).map(t => ({ ...t, title: t.name, due_at: t.due_date }));
        setDeadlines(mappedDl.length ? mappedDl : (dashDemo()?.tasks || []).filter(t => t.due_at || t.due_date).slice(0, 5));
      } catch(e) {
        const demo = dashDemo();
        if (demo) {
          setTasks(demo.tasks);
          setBigWins(demo.tasks.filter(t => t.is_big_win));
          setDeadlines(demo.tasks.filter(t => t.due_at || t.due_date).slice(0, 5));
        }
      } finally {
        setLoadingTasks(false);
      }
    }
    loadTasks();
  }, []);

  useDashEffect(() => {
    async function loadRoutines() {
      try {
        const today = new Date().toISOString().split('T')[0];
        const { data: rData } = await supabaseClient
          .from('routines')
          .select('id, name, work_personal_category, category, icon, position, archived_at')
          .is('archived_at', null)
          .order('position', { ascending: true })
          .limit(12);

        if (rData && rData.length > 0) {
          const { data: eData } = await supabaseClient
            .from('routine_entries')
            .select('routine_id, status')
            .in('routine_id', rData.map(r=>r.id))
            .eq('entry_date', today);

          const doneIds = new Set((eData||[]).filter(e=>e.status==='done').map(e=>e.routine_id));
          setRoutines(rData.map(r => ({ ...r, completed: doneIds.has(r.id), streak: 0 })));
        } else if (dashDemo()) {
          setRoutines(dashDemo().routines);
        }
      } catch(e) {
        if (dashDemo()) setRoutines(dashDemo().routines);
      }
    }
    loadRoutines();
  }, []);

  // Hard cap on note count shown in the dashboard switcher (§3.14)
  const MAX_DASH_NOTES = 8;

  useDashEffect(() => {
    async function loadNotes() {
      try {
        // Load favorites + most-recently-opened. Single query, cap at MAX_DASH_NOTES * 2
        // so we have enough rows on either side of the favorite filter; trim afterwards.
        const { data } = await supabaseClient
          .from('inbox_notes')
          .select('id, heading, content, is_favorite, last_opened_at, updated_at')
          .order('is_favorite', { ascending: false })
          .order('last_opened_at', { ascending: false, nullsFirst: false })
          .order('updated_at', { ascending: false })
          .limit(MAX_DASH_NOTES * 2);

        const list = (data || []).slice(0, MAX_DASH_NOTES);
        setNotes(list);

        // Default: highest last_opened_at (the order above already places it first)
        const initial = list[0] || dashDemo()?.note || null;
        if (initial) {
          setNote(initial.content || '');
          setNoteId(initial.id);
          setIsFavorite(!!initial.is_favorite);
          markOpened(initial.id);
        }
      } catch(e) {
        const demoNote = dashDemo()?.note;
        if (demoNote) { setNote(demoNote.content || ''); setNoteId(demoNote.id); }
      } finally {
        setLoadingNote(false);
      }
    }
    loadNotes();
  }, []);

  function markOpened(id) {
    if (!id || dashDemo()) return;
    // Fire-and-forget; we don't refresh the local order until user reopens.
    supabaseClient.from('inbox_notes')
      .update({ last_opened_at: new Date().toISOString() })
      .eq('id', id)
      .then(() => {}, () => {});
  }

  function handleNoteChange(html) {
    setNote(html);
    if (noteSaveRef.current) clearTimeout(noteSaveRef.current);
    noteSaveRef.current = setTimeout(() => saveNote(html), 1200);
  }

  async function saveNote(content) {
    if (dashDemo()) return;
    try {
      if (noteId) {
        await supabaseClient.from('inbox_notes')
          .update({ content, updated_at: new Date().toISOString() }).eq('id', noteId);
        setNotes(prev => prev.map(n => n.id === noteId ? { ...n, content } : n));
      } else {
        const uid = await window.ensureCurrentUserId();
        if (!uid) return;
        const today = new Date().toISOString().split('T')[0];
        const { data } = await supabaseClient.from('inbox_notes')
          .insert({ content, heading: 'Hurtignotat', user_id: uid, note_date: today, last_opened_at: new Date().toISOString() }).select().single();
        if (data) {
          setNoteId(data.id);
          setIsFavorite(!!data.is_favorite);
          setNotes(prev => [data, ...prev].slice(0, MAX_DASH_NOTES));
        }
      }
    } catch(e) {}
  }

  async function pickNote(id) {
    if (id === noteId) return;
    const target = notes.find(n => n.id === id);
    if (!target) return;
    // Flush any pending save before switching
    if (noteSaveRef.current) { clearTimeout(noteSaveRef.current); noteSaveRef.current = null; await saveNote(note); }
    setNote(target.content || '');
    setNoteId(target.id);
    setIsFavorite(!!target.is_favorite);
    markOpened(target.id);
  }

  async function createNote() {
    if (noteSaveRef.current) { clearTimeout(noteSaveRef.current); noteSaveRef.current = null; await saveNote(note); }
    if (dashDemo()) {
      const id = `demo-note-${Date.now()}`;
      setNotes(prev => [{ id, heading: 'Nytt notat', content: '', is_favorite: false, last_opened_at: new Date().toISOString() }, ...prev].slice(0, MAX_DASH_NOTES));
      setNote(''); setNoteId(id); setIsFavorite(false);
      return;
    }
    const uid = await window.ensureCurrentUserId();
    if (!uid) return;
    const today = new Date().toISOString().split('T')[0];
    const { data } = await supabaseClient.from('inbox_notes')
      .insert({ content: '', heading: 'Hurtignotat', user_id: uid, note_date: today, last_opened_at: new Date().toISOString() })
      .select()
      .single();
    if (data) {
      setNotes(prev => [data, ...prev].slice(0, MAX_DASH_NOTES));
      setNote(''); setNoteId(data.id); setIsFavorite(!!data.is_favorite);
    }
  }

  async function toggleNoteFavorite() {
    if (!noteId) return;
    const next = !isFavorite;
    setIsFavorite(next);
    setNotes(prev => prev.map(n => n.id === noteId ? { ...n, is_favorite: next } : n));
    if (dashDemo()) return;
    await supabaseClient.from('inbox_notes').update({ is_favorite: next }).eq('id', noteId);
  }

  async function toggleTask(id, completed) {
    const newCompletedAt = completed ? null : new Date().toISOString();
    setTasks(prev => prev.map(t => t.id===id ? {...t, completed: !completed, completed_at: newCompletedAt} : t));
    if (!dashDemo()) await supabaseClient.from('todo_tasks').update({ completed_at: newCompletedAt }).eq('id', id);
  }

  async function toggleRoutine(id, completed) {
    setRoutines(prev => prev.map(r => r.id===id ? {...r, completed: !completed} : r));
    const today = new Date().toISOString().split('T')[0];
    if (dashDemo()) return;
    const uid = await window.ensureCurrentUserId();
    if (!uid) return;
    if (!completed) {
      await supabaseClient.from('routine_entries')
        .upsert({ routine_id: id, user_id: uid, entry_date: today, status: 'done' }, { onConflict: 'routine_id,entry_date' });
    } else {
      await supabaseClient.from('routine_entries')
        .delete().eq('routine_id', id).eq('entry_date', today);
    }
  }

  async function saveRoutineEdit(patch) {
    const isNew = !patch.id;
    if (dashDemo()) {
      if (isNew) {
        const row = {
          id: `demo-routine-${Date.now()}`,
          name: patch.name, text: patch.name,
          frequency: patch.frequency, days: patch.days,
          category: patch.work_personal_category, work_personal_category: patch.work_personal_category,
          completed: false, streak: 0,
        };
        setRoutines(prev => [...prev, row]);
      } else {
        setRoutines(prev => prev.map(r => r.id === patch.id ? { ...r, ...patch, text: patch.name } : r));
      }
      return;
    }
    if (isNew) {
      const uid = await window.ensureCurrentUserId();
      if (!uid) return;
      const { data } = await supabaseClient
        .from('routines')
        .insert({
          user_id: uid,
          name: patch.name,
          frequency: patch.frequency,
          days: patch.days,
          work_personal_category: patch.work_personal_category,
          position: Date.now(),
          open_ended: true,
          start_date: new Date().toISOString().split('T')[0],
        })
        .select().single();
      if (data) setRoutines(prev => [...prev, { ...data, completed: false, streak: 0 }]);
    } else {
      setRoutines(prev => prev.map(r => r.id === patch.id ? { ...r, ...patch, text: patch.name } : r));
      const { id, ...fields } = patch;
      await supabaseClient.from('routines').update(fields).eq('id', id);
    }
  }

  async function deleteRoutine(id) {
    setRoutines(prev => prev.filter(r => r.id !== id));
    if (dashDemo()) return;
    // Soft-delete via archived_at so history is preserved
    await supabaseClient.from('routines').update({ archived_at: new Date().toISOString() }).eq('id', id);
  }

  async function addTask(text, category) {
    if (dashDemo()) {
      const data = { id: `demo-task-${Date.now()}`, title: text, name: text, category, completed: false, completed_at: null, priority: 'do', v2_priority: 'do' };
      setTasks(prev => [data, ...prev]);
      return;
    }
    const uid = await window.ensureCurrentUserId();
    if (!uid) return;
    const cat = String(category || '').toLowerCase();
    const { data } = await supabaseClient
      .from('todo_tasks')
      .insert({ user_id: uid, name: text, category: cat || 'none', workflow: 'tasks_backlog', position: Date.now() })
      .select().single();
    if (data) {
      const mapped = { ...data, title: data.name, completed: !!data.completed_at, due_at: data.due_date };
      setTasks(prev => [mapped, ...prev]);
    }
  }

  async function saveTaskEdit(patch) {
    setTasks(prev => prev.map(t => t.id === patch.id ? { ...t, ...patch, title: patch.name || t.title } : t));
    if (dashDemo()) return;
    const { id, ...fields } = patch;
    await supabaseClient.from('todo_tasks').update(fields).eq('id', id);
  }

  async function deleteDashTask(id) {
    setTasks(prev => prev.filter(t => t.id !== id));
    if (!dashDemo()) await supabaseClient.from('todo_tasks').delete().eq('id', id);
  }

  const routineModal = (
    <RoutineSettings
      isOpen={!!editRoutine}
      routine={editRoutine && editRoutine.id ? editRoutine : null}
      variant={isMobile ? 'mobile' : 'desktop'}
      onClose={() => setEditRoutine(null)}
      onSave={saveRoutineEdit}
      onDelete={deleteRoutine}
    />
  );

  const taskModal = (
    <TaskSettings
      isOpen={!!editTask}
      task={editTask}
      variant={isMobile ? 'mobile' : 'desktop'}
      onClose={() => setEditTask(null)}
      onSave={saveTaskEdit}
      onDelete={deleteDashTask}
    />
  );

  // Mobile: always show Easy layout (Pro mode is desktop-only)
  if (isMobile) {
    return (
      <>
        <MobileDashboard
          tasks={tasks} routines={routines}
          loading={loadingTasks}
          onToggleTask={toggleTask} onToggleRoutine={toggleRoutine} onAddTask={addTask}
          onAddRoutine={() => setEditRoutine({})}
          onEditRoutine={r => setEditRoutine(r)}
        />
        {routineModal}
        {taskModal}
      </>
    );
  }

  return (
    <div className="v2-page dash-root">
      {uiMode === 'pro' ? (
        <ProDashboard
          tasks={tasks} routines={routines} bigWins={bigWins} deadlines={deadlines}
          loading={loadingTasks}
          onToggleTask={toggleTask} onToggleRoutine={toggleRoutine} onAddTask={addTask}
          onAddRoutine={() => setEditRoutine({})}
          onEditRoutine={r => setEditRoutine(r)}
        />
      ) : (
        <EasyDashboard
          tasks={tasks} routines={routines} note={note}
          notes={notes} currentNoteId={noteId} isFavorite={isFavorite}
          loadingTasks={loadingTasks} loadingNote={loadingNote}
          onToggleTask={toggleTask} onToggleRoutine={toggleRoutine} onNoteChange={handleNoteChange}
          onPickNote={pickNote} onCreateNote={createNote} onToggleFavorite={toggleNoteFavorite}
          onAddRoutine={() => setEditRoutine({})}
          onEditRoutine={r => setEditRoutine(r)}
        />
      )}

      {routineModal}
      {taskModal}
    </div>
  );
}
