﻿/* Journey admin page */

/* Journey Page */
function JourneyPage({ tweaks, onBackHome }) {
  const primary = tweaks.primaryColor;
  const [code, setCode] = React.useState('');
  const [unlocked, setUnlocked] = React.useState(false);
  const [loading, setLoading] = React.useState(false);
  const [saving, setSaving] = React.useState(false);
  const [saveState, setSaveState] = React.useState('saved');
  const [error, setError] = React.useState('');
  const [data, setData] = React.useState(getDefaultJourneyData);
  const [newProgressTitle, setNewProgressTitle] = React.useState('');
  const [newProjectTitle, setNewProjectTitle] = React.useState('');
  const [newSkillName, setNewSkillName] = React.useState('');
  const [activeJourneyTab, setActiveJourneyTab] = React.useState('notes');

  const fieldStyle = {
    width: '100%',
    padding: '12px 14px',
    borderRadius: 12,
    background: 'rgba(var(--theme-bg-rgb),0.5)',
    border: '1px solid rgba(var(--theme-text-rgb),0.12)',
    color: 'var(--theme-text)',
    fontFamily: 'Poppins, sans-serif',
    fontSize: 14,
    outline: 'none',
  };

  const buttonStyle = (filled = true) => ({
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    gap: 8,
    padding: '11px 16px',
    borderRadius: 22,
    border: `1px solid ${filled ? primary : primary + '55'}`,
    background: filled ? primary : `${primary}12`,
    color: filled ? 'var(--theme-on-accent)' : primary,
    fontFamily: 'Poppins, sans-serif',
    fontWeight: 700,
    fontSize: 14,
    cursor: 'pointer',
    transition: 'all 0.25s ease',
    whiteSpace: 'nowrap',
  });

  const iconButtonStyle = {
    width: 40,
    height: 40,
    borderRadius: 12,
    border: '1px solid rgba(var(--theme-text-rgb),0.1)',
    background: 'rgba(var(--theme-surface-rgb),0.35)',
    color: 'rgba(var(--theme-text-rgb),0.8)',
    display: 'inline-flex',
    alignItems: 'center',
    justifyContent: 'center',
    cursor: 'pointer',
    flex: '0 0 auto',
  };

  const deleteButtonStyle = {
    ...iconButtonStyle,
    border: '1px solid rgba(255,82,82,0.24)',
    background: 'rgba(255,82,82,0.1)',
    color: '#FF6B6B',
  };

  const requestJourney = async (path, options = {}) => {
    const response = await fetch(`/api/journey${path}`, {
      ...options,
      headers: {
        'Content-Type': 'application/json',
        ...(options.headers || {}),
      },
    });
    const payload = await response.json().catch(() => ({}));

    if (!response.ok || payload.ok === false) {
      throw new Error(payload.error || 'Journey API error');
    }

    return payload;
  };

  const unlockJourney = async (candidateCode) => {
    const trimmedCode = candidateCode.trim();
    setLoading(true);
    setError('');

    try {
      const payload = await requestJourney('/verify', {
        method: 'POST',
        body: JSON.stringify({ code: trimmedCode }),
      });
      sessionStorage.setItem(JOURNEY_CODE_STORAGE_KEY, trimmedCode);
      setCode(trimmedCode);
      setData(normalizeJourneyData(payload.data));
      setUnlocked(true);
      setSaveState('saved');
    } catch (err) {
      sessionStorage.removeItem(JOURNEY_CODE_STORAGE_KEY);
      setUnlocked(false);
      setError(err.message === 'Invalid code' ? 'Code is not correct.' : err.message);
    } finally {
      setLoading(false);
    }
  };

  React.useEffect(() => {
    const savedCode = sessionStorage.getItem(JOURNEY_CODE_STORAGE_KEY);
    if (savedCode) unlockJourney(savedCode);
  }, []);

  const updateJourney = (updater) => {
    setData(prev => normalizeJourneyData(
      typeof updater === 'function' ? updater(prev) : { ...prev, ...updater }
    ));
    setSaveState('dirty');
    setError('');
  };

  const saveJourney = async () => {
    setSaving(true);
    setError('');

    try {
      const payload = await requestJourney('', {
        method: 'PUT',
        headers: { 'X-Journey-Code': code },
        body: JSON.stringify({ data }),
      });
      setData(normalizeJourneyData(payload.data));
      setSaveState('saved');
    } catch (err) {
      setError(err.message === 'Invalid code' ? 'Session code expired or changed.' : err.message);
      setSaveState('dirty');
    } finally {
      setSaving(false);
    }
  };

  const canLeaveJourney = () => saveState !== 'dirty' || window.confirm('Discard unsaved changes?');

  const lockJourney = () => {
    if (!canLeaveJourney()) return;

    sessionStorage.removeItem(JOURNEY_CODE_STORAGE_KEY);
    setUnlocked(false);
    setCode('');
  };

  const backHome = () => {
    if (canLeaveJourney()) onBackHome();
  };

  const addProgressItem = (event) => {
    event.preventDefault();
    const title = newProgressTitle.trim();
    if (!title) return;

    updateJourney(prev => ({
      ...prev,
      progress: [
        ...prev.progress,
        { id: createJourneyId(), title, status: 'Active', progress: 0 },
      ],
    }));
    setNewProgressTitle('');
  };

  const updateProgressItem = (id, patch) => {
    updateJourney(prev => ({
      ...prev,
      progress: prev.progress.map(item => item.id === id ? { ...item, ...patch } : item),
    }));
  };

  const removeProgressItem = (id) => {
    updateJourney(prev => ({
      ...prev,
      progress: prev.progress.filter(item => item.id !== id),
    }));
  };

  const addProjectItem = (event) => {
    event.preventDefault();
    const title = newProjectTitle.trim();
    if (!title) return;

    updateJourney(prev => ({
      ...prev,
      projects: [
        ...prev.projects,
        { id: createJourneyId(), title, summary: '', nextStep: '' },
      ],
    }));
    setNewProjectTitle('');
  };

  const updateProjectItem = (id, patch) => {
    updateJourney(prev => ({
      ...prev,
      projects: prev.projects.map(item => item.id === id ? { ...item, ...patch } : item),
    }));
  };

  const removeProjectItem = (id) => {
    updateJourney(prev => ({
      ...prev,
      projects: prev.projects.filter(item => item.id !== id),
    }));
  };

  const addSkillItem = (event) => {
    event.preventDefault();
    const name = newSkillName.trim();
    if (!name) return;

    updateJourney(prev => ({
      ...prev,
      skills: [
        ...prev.skills,
        { id: createJourneyId(), name, level: 'Learning', progress: 0, focus: '' },
      ],
    }));
    setNewSkillName('');
  };

  const updateSkillItem = (id, patch) => {
    updateJourney(prev => ({
      ...prev,
      skills: prev.skills.map(item => item.id === id ? { ...item, ...patch } : item),
    }));
  };

  const removeSkillItem = (id) => {
    updateJourney(prev => ({
      ...prev,
      skills: prev.skills.filter(item => item.id !== id),
    }));
  };

  const averageProgress = data.progress.length
    ? Math.round(data.progress.reduce((sum, item) => sum + clampProgress(item.progress), 0) / data.progress.length)
    : 0;
  const activeSkills = data.skills.filter(skill => skill.level !== 'Paused').length;
  const projectCount = data.projects.length;
  const journeyTabs = [
    { id: 'notes', label: 'Notes', count: data.notes.trim() ? '1' : '0' },
    { id: 'progress', label: 'Progress', count: data.progress.length },
    { id: 'projects', label: 'Projects', count: projectCount },
    { id: 'skills', label: 'Skills', count: data.skills.length },
  ];

  if (!unlocked) {
    return (
      <main className="journey-page" style={{
        minHeight: '100vh',
        padding: '124px 80px 80px',
        background: 'var(--theme-bg)',
        color: 'var(--theme-text)',
        position: 'relative',
        overflow: 'hidden',
      }}>
        <DoodleBrackets style={{ position: 'absolute', top: 150, left: 70 }} color={primary}/>
        <DoodleCode style={{ position: 'absolute', top: 220, right: 110 }} color={primary}/>
        <DoodleCircle style={{ position: 'absolute', bottom: 140, right: 160 }} color={primary} size={86}/>

        <div className="journey-lock" style={{
          maxWidth: 520,
          margin: '8vh auto 0',
          padding: 34,
          borderRadius: 20,
          background: 'rgba(var(--theme-surface-rgb),0.24)',
          border: '1px solid rgba(var(--theme-text-rgb),0.08)',
          boxShadow: '0 24px 60px rgba(0,0,0,0.24)',
          position: 'relative',
          zIndex: 1,
        }}>
          <div style={{
            width: 54,
            height: 54,
            borderRadius: 16,
            background: `${primary}18`,
            color: primary,
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'center',
            marginBottom: 22,
          }}>
            <svg width="25" height="25" viewBox="0 0 24 24" fill="none"
              stroke="currentColor" strokeWidth="2.2" strokeLinecap="round" strokeLinejoin="round">
              <path d="M7 11V8a5 5 0 0110 0v3M6 11h12a1 1 0 011 1v8a1 1 0 01-1 1H6a1 1 0 01-1-1v-8a1 1 0 011-1z"/>
            </svg>
          </div>
          <div style={{
            fontSize: 12,
            fontWeight: 700,
            color: primary,
            letterSpacing: '3px',
            textTransform: 'uppercase',
            marginBottom: 10,
          }}>Private workspace</div>
          <h1 style={{
            fontFamily: 'Poppins, sans-serif',
            fontWeight: 700,
            fontSize: 'clamp(34px, 5vw, 52px)',
            color: 'var(--theme-strong)',
            lineHeight: 1.05,
            margin: '0 0 14px',
          }}>Journey</h1>
          <p style={{
            color: 'rgba(var(--theme-text-rgb),0.68)',
            fontSize: 15,
            lineHeight: 1.7,
            margin: '0 0 26px',
          }}>
            Enter the 32-character server code to open notes, progress, and learning skills.
          </p>

          <form onSubmit={(event) => {
            event.preventDefault();
            unlockJourney(code);
          }} style={{ display: 'flex', flexDirection: 'column', gap: 14 }}>
            <input
              value={code}
              onChange={event => setCode(event.target.value)}
              placeholder="32-character secret code"
              autoComplete="off"
              spellCheck="false"
              style={{ ...fieldStyle, fontSize: 16, letterSpacing: '1px' }}
            />
            {error && (
              <div style={{
                padding: '10px 12px',
                borderRadius: 12,
                background: 'rgba(255,82,82,0.12)',
                color: '#FF8A8A',
                fontSize: 13,
                border: '1px solid rgba(255,82,82,0.22)',
              }}>{error}</div>
            )}
            <div style={{ display: 'flex', gap: 12, flexWrap: 'wrap', marginTop: 4 }}>
              <button type="submit" disabled={loading || code.trim().length !== 32} style={{
                ...buttonStyle(true),
                opacity: loading || code.trim().length !== 32 ? 0.55 : 1,
              }}>
                {loading ? 'Checking...' : 'Unlock'}
                <svg width="17" height="17" viewBox="0 0 24 24" fill="none"
                  stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
                  <path d="M5 12h14M12 5l7 7-7 7"/>
                </svg>
              </button>
              <button type="button" onClick={backHome} style={buttonStyle(false)}>Back home</button>
            </div>
          </form>
        </div>
      </main>
    );
  }

  return (
    <main className="journey-page" style={{
      minHeight: '100vh',
      padding: '118px clamp(24px, 3vw, 56px) 80px',
      background: 'var(--theme-bg)',
      color: 'var(--theme-text)',
      position: 'relative',
      overflow: 'hidden',
      animation: 'fadeIn 0.3s ease',
    }}>
      <DoodleArrow style={{ position: 'absolute', top: 160, left: 55, transform: 'rotate(-18deg)' }} color={primary}/>
      <DoodleChart style={{ position: 'absolute', top: 210, right: 90 }} color={primary}/>
      <DoodleStar style={{ position: 'absolute', bottom: 140, left: 110 }} color={primary} size={30}/>
      <DoodleBrackets style={{ position: 'absolute', top: 420, left: '5%' }} color={primary}/>
      <DoodleCode style={{ position: 'absolute', bottom: 310, right: '6%', transform: 'rotate(10deg)' }} color={primary}/>
      <DoodleCircle style={{ position: 'absolute', top: '52%', left: '2%' }} color={primary} size={68}/>
      <DoodleStar style={{ position: 'absolute', top: '42%', right: '28%' }} color={primary} size={22}/>
      <DoodleCircle style={{ position: 'absolute', bottom: 70, right: '20%' }} color={primary} size={42}/>

      <div className="journey-shell" style={{ maxWidth: 1480, margin: '0 auto', position: 'relative', zIndex: 1 }}>
        <div className="journey-header" style={{
          display: 'flex',
          alignItems: 'flex-start',
          justifyContent: 'space-between',
          gap: 24,
          marginBottom: 28,
        }}>
          <div>
            <div style={{
              fontSize: 12,
              fontWeight: 700,
              color: primary,
              letterSpacing: '3px',
              textTransform: 'uppercase',
              marginBottom: 10,
            }}>Personal journey</div>
            <h1 style={{
              fontFamily: 'Poppins, sans-serif',
              fontWeight: 700,
              fontSize: 'clamp(40px, 5vw, 64px)',
              color: 'var(--theme-strong)',
              margin: '0 0 12px',
              lineHeight: 1.05,
            }}>Journey</h1>
            <div style={{ color: 'rgba(var(--theme-text-rgb),0.58)', fontSize: 14 }}>
              {saveState === 'dirty'
                ? 'Unsaved changes'
                : data.updatedAt
                ? `Last saved ${new Date(data.updatedAt).toLocaleString()}`
                : 'Not saved yet'}
            </div>
          </div>

          <div className="journey-actions" style={{ display: 'flex', gap: 12, flexWrap: 'wrap', justifyContent: 'flex-end' }}>
            <button type="button" onClick={saveJourney} disabled={saving || saveState !== 'dirty'} style={{
              ...buttonStyle(true),
              opacity: saving || saveState !== 'dirty' ? 0.6 : 1,
            }}>
              {saving ? 'Saving...' : saveState === 'dirty' ? 'Save changes' : 'Saved'}
              <svg width="17" height="17" viewBox="0 0 24 24" fill="none"
                stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round">
                <path d={saveState === 'dirty' ? 'M19 21H5a2 2 0 01-2-2V5a2 2 0 012-2h11l5 5v11a2 2 0 01-2 2zM7 21v-8h10v8M7 3v5h8' : 'M5 12l5 5L20 7'}/>
              </svg>
            </button>
            <button type="button" onClick={lockJourney} style={buttonStyle(false)}>Lock</button>
            <button type="button" onClick={backHome} style={buttonStyle(false)}>Back home</button>
          </div>
        </div>

        {error && (
          <div style={{
            padding: '12px 14px',
            borderRadius: 14,
            background: 'rgba(255,82,82,0.12)',
            color: '#FF8A8A',
            fontSize: 13,
            border: '1px solid rgba(255,82,82,0.22)',
            marginBottom: 22,
          }}>{error}</div>
        )}

        <div className="journey-stats" style={{
          display: 'grid',
          gridTemplateColumns: 'repeat(4, minmax(0, 1fr))',
          gap: 16,
          marginBottom: 24,
        }}>
          <JourneyStat label="Notes" value={`${data.notes.length} chars`} color={primary}
            icon="M4 4h16v16H4zM8 8h8M8 12h8M8 16h5"/>
          <JourneyStat label="Average progress" value={`${averageProgress}%`} color={primary}
            icon="M4 19V5M4 19h16M8 16v-5M12 16V8M16 16v-8"/>
          <JourneyStat label="Projects" value={projectCount} color={primary}
            icon="M3 7v10a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-6l-2-2H5a2 2 0 00-2 2z"/>
          <JourneyStat label="Learning skills" value={activeSkills} color={primary}
            icon="M12 3l8 4-8 4-8-4zM4 11l8 4 8-4M4 15l8 4 8-4"/>
        </div>

        <div className="journey-tabs" style={{
          display: 'flex',
          gap: 10,
          flexWrap: 'wrap',
          padding: 6,
          borderRadius: 18,
          background: 'rgba(var(--theme-surface-rgb),0.18)',
          border: '1px solid rgba(var(--theme-text-rgb),0.08)',
          marginBottom: 24,
        }}>
          {journeyTabs.map(tab => (
            <JourneyTabButton
              key={tab.id}
              tab={tab}
              active={activeJourneyTab === tab.id}
              color={primary}
              onClick={() => setActiveJourneyTab(tab.id)}
            />
          ))}
        </div>

        <div className="journey-tab-content">
          {activeJourneyTab === 'notes' && (
            <JourneyPanel title="Notes" eyebrow="Ideas and reminders" color={primary}>
              <textarea
                value={data.notes}
                onChange={event => updateJourney({ notes: event.target.value })}
                placeholder="Write what you need to remember, think through, or review later..."
                rows={24}
                style={{
                  ...fieldStyle,
                  minHeight: 620,
                  resize: 'vertical',
                  lineHeight: 1.7,
                  fontSize: 15,
                }}
              />
            </JourneyPanel>
          )}

          {activeJourneyTab === 'progress' && (
            <JourneyPanel title="Progress" eyebrow="Tracking" color={primary}>
              <form onSubmit={addProgressItem} style={{ display: 'flex', gap: 10, marginBottom: 18 }}>
                <input
                  value={newProgressTitle}
                  onChange={event => setNewProgressTitle(event.target.value)}
                  placeholder="Add progress item"
                  style={fieldStyle}
                />
                <JourneyAddButton color={primary}>Add</JourneyAddButton>
              </form>

              <div className="journey-tab-list" style={{
                display: 'grid',
                gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
                gap: 14,
              }}>
                {data.progress.length === 0 && <JourneyEmpty text="No progress items yet."/>}
                {data.progress.map(item => (
                  <div key={item.id} style={{
                    padding: 16,
                    borderRadius: 16,
                    background: 'rgba(var(--theme-bg-rgb),0.34)',
                    border: '1px solid rgba(var(--theme-text-rgb),0.08)',
                  }}>
                    <div className="journey-item-row" style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) 138px 40px', gap: 10 }}>
                      <input
                        value={item.title}
                        onChange={event => updateProgressItem(item.id, { title: event.target.value })}
                        style={fieldStyle}
                      />
                      <JourneyStatusDropdown
                        value={item.status}
                        onChange={status => updateProgressItem(item.id, { status })}
                      />
                      <JourneyDeleteButton
                        onClick={() => removeProgressItem(item.id)}
                        ariaLabel="Remove progress item"
                        style={deleteButtonStyle}
                      >
                        <TrashIcon/>
                      </JourneyDeleteButton>
                    </div>
                    <JourneyProgressInput
                      value={item.progress}
                      onChange={value => updateProgressItem(item.id, { progress: value })}
                      color={primary}
                      fieldStyle={fieldStyle}
                    />
                  </div>
                ))}
              </div>
            </JourneyPanel>
          )}

          {activeJourneyTab === 'projects' && (
            <JourneyPanel title="Projects" eyebrow="Content notes" color={primary}>
              <form onSubmit={addProjectItem} style={{ display: 'flex', gap: 10, marginBottom: 18 }}>
                <input
                  value={newProjectTitle}
                  onChange={event => setNewProjectTitle(event.target.value)}
                  placeholder="Add project"
                  style={fieldStyle}
                />
                <JourneyAddButton color={primary}>Add</JourneyAddButton>
              </form>

              <div className="journey-tab-list" style={{
                display: 'grid',
                gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
                gap: 14,
              }}>
                {data.projects.length === 0 && <JourneyEmpty text="No project content yet."/>}
                {data.projects.map(project => (
                  <div key={project.id} style={{
                    padding: 16,
                    borderRadius: 16,
                    background: 'rgba(var(--theme-bg-rgb),0.34)',
                    border: '1px solid rgba(var(--theme-text-rgb),0.08)',
                  }}>
                    <div style={{ display: 'grid', gridTemplateColumns: 'minmax(0, 1fr) 40px', gap: 10, marginBottom: 10 }}>
                      <input
                        value={project.title}
                        onChange={event => updateProjectItem(project.id, { title: event.target.value })}
                        placeholder="Project title"
                        style={fieldStyle}
                      />
                      <JourneyDeleteButton
                        onClick={() => removeProjectItem(project.id)}
                        ariaLabel="Remove project"
                        style={deleteButtonStyle}
                      >
                        <TrashIcon/>
                      </JourneyDeleteButton>
                    </div>
                    <textarea
                      value={project.summary}
                      onChange={event => updateProjectItem(project.id, { summary: event.target.value })}
                      placeholder="Project content, decisions, context..."
                      rows={5}
                      style={{ ...fieldStyle, resize: 'vertical', lineHeight: 1.6, marginBottom: 10 }}
                    />
                    <input
                      value={project.nextStep}
                      onChange={event => updateProjectItem(project.id, { nextStep: event.target.value })}
                      placeholder="Next step"
                      style={fieldStyle}
                    />
                  </div>
                ))}
              </div>
            </JourneyPanel>
          )}

          {activeJourneyTab === 'skills' && (
            <JourneyPanel title="Skills" eyebrow="Currently learning" color={primary}>
              <form onSubmit={addSkillItem} style={{ display: 'flex', gap: 10, marginBottom: 18 }}>
                <input
                  value={newSkillName}
                  onChange={event => setNewSkillName(event.target.value)}
                  placeholder="Add skill"
                  style={fieldStyle}
                />
                <JourneyAddButton color={primary}>Add</JourneyAddButton>
              </form>

              <div className="journey-tab-list" style={{
                display: 'grid',
                gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
                gap: 14,
              }}>
                {data.skills.length === 0 && <JourneyEmpty text="No skills added yet."/>}
                {data.skills.map(skill => (
                  <div key={skill.id} style={{
                    padding: 16,
                    borderRadius: 16,
                    background: 'rgba(var(--theme-bg-rgb),0.34)',
                    border: '1px solid rgba(var(--theme-text-rgb),0.08)',
                  }}>
                    <div className="journey-item-row" style={{ display: 'grid', gridTemplateColumns: '1fr 124px 40px', gap: 10, marginBottom: 10 }}>
                      <input
                        value={skill.name}
                        onChange={event => updateSkillItem(skill.id, { name: event.target.value })}
                        style={fieldStyle}
                      />
                      <select
                        value={skill.level}
                        onChange={event => updateSkillItem(skill.id, { level: event.target.value })}
                        style={fieldStyle}
                      >
                        <option>Learning</option>
                        <option>Practicing</option>
                        <option>Confident</option>
                        <option>Paused</option>
                      </select>
                      <JourneyDeleteButton
                        onClick={() => removeSkillItem(skill.id)}
                        ariaLabel="Remove skill"
                        style={deleteButtonStyle}
                      >
                        <TrashIcon/>
                      </JourneyDeleteButton>
                    </div>
                    <input
                      value={skill.focus}
                      onChange={event => updateSkillItem(skill.id, { focus: event.target.value })}
                      placeholder="Focus area"
                      style={{ ...fieldStyle, marginBottom: 10 }}
                    />
                    <JourneyProgressInput
                      value={skill.progress}
                      onChange={value => updateSkillItem(skill.id, { progress: value })}
                      color={primary}
                      fieldStyle={fieldStyle}
                    />
                  </div>
                ))}
              </div>
            </JourneyPanel>
          )}
        </div>
      </div>
    </main>
  );
}

function JourneyTabButton({ tab, active, color, onClick }) {
  const [hovered, setHovered] = React.useState(false);

  return (
    <button
      type="button"
      onClick={onClick}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      style={{
        minHeight: 42,
        display: 'inline-flex',
        alignItems: 'center',
        gap: 10,
        padding: '10px 16px',
        borderRadius: 14,
        border: `1px solid ${active ? color : 'rgba(var(--theme-text-rgb),0.1)'}`,
        background: active
          ? color
          : hovered
          ? 'rgba(var(--theme-surface-rgb),0.34)'
          : 'transparent',
        color: active ? 'var(--theme-on-accent)' : 'var(--theme-text)',
        fontFamily: 'Poppins, sans-serif',
        fontWeight: 700,
        fontSize: 14,
        cursor: 'pointer',
        transition: 'all 0.2s ease',
      }}
    >
      {tab.label}
      <span style={{
        minWidth: 24,
        height: 22,
        padding: '0 7px',
        borderRadius: 999,
        display: 'inline-flex',
        alignItems: 'center',
        justifyContent: 'center',
        background: active ? 'rgba(13,27,42,0.14)' : `${color}18`,
        color: active ? 'var(--theme-on-accent)' : color,
        fontSize: 12,
        fontWeight: 800,
        fontVariantNumeric: 'tabular-nums',
      }}>{tab.count}</span>
    </button>
  );
}

function JourneyPanel({ title, eyebrow, color, children }) {
  return (
    <section className="journey-panel" style={{
      padding: 24,
      borderRadius: 20,
      background: 'rgba(var(--theme-surface-rgb),0.22)',
      border: '1px solid rgba(var(--theme-text-rgb),0.08)',
      boxShadow: '0 18px 50px rgba(0,0,0,0.16)',
    }}>
      <div style={{ marginBottom: 18 }}>
        <div style={{
          color,
          fontSize: 11,
          fontWeight: 700,
          letterSpacing: '2px',
          textTransform: 'uppercase',
          marginBottom: 7,
        }}>{eyebrow}</div>
        <h2 style={{
          fontFamily: 'Poppins, sans-serif',
          fontWeight: 700,
          fontSize: 24,
          color: 'var(--theme-strong)',
          margin: 0,
        }}>{title}</h2>
      </div>
      {children}
    </section>
  );
}

function JourneyStat({ label, value, icon, color }) {
  return (
    <div style={{
      display: 'flex',
      alignItems: 'center',
      gap: 14,
      padding: 18,
      borderRadius: 18,
      background: 'rgba(var(--theme-surface-rgb),0.22)',
      border: '1px solid rgba(var(--theme-text-rgb),0.08)',
    }}>
      <div style={{
        width: 44,
        height: 44,
        borderRadius: 14,
        background: `${color}18`,
        color,
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'center',
        flex: '0 0 auto',
      }}>
        <svg width="21" height="21" viewBox="0 0 24 24" fill="none"
          stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <path d={icon}/>
        </svg>
      </div>
      <div>
        <div style={{ color: 'var(--theme-strong)', fontWeight: 700, fontSize: 22, lineHeight: 1 }}>{value}</div>
        <div style={{ color: 'rgba(var(--theme-text-rgb),0.58)', fontSize: 13, marginTop: 5 }}>{label}</div>
      </div>
    </div>
  );
}

function JourneyAddButton({ color, children }) {
  const [hovered, setHovered] = React.useState(false);

  return (
    <button
      type="submit"
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      style={{
        display: 'inline-flex',
        alignItems: 'center',
        justifyContent: 'center',
        gap: 8,
        padding: '11px 16px',
        borderRadius: 22,
        border: `1px solid ${hovered ? '#FFF' : color}`,
        background: hovered ? '#FFF' : color,
        color: 'var(--theme-on-accent)',
        fontFamily: 'Poppins, sans-serif',
        fontWeight: 700,
        fontSize: 14,
        cursor: 'pointer',
        whiteSpace: 'nowrap',
        transform: hovered ? 'translateY(-2px)' : 'translateY(0)',
        boxShadow: hovered ? `0 10px 24px ${color}30` : 'none',
        transition: 'all 0.2s ease',
      }}
    >
      {children}
      <svg width="16" height="16" viewBox="0 0 24 24" fill="none"
        stroke="currentColor" strokeWidth="2.5" strokeLinecap="round">
        <path d="M12 5v14M5 12h14"/>
      </svg>
    </button>
  );
}

function JourneyDeleteButton({ onClick, ariaLabel, style, children }) {
  const [hovered, setHovered] = React.useState(false);

  return (
    <button
      type="button"
      onClick={onClick}
      aria-label={ariaLabel}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      style={{
        ...style,
        background: hovered ? '#FF5252' : style.background,
        borderColor: hovered ? '#FF5252' : 'rgba(255,82,82,0.24)',
        color: hovered ? '#FFF' : '#FF6B6B',
        transform: hovered ? 'translateY(-1px)' : 'translateY(0)',
        boxShadow: hovered ? '0 10px 22px rgba(255,82,82,0.24)' : 'none',
        transition: 'all 0.2s ease',
      }}
    >
      {children}
    </button>
  );
}

function JourneyStatusDropdown({ value, onChange }) {
  const [open, setOpen] = React.useState(false);
  const current = getJourneyStatusOption(value);

  return (
    <div
      style={{ position: 'relative' }}
      onBlur={(event) => {
        if (!event.currentTarget.contains(event.relatedTarget)) setOpen(false);
      }}
    >
      <button
        type="button"
        onClick={() => setOpen(prev => !prev)}
        style={{
          width: '100%',
          height: 42,
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'space-between',
          gap: 10,
          padding: '0 12px',
          borderRadius: 14,
          border: `1px solid ${current.color}45`,
          background: `linear-gradient(135deg, ${current.bg}, rgba(var(--theme-bg-rgb),0.5))`,
          color: current.color,
          fontFamily: 'Poppins, sans-serif',
          fontSize: 13,
          fontWeight: 700,
          cursor: 'pointer',
          boxShadow: open ? `0 0 0 3px ${current.color}18` : 'none',
          transition: 'all 0.2s ease',
        }}
      >
        <span style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
          <span style={{
            width: 8,
            height: 8,
            borderRadius: '50%',
            background: current.color,
            boxShadow: `0 0 0 4px ${current.bg}`,
            flex: '0 0 auto',
          }}/>
          <span style={{ overflow: 'hidden', textOverflow: 'ellipsis' }}>{current.label}</span>
        </span>
        <svg width="15" height="15" viewBox="0 0 24 24" fill="none"
          stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round"
          style={{ transform: open ? 'rotate(180deg)' : 'rotate(0deg)', transition: 'transform 0.2s ease' }}>
          <path d="M6 9l6 6 6-6"/>
        </svg>
      </button>

      {open && (
        <div style={{
          position: 'absolute',
          left: 0,
          right: 0,
          top: 48,
          zIndex: 40,
          padding: 6,
          borderRadius: 16,
          background: 'rgba(var(--theme-bg-rgb),0.96)',
          border: '1px solid rgba(var(--theme-text-rgb),0.12)',
          boxShadow: '0 18px 40px rgba(0,0,0,0.28)',
          backdropFilter: 'blur(14px)',
        }}>
          {JOURNEY_STATUS_OPTIONS.map(option => (
            <button
              key={option.value}
              type="button"
              onClick={() => {
                onChange(option.value);
                setOpen(false);
              }}
              style={{
                width: '100%',
                display: 'flex',
                alignItems: 'center',
                gap: 9,
                padding: '9px 10px',
                border: 'none',
                borderRadius: 11,
                background: option.value === current.value ? option.bg : 'transparent',
                color: option.color,
                fontFamily: 'Poppins, sans-serif',
                fontSize: 13,
                fontWeight: 700,
                cursor: 'pointer',
                textAlign: 'left',
              }}
            >
              <span style={{ width: 8, height: 8, borderRadius: '50%', background: option.color, flex: '0 0 auto' }}/>
              {option.label}
            </button>
          ))}
        </div>
      )}
    </div>
  );
}

function JourneyProgressInput({ value, onChange, color, fieldStyle }) {
  const percent = clampProgress(value);
  const tone = getJourneyProgressTone(percent);

  return (
    <div style={{ marginTop: 14 }}>
      <div style={{
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'space-between',
        gap: 12,
        marginBottom: 9,
      }}>
        <span style={{
          color: 'rgba(var(--theme-text-rgb),0.58)',
          fontSize: 12,
          fontWeight: 700,
          letterSpacing: '1.5px',
          textTransform: 'uppercase',
        }}>Completed</span>
        <span style={{
          minWidth: 54,
          padding: '5px 10px',
          borderRadius: 999,
          background: tone.bg,
          border: `1px solid ${tone.color}40`,
          color: tone.color,
          fontSize: 13,
          fontWeight: 800,
          textAlign: 'center',
          fontVariantNumeric: 'tabular-nums',
        }}>{percent}%</span>
      </div>

      <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
        <input
          type="range"
          min="0"
          max="100"
          value={percent}
          onChange={event => onChange(clampProgress(event.target.value))}
          style={{ flex: 1, accentColor: tone.color }}
        />
      </div>
    </div>
  );
}

function JourneyEmpty({ text }) {
  return (
    <div style={{
      padding: 16,
      borderRadius: 14,
      color: 'rgba(var(--theme-text-rgb),0.52)',
      background: 'rgba(var(--theme-bg-rgb),0.28)',
      border: '1px dashed rgba(var(--theme-text-rgb),0.12)',
      fontSize: 14,
    }}>{text}</div>
  );
}
