const { useState, useMemo, useEffect, useRef } = React;

/* ============================================================
   ICONS — minimal stroke set, no external deps
============================================================ */
const I = {
  dot: (p) => <span style={{ display:'inline-block', width:6, height:6, borderRadius:99, background:'currentColor', ...p?.style }} />,
  search: (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>,
  bell:   (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M6 8a6 6 0 1 1 12 0c0 7 3 7 3 9H3c0-2 3-2 3-9Z"/><path d="M10 21a2 2 0 0 0 4 0"/></svg>,
  mail:   (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="5" width="18" height="14" rx="2"/><path d="m3 7 9 6 9-6"/></svg>,
  cog:    (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1.1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1A1.7 1.7 0 0 0 4.6 9a1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1A1.7 1.7 0 0 0 9 4.7 1.7 1.7 0 0 0 10 3.2V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8V9c.4.6 1 1 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1Z"/></svg>,
  home:   (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="m3 11 9-8 9 8"/><path d="M5 10v10h14V10"/></svg>,
  cal:    (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 9h18M8 3v4M16 3v4"/></svg>,
  book:   (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M4 4h11a4 4 0 0 1 4 4v12H8a4 4 0 0 1-4-4Z"/><path d="M4 16a4 4 0 0 1 4-4h11"/></svg>,
  list:   (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"><path d="M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01"/></svg>,
  cash:   (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><rect x="2" y="6" width="20" height="12" rx="2"/><circle cx="12" cy="12" r="3"/><path d="M6 10v.01M18 14v.01"/></svg>,
  user:   (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="8" r="4"/><path d="M4 21a8 8 0 0 1 16 0"/></svg>,
  mega:   (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M3 11v2a2 2 0 0 0 2 2h2l8 5V4L7 9H5a2 2 0 0 0-2 2Z"/></svg>,
  file:   (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M14 3H6a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V9Z"/><path d="M14 3v6h6"/></svg>,
  edit:   (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M4 20h4l11-11-4-4L4 16v4Z"/><path d="m14 6 4 4"/></svg>,
  arrow:  (p) => <svg width={p?.s||14} height={p?.s||14} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h14M13 5l7 7-7 7"/></svg>,
  ext:    (p) => <svg width={p?.s||12} height={p?.s||12} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M7 17 17 7M9 7h8v8"/></svg>,
  chev:   (p) => <svg width={p?.s||14} height={p?.s||14} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" style={{ transform: p?.open?'rotate(90deg)':'rotate(0)', transition:'transform .15s' }}><path d="m9 6 6 6-6 6"/></svg>,
  pin:    (p) => <svg width={p?.s||14} height={p?.s||14} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="10" r="3"/><path d="M12 22s7-7 7-12a7 7 0 1 0-14 0c0 5 7 12 7 12Z"/></svg>,
  check:  (p) => <svg width={p?.s||14} height={p?.s||14} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="m5 12 5 5L20 7"/></svg>,
  out:    (p) => <svg width={p?.s||14} height={p?.s||14} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><path d="M16 17l5-5-5-5M21 12H9"/></svg>,
  shield: (p) => <svg width={p?.s||14} height={p?.s||14} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3 4 6v6c0 5 4 8 8 9 4-1 8-4 8-9V6Z"/></svg>,
  help:   (p) => <svg width={p?.s||14} height={p?.s||14} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="9"/><path d="M9.5 9a2.5 2.5 0 1 1 3.5 2.3c-.7.3-1 .9-1 1.7M12 17h.01"/></svg>,
  star:   (p) => <svg width={p?.s||14} height={p?.s||14} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round" strokeLinejoin="round"><path d="m12 3 2.9 6 6.6.6-5 4.5 1.5 6.5L12 17l-6 3.6 1.5-6.5-5-4.5L9 9Z"/></svg>,
  menu:   (p) => <svg width={p?.s||18} height={p?.s||18} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M4 7h16M4 12h16M4 17h16"/></svg>,
  x:      (p) => <svg width={p?.s||16} height={p?.s||16} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round"><path d="M6 6l12 12M18 6 6 18"/></svg>,
};

/* ============================================================
   DATA — fully anonymized, generic "School"
============================================================ */
const me = {
  name: 'Name Surname',
  album: '00000',
  programs: ['Computer Science, BEng', 'sem. 6'],
  email: 'name.surname@school.edu',
  initials: 'NS',
};

const upcoming = [
  {
    when: 'Day after tomorrow · Thursday, May 28',
    blocks: [
      { time: '12:15–14:00', code: 'STAT-DC', name: 'Mathematical Statistics', type: 'lab', room: 'B-204', online: 'Teams', teacher: 'Dr. K. Miller' },
    ],
  },
  {
    when: 'Friday · May 29',
    blocks: [
      { time: '08:00–09:30', code: 'ELEC-DB', name: 'Electronics Laboratory', type: 'lab', room: 'C-117', online: null, teacher: 'J. Sawyer, MSc' },
      { time: '11:45–13:15', code: 'PY-2', name: 'Python — Data Mining', type: 'lab', room: 'A-301', online: 'Teams', teacher: 'Dr. M. Collins' },
    ],
  },
  {
    when: 'Thursday · June 11',
    blocks: [
      { time: '10:15–12:00', code: 'STAT-DC', name: 'Mathematical Statistics', type: 'lecture', room: 'Aula A', online: 'Teams', teacher: 'Prof. P. Lawson' },
      { time: '12:00–13:30', code: 'STAT-DC', name: 'Mathematical Statistics · 2nd midterm (25/26)', type: 'midterm', room: '—', online: 'Inspera', teacher: 'Dr. K. Miller' },
      { time: '12:15–14:00', code: 'STAT-DC', name: 'Mathematical Statistics', type: 'lab', room: 'B-204', online: 'Teams', teacher: 'Dr. K. Miller' },
    ],
  },
  {
    when: 'Tuesday · June 16',
    blocks: [
      { time: '09:00–10:30', code: 'OR-DC', name: 'Operations Research — final test', type: 'midterm', room: 'D-22', online: null, teacher: 'Dr. B. Jenkins' },
    ],
  },
];

const announcements = [
  { course: 'Programming Lab 2 — Python (Data Mining)', subject: 'Running late', body: 'Good morning, my sincere apologies — I will be about 15 minutes late today.', when: 'today · 08:17', author: 'Dr. M. Collins', unread: true },
  { course: 'Programming Lab 2 — Python (Data Mining)', subject: 'Project — summary as requested', body: 'Dear students, for the Python 2 — Data Mining course you are required to prepare a final project as a notebook, e.g. Jupyter Notebook or Google Colab. (…)', when: 'May 24 · 12:22', author: 'Dr. M. Collins', unread: true },
  { course: 'Programming Lab 2 — Python (Data Mining)', subject: 'Action needed — project groups', body: 'Please fill in the group assignment table by May 25. Four people are still missing.', when: 'May 19 · 10:15', author: 'Dr. M. Collins', unread: false },
  { course: 'Operations Research & Logistics', subject: 'Materials for lecture 11', body: 'I have uploaded the presentation and two exercise files to the documents section.', when: 'May 18 · 09:01', author: 'Dr. B. Jenkins', unread: false },
];

const fileGroups = [
  {
    course: 'Applied Electronics Laboratory',
    items: [
      { name: 'Distance-sensor-HC-SR04-1.ino', when: 'today · 17:23', kind: 'ino' },
      { name: 'Motion-sensor-test-PIR-HC-SR501.ino', when: 'today · 17:23', kind: 'ino' },
      { name: 'ELEC-DB-group-Lab-12-surname-name-id.docx', when: 'today · 17:23', kind: 'docx' },
      { name: 'ELEC-DB-Lab-12.pptx', when: 'today · 17:23', kind: 'pptx' },
      { name: 'Programmable-LEDs-Task-1.ino', when: 'May 18 · 14:53', kind: 'ino' },
    ],
  },
  {
    course: 'Programming Lab 2 — Python (Data Mining)',
    items: [
      { name: 'Python_data_mining_LAB_12_2.pptx', when: 'today · 10:22', kind: 'pptx' },
      { name: 'Python_data_mining_LAB_12_1.pdf', when: 'today · 10:21', kind: 'pdf' },
      { name: 'Python_data_mining_LAB_11.pdf', when: 'today · 09:20', kind: 'pdf' },
      { name: '3classificationFinal.py', when: 'May 19 · 09:46', kind: 'py' },
      { name: '2classificationTest.py', when: 'May 19 · 09:46', kind: 'py' },
    ],
  },
  {
    course: 'Operations Research & Logistics',
    items: [
      { name: 'Lecture 11.pdf', when: 'yesterday · 10:56', kind: 'pdf' },
      { name: 'Lecture 11.pdf', when: 'yesterday · 10:55', kind: 'pdf' },
    ],
  },
];

const activity = [
  { browser: 'Chrome 148', host: '178.42.0.10 · home-isp.example.net', when: 'May 26 · 21:10', status: 'ok' },
  { browser: 'Chrome 148', host: 'lab392.school.edu', when: 'May 26 · 13:34', status: 'ok' },
  { browser: 'Chrome 148', host: 'lab392.school.edu', when: 'May 26 · 09:45', status: 'ok' },
  { browser: 'Chrome 143 · Android', host: 'mobile-5453.carrier.example.net', when: 'May 26 · 09:28', status: 'ok' },
  { browser: 'Chrome 148', host: 'lab392.school.edu', when: 'May 25 · 14:25', status: 'ok' },
  { browser: 'Chrome 148', host: '178.42.0.10 · home-isp.example.net', when: 'May 25 · 11:43', status: 'ok' },
  { browser: 'Chrome 148', host: '178.42.0.10 · home-isp.example.net', when: 'May 25 · 11:43', status: 'bad' },
  { browser: 'Chrome 136 · Android', host: '178.42.0.10 · home-isp.example.net', when: 'May 25 · 10:05', status: 'ok' },
];

const events = [
  { date: 'Jun 13', time: '10:00', title: 'School Open Day — main campus', tag: 'soon' },
  { date: 'Jun 10', time: '18:00', title: 'Print Design in the 21st Century — online webinar', tag: 'webinar' },
  { date: 'Jun 03', time: '17:30', title: 'AI Student Club meetup', tag: 'student club' },
];

const news = [
  { kind: 'Accreditation', title: 'Graphic Design program receives a positive accreditation review' },
  { kind: 'Partnership', title: 'School joins a creative-campus program — a new era of digital education' },
  { kind: 'Timetable', title: 'Timetable search for other groups is now open — check their schedules' },
];

const navMain = [
  { id: 'dashboard', label: 'Dashboard', icon: 'home', badge: null },
  { id: 'timetable', label: 'Timetable', icon: 'cal', badge: '3' },
  { id: 'grades', label: 'Grades', icon: 'list', badge: null },
  { id: 'courses', label: 'Courses', icon: 'book', badge: null },
  { id: 'finance', label: 'Finance', icon: 'cash', badge: null },
];

const navAccount = [
  { id: 'profile', label: 'Profile', icon: 'user' },
  { id: 'announcements', label: 'Announcements', icon: 'mega', badge: '2' },
  { id: 'documents', label: 'Documents', icon: 'file' },
  { id: 'enrollment', label: 'Enrollment', icon: 'edit' },
];

/* ============================================================
   PRIMITIVES
============================================================ */
const Pill = ({ children, tone='neutral', size='sm', ...rest }) => {
  const map = {
    neutral: { bg:'#F2E7D9', fg:'#5A4A42', bd:'#E8DAC6' },
    accent:  { bg:'var(--accent-soft)', fg:'var(--accent-ink)', bd:'transparent' },
    warn:    { bg:'var(--warn-soft)', fg:'var(--warn)', bd:'transparent' },
    info:    { bg:'var(--info-soft)', fg:'var(--info)', bd:'transparent' },
    ink:     { bg:'var(--ink)', fg:'#F6EDE4', bd:'transparent' },
    ghost:   { bg:'transparent', fg:'var(--ink-2)', bd:'var(--line)' },
  };
  const t = map[tone] || map.neutral;
  const sz = size==='xs' ? { padding:'1px 7px', fontSize:10.5, letterSpacing:'.04em' } : { padding:'2px 9px', fontSize:11.5, letterSpacing:'.02em' };
  return <span style={{ display:'inline-flex', alignItems:'center', gap:5, borderRadius:99, background:t.bg, color:t.fg, border:`1px solid ${t.bd}`, fontWeight:500, lineHeight:1.5, ...sz, ...rest.style }} {...rest}>{children}</span>;
};

const Card = ({ children, style, pad=20, className, ...rest }) => (
  <section className={className} style={{ background:'var(--surface)', borderRadius:16, border:'1px solid var(--line)', padding:pad, boxShadow:'0 1px 0 rgba(60,20,10,.02)', ...style }} {...rest}>{children}</section>
);

const SectionLabel = ({ children, action, icon }) => (
  <div className="section-label" style={{ display:'flex', alignItems:'baseline', justifyContent:'space-between', marginBottom:14 }}>
    <div style={{ display:'flex', alignItems:'center', gap:8 }}>
      {icon && <span style={{ color:'var(--muted)' }}>{icon}</span>}
      <h3 style={{ margin:0, fontFamily:'Geist', fontSize:11, fontWeight:600, textTransform:'uppercase', letterSpacing:'.14em', color:'var(--muted)' }}>{children}</h3>
    </div>
    {action}
  </div>
);

const Avatar = ({ initials='NS', size=36 }) => (
  <div style={{
    width:size, height:size, borderRadius:99, flex:'0 0 auto',
    display:'inline-flex', alignItems:'center', justifyContent:'center',
    background:'linear-gradient(135deg, oklch(0.5 0.18 25), oklch(0.36 0.13 22))',
    color:'#F6EDE4', fontWeight:600, fontSize:size*0.36, letterSpacing:'.04em',
    border:'2px solid #FFF', boxShadow:'0 1px 2px rgba(60,20,10,.15)'
  }}>{initials}</div>
);

const btnPrimary = {
  display:'inline-flex', alignItems:'center', gap:7,
  padding:'9px 13px', borderRadius:10,
  background:'var(--ink)', color:'#F6EDE4',
  fontSize:13, fontWeight:500
};
const btnGhost = {
  display:'inline-flex', alignItems:'center', gap:7,
  padding:'9px 13px', borderRadius:10,
  background:'#FFF', color:'var(--ink)',
  border:'1px solid var(--line)',
  fontSize:13, fontWeight:500
};

/* ============================================================
   SIDEBAR
============================================================ */
function Sidebar({ active, onSelect, open, onClose }) {
  return (
    <aside className={`sidebar${open ? ' open' : ''}`} style={{
      width:248, flex:'0 0 248px',
      background:'var(--surface-2)',
      borderRight:'1px solid var(--line)',
      display:'flex', flexDirection:'column',
      padding:'18px 14px', gap:18, position:'sticky', top:0, height:'100vh',
      overflowY:'auto'
    }}>
      {/* Brand */}
      <div style={{ display:'flex', alignItems:'center', gap:10, padding:'4px 8px' }}>
        <div style={{
          width:32, height:32, borderRadius:9,
          background:'oklch(0.42 0.18 25)', color:'#F6EDE4',
          display:'inline-flex', alignItems:'center', justifyContent:'center',
          fontFamily:'Instrument Serif', fontSize:20, fontStyle:'italic',
          boxShadow:'inset 0 -2px 0 rgba(0,0,0,.15)'
        }}>s</div>
        <div style={{ lineHeight:1 }}>
          <div className="serif" style={{ fontSize:20, lineHeight:1 }}>School</div>
          <div style={{ fontSize:10.5, color:'var(--muted)', letterSpacing:'.1em', textTransform:'uppercase', marginTop:2 }}>student portal</div>
        </div>
        <button className="hamburger" onClick={onClose} title="Close menu" style={{ marginLeft:'auto', width:32, height:32, alignItems:'center', justifyContent:'center', color:'var(--muted)', borderRadius:8 }}><I.x/></button>
      </div>

      {/* Search */}
      <button style={{
        display:'flex', alignItems:'center', gap:8,
        padding:'8px 12px', background:'#FFF', border:'1px solid var(--line)',
        borderRadius:10, color:'var(--muted)', fontSize:12.5, textAlign:'left'
      }}>
        <I.search />
        <span>Search…</span>
        <span className="mono" style={{ marginLeft:'auto', fontSize:10.5, color:'#B3A699', background:'var(--bg)', padding:'1px 6px', borderRadius:4 }}>⌘K</span>
      </button>

      {/* NAV */}
      <NavGroup title="Main">
        {navMain.map(n => <NavItem key={n.id} active={active===n.id} onClick={()=>onSelect(n.id)} {...n} />)}
      </NavGroup>
      <NavGroup title="Account">
        {navAccount.map(n => <NavItem key={n.id} active={active===n.id} onClick={()=>onSelect(n.id)} {...n} />)}
      </NavGroup>

      <div style={{ flex:1 }}/>

      {/* User card */}
      <div style={{ display:'flex', alignItems:'center', gap:10, padding:'10px', background:'#FFF', borderRadius:12, border:'1px solid var(--line)' }}>
        <Avatar initials={me.initials} size={36}/>
        <div style={{ minWidth:0, flex:1, lineHeight:1.25 }}>
          <div style={{ fontWeight:600, fontSize:13, color:'var(--ink)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{me.name}</div>
          <div style={{ fontSize:11, color:'var(--muted)' }}>ID {me.album}</div>
        </div>
        <button title="Sign out" style={{ color:'var(--muted)', padding:6, borderRadius:6 }}><I.out/></button>
      </div>
    </aside>
  );
}

function NavGroup({ title, children }) {
  return (
    <div>
      <div style={{ fontSize:10.5, color:'var(--muted)', letterSpacing:'.14em', textTransform:'uppercase', padding:'0 10px 6px' }}>{title}</div>
      <div style={{ display:'flex', flexDirection:'column', gap:1 }}>{children}</div>
    </div>
  );
}

function NavItem({ active, icon, label, badge, onClick }) {
  const Icon = I[icon] || I.dot;
  return (
    <button onClick={onClick} style={{
      display:'flex', alignItems:'center', gap:10,
      padding:'8px 10px', borderRadius:8, fontSize:13.5, fontWeight: active?600:450,
      color: active ? 'var(--ink)' : 'var(--ink-2)',
      background: active ? '#FFF' : 'transparent',
      border: active ? '1px solid var(--line)' : '1px solid transparent',
      boxShadow: active ? '0 1px 0 rgba(60,20,10,.03)' : 'none',
      width:'100%', textAlign:'left', minHeight:36,
    }}
    onMouseEnter={e=> { if(!active) e.currentTarget.style.background='#FFFBF5'; }}
    onMouseLeave={e=> { if(!active) e.currentTarget.style.background='transparent'; }}>
      <Icon s={16}/> {label}
      {badge && <span style={{ marginLeft:'auto', background:'var(--accent)', color:'#FFF', borderRadius:99, padding:'1px 7px', fontSize:10.5, fontWeight:600 }}>{badge}</span>}
    </button>
  );
}

/* ============================================================
   TOPBAR
============================================================ */
function TopBar({ active, onMenu, onSelect }) {
  const labels = {
    dashboard:'Dashboard', timetable:'Timetable', grades:'Grades', courses:'Courses',
    finance:'Finance', profile:'Profile', announcements:'Announcements',
    documents:'Documents', enrollment:'Enrollment'
  };
  const [open, setOpen] = useState(null); // 'mail' | 'bell' | 'settings' | 'user'
  const wrapRef = useRef(null);
  useEffect(() => {
    const close = (e) => { if (wrapRef.current && !wrapRef.current.contains(e.target)) setOpen(null); };
    document.addEventListener('pointerdown', close);
    return () => document.removeEventListener('pointerdown', close);
  }, []);
  const toggle = (k) => setOpen(o => o===k ? null : k);
  const go = (id) => { setOpen(null); onSelect && onSelect(id); };
  return (
    <header className="topbar" style={{
      display:'flex', alignItems:'center', gap:12,
      padding:'18px 32px', borderBottom:'1px solid var(--line)',
      background:'rgba(246,237,228,.72)', backdropFilter:'blur(8px)',
      position:'sticky', top:0, zIndex:10
    }}>
      <button className="hamburger" onClick={onMenu} title="Menu" style={{
        width:38, height:38, borderRadius:9, alignItems:'center', justifyContent:'center',
        color:'var(--ink)', border:'1px solid var(--line)', background:'#FFF'
      }}><I.menu/></button>
      <nav style={{ display:'flex', alignItems:'center', gap:8, fontSize:12.5, color:'var(--muted)', minWidth:0 }}>
        <span className="crumb-root">School</span>
        <span className="crumb-root" style={{ opacity:.5 }}>/</span>
        <span className="crumb-root" style={{ color:'var(--ink-2)' }}>Student portal</span>
        <span className="crumb-root" style={{ opacity:.5 }}>/</span>
        <span style={{ color:'var(--ink)', fontWeight:500, whiteSpace:'nowrap' }}>{labels[active] || 'Dashboard'}</span>
      </nav>
      <div style={{ flex:1 }}/>
      <div ref={wrapRef} style={{ display:'flex', alignItems:'center', gap:6, color:'var(--ink-2)' }}>
        <div style={{ position:'relative' }}>
          <IconBtn title="Mail" badge="4" active={open==='mail'} onClick={()=>toggle('mail')}><I.mail/></IconBtn>
          {open==='mail' && (
            <Dropdown title="Inbox" footer="Open inbox" onFooter={()=>go('announcements')}>
              {[
                { from:'Dr. M. Collins', subject:'Running late', when:'08:17', unread:true },
                { from:'Dean\u2019s Office', subject:'Student ID renewal confirmation', when:'yesterday', unread:true },
                { from:'Dr. K. Miller', subject:'Midterm scope — chapters 5–8', when:'May 24', unread:false },
                { from:'Library', subject:'Return reminder: 2 items due Friday', when:'May 23', unread:false },
              ].map((m, i) => (
                <button key={i} onClick={()=>go('announcements')} style={{ display:'grid', gridTemplateColumns:'auto 1fr auto', gap:10, alignItems:'center', padding:'9px 12px', width:'100%', textAlign:'left', borderRadius:8 }}
                  onMouseEnter={e=>e.currentTarget.style.background='var(--surface-2)'}
                  onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
                  <span style={{ width:7, height:7, borderRadius:99, background: m.unread ? 'var(--warn)' : '#E0D2BF' }}></span>
                  <span style={{ minWidth:0 }}>
                    <span style={{ display:'block', fontSize:12.5, fontWeight:600, color:'var(--ink)' }}>{m.from}</span>
                    <span style={{ display:'block', fontSize:12, color:'var(--ink-2)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{m.subject}</span>
                  </span>
                  <span className="mono" style={{ fontSize:10.5, color:'var(--muted)' }}>{m.when}</span>
                </button>
              ))}
            </Dropdown>
          )}
        </div>
        <div style={{ position:'relative' }}>
          <IconBtn title="Notifications" badge="2" active={open==='bell'} onClick={()=>toggle('bell')}><I.bell/></IconBtn>
          {open==='bell' && (
            <Dropdown title="Notifications" footer="See all activity" onFooter={()=>go('dashboard')}>
              {[
                { icon:<I.mega s={13}/>, text:'2 new announcements in Python — Data Mining', when:'today', tone:'var(--warn-soft)', fg:'var(--warn)' },
                { icon:<I.cal s={13}/>, text:'Midterm scheduled: Mathematical Statistics · Jun 11', when:'yesterday', tone:'var(--info-soft)', fg:'var(--info)' },
                { icon:<I.file s={13}/>, text:'5 new files in Applied Electronics Laboratory', when:'May 26', tone:'var(--green-soft)', fg:'var(--green)' },
              ].map((n, i) => (
                <button key={i} onClick={()=>go('dashboard')} style={{ display:'grid', gridTemplateColumns:'auto 1fr', gap:10, alignItems:'flex-start', padding:'9px 12px', width:'100%', textAlign:'left', borderRadius:8 }}
                  onMouseEnter={e=>e.currentTarget.style.background='var(--surface-2)'}
                  onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
                  <span style={{ width:26, height:26, borderRadius:7, background:n.tone, color:n.fg, display:'inline-flex', alignItems:'center', justifyContent:'center', marginTop:1 }}>{n.icon}</span>
                  <span style={{ minWidth:0 }}>
                    <span style={{ display:'block', fontSize:12.5, color:'var(--ink)', lineHeight:1.4 }}>{n.text}</span>
                    <span className="mono" style={{ fontSize:10.5, color:'var(--muted)' }}>{n.when}</span>
                  </span>
                </button>
              ))}
            </Dropdown>
          )}
        </div>
        <div className="hide-mobile" style={{ position:'relative' }}>
          <IconBtn title="Settings" active={open==='settings'} onClick={()=>toggle('settings')}><I.cog/></IconBtn>
          {open==='settings' && (
            <Dropdown title="Settings">
              <MenuRow icon={<I.user s={14}/>} label="Account settings" onClick={()=>go('profile')}/>
              <MenuRow icon={<I.bell s={14}/>} label="Notification preferences" onClick={()=>go('profile')}/>
              <MenuRow icon={<I.shield s={14}/>} label="Password & security" onClick={()=>go('profile')}/>
              <MenuRow icon={<I.cal s={14}/>} label="Language — English" hint="EN" onClick={()=>setOpen(null)}/>
            </Dropdown>
          )}
        </div>
        <div className="hide-mobile" style={{ width:1, height:22, background:'var(--line)', margin:'0 6px' }}></div>
        <div style={{ position:'relative' }}>
          <button onClick={()=>toggle('user')} style={{ display:'flex', alignItems:'center', gap:9, padding:'6px 10px', borderRadius:10, border:`1px solid ${open==='user'?'var(--accent)':'var(--line)'}`, background:'#FFF' }}>
            <Avatar initials={me.initials} size={26}/>
            <div className="topbar-user-text" style={{ textAlign:'left', lineHeight:1.1 }}>
              <div style={{ fontSize:12.5, fontWeight:600 }}>{me.name.split(' ')[0]}</div>
              <div style={{ fontSize:10.5, color:'var(--muted)' }}>{me.programs[1]}</div>
            </div>
          </button>
          {open==='user' && (
            <Dropdown>
              <div style={{ display:'flex', alignItems:'center', gap:10, padding:'10px 12px', borderBottom:'1px solid var(--line-2)', marginBottom:4 }}>
                <Avatar initials={me.initials} size={34}/>
                <div style={{ minWidth:0, lineHeight:1.3 }}>
                  <div style={{ fontSize:13, fontWeight:600 }}>{me.name}</div>
                  <div className="mono" style={{ fontSize:10.5, color:'var(--muted)' }}>{me.email}</div>
                </div>
              </div>
              <MenuRow icon={<I.user s={14}/>} label="My profile" onClick={()=>go('profile')}/>
              <MenuRow icon={<I.list s={14}/>} label="My grades" onClick={()=>go('grades')}/>
              <MenuRow icon={<I.cash s={14}/>} label="Billing" onClick={()=>go('finance')}/>
              <div style={{ height:1, background:'var(--line-2)', margin:'4px 8px' }}></div>
              <MenuRow icon={<I.out s={14}/>} label="Sign out" danger onClick={()=>setOpen(null)}/>
            </Dropdown>
          )}
        </div>
      </div>
    </header>
  );
}

function Dropdown({ title, children, footer, onFooter }) {
  return (
    <div style={{
      position:'absolute', right:0, top:'calc(100% + 10px)', zIndex:60,
      width:'min(320px, calc(100vw - 28px))',
      background:'#FFF', border:'1px solid var(--line)', borderRadius:14,
      boxShadow:'0 12px 40px rgba(60,20,10,.14), 0 2px 8px rgba(60,20,10,.06)',
      padding:6, animation:'ddIn .14s ease'
    }}>
      <style>{`@keyframes ddIn { from { opacity:0; transform: translateY(-4px); } to { opacity:1; transform:none; } }`}</style>
      {title && <div style={{ padding:'8px 12px 6px', fontSize:10.5, fontWeight:600, letterSpacing:'.14em', textTransform:'uppercase', color:'var(--muted)' }}>{title}</div>}
      {children}
      {footer && (
        <button onClick={onFooter} style={{ display:'flex', alignItems:'center', justifyContent:'center', gap:6, width:'100%', padding:'9px 12px', marginTop:4, borderTop:'1px solid var(--line-2)', fontSize:12.5, fontWeight:500, color:'var(--accent-ink)' }}>
          {footer} <I.arrow s={11}/>
        </button>
      )}
    </div>
  );
}

function MenuRow({ icon, label, hint, danger, onClick }) {
  return (
    <button onClick={onClick} style={{ display:'flex', alignItems:'center', gap:10, padding:'9px 12px', width:'100%', textAlign:'left', borderRadius:8, fontSize:13, color: danger ? 'var(--accent)' : 'var(--ink-2)', minHeight:38 }}
      onMouseEnter={e=>e.currentTarget.style.background='var(--surface-2)'}
      onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
      <span style={{ color: danger ? 'var(--accent)' : 'var(--muted)', display:'inline-flex' }}>{icon}</span>
      {label}
      {hint && <span className="mono" style={{ marginLeft:'auto', fontSize:10.5, color:'var(--muted)', background:'var(--surface-2)', padding:'1px 6px', borderRadius:4 }}>{hint}</span>}
    </button>
  );
}

function IconBtn({ children, badge, title, active, onClick }) {
  return (
    <button title={title} onClick={onClick} style={{
      position:'relative', width:38, height:38, borderRadius:9, display:'inline-flex',
      alignItems:'center', justifyContent:'center', color: active ? 'var(--ink)' : 'var(--ink-2)',
      background: active ? '#F2E7D9' : 'transparent',
      border: active ? '1px solid var(--line)' : '1px solid transparent'
    }}
    onMouseEnter={e=>{ if(!active) e.currentTarget.style.background='#F2E7D9'; }}
    onMouseLeave={e=>{ if(!active) e.currentTarget.style.background='transparent'; }}>
      {children}
      {badge && <span style={{ position:'absolute', top:5, right:5, minWidth:14, height:14, padding:'0 4px', borderRadius:99, background:'var(--warn)', color:'#FFF', fontSize:9.5, fontWeight:700, display:'inline-flex', alignItems:'center', justifyContent:'center' }}>{badge}</span>}
    </button>
  );
}

/* ============================================================
   HERO — greeting + next class
============================================================ */
function Hero() {
  const greeting = useMemo(()=> {
    const h=new Date().getHours();
    if (h<12) return 'Good morning';
    if (h<18) return 'Good afternoon';
    return 'Good evening';
  }, []);
  const today = new Date().toLocaleDateString('en-US', { weekday:'long', month:'long', day:'numeric' });

  return (
    <div className="hero-grid" style={{ display:'grid', gridTemplateColumns:'1.3fr 1fr', gap:20, alignItems:'stretch' }}>
      {/* Greeting */}
      <div style={{ padding:'12px 4px', minWidth:0 }}>
        <div style={{ display:'flex', alignItems:'center', gap:8, color:'var(--muted)', fontSize:12.5, flexWrap:'wrap' }}>
          <span className="mono">{today}</span>
          <span style={{ opacity:.5 }}>·</span>
          <span>Even week</span>
        </div>
        <h1 className="serif" style={{ margin:'10px 0 10px', fontSize:'clamp(34px, 4.4vw, 56px)', lineHeight:1.05, letterSpacing:'-0.02em', textWrap:'balance' }}>
          {greeting}, <em style={{ fontStyle:'italic' }}>Name.</em>
        </h1>
        <p style={{ margin:0, color:'var(--ink-2)', fontSize:15, maxWidth:520, lineHeight:1.55 }}>
          You have <strong>2 new announcements</strong> from your lecturers and <strong>one midterm</strong> next week. Enrollment for the winter semester opens <strong>June 2</strong>.
        </p>
        <div style={{ display:'flex', gap:8, marginTop:18, flexWrap:'wrap' }}>
          <button style={btnPrimary}>Open weekly timetable <I.arrow s={12}/></button>
          <button style={btnGhost}>Enroll in courses</button>
          <button style={btnGhost}>Documents <Pill tone="neutral" size="xs" style={{ marginLeft:6 }}>5</Pill></button>
        </div>
      </div>

      {/* Next class card */}
      <Card pad={0} style={{ overflow:'hidden', position:'relative', background:'oklch(0.32 0.12 25)', color:'#F6EDE4', border:'1px solid oklch(0.28 0.1 25)' }}>
        <div style={{
          position:'absolute', inset:0, opacity:.18,
          backgroundImage:'radial-gradient(circle at 20% 10%, oklch(0.55 0.2 30), transparent 45%), radial-gradient(circle at 90% 90%, oklch(0.35 0.15 15), transparent 55%)'
        }}></div>
        <div style={{ position:'absolute', inset:0, opacity:.06, pointerEvents:'none',
          backgroundImage:'repeating-linear-gradient(45deg, #fff 0 1px, transparent 1px 14px)' }}></div>
        <div style={{ position:'relative', padding:'22px 24px 24px' }}>
          <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', flexWrap:'wrap', gap:8 }}>
            <Pill tone="accent" size="sm" style={{ background:'rgba(255,255,255,.1)', color:'#F8D9C9', border:'1px solid rgba(255,255,255,.18)' }}>
              <I.dot style={{ background:'#F2B89A', boxShadow:'0 0 0 4px rgba(242,184,154,.2)' }}/> Next class
            </Pill>
            <span className="mono" style={{ fontSize:11.5, color:'rgba(246,237,228,.6)' }}>in ~ 47h</span>
          </div>
          <h2 className="serif" style={{ margin:'12px 0 2px', fontSize:30, lineHeight:1.1 }}>
            Mathematical <em style={{ fontStyle:'italic' }}>Statistics</em>
          </h2>
          <div style={{ fontSize:13, color:'rgba(246,237,228,.65)' }}>lab · Dr. K. Miller</div>

          <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:1, marginTop:18, background:'rgba(246,237,228,.12)', border:'1px solid rgba(246,237,228,.12)', borderRadius:10, overflow:'hidden' }}>
            <MetaCell k="When" v="Thu, May 28" sub="12:15 – 14:00"/>
            <MetaCell k="Room" v="B-204" sub="bldg. B, fl. 2"/>
            <MetaCell k="Online" v="Microsoft Teams" sub="link in course page"/>
          </div>

          <div style={{ display:'flex', gap:8, marginTop:14, flexWrap:'wrap' }}>
            <button style={{ ...btnPrimary, background:'#F6EDE4', color:'oklch(0.32 0.12 25)' }}>Join on Teams <I.ext s={11}/></button>
            <button style={{ ...btnGhost, background:'transparent', color:'#F6EDE4', borderColor:'rgba(246,237,228,.22)' }}>Details</button>
          </div>
        </div>
      </Card>
    </div>
  );
}

function MetaCell({ k, v, sub }) {
  return (
    <div style={{ padding:'12px 14px', background:'rgba(246,237,228,.03)' }}>
      <div style={{ fontSize:10.5, letterSpacing:'.14em', textTransform:'uppercase', color:'rgba(246,237,228,.6)' }}>{k}</div>
      <div style={{ fontSize:14.5, fontWeight:600, marginTop:4 }}>{v}</div>
      <div style={{ fontSize:11.5, color:'rgba(246,237,228,.55)' }}>{sub}</div>
    </div>
  );
}

/* ============================================================
   SCHEDULE
============================================================ */
function Schedule({ initialTab='online', dense=false }) {
  const [tab, setTab] = useState(initialTab);
  const filtered = useMemo(()=> {
    return upcoming.map(d => ({
      ...d,
      blocks: d.blocks.filter(b => {
        if (tab==='week') return true;
        if (tab==='online') return !!b.online;
        if (tab==='exams') return b.type==='midterm';
        return true;
      })
    })).filter(d => d.blocks.length>0);
  }, [tab]);

  return (
    <Card>
      <SectionLabel
        icon={<I.cal s={13}/>}
        action={
          <div style={{ display:'flex', gap:2, padding:2, background:'var(--surface-2)', borderRadius:8, border:'1px solid var(--line)', flexWrap:'wrap' }}>
            {[['online','Online classes'],['week','Full week'],['exams','Exams']].map(([k,l])=>(
              <button key={k} onClick={()=>setTab(k)} style={{
                padding:'4px 10px', fontSize:12, fontWeight: tab===k?600:450, borderRadius:6,
                background: tab===k ? '#FFF' : 'transparent',
                color: tab===k ? 'var(--ink)' : 'var(--muted)',
                boxShadow: tab===k ? '0 1px 2px rgba(60,20,20,.06)' : 'none',
                minHeight:28
              }}>{l}</button>
            ))}
          </div>
        }
      >{dense ? 'Weekly plan' : 'Upcoming classes'}</SectionLabel>

      <div style={{ display:'flex', flexDirection:'column', gap:18 }}>
        {filtered.length === 0 && (
          <div style={{ padding:'28px 16px', textAlign:'center', color:'var(--muted)', fontSize:13, background:'var(--surface-2)', borderRadius:11, border:'1px dashed var(--line)' }}>
            Nothing in this view — switch to <strong>Full week</strong> to see all classes.
          </div>
        )}
        {filtered.map((d, i) => (
          <div key={i}>
            <div style={{ display:'flex', alignItems:'center', gap:10, marginBottom:9 }}>
              <span className="mono" style={{ fontSize:11, color:'var(--muted)', letterSpacing:'.04em' }}>{d.when}</span>
              <span style={{ flex:1, height:1, background:'var(--line-2)' }}></span>
            </div>
            <div style={{ display:'flex', flexDirection:'column', gap:6 }}>
              {d.blocks.map((b, j) => <ClassRow key={j} {...b}/>)}
            </div>
          </div>
        ))}
      </div>

      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginTop:18, paddingTop:14, borderTop:'1px dashed var(--line-2)', flexWrap:'wrap', gap:8 }}>
        <div style={{ display:'flex', alignItems:'center', gap:8, fontSize:12, color:'var(--muted)' }}>
          <I.shield s={13}/> Online class times are set by the lecturer and may differ from the timetable.
        </div>
        <button style={{ fontSize:12.5, fontWeight:500, color:'var(--accent-ink)', display:'inline-flex', alignItems:'center', gap:4 }}>
          Open full timetable <I.arrow s={11}/>
        </button>
      </div>
    </Card>
  );
}

function ClassRow({ time, code, name, type, room, online, teacher }) {
  const onlineMap = {
    'Teams':   { bg:'oklch(0.94 0.04 270)', fg:'oklch(0.42 0.13 270)', label:'Teams' },
    'Inspera': { bg:'oklch(0.95 0.05 50)',  fg:'oklch(0.5 0.13 50)',  label:'Inspera' },
  };
  const o = online ? onlineMap[online] : null;
  const typeTone = type==='midterm' ? 'warn' : type==='lecture' ? 'info' : 'neutral';
  return (
    <div className="class-row" style={{
      display:'grid', gridTemplateColumns:'92px 1fr auto', gap:14,
      padding:'12px 14px', background:'var(--surface-2)', border:'1px solid var(--line)', borderRadius:11
    }}
    onMouseEnter={e=>e.currentTarget.style.background='#FCEFE0'}
    onMouseLeave={e=>e.currentTarget.style.background='var(--surface-2)'}>
      <div style={{ display:'flex', flexDirection:'column' }}>
        <span className="mono" style={{ fontSize:12, fontWeight:600, color:'var(--ink)' }}>{time.split('–')[0]}</span>
        <span className="mono" style={{ fontSize:11, color:'var(--muted)' }}>{time.split('–')[1]}</span>
      </div>
      <div style={{ minWidth:0 }}>
        <div style={{ display:'flex', alignItems:'center', gap:8, flexWrap:'wrap' }}>
          <span className="mono" style={{ fontSize:10.5, color:'var(--muted)', background:'#FFF', padding:'1px 6px', borderRadius:5, border:'1px solid var(--line)' }}>{code}</span>
          <span style={{ fontWeight:600, fontSize:14 }}>{name}</span>
          <Pill tone={typeTone} size="xs">{type}</Pill>
        </div>
        <div style={{ fontSize:12, color:'var(--muted)', marginTop:3 }}>
          {teacher} · room {room}
        </div>
      </div>
      <div style={{ display:'flex', alignItems:'center', gap:6 }}>
        {o ? (
          <span style={{ display:'inline-flex', alignItems:'center', gap:6, padding:'4px 9px', background:o.bg, color:o.fg, borderRadius:99, fontSize:11.5, fontWeight:500 }}>
            <I.dot style={{ background:'currentColor' }}/> {o.label}
          </span>
        ) : (
          <Pill tone="ghost" size="xs"><I.pin s={11}/> in person</Pill>
        )}
        <button style={{ padding:6, borderRadius:7, color:'var(--muted)', minWidth:32, minHeight:32 }}><I.ext/></button>
      </div>
    </div>
  );
}

/* ============================================================
   ANNOUNCEMENTS
============================================================ */
function Announcements() {
  const [filter, setFilter] = useState('all');
  return (
    <Card>
      <SectionLabel
        icon={<I.mega s={13}/>}
        action={
          <div style={{ display:'flex', alignItems:'center', gap:8, fontSize:12 }}>
            <button onClick={()=>setFilter('all')} style={{ color: filter==='all'?'var(--ink)':'var(--muted)', fontWeight: filter==='all'?600:450, minHeight:28 }}>All</button>
            <span style={{ color:'var(--line)' }}>·</span>
            <button onClick={()=>setFilter('unread')} style={{ color: filter==='unread'?'var(--ink)':'var(--muted)', fontWeight: filter==='unread'?600:450, minHeight:28 }}>Unread <Pill tone="warn" size="xs">2</Pill></button>
          </div>
        }
      >Latest announcements</SectionLabel>

      <div style={{ display:'flex', flexDirection:'column' }}>
        {announcements
          .filter(a => filter==='all' || a.unread)
          .map((a, i) => (
            <div key={i} style={{
              display:'grid', gridTemplateColumns:'auto 1fr auto', gap:14,
              padding:'14px 4px', borderTop: i===0 ? 'none' : '1px solid var(--line-2)',
              cursor:'pointer'
            }}>
              <div style={{ paddingTop:5 }}>
                <span style={{ width:8, height:8, borderRadius:99, display:'inline-block', background: a.unread ? 'var(--warn)' : '#E0D2BF' }}></span>
              </div>
              <div style={{ minWidth:0 }}>
                <div style={{ fontSize:11.5, color:'var(--muted)', display:'flex', gap:6, alignItems:'center' }}>
                  <I.book s={11}/>
                  <span style={{ whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{a.course}</span>
                </div>
                <div style={{ fontWeight: a.unread?600:550, fontSize:14.5, marginTop:2, color:'var(--ink)' }}>{a.subject}</div>
                <div style={{ color:'var(--ink-2)', fontSize:13, marginTop:4, lineHeight:1.5,
                  display:'-webkit-box', WebkitLineClamp:2, WebkitBoxOrient:'vertical', overflow:'hidden'
                }}>{a.body}</div>
                <div style={{ fontSize:11.5, color:'var(--muted)', marginTop:6 }}>{a.author} · {a.when}</div>
              </div>
              <button style={{ color:'var(--muted)', padding:'4px 6px', alignSelf:'flex-start' }}><I.arrow/></button>
            </div>
          ))}
      </div>
    </Card>
  );
}

/* ============================================================
   FILES
============================================================ */
const fileColors = {
  pdf:  { bg:'oklch(0.95 0.04 25)', fg:'oklch(0.45 0.15 25)' },
  pptx: { bg:'oklch(0.95 0.05 50)', fg:'oklch(0.45 0.14 50)' },
  docx: { bg:'oklch(0.95 0.04 240)', fg:'oklch(0.42 0.13 240)' },
  ino:  { bg:'oklch(0.95 0.05 200)', fg:'oklch(0.42 0.12 200)' },
  py:   { bg:'oklch(0.95 0.04 145)', fg:'oklch(0.4 0.1 145)' },
};

function FileGroup({ group, defaultOpen=false }) {
  const [open, setOpen] = useState(defaultOpen);
  return (
    <div style={{ borderBottom:'1px solid var(--line-2)' }}>
      <button onClick={()=>setOpen(o=>!o)} style={{
        display:'flex', alignItems:'center', gap:9, padding:'12px 4px',
        width:'100%', textAlign:'left', minHeight:44
      }}>
        <I.chev s={13} open={open}/>
        <span style={{ fontWeight:550, fontSize:13.5 }}>{group.course}</span>
        <span style={{ marginLeft:'auto', fontSize:11.5, color:'var(--muted)', whiteSpace:'nowrap' }}>{group.items.length} files</span>
      </button>
      {open && (
        <div style={{ display:'flex', flexDirection:'column', paddingBottom:8 }}>
          {group.items.map((f, i) => (
            <a key={i} href="#" style={{
              display:'grid', gridTemplateColumns:'28px 1fr auto auto', gap:10, alignItems:'center',
              padding:'7px 8px', borderRadius:8, minHeight:40
            }}
            onMouseEnter={e=>e.currentTarget.style.background='var(--surface-2)'}
            onMouseLeave={e=>e.currentTarget.style.background='transparent'}>
              <FileIcon kind={f.kind}/>
              <span style={{ fontSize:13, color:'var(--ink)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{f.name}</span>
              <span className="mono hide-mobile" style={{ fontSize:11, color:'var(--muted)' }}>{f.when}</span>
              <I.ext s={12} style={{ color:'var(--muted)' }}/>
            </a>
          ))}
        </div>
      )}
    </div>
  );
}

function FileIcon({ kind }) {
  const c = fileColors[kind] || { bg:'#F2E7D9', fg:'#6B5D52' };
  return (
    <span style={{
      width:28, height:28, borderRadius:7, background:c.bg, color:c.fg,
      display:'inline-flex', alignItems:'center', justifyContent:'center',
      fontSize:9, fontWeight:700, letterSpacing:'.04em', textTransform:'uppercase',
      fontFamily:'Geist Mono'
    }}>.{kind}</span>
  );
}

function Files() {
  return (
    <Card>
      <SectionLabel
        icon={<I.file s={13}/>}
        action={<button style={{ fontSize:12.5, fontWeight:500, color:'var(--accent-ink)', display:'inline-flex', alignItems:'center', gap:4 }}>Go to documents <I.arrow s={11}/></button>}
      >Latest files</SectionLabel>
      <div>
        {fileGroups.map((g, i) => <FileGroup key={i} group={g} defaultOpen={i===0}/>)}
      </div>
    </Card>
  );
}

/* ============================================================
   ACTIVITY
============================================================ */
function Activity() {
  const [showAll, setShowAll] = useState(false);
  const visible = showAll ? activity : activity.slice(0,5);
  return (
    <Card>
      <SectionLabel
        icon={<I.shield s={13}/>}
        action={<button onClick={()=>setShowAll(a=>!a)} style={{ fontSize:12.5, fontWeight:500, color:'var(--accent-ink)', minHeight:28 }}>{showAll?'Show less':'Show all'}</button>}
      >Account activity</SectionLabel>
      <div style={{ display:'flex', flexDirection:'column' }}>
        {visible.map((a, i) => (
          <div key={i} style={{
            display:'grid', gridTemplateColumns:'auto 1fr auto', gap:12, alignItems:'center',
            padding:'9px 0', borderTop: i===0 ? 'none' : '1px solid var(--line-2)'
          }}>
            <span style={{
              width:7, height:7, borderRadius:99,
              background: a.status==='bad' ? 'var(--warn)' : 'var(--green)'
            }}></span>
            <div style={{ minWidth:0 }}>
              <div style={{ fontSize:12.5, color:'var(--ink-2)', fontWeight:500 }}>{a.browser} <span className="mono hide-mobile" style={{ fontSize:11, color:'var(--muted)', fontWeight:400 }}> · {a.when}</span></div>
              <div className="mono" style={{ fontSize:11, color:'var(--muted)', whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{a.host}</div>
            </div>
            <Pill tone={a.status==='bad' ? 'warn' : 'neutral'} size="xs">
              {a.status==='bad' ? 'failed' : 'signed in'}
            </Pill>
          </div>
        ))}
      </div>
    </Card>
  );
}

/* ============================================================
   NEWS, EVENTS, SOCIAL
============================================================ */
function NewsBoard() {
  return (
    <Card>
      <SectionLabel
        icon={<I.star s={13}/>}
        action={<button style={{ fontSize:12.5, fontWeight:500, color:'var(--accent-ink)' }}>All news</button>}
      >School news</SectionLabel>

      <div className="news-grid" style={{ display:'grid', gridTemplateColumns:'1.1fr 1fr', gap:18 }}>
        {/* Events */}
        <div>
          <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', letterSpacing:'.14em', textTransform:'uppercase', marginBottom:10 }}>Events</div>
          <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
            {events.map((e, i) => (
              <div key={i} style={{
                display:'grid', gridTemplateColumns:'48px 1fr auto', gap:12, alignItems:'center',
                padding:'10px 12px', background:'var(--surface-2)', borderRadius:11, border:'1px solid var(--line)'
              }}>
                <div style={{ textAlign:'center', borderRight:'1px dashed var(--line)', paddingRight:10 }}>
                  <div className="serif" style={{ fontSize:20, lineHeight:1 }}>{e.date.split(' ')[1]}</div>
                  <div className="mono" style={{ fontSize:9.5, color:'var(--muted)', textTransform:'uppercase' }}>{e.date.split(' ')[0]}</div>
                </div>
                <div style={{ minWidth:0 }}>
                  <div style={{ fontSize:13.5, fontWeight:550, lineHeight:1.35 }}>{e.title}</div>
                  <div style={{ fontSize:11.5, color:'var(--muted)', marginTop:3 }}><span className="mono">{e.time}</span> · {e.tag}</div>
                </div>
                <button style={{ color:'var(--muted)', padding:6 }}><I.arrow/></button>
              </div>
            ))}
          </div>

          <div style={{ fontSize:11, fontWeight:600, color:'var(--muted)', letterSpacing:'.14em', textTransform:'uppercase', margin:'18px 0 10px' }}>School notices</div>
          <div style={{ display:'flex', flexDirection:'column', gap:2 }}>
            {news.map((n, i) => (
              <a key={i} href="#" style={{
                display:'grid', gridTemplateColumns:'auto 1fr auto', gap:10, alignItems:'center',
                padding:'9px 4px', borderTop: i===0 ? 'none' : '1px dashed var(--line-2)'
              }}>
                <Pill tone="ghost" size="xs">{n.kind}</Pill>
                <span style={{ fontSize:13, color:'var(--ink-2)' }}>{n.title}</span>
                <I.arrow s={11} style={{ color:'var(--muted)' }}/>
              </a>
            ))}
          </div>
        </div>

        {/* Social */}
        <div>
          <div style={{ display:'flex', alignItems:'center', gap:8, marginBottom:10 }}>
            <span style={{ fontSize:11, fontWeight:600, color:'var(--muted)', letterSpacing:'.14em', textTransform:'uppercase' }}>School online</span>
            <div style={{ flex:1, height:1, background:'var(--line-2)' }}></div>
            <span className="mono" style={{ fontSize:10.5, color:'var(--muted)' }}>live</span>
          </div>
          <SocialGrid/>
        </div>
      </div>
    </Card>
  );
}

function SocialGrid() {
  const tiles = [
    { tag:'IG', seed:'campus-lecture', text:'Explore the Computer Science specializations' },
    { tag:'IG', seed:'laptop-code', text:'If you are into more than just graphics…' },
    { tag:'IG', seed:'design-studio', text:'Positive accreditation review for Graphic Design' },
    { tag:'IG', seed:'open-day', text:'Come to the Open Day and see for yourself…' },
    { tag:'TT', seed:'students-talk', text:'Like taking the lead? Hear from our graduates.' },
    { tag:'IG', seed:'gallery-night', text:'Reminder: exhibition opening tomorrow evening' },
  ];
  return (
    <div className="social-grid" style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr', gap:8 }}>
      {tiles.map((t, i) => (
        <a key={i} href="#" style={{ borderRadius:11, border:'1px solid var(--line)', overflow:'hidden', background:'#FFF', display:'block' }}>
          <div style={{ aspectRatio:'1 / 1.05', position:'relative', background:'var(--surface-2)' }}>
            <img
              src={`https://picsum.photos/seed/${t.seed}/400/420`}
              alt={t.text}
              loading="lazy"
              style={{ position:'absolute', inset:0, width:'100%', height:'100%', objectFit:'cover', display:'block' }}
            />
            <span style={{ position:'absolute', top:8, left:8, padding:'2px 6px', background:'rgba(255,255,255,.92)', borderRadius:5, fontSize:10, fontWeight:700, letterSpacing:'.06em', color:'var(--ink-2)' }}>
              {t.tag}
            </span>
          </div>
          <div style={{ padding:'8px 10px 10px', fontSize:11.5, color:'var(--ink-2)', lineHeight:1.4,
            display:'-webkit-box', WebkitLineClamp:2, WebkitBoxOrient:'vertical', overflow:'hidden'
          }}>{t.text}</div>
        </a>
      ))}
    </div>
  );
}

/* ============================================================
   CONTACT FOOTER
============================================================ */
function ContactFooter() {
  const items = [
    { tag:'ACCOUNT', label:'Locked or inactive account', value:'passwords@school.edu', icon:<I.shield/> },
    { tag:'E-MAIL', label:'Mailbox issues', value:'mail-support@school.edu', icon:<I.mail/> },
    { tag:'DEAN\u2019S OFFICE', label:'Graphic Design · Computer Science', value:'cs-office@school.edu', icon:<I.book/> },
    { tag:'DEAN\u2019S OFFICE', label:'IT Management · Management', value:'mgmt-office@school.edu', icon:<I.book/> },
  ];
  return (
    <Card>
      <SectionLabel icon={<I.help s={13}/>}>Contact — when something breaks</SectionLabel>
      <div className="contact-grid" style={{ display:'grid', gridTemplateColumns:'repeat(4, 1fr)', gap:10 }}>
        {items.map((c, i) => (
          <a key={i} href={`mailto:${c.value}`} style={{
            display:'flex', flexDirection:'column', gap:6, padding:'14px 14px',
            background:'var(--surface-2)', borderRadius:11, border:'1px solid var(--line)',
          }}>
            <div style={{ display:'flex', alignItems:'center', gap:8, color:'var(--muted)' }}>
              <span style={{ width:28, height:28, borderRadius:7, background:'#FFF', border:'1px solid var(--line)', display:'inline-flex', alignItems:'center', justifyContent:'center' }}>{c.icon}</span>
              <span style={{ fontSize:10.5, fontWeight:600, letterSpacing:'.14em', textTransform:'uppercase' }}>{c.tag}</span>
            </div>
            <div style={{ fontSize:13, fontWeight:550, color:'var(--ink)' }}>{c.label}</div>
            <div className="mono" style={{ fontSize:12, color:'var(--accent-ink)' }}>{c.value}</div>
          </a>
        ))}
      </div>
    </Card>
  );
}

/* ============================================================
   PAGE HEADER
============================================================ */
function PageHeader({ title, eyebrow, lead, action }) {
  return (
    <div className="page-header" style={{ display:'flex', alignItems:'flex-end', justifyContent:'space-between', gap:24, padding:'12px 4px' }}>
      <div>
        <div style={{ fontSize:11, fontWeight:600, color:'var(--accent-ink)', letterSpacing:'.14em', textTransform:'uppercase' }}>{eyebrow}</div>
        <h1 className="serif" style={{ margin:'4px 0 6px', fontSize:'clamp(30px, 3.5vw, 42px)', lineHeight:1.05, letterSpacing:'-.02em' }}>{title}</h1>
        {lead && <p style={{ margin:0, color:'var(--ink-2)', fontSize:14.5, maxWidth:600, lineHeight:1.55 }}>{lead}</p>}
      </div>
      {action}
    </div>
  );
}

/* Share with views file */
Object.assign(window, {
  I, me, upcoming, announcements, fileGroups, activity, events, news,
  navMain, navAccount,
  Pill, Card, SectionLabel, Avatar, btnPrimary, btnGhost,
  Sidebar, TopBar, Hero, Schedule, ClassRow, Announcements, Files, FileGroup,
  Activity, NewsBoard, ContactFooter, PageHeader,
});
