<!doctype html>
<html lang="en" data-theme="">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Personal Journal</title>
<style>
  :root {
  --bg: #1a0b1f;             /* deep purple-black */
  --card: #2a0d2e;           /* darker pinkish-purple */
  --muted: #c084fc;          /* muted lilac for secondary text */
  --text: #fdf2f8;           /* light pink-white for primary text */
  --accent: #ec4899;         /* hot pink */
  --accent-2: #8b5cf6;       /* vibrant purple */
  --danger: #ef4444;         /* strong red for errors/danger */
  --glass: rgba(255, 0, 128, 0.15); /* pink glow */
  --glass-2: rgba(139, 92, 246, 0.15); /* purple glow */
  --shadow: 0 8px 24px rgba(236, 72, 153, 0.3); /* pink shadow */
  --radius: 12px;
  --grid-gap: 18px;
  --card-padding: 14px;
  --compact-gap: 8px;
  --ui-gap: 10px;
  --small-radius: 8px;
  --mono: ui-monospace, SFMono-Regular, Menlo, Monaco, "Roboto Mono", "Courier New", monospace;
  --ui-font: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
}

html,body {
  height: 100%;
  margin: 0;
  font-family: var(--ui-font);
  background: linear-gradient(180deg, var(--bg) 0%, #2a0d2e 100%);
  color: var(--text);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

/* prevent accidental page-level horizontal scrolling caused by tiny rounding differences */
html, body {
  overflow-x: hidden;
}

.app {
  max-width: 1100px;
  margin: 28px auto;
  padding: 18px;
  display: grid;
  grid-template-columns: 360px 1fr;
  gap: var(--grid-gap);
}

.compact .app { gap: var(--compact-gap); }
.compact .card { padding: 8px; border-radius: 8px; }

header {
  grid-column: 1/-1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 6px;
}
h1 {
  font-size: 18px;
  margin: 0;
  letter-spacing: -0.2px;
}
.sub {
  color: var(--muted);
  font-size: 13px;
}

.card {
  background: var(--card);
  box-shadow: var(--shadow);
  border-radius: var(--radius);
  padding: var(--card-padding);
}

.controls {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px 12px;
  border-radius: 10px;
  border: none;
  cursor: pointer;
  font-weight: 600;
  background: transparent;
  transition: transform .08s ease, box-shadow .12s ease;
  white-space: nowrap; /* prevent text inside buttons from wrapping */
}
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: linear-gradient(90deg, var(--accent), var(--accent-2));
  color: white;
  box-shadow: 0 6px 14px rgba(236, 72, 153, 0.25);
}
.btn-secondary {
  background: transparent;
  border: 1px solid var(--glass-2);
  color: var(--text);
}
.btn-ghost {
  background: transparent;
  color: var(--text);
  opacity: 0.95;
}
.btn-large { padding: 12px 16px; font-size: 15px; border-radius: 12px; }

.row { display: flex; gap: 10px; align-items: center; }
.col { display: flex; flex-direction: column; gap: 8px; }

label { font-size: 13px; color: var(--muted); display: block; }
input[type="text"], input[type="time"], input[type="number"], select, textarea {
  width: 100%;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--glass-2);
  background: transparent;
  color: var(--text);
  box-sizing: border-box;
  font-size: 14px;
}
textarea { min-height: 80px; resize: vertical; padding-top: 10px; }

.right {
  display: flex;
  flex-direction: column;
  gap: var(--grid-gap);
}

.chart-wrap {
  display: grid;
  grid-template-columns: 1fr 160px;
  gap: 12px;
  align-items: center;
}
canvas {
  width: 100%; height: 140px; display: block;
  border-radius: 8px;
  background: linear-gradient(180deg, rgba(139,92,246,0.08), transparent);
}

.overview {
  padding: 12px;
  border-radius: 10px;
  background: linear-gradient(180deg, rgba(236,72,153,0.08), transparent);
  min-height: 80px;
}
.muted { color: var(--muted); font-size: 13px; }

.table-wrap {
  margin-top:10px;
  overflow:auto; /* only scroll when strictly necessary */
  -webkit-overflow-scrolling: touch;
}

/* Keep table flexible, allow browser to size columns sensibly */
table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
  table-layout: auto; /* changed from fixed so actions column isn't squeezed */
  word-break: break-word;
}
th,td {
  text-align: left;
  padding: 10px 8px;
  border-bottom: 1px solid var(--glass-2);
  vertical-align: top;
  overflow-wrap: anywhere;
}
th { 
  font-weight: 700; 
  color: var(--muted); 
  font-size: 12px; 
  text-transform: uppercase; 
  letter-spacing: 0.6px; 
}
tr:hover td { background: linear-gradient(90deg, rgba(236,72,153,0.05), transparent); }

td.notes-cell {
  white-space: pre-wrap;
  word-break: break-word;
}

.pill {
  display: inline-block;
  padding: 6px 8px;
  border-radius: 999px;
  background: var(--glass);
  font-weight: 600;
  font-size: 13px;
}

.backdrop {
  position: fixed;
  inset: 0;
  background: rgba(10, 0, 20, 0.75);
  display: none;
  align-items: center;
  justify-content: center;
  z-index: 9998;
  padding: 20px;
}
.backdrop.show { display: flex; }
.modal {
  width: min(720px, 98%);
  max-height: 90vh;
  overflow: auto;
  border-radius: 12px;
}
.modal .card { padding: 18px; }

.emoji-grid { display: grid; grid-template-columns: repeat(8,1fr); gap: 8px; }
.emoji-btn { font-size: 18px; padding: 8px; border-radius: 8px; background: var(--glass); border: none; cursor: pointer; }

.small { font-size: 13px; color: var(--muted); }

/* modal actions (kept intentionally separate from table action cell) */
.actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; }

/* type list */
.type-item { display: flex; gap: 8px; align-items: center; padding: 8px; border-radius: 8px; background: var(--glass); }
.type-list { display: flex; flex-direction: column; gap: 8px; }

.hidden { display: none !important; }

.controls .card { display: flex; flex-direction: column; gap: 12px; }

.flex { display: flex; gap: 8px; align-items: center; }
.spacer { flex: 1; }

.danger { color: var(--danger); font-weight: 700; }

/* ===========================================
   ACTIONS CELL: keep buttons horizontally aligned
   =========================================== */

/* A dedicated class applied to the <td> that contains action buttons.
   Keeps buttons on a single row and prevents them from expanding to full width. */
.actions-cell {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end; /* keep to the right of the cell */
  gap: 8px;
  white-space: nowrap;       /* prevent internal text wrapping */
  flex-wrap: nowrap;         /* prevent button wrapping to a new line */
  padding: 8px;              /* consistent padding with other cells */
  box-sizing: border-box;
}

/* Prevent buttons inside the actions cell from stretching */
.actions-cell .btn {
  flex: 0 0 auto;            /* don't grow or shrink; keep intrinsic size */
  padding: 6px 8px;
  min-width: 40px;           /* keeps buttons comfortably tappable on touch screens */
  font-size: 13px;
}

/* Apply a modest fixed width to the Actions column so two buttons usually fit.
   Adjust the width to taste (increase if your labels are longer). */
.actions-col {
  width: 160px;
  min-width: 120px;
  max-width: 240px;
  vertical-align: middle;
  overflow: visible;
}

/* Make sure header cell follows same sizing */
th.actions-col { width: 160px; min-width: 120px; }

/* Responsive behavior:
   - The table container already has overflow:auto — if viewport is very narrow,
     the table will scroll horizontally instead of wrapping the action buttons.
   - On very narrow screens we tighten spacing so buttons remain side-by-side when possible.
*/
@media (max-width: 420px) {
  /* Keep the action buttons side-by-side, but reduce spacing */
  .actions-cell { gap: 6px; }
  .actions-cell .btn { padding: 5px 6px; min-width: 36px; font-size: 13px; }
  /* If you want icons only on tiny screens you can swap text to icons in JS/rendering */
}

/* responsive layout rules */
@media (max-width:960px) {
  .app { grid-template-columns: 1fr; padding: 12px; }
  .chart-wrap{ grid-template-columns: 1fr; }
}

footer {
  grid-column: 1/-1;
  text-align: center;
  color: var(--muted);
  margin-top: 10px;
  font-size: 12px;
}

</style>
</head>
<body>
  <div style="max-width:1100px;margin:24px auto;padding:0 18px;">
    <div class="app card" id="root">
      <header>
        <div>
          <h1>Local Journal</h1>
          <div class="sub">Private, local-only tracking — entries saved to your browser.</div>
        </div>
        <div class="row">
          <button class="btn btn-secondary" id="openSettings">Settings</button>
        </div>
      </header>

      <!-- Left column -->
      <div class="controls">
        <div class="card">
          <div style="display:flex;justify-content:space-between;align-items:center;">
            <div><strong>Quick Actions</strong><div class="small muted">Add an entry, manage types, or quick-log.</div></div>
          </div>

          <div class="row">
            <button class="btn btn-primary btn-large" id="btnAddEntry">+ Add Entry</button>
            <button class="btn btn-secondary" id="btnQuickLog">Quick Log</button>
          </div>

          <div class="row">
            <button class="btn btn-ghost" id="btnManageTypes">Manage Event Types</button>
            <button class="btn btn-ghost" id="btnReminders">Reminders</button>
            <button class="btn btn-ghost" id="btnExport">Export</button>
          </div>

          <div style="border-top:1px dashed var(--glass-2);padding-top:10px" class="small muted">
            <div><strong id="totalCount">0</strong> total entries</div>
            <div id="overviewText" style="margin-top:6px;">No entries yet — add one to get started.</div>
          </div>
        </div>

        <div class="card">
          <div style="display:flex;align-items:center;justify-content:space-between">
            <div>
              <strong>Event Types</strong>
              <div class="small muted">Manage categories used when logging entries.</div>
            </div>
            <button class="btn btn-secondary" id="btnManageTypes2">Edit</button>
          </div>
          <div id="typesPreview" style="margin-top:12px;display:flex;flex-wrap:wrap;gap:8px;"></div>
        </div>

        <div class="card">
          <div style="display:flex;align-items:center;justify-content:space-between">
            <div>
              <strong>Data</strong>
              <div class="small muted">Export, import, or clear all local data.</div>
            </div>
          </div>

          <div class="row">
            <button class="btn btn-secondary" id="btnExport2">Export CSV/JSON</button>
            <button class="btn btn-ghost" id="btnImport">Import JSON</button>
            <button class="btn btn-ghost danger" id="btnClearAll">Clear All</button>
          </div>
        </div>
      </div>

      <!-- Right column -->
      <div class="right">
        <div class="card chart-wrap">
          <canvas id="weekChart" aria-label="Weekly entries chart"></canvas>
          <div class="overview card" style="padding:12px;">
            <div style="display:flex;flex-direction:column;gap:8px;">
              <div><strong id="weekTotal">0</strong> entries in last 7 days</div>
              <div class="muted" id="topType">—</div>
              <div class="muted" id="topMood">—</div>
            </div>
          </div>
        </div>

        <div class="card">
          <div style="display:flex;align-items:center;justify-content:space-between">
            <strong>Entries</strong>
            <div class="row">
              <button class="btn btn-ghost" id="toggleCollapse">Collapse</button>
              <button class="btn btn-secondary" id="btnClearEntries">Clear</button>
            </div>
          </div>

          <div class="table-wrap">
            <table id="entriesTable">
              <thead>
                <tr>
                  <th style="width:160px">Date</th>
                  <th>Type</th>
                  <th class="col-mood">Mood</th>
                  <th class="col-sev">Severity</th>
                  <th>Duration</th>
                  <th>Notes</th>
                  <th class="actions-col">Actions</th>
                </tr>
              </thead>
              <tbody id="entriesBody">
                <!-- rows -->
              </tbody>
            </table>
          </div>
        </div>

        <footer class="muted">All data stays in your browser. Use Export to make backups.</footer>
      </div>
    </div>
  </div>

  <!-- Backdrop & Modals -->
  <div class="backdrop" id="backdrop" role="dialog" aria-hidden="true">
    <!-- Add Entry Modal -->
    <div class="modal card hidden" id="modalAddEntry">
      <div class="card">
        <h3 id="addEntryTitle">Add Entry</h3>
        <div class="row">
          <div style="flex:1">
            <label for="entryDate">Date & time</label>
            <input type="datetime-local" id="entryDate" />
          </div>
          <div style="width:200px">
            <label for="entryType">Type</label>
            <select id="entryType"></select>
          </div>
        </div>

        <div id="fieldMood" class="col">
          <label>Mood</label>
          <div style="display:flex;gap:8px;align-items:center;">
            <input type="text" id="entryMood" placeholder="Choose emoji or type" />
            <button class="btn btn-ghost" id="openEmojiPicker">😀</button>
          </div>
          <div id="emojiPicker" class="emoji-grid hidden" style="margin-top:8px;"></div>
        </div>

        <div id="fieldSeverity" class="col">
          <label>Severity (1-10)</label>
          <input type="number" id="entrySeverity" min="1" max="10" />
        </div>

        <div class="col">
          <label>Duration (minutes)</label>
          <input type="number" id="entryDuration" min="0" />
        </div>

        <div class="col">
          <label>Notes</label>
          <textarea id="entryNotes" placeholder="Optional notes..."></textarea>
        </div>

        <div class="actions">
          <button class="btn btn-secondary" id="btnClearEntry">Clear</button>
          <button class="btn btn-ghost" id="btnCancelEntry">Cancel</button>
          <button class="btn btn-primary" id="btnSaveEntry">Save</button>
        </div>
      </div>
    </div>

    <!-- Quick Log Modal -->
    <div class="modal card hidden" id="modalQuickLog">
      <div class="card">
        <h3>Quick Log</h3>
        <div class="row">
          <div style="flex:1">
            <label>Time</label>
            <input type="datetime-local" id="quickDate" />
          </div>
          <div style="width:200px">
            <label>Type</label>
            <select id="quickType"></select>
          </div>
        </div>

        <div id="quickMoodWrap" class="col">
          <label>Mood</label>
          <input type="text" id="quickMood" />
        </div>

        <div class="actions">
          <button class="btn btn-ghost" id="btnCancelQuick">Cancel</button>
          <button class="btn btn-primary" id="btnSaveQuick">Save</button>
        </div>
      </div>
    </div>

    <!-- Manage Types Modal -->
    <div class="modal card hidden" id="modalManageTypes">
      <div class="card">
        <h3>Manage Event Types</h3>
        <div class="type-list" id="typeList"></div>

        <div style="display:flex;gap:8px;margin-top:12px;align-items:center;">
          <input type="text" id="newTypeName" placeholder="New type name" />
          <label style="display:flex;align-items:center;gap:8px;"><input type="checkbox" id="newTypeAction" /> action</label>
          <button class="btn btn-primary" id="btnAddType">Add</button>
        </div>

        <div class="actions">
          <button class="btn btn-ghost" id="btnCloseTypes">Close</button>
        </div>
      </div>
    </div>

    <!-- Reminders Modal -->
    <div class="modal card hidden" id="modalReminders">
      <div class="card">
        <h3>Daily Reminder</h3>
        <div class="col">
          <label>Reminder time</label>
          <input type="time" id="reminderTime" />
        </div>

        <div class="row" style="align-items:center">
          <label style="margin-right:8px;">Enable reminders</label>
          <input type="checkbox" id="enableReminders" />
        </div>

        <div class="small muted" id="reminderStatus"></div>

        <div class="actions">
          <button class="btn btn-ghost" id="btnCancelReminders">Close</button>
          <button class="btn btn-primary" id="btnSaveReminders">Save</button>
        </div>
      </div>
    </div>

    <!-- Settings Modal -->
    <div class="modal card hidden" id="modalSettings">
      <div class="card">
        <h3>Settings</h3>
        <div class="col">
          <label><input type="checkbox" id="settingMood" /> Enable Mood field</label>
          <label><input type="checkbox" id="settingSeverity" /> Enable Severity field</label>
          <label><input type="checkbox" id="settingReminders" /> Enable Reminders feature</label>
          <label><input type="checkbox" id="settingExport" /> Enable Export/Import</label>
          <label><input type="checkbox" id="settingCompact" /> Compact UI</label>
        </div>

        <div style="margin-top:10px" class="small muted">Changes apply immediately and persist in localStorage.</div>

        <div class="actions">
          <button class="btn btn-ghost" id="btnCloseSettings">Close</button>
        </div>
      </div>
    </div>

    <!-- Export Modal -->
    <div class="modal card hidden" id="modalExport">
      <div class="card">
        <h3>Export</h3>
        <div class="col">
          <label>Export format</label>
          <div class="row">
            <button class="btn btn-secondary" id="exportCSV">Download CSV</button>
            <button class="btn btn-secondary" id="exportJSON">Download JSON</button>
            <button class="btn btn-ghost" id="openImportFile">Import JSON</button>
            <input type="file" id="importFile" accept="application/json" class="hidden" />
          </div>
        </div>

        <div class="actions">
          <button class="btn btn-ghost" id="btnCloseExport">Close</button>
        </div>
      </div>
    </div>

    <!-- View Entry Modal -->
    <div class="modal card hidden" id="modalViewEntry">
      <div class="card">
        <h3>View Entry</h3>
        <div id="viewEntryBody" class="col"></div>
        <div class="actions">
          <button class="btn btn-ghost" id="btnCloseView">Close</button>
          <button class="btn btn-secondary" id="btnDeleteEntry">Delete</button>
        </div>
      </div>
    </div>
  </div>

<script>
/* =========================
   VERSIONED STORAGE KEYS
   ========================= */
const APP_VERSION = 'v1';
const KEYS = {
  ENTRIES: `LOCALJOURNAL_${APP_VERSION}_ENTRIES`,
  TYPES: `LOCALJOURNAL_${APP_VERSION}_TYPES`,
  REMINDER: `LOCALJOURNAL_${APP_VERSION}_REMINDER`,
  SETTINGS: `LOCALJOURNAL_${APP_VERSION}_SETTINGS`
};

/* =========================
   DEFAULTS
   ========================= */
const defaultTypes = [
  { id: 'nssi_action', name: 'NSSI — action', action: true },
  { id: 'nssi_ideation', name: 'NSSI — ideation', action: false },
  { id: 'depressive', name: 'Depressive episode', action: false },
  { id: 'suicidal_ideation', name: 'Suicidal ideation', action: false },
  { id: 'suicidal_action', name: 'Suicidal — action', action: true }
];

const DEFAULT_SETTINGS = {
  enableMood: true,
  enableSeverity: true,
  enableReminders: false,
  enableExport: true,
  compactUI: false
};

const DEFAULT_REMINDER = { time: null, enabled: false };

/* =========================
   Persistence helpers
   ========================= */
function loadJSON(key, fallback) {
  try {
    const raw = localStorage.getItem(key);
    if (!raw) return fallback;
    return JSON.parse(raw);
  } catch (e) {
    console.warn('Failed to parse localStorage key', key, e);
    return fallback;
  }
}
function saveJSON(key, value) {
  try {
    localStorage.setItem(key, JSON.stringify(value));
  } catch (e) {
    console.error('Failed to save', key, e);
  }
}

/* =========================
   Utilities
   ========================= */
function esc(s){ // safe HTML insertion
  if (s === null || s === undefined) return '';
  return String(s)
    .replaceAll('&','&amp;')
    .replaceAll('<','&lt;')
    .replaceAll('>','&gt;')
    .replaceAll('"','&quot;')
    .replaceAll("'", '&#39;');
}
function isoDate(ts){ return (new Date(ts)).toISOString(); }
function formatShort(ts){
  const d = new Date(ts);
  return d.toLocaleString([], {month:'short', day:'numeric', hour:'2-digit', minute:'2-digit'});
}
function friendlyDateTime(ts){
  const d = new Date(ts);
  return d.toLocaleString();
}
function pad(n){ return String(n).padStart(2,'0'); }
function downloadBlob(filename, blob){
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  a.remove();
  setTimeout(()=> URL.revokeObjectURL(url), 5000);
}
function isActionType(typeId){
  const t = types.find(x => x.id === typeId);
  return !!(t && t.action);
}

/* =========================
   App state
   ========================= */
let entries = loadJSON(KEYS.ENTRIES, []);
let types = loadJSON(KEYS.TYPES, defaultTypes);
let settings = loadJSON(KEYS.SETTINGS, DEFAULT_SETTINGS);
let reminder = loadJSON(KEYS.REMINDER, DEFAULT_REMINDER);
let reminderInterval = null;

/* =========================
   DOM refs
   ========================= */
const rootEl = document.getElementById('root');
const weekCanvas = document.getElementById('weekChart');
const entriesBody = document.getElementById('entriesBody');
const totalCountEl = document.getElementById('totalCount');
const overviewText = document.getElementById('overviewText');
const typesPreview = document.getElementById('typesPreview');
const weekTotalEl = document.getElementById('weekTotal');
const topTypeEl = document.getElementById('topType');
const topMoodEl = document.getElementById('topMood');
const backdrop = document.getElementById('backdrop');

/* Modal nodes */
const modalAddEntry = document.getElementById('modalAddEntry');
const modalQuickLog = document.getElementById('modalQuickLog');
const modalManageTypes = document.getElementById('modalManageTypes');
const modalReminders = document.getElementById('modalReminders');
const modalSettings = document.getElementById('modalSettings');
const modalExport = document.getElementById('modalExport');
const modalViewEntry = document.getElementById('modalViewEntry');

/* inputs */
const entryDate = document.getElementById('entryDate');
const entryType = document.getElementById('entryType');
const entryMood = document.getElementById('entryMood');
const entrySeverity = document.getElementById('entrySeverity');
const entryDuration = document.getElementById('entryDuration');
const entryNotes = document.getElementById('entryNotes');
const emojiPicker = document.getElementById('emojiPicker');

const quickDate = document.getElementById('quickDate');
const quickType = document.getElementById('quickType');
const quickMood = document.getElementById('quickMood');

const typeList = document.getElementById('typeList');
const newTypeName = document.getElementById('newTypeName');
const newTypeAction = document.getElementById('newTypeAction');

const reminderTime = document.getElementById('reminderTime');
const enableRemindersInput = document.getElementById('enableReminders');
const reminderStatus = document.getElementById('reminderStatus');

const settingMood = document.getElementById('settingMood');
const settingSeverity = document.getElementById('settingSeverity');
const settingReminders = document.getElementById('settingReminders');
const settingExport = document.getElementById('settingExport');
const settingCompact = document.getElementById('settingCompact');

const entriesTable = document.getElementById('entriesTable');

let isListCollapsed = false;
let currentViewEntryId = null;

/* =========================
   Initial setup
   ========================= */

function init(){
  // apply settings UI
  applySettingsToForm();
  applySettings();
  // wire up UI buttons
  wireUI();
  // draw initial UI
  renderTypeSelectors();
  renderTypesPreview();
  renderEntries();
  drawWeekChart();
  setupEmojiPicker();
  scheduleReminderLoop();
}

function applySettingsToForm(){
  settingMood.checked = !!settings.enableMood;
  settingSeverity.checked = !!settings.enableSeverity;
  settingReminders.checked = !!settings.enableReminders;
  settingExport.checked = !!settings.enableExport;
  settingCompact.checked = !!settings.compactUI;
  // apply reminder form
  reminderTime.value = reminder.time || '';
  enableRemindersInput.checked = !!(reminder.enabled);
}

function applySettings(){
  // Show/hide mood & severity fields in Add Entry modal and Quick Log
  const fieldMood = document.getElementById('fieldMood');
  const fieldSeverity = document.getElementById('fieldSeverity');
  const quickMoodWrap = document.getElementById('quickMoodWrap');

  if (settings.enableMood) { fieldMood.classList.remove('hidden'); quickMoodWrap.classList.remove('hidden'); }
  else { fieldMood.classList.add('hidden'); quickMoodWrap.classList.add('hidden'); }

  if (settings.enableSeverity) fieldSeverity.classList.remove('hidden'); else fieldSeverity.classList.add('hidden');

  // Export/Import availability
  if (settings.enableExport) {
    document.getElementById('btnExport').classList.remove('hidden');
    document.getElementById('btnExport2').classList.remove('hidden');
  } else {
    document.getElementById('btnExport').classList.add('hidden');
    document.getElementById('btnExport2').classList.add('hidden');
  }

  // Reminders
  if (settings.enableReminders) {
    document.getElementById('btnReminders').classList.remove('hidden');
  } else {
    document.getElementById('btnReminders').classList.add('hidden');
  }

  // compact UI
  if (settings.compactUI) document.body.classList.add('compact'); else document.body.classList.remove('compact');

  // columns in table
  document.querySelectorAll('.col-mood').forEach(n => n.style.display = settings.enableMood ? '' : 'none');
  document.querySelectorAll('.col-sev').forEach(n => n.style.display = settings.enableSeverity ? '' : 'none');
}

/* =========================
   Event wiring
   ========================= */
function wireUI(){
  document.getElementById('btnAddEntry').addEventListener('click', openAddEntry);
  document.getElementById('btnQuickLog').addEventListener('click', openQuickLog);
  document.getElementById('btnManageTypes').addEventListener('click', openManageTypes);
  document.getElementById('btnManageTypes2').addEventListener('click', openManageTypes);
  document.getElementById('btnReminders').addEventListener('click', openReminders);
  document.getElementById('btnExport').addEventListener('click', openExport);
  document.getElementById('btnExport2').addEventListener('click', openExport);
  document.getElementById('btnImport').addEventListener('click', ()=> document.getElementById('importFile').click());
  document.getElementById('importFile').addEventListener('change', handleImportFile);
  document.getElementById('btnClearAll').addEventListener('click', clearAllData);

  document.getElementById('btnClearEntries').addEventListener('click', clearEntries);
  document.getElementById('toggleCollapse').addEventListener('click', toggleCollapse);

  document.getElementById('btnSaveEntry').addEventListener('click', saveEntryFromModal);
  document.getElementById('btnCancelEntry').addEventListener('click', hideBackdrop);

  document.getElementById('btnSaveQuick').addEventListener('click', saveQuickLog);
  document.getElementById('btnCancelQuick').addEventListener('click', hideBackdrop);

  document.getElementById('btnAddType').addEventListener('click', addTypeFromInput);
  document.getElementById('btnCloseTypes').addEventListener('click', hideBackdrop);

  document.getElementById('btnSaveReminders').addEventListener('click', saveReminderSettings);
  document.getElementById('btnCancelReminders').addEventListener('click', hideBackdrop);

  document.getElementById('openSettings').addEventListener('click', openSettings);
  document.getElementById('btnCloseSettings').addEventListener('click', hideBackdrop);

  // settings toggles
  settingMood.addEventListener('change', ()=> { settings.enableMood = settingMood.checked; saveJSON(KEYS.SETTINGS, settings); applySettings(); });
  settingSeverity.addEventListener('change', ()=> { settings.enableSeverity = settingSeverity.checked; saveJSON(KEYS.SETTINGS, settings); applySettings(); });
  settingReminders.addEventListener('change', ()=> { settings.enableReminders = settingReminders.checked; saveJSON(KEYS.SETTINGS, settings); applySettings(); scheduleReminderLoop(); });
  settingExport.addEventListener('change', ()=> { settings.enableExport = settingExport.checked; saveJSON(KEYS.SETTINGS, settings); applySettings(); });
  settingCompact.addEventListener('change', ()=> { settings.compactUI = settingCompact.checked; saveJSON(KEYS.SETTINGS, settings); applySettings(); });

  // emoji
  document.getElementById('openEmojiPicker').addEventListener('click', ()=> emojiPicker.classList.toggle('hidden'));

  // export modal
  document.getElementById('exportCSV').addEventListener('click', exportCSV);
  document.getElementById('exportJSON').addEventListener('click', exportJSON);
  document.getElementById('openImportFile').addEventListener('click', ()=> document.getElementById('importFile').click());
  document.getElementById('btnCloseExport').addEventListener('click', hideBackdrop);

  // view modal
  document.getElementById('btnCloseView').addEventListener('click', hideBackdrop);
  document.getElementById('btnDeleteEntry').addEventListener('click', deleteViewedEntry);

  // backdrop click closes
  backdrop.addEventListener('click', (e) => {
    if (e.target === backdrop) hideBackdrop();
  });
}

/* =========================
   UI: Modals open/close
   ========================= */
function showBackdrop(){
  backdrop.classList.add('show');
  // set first modal's aria
  backdrop.setAttribute('aria-hidden','false');
}
function hideBackdrop(){
  backdrop.classList.remove('show');
  // hide all modals
  document.querySelectorAll('.modal').forEach(m=>m.classList.add('hidden'));
  backdrop.setAttribute('aria-hidden','true');
}

/* =========================
   Add / Quick entries
   ========================= */
function openAddEntry(){
  // prefill
  entryDate.value = (new Date()).toISOString().slice(0,16);
  entryType.innerHTML = '';
  renderTypeSelectors(); // fill select
  entrySeverity.value = '';
  entryDuration.value = '';
  entryMood.value = '';
  entryNotes.value = '';
  document.getElementById('addEntryTitle').textContent = 'Add Entry';
  document.querySelectorAll('.modal').forEach(m=>m.classList.add('hidden'));
  modalAddEntry.classList.remove('hidden');
  showBackdrop();
}
function saveEntryFromModal(){
  const ts = entryDate.value ? new Date(entryDate.value).toISOString() : new Date().toISOString();
  const t = entryType.value;
  const moodVal = settings.enableMood ? (entryMood.value || '') : '';
  const sevVal = settings.enableSeverity ? (entrySeverity.value ? Number(entrySeverity.value) : null) : null;
  const dur = entryDuration.value ? Number(entryDuration.value) : null;
  const notesVal = entryNotes.value || '';

  const entry = {
    id: 'e_' + Date.now(),
    timestamp: ts,
    type: t,
    mood: moodVal,
    severity: sevVal,
    duration: dur,
    notes: notesVal
  };
  entries.unshift(entry);
  saveJSON(KEYS.ENTRIES, entries);
  renderEntries();
  drawWeekChart();
  hideBackdrop();
}

function openQuickLog(){
  quickDate.value = (new Date()).toISOString().slice(0,16);
  quickType.innerHTML = '';
  renderTypeSelectors(true);
  quickMood.value = '';
  document.querySelectorAll('.modal').forEach(m=>m.classList.add('hidden'));
  modalQuickLog.classList.remove('hidden');
  showBackdrop();
}
function saveQuickLog(){
  const ts = quickDate.value ? new Date(quickDate.value).toISOString() : new Date().toISOString();
  const t = quickType.value;
  const moodVal = settings.enableMood ? (quickMood.value || '') : '';
  const entry = {
    id: 'e_' + Date.now(),
    timestamp: ts,
    type: t,
    mood: moodVal,
    severity: null, duration: null, notes: ''
  };
  entries.unshift(entry);
  saveJSON(KEYS.ENTRIES, entries);
  renderEntries();
  drawWeekChart();
  hideBackdrop();
}

/* =========================
   Render types selectors & preview
   ========================= */
function renderTypeSelectors(quick=false){
  // fill both selects
  const selects = quick ? [quickType] : [entryType, quickType];
  selects.forEach(sel => {
    if (!sel) return;
    sel.innerHTML = '';
    types.forEach(t => {
      const opt = document.createElement('option');
      opt.value = t.id;
      opt.textContent = t.name + (t.action ? ' (action)' : '');
      sel.appendChild(opt);
    });
  });
}

function renderTypesPreview(){
  typesPreview.innerHTML = '';
  types.slice(0,8).forEach(t => {
    const d = document.createElement('div');
    d.className = 'pill';
    d.textContent = t.name;
    typesPreview.appendChild(d);
  });
}

/* =========================
   Manage types
   ========================= */
function openManageTypes(){
  typeList.innerHTML = '';
  types.forEach(t => {
    const row = document.createElement('div');
    row.className = 'type-item';
    row.innerHTML = `
      <div style="flex:1">
        <input type="text" data-id="${esc(t.id)}" class="typeNameInput" value="${esc(t.name)}" />
      </div>
      <label style="display:flex;align-items:center;gap:6px;">
        <input type="checkbox" class="typeActionInput" ${t.action ? 'checked' : ''} />
        action
      </label>
      <button class="btn btn-ghost btn-sm typeRename" data-id="${esc(t.id)}">Save</button>
      <button class="btn btn-ghost danger typeDelete" data-id="${esc(t.id)}">Delete</button>
    `;
    typeList.appendChild(row);

    // wire inside
    row.querySelector('.typeRename').addEventListener('click', ()=>{
      const input = row.querySelector('.typeNameInput');
      const chk = row.querySelector('.typeActionInput');
      const id = input.getAttribute('data-id');
      const idx = types.findIndex(x => x.id === id);
      if (idx >= 0){
        types[idx].name = input.value.trim() || types[idx].name;
        types[idx].action = chk.checked;
        saveJSON(KEYS.TYPES, types);
        renderTypeSelectors();
        renderTypesPreview();
        renderEntries();
      }
    });
    row.querySelector('.typeDelete').addEventListener('click', ()=>{
      const id = row.querySelector('.typeNameInput').getAttribute('data-id');
      if (!confirm('Delete type "' + types.find(x=>x.id===id).name + '"? Existing entries will keep their type id.')) return;
      types = types.filter(x=>x.id !== id);
      saveJSON(KEYS.TYPES, types);
      renderTypeSelectors();
      renderTypesPreview();
      renderEntries();
      openManageTypes();
    });
  });

  // prepare new-type inputs
  newTypeName.value = '';
  newTypeAction.checked = false;

  document.querySelectorAll('.modal').forEach(m=>m.classList.add('hidden'));
  modalManageTypes.classList.remove('hidden');
  showBackdrop();
}

function addTypeFromInput(){
  const nm = newTypeName.value.trim();
  if (!nm) return alert('Please provide a type name.');
  const id = nm.toLowerCase().replace(/\s+/g,'_').replace(/[^\w\-]/g,'') + '_' + Date.now().toString(36);
  const obj = { id, name: nm, action: !!newTypeAction.checked };
  types.push(obj);
  saveJSON(KEYS.TYPES, types);
  renderTypeSelectors();
  renderTypesPreview();
  addTypeFromInputClear();
  openManageTypes(); // refresh
}
function addTypeFromInputClear(){ newTypeName.value=''; newTypeAction.checked=false; }

/* =========================
   Entries rendering & actions
   ========================= */
function renderEntries(){
  // sort entries by timestamp desc
  entries.sort((a,b)=> new Date(b.timestamp) - new Date(a.timestamp));
  entriesBody.innerHTML = '';
  entries.forEach(e => {
    const tr = document.createElement('tr');
    const typeObj = types.find(t=>t.id===e.type) || { name: e.type || 'Unknown', action: false };

    const dateTd = document.createElement('td');
    dateTd.innerHTML = `<div style="font-weight:700">${esc(formatShort(e.timestamp))}</div><div class="small muted">${esc(new Date(e.timestamp).toLocaleString())}</div>`;

    const typeTd = document.createElement('td');
    typeTd.innerHTML = `<div>${esc(typeObj.name)}</div>`;

    const moodTd = document.createElement('td');
    moodTd.className = 'col-mood';
    moodTd.textContent = settings.enableMood ? (e.mood || '') : '';

    const sevTd = document.createElement('td');
    sevTd.className = 'col-sev';
    sevTd.textContent = (settings.enableSeverity && isActionType(e.type) && e.severity) ? String(e.severity) : (isActionType(e.type) ? '—' : '');

    const durTd = document.createElement('td');
    durTd.textContent = e.duration != null ? (String(e.duration) + ' min') : '—';

    const notesTd = document.createElement('td');
    notesTd.className = 'notes-cell';
    notesTd.textContent = e.notes && e.notes.trim() ? e.notes : '—';

    // Actions cell: use classes that keep buttons in a single row and prevent stretching
    const actTd = document.createElement('td');
    actTd.className = 'actions-cell actions-col';
    actTd.innerHTML = `
      <button class="btn btn-ghost" data-id="${esc(e.id)}" data-action="view" title="View">View</button>
      <button class="btn btn-ghost danger" data-id="${esc(e.id)}" data-action="delete" title="Delete">Delete</button>
    `;

    tr.appendChild(dateTd);
    tr.appendChild(typeTd);
    tr.appendChild(moodTd);
    tr.appendChild(sevTd);
    tr.appendChild(durTd);
    tr.appendChild(notesTd);
    tr.appendChild(actTd);
    entriesBody.appendChild(tr);

    // wire actions
    actTd.querySelectorAll('button').forEach(btn => {
      btn.addEventListener('click', (ev)=>{
        const id = btn.getAttribute('data-id');
        const action = btn.getAttribute('data-action');
        if (action === 'view') viewEntry(id);
        if (action === 'delete') {
          if (confirm('Delete this entry?')) {
            entries = entries.filter(x=>x.id !== id);
            saveJSON(KEYS.ENTRIES, entries);
            renderEntries();
            drawWeekChart();
          }
        }
      });
    });
  });

  totalCountEl.textContent = entries.length;
  overviewText.textContent = entries.length ? `Most recent: ${entries.length? formatShort(entries[0].timestamp) : '—'}` : 'No entries yet — add one to get started.';
  renderTypesPreview();
}

/* =========================
   View Entry modal
   ========================= */
function viewEntry(id){
  const ent = entries.find(x => x.id === id);
  if (!ent) return alert('Entry not found.');
  currentViewEntryId = id;
  const typeObj = types.find(t => t.id === ent.type) || { name: ent.type || 'Unknown', action:false };
  const wrap = document.getElementById('viewEntryBody');
  wrap.innerHTML = `
    <div><strong>Date</strong><div class="small muted">${esc(friendlyDateTime(ent.timestamp))}</div></div>
    <div style="margin-top:8px"><strong>Type</strong><div class="small muted">${esc(typeObj.name)}</div></div>
    ${settings.enableMood ? `<div style="margin-top:8px"><strong>Mood</strong><div class="small muted">${esc(ent.mood||'—')}</div></div>` : ''}
    ${settings.enableSeverity && typeObj.action ? `<div style="margin-top:8px"><strong>Severity</strong><div class="small muted">${esc(ent.severity||'—')}</div></div>` : ''}
    <div style="margin-top:8px"><strong>Duration</strong><div class="small muted">${ent.duration != null ? esc(String(ent.duration) + ' min') : '—'}</div></div>
    <div style="margin-top:8px"><strong>Notes</strong><div class="small muted">${ent.notes ? esc(ent.notes) : '—'}</div></div>
  `;
  document.querySelectorAll('.modal').forEach(m=>m.classList.add('hidden'));
  modalViewEntry.classList.remove('hidden');
  showBackdrop();
}

function deleteViewedEntry(){
  if (!currentViewEntryId) return;
  if (!confirm('Delete this entry?')) return;
  entries = entries.filter(x => x.id !== currentViewEntryId);
  saveJSON(KEYS.ENTRIES, entries);
  currentViewEntryId = null;
  renderEntries();
  drawWeekChart();
  hideBackdrop();
}

/* =========================
   Chart: weekly bar chart
   ========================= */
function drawWeekChart(){
  const ctx = weekCanvas.getContext('2d');
  const DPR = window.devicePixelRatio || 1;
  const W = weekCanvas.clientWidth;
  const H = weekCanvas.clientHeight;
  weekCanvas.width = Math.floor(W * DPR);
  weekCanvas.height = Math.floor(H * DPR);
  ctx.scale(DPR, DPR);

  // compute last 7 days (including today)
  const counts = [];
  const labels = [];
  const today = new Date();
  for (let i = 6; i >= 0; i--){
    const d = new Date(today);
    d.setDate(today.getDate() - i);
    const start = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 0,0,0,0);
    const end = new Date(d.getFullYear(), d.getMonth(), d.getDate(), 23,59,59,999);
    const c = entries.filter(e => {
      const t = new Date(e.timestamp);
      return t >= start && t <= end;
    }).length;
    counts.push(c);
    labels.push(d.toLocaleDateString([], {weekday:'short'}).slice(0,3));
  }

  // clear
  ctx.clearRect(0,0,W,H);

  // visual params
  const padding = 18;
  const barGap = 10;
  const maxVal = Math.max(1, ...counts);
  const barAreaW = W - padding*2;
  const barW = (barAreaW - (counts.length - 1)*barGap) / counts.length;
  const chartH = H - padding*2;

  // colors from CSS variables
  const barColor = getComputedStyle(document.documentElement).getPropertyValue('--accent').trim() || '#2563eb';
  const barColor2 = getComputedStyle(document.documentElement).getPropertyValue('--accent-2').trim() || '#10b981';
  const textColor = getComputedStyle(document.documentElement).getPropertyValue('--muted').trim() || '#6b7280';

  // draw grid lines
  ctx.strokeStyle = 'rgba(0,0,0,0.06)';
  ctx.lineWidth = 1;
  ctx.beginPath();
  for (let row=0; row<=3; row++){
    const y = padding + (chartH * row / 3);
    ctx.moveTo(padding, y);
    ctx.lineTo(W - padding, y);
  }
  ctx.stroke();

  // draw bars
  counts.forEach((val, i) => {
    const x = padding + i * (barW + barGap);
    const h = (val / maxVal) * (chartH - 20);
    const y = padding + (chartH - h) - 6;
    // gradient
    const grad = ctx.createLinearGradient(x, y, x, y + h);
    grad.addColorStop(0, barColor);
    grad.addColorStop(1, barColor2);
    ctx.fillStyle = grad;
    // rounded rect
    const r = 6;
    roundRect(ctx, x, y, barW, h, r);
    ctx.fill();

    // label (count)
    ctx.fillStyle = textColor;
    ctx.font = '600 12px system-ui, sans-serif';
    ctx.textAlign = 'center';
    ctx.fillText(String(val), x + barW / 2, y - 8);

    // day label
    ctx.font = '12px system-ui, sans-serif';
    ctx.fillText(labels[i], x + barW / 2, padding + chartH + 14);
  });

  // summary stats
  const last7 = counts.reduce((a,b)=>a+b,0);
  weekTotalEl.textContent = last7;
  // top type
  const since = new Date();
  since.setDate(since.getDate() - 6);
  const recent = entries.filter(e => new Date(e.timestamp) >= new Date(since.getFullYear(), since.getMonth(), since.getDate(),0,0,0));
  const typeCounts = {};
  recent.forEach(r => typeCounts[r.type] = (typeCounts[r.type] || 0) + 1);
  let topType = '—';
  if (Object.keys(typeCounts).length){
    const topId = Object.keys(typeCounts).sort((a,b)=> typeCounts[b]-typeCounts[a])[0];
    const tObj = types.find(t=>t.id===topId);
    topType = tObj ? `${tObj.name} (${typeCounts[topId]})` : `${topId} (${typeCounts[topId]})`;
  }
  topTypeEl.textContent = topType;
  // top mood
  const moodCounts = {};
  recent.forEach(r => { if (r.mood) moodCounts[r.mood] = (moodCounts[r.mood]||0)+1; });
  let topMood = '—';
  if (Object.keys(moodCounts).length){
    const m = Object.keys(moodCounts).sort((a,b)=> moodCounts[b]-moodCounts[a])[0];
    topMood = `${m} (${moodCounts[m]})`;
  }
  topMoodEl.textContent = topMood;
}

function roundRect(ctx, x, y, w, h, r){
  const radius = Math.min(r, w/2, h/2);
  ctx.beginPath();
  ctx.moveTo(x + radius, y);
  ctx.arcTo(x + w, y, x + w, y + h, radius);
  ctx.arcTo(x + w, y + h, x, y + h, radius);
  ctx.arcTo(x, y + h, x, y, radius);
  ctx.arcTo(x, y, x + w, y, radius);
  ctx.closePath();
}

/* =========================
   Reminders
   ========================= */
function openReminders(){
  reminderTime.value = reminder.time || '';
  enableRemindersInput.checked = !!reminder.enabled;
  reminderStatus.textContent = `Current saved: ${reminder.time || 'none'} (enabled: ${reminder.enabled ? 'yes' : 'no'})`;
  document.querySelectorAll('.modal').forEach(m=>m.classList.add('hidden'));
  modalReminders.classList.remove('hidden');
  showBackdrop();
}

async function saveReminderSettings(){
  const t = reminderTime.value || null;
  const en = !!enableRemindersInput.checked;
  reminder.time = t;
  reminder.enabled = en;
  saveJSON(KEYS.REMINDER, reminder);
  settings.enableReminders = en;
  saveJSON(KEYS.SETTINGS, settings);
  applySettingsToForm();
  applySettings();
  scheduleReminderLoop();
  hideBackdrop();
  if (en){
    // request permission if necessary
    if (Notification && Notification.permission !== 'granted') {
      try {
        await Notification.requestPermission();
      } catch(e){}
    }
  }
}

function scheduleReminderLoop(){
  if (reminderInterval) {
    clearInterval(reminderInterval);
    reminderInterval = null;
  }
  // only run if feature is enabled in settings and reminder.enabled
  if (!settings.enableReminders || !reminder.enabled || !reminder.time) return;
  // Do a check every 60 seconds (aligned to minute)
  checkReminderNow(); // immediate check
  reminderInterval = setInterval(checkReminderNow, 60 * 1000);
}

let lastReminderTrigger = null;
function checkReminderNow(){
  if (!reminder.time || !reminder.enabled) return;
  const now = new Date();
  const hh = pad(now.getHours());
  const mm = pad(now.getMinutes());
  const cur = `${hh}:${mm}`;
  if (cur !== reminder.time) return;
  // avoid repeat triggers within the same minute
  if (lastReminderTrigger === cur) return;
  lastReminderTrigger = cur;
  // show notification if permission
  if (window.Notification && Notification.permission === 'granted') {
    new Notification('Reminder', { body: 'Time to log an entry', silent: false });
  } else {
    // fallback: small on-screen prompt
    alert('Reminder: time to log an entry.');
  }
}

/* =========================
   Export / Import
   ========================= */
function csvEscape(val){
  if (val === null || val === undefined) return '';
  const s = String(val).replace(/\r?\n/g,' ');
  if (s.includes(',') || s.includes('"')) {
    return '"' + s.replaceAll('"','""') + '"';
  }
  return s;
}
function exportCSV(){
  if (!settings.enableExport) return alert('Export is disabled in Settings.');
  const header = ['timestamp','type','mood','severity','duration','notes'];
  const rows = entries.map(e => [e.timestamp, e.type, e.mood || '', e.severity ?? '', e.duration ?? '', e.notes || '']);
  const csv = [header.join(',')].concat(rows.map(r => r.map(csvEscape).join(','))).join('\n');
  const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
  downloadBlob('local-journal-export.csv', blob);
}

function exportJSON(){
  if (!settings.enableExport) return alert('Export is disabled in Settings.');
  const blob = new Blob([JSON.stringify(entries, null, 2)], { type: 'application/json;charset=utf-8' });
  downloadBlob('local-journal-export.json', blob);
}

function handleImportFile(e){
  const file = e.target.files && e.target.files[0];
  if (!file) return;
  const reader = new FileReader();
  reader.onload = (ev) => {
    try{
      const parsed = JSON.parse(ev.target.result);
      if (!Array.isArray(parsed)) return alert('Invalid JSON: expected an array of entries.');
      // basic validation
      const good = parsed.filter(p => p.timestamp && p.type);
      if (!good.length) return alert('No valid entries found.');
      // ask user whether to append or replace
      if (!confirm(`Import ${good.length} entries. Click OK to append to existing entries.`)) return;
      // ensure ids
      const normalized = good.map(x=>{
        return {
          id: x.id || ('e_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2,8)),
          timestamp: x.timestamp,
          type: x.type,
          mood: x.mood || '',
          severity: x.severity ?? null,
          duration: x.duration ?? null,
          notes: x.notes || ''
        };
      });
      entries = entries.concat(normalized);
      saveJSON(KEYS.ENTRIES, entries);
      renderEntries();
      drawWeekChart();
      alert('Import complete.');
    }catch(err){
      console.error(err);
      alert('Failed to import JSON: ' + err.message);
    } finally {
      e.target.value = '';
    }
  };
  reader.readAsText(file);
}

/* =========================
   Clearing
   ========================= */
function clearAllData(){
  if (!confirm('Clear all app data (entries, types, settings, reminders)? This cannot be undone.')) return;
  localStorage.removeItem(KEYS.ENTRIES);
  localStorage.removeItem(KEYS.TYPES);
  localStorage.removeItem(KEYS.SETTINGS);
  localStorage.removeItem(KEYS.REMINDER);
  entries = [];
  types = defaultTypes.slice();
  settings = DEFAULT_SETTINGS;
  reminder = DEFAULT_REMINDER;
  applySettingsToForm();
  applySettings();
  renderTypeSelectors();
  renderEntries();
  drawWeekChart();
  alert('All data cleared.');
}

function clearEntries(){
  if (!confirm('Clear all saved entries?')) return;
  entries = [];
  saveJSON(KEYS.ENTRIES, entries);
  renderEntries();
  drawWeekChart();
}

/* =========================
   Export modal & import
   ========================= */
function openExport(){
  if (!settings.enableExport) return alert('Export is disabled in settings.');
  document.querySelectorAll('.modal').forEach(m=>m.classList.add('hidden'));
  modalExport.classList.remove('hidden');
  showBackdrop();
}

/* =========================
   Settings modal
   ========================= */
function openSettings(){
  applySettingsToForm();
  document.querySelectorAll('.modal').forEach(m=>m.classList.add('hidden'));
  modalSettings.classList.remove('hidden');
  showBackdrop();
}

/* =========================
   Emoji picker
   ========================= */
const EMOJIS = [
  // Saddest / Negative
  '😭','😢','😞','😟','🙁','☹️',
  '😣','😖','😫','😩',
  '😠','😡','🤬',

  // Worried / Fearful
  '😨','😰','😱','😧',

  // Neutral / Ambiguous
  '😶','😐','😑','🙄','😬','🤔','🤨',

  // Surprised / Shocked
  '😯','😮','😲','😳','😵','🤯',

  // Slightly Positive
  '🙂','😊','😌','😉',

  // Happy / Laughing
  '😃','😄','😁','😆','😂','🤣',

  // Playful / Excited
  '😋','😜','🤪','😝','🤩','🥳'
]

function setupEmojiPicker(){
  emojiPicker.innerHTML = '';
  EMOJIS.forEach(e=>{
    const b = document.createElement('button');
    b.className = 'emoji-btn';
    b.textContent = e;
    b.title = e;
    b.addEventListener('click', ()=> {
      entryMood.value = e;
      quickMood.value = e;
      emojiPicker.classList.add('hidden');
    });
    emojiPicker.appendChild(b);
  });
}

/* =========================
   Toggle collapse list
   ========================= */
function toggleCollapse(){
  isListCollapsed = !isListCollapsed;
  entriesBody.parentElement.style.display = isListCollapsed ? 'none' : '';
  document.getElementById('toggleCollapse').textContent = isListCollapsed ? 'Expand' : 'Collapse';
}

/* =========================
   Import/Export helpers in settings
   ========================= */
function handleImportJsonText(jsonText){
  try{
    const parsed = JSON.parse(jsonText);
    if (!Array.isArray(parsed)) throw new Error('Expected array');
    entries = entries.concat(parsed.map(x => ({
      id: x.id || ('e_' + Date.now().toString(36) + Math.random().toString(36).slice(2,5)),
      timestamp: x.timestamp,
      type: x.type,
      mood: x.mood || '',
      severity: x.severity ?? null,
      duration: x.duration ?? null,
      notes: x.notes || ''
    })));
    saveJSON(KEYS.ENTRIES, entries);
    renderEntries();
    drawWeekChart();
    alert('Imported ' + parsed.length + ' entries.');
  }catch(err){
    alert('Import failed: ' + err.message);
  }
}

/* =========================
   Init: ensure types set
   ========================= */
if (!Array.isArray(types) || types.length === 0){
  types = defaultTypes.slice();
  saveJSON(KEYS.TYPES, types);
}
if (!settings || typeof settings !== 'object'){ settings = DEFAULT_SETTINGS; saveJSON(KEYS.SETTINGS, settings); }
if (!reminder || typeof reminder !== 'object'){ reminder = DEFAULT_REMINDER; saveJSON(KEYS.REMINDER, reminder); }

init();

/* =========================
   Extra: Save settings watchers
   ========================= */
window.addEventListener('beforeunload', ()=> {
  saveJSON(KEYS.ENTRIES, entries);
  saveJSON(KEYS.TYPES, types);
  saveJSON(KEYS.SETTINGS, settings);
  saveJSON(KEYS.REMINDER, reminder);
});

/* =========================
   Other UI wiring for convenience
   ========================= */
document.getElementById('btnExport2').addEventListener('click', openExport);
document.getElementById('btnExport').addEventListener('click', openExport);
document.getElementById('btnQuickLog').addEventListener('click', openQuickLog);

/* === Handle imported file from sidebar input === */
document.getElementById('importFile').addEventListener('change', handleImportFile);

</script>
</body>
</html>
/* Add your styles here */

// Add your code here

<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>Local Journal — Complete User Guide</title>
<style>
  :root{
    --bg:#0f1724; --card:#0b1220; --muted:#94a3b8; --text:#e6eef8; --accent:#7c3aed;
    --glass: rgba(124,58,237,0.06);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
  }
  html,body{margin:0;height:100%;background:linear-gradient(180deg,#071029 0%, #07121d 100%);color:var(--text);}
  .wrap{max-width:1000px;margin:28px auto;padding:20px;}
  header{display:flex;align-items:baseline;gap:12px;flex-wrap:wrap}
  h1{margin:0;font-size:20px}
  .card{background:linear-gradient(180deg,rgba(255,255,255,0.02),transparent);border-radius:10px;padding:14px;box-shadow:0 8px 24px rgba(0,0,0,0.6);margin-top:14px}
  nav {display:flex; gap:8px; flex-wrap:wrap}
  a.btn {padding:8px 10px;border-radius:8px;background:var(--accent);color:white;text-decoration:none;font-weight:600}
  .muted{color:var(--muted);font-size:13px}
  .toc {display:grid;grid-template-columns: 1fr 220px; gap:12px}
  ul {margin:0;padding-left:18px}
  pre {background:#031126;padding:12px;border-radius:8px;overflow:auto}
  table{width:100%;border-collapse:collapse;margin-top:8px}
  th,td{padding:8px;border-bottom:1px solid rgba(255,255,255,0.04);text-align:left;font-family:monospace;font-size:13px}
  .id {background:var(--glass);padding:4px 6px;border-radius:6px;font-family:monospace;display:inline-block}
  .kbd{background:#071730;padding:2px 6px;border-radius:4px;border:1px solid rgba(255,255,255,0.02);font-family:monospace}
  .search{margin-top:8px;display:flex;gap:8px}
  input[type="search"]{flex:1;padding:8px;border-radius:8px;border:1px solid rgba(255,255,255,0.04);background:transparent;color:var(--text)}
  .example {background:linear-gradient(90deg, rgba(124,58,237,0.06), transparent);padding:10px;border-radius:8px}
  footer{margin-top:18px;color:var(--muted);font-size:13px}
  details summary{cursor:pointer}
  .warn{color:#fecaca}
  .ok{color:#bbf7d0}
</style>
</head>
<body>
  <div class="wrap">
    <header>
      <h1>Local Journal — Complete User Guide</h1>
      <div class="muted">Reference & walkthrough for the UI in your app (based on your uploaded file). :contentReference[oaicite:1]{index=1}</div>
    </header>

    <div class="card">
      <nav>
        <a class="btn" href="#quickstart">Quick start</a>
        <a class="btn" href="#ui-map">UI map</a>
        <a class="btn" href="#modals">Modals</a>
        <a class="btn" href="#data">Data & Storage</a>
        <a class="btn" href="#tips">Tips & Troubleshooting</a>
      </nav>

      <div style="margin-top:12px" class="muted">
        This guide documents every control, id, and behavior in the web app so you (or another developer) can use or extend it reliably.
      </div>
    </div>

    <section id="quickstart" class="card">
      <h2>Quick start — common tasks</h2>
      <ol>
        <li><strong>Add a full entry</strong>
          <ul>
            <li>Click <span class="id">+ Add Entry</span> (ID: <span class="id">btnAddEntry</span>).</li>
            <li>In the modal: set <span class="id">Date & time</span> (<span class="id">entryDate</span>), choose a <span class="id">Type</span> (<span class="id">entryType</span>), optionally set <span class="id">Mood</span> (<span class="id">entryMood</span>), <span class="id">Severity</span> (<span class="id">entrySeverity</span>), <span class="id">Duration</span> (<span class="id">entryDuration</span>), and enter <span class="id">Notes</span> (<span class="id">entryNotes</span>).</li>
            <li>Click <span class="id">Save</span> (ID: <span class="id">btnSaveEntry</span>).</li>
          </ul>
        </li>
        <li><strong>Quick log</strong>
          <ul>
            <li>Click <span class="id">Quick Log</span> (ID: <span class="id">btnQuickLog</span>) to add a minimal entry (time + type + optional mood).</li>
            <li>Click <span class="id">Save</span> (ID: <span class="id">btnSaveQuick</span>).</li>
          </ul>
        </li>
        <li><strong>View or delete an entry</strong>
          <ul>
            <li>In the entries table click <span class="id">View</span> or <span class="id">Delete</span> actions for a row (table body ID: <span class="id">entriesBody</span>).</li>
            <li>Viewing opens <span class="id">View Entry</span> modal (ID: <span class="id">modalViewEntry</span>); delete confirms and removes from storage.</li>
          </ul>
        </li>
        <li><strong>Export / import</strong>
          <ul>
            <li>Open Export via <span class="id">Export</span> button (IDs: <span class="id">btnExport</span>, <span class="id">btnExport2</span>) and choose CSV or JSON (IDs: <span class="id">exportCSV</span>, <span class="id">exportJSON</span>).</li>
            <li>To import JSON: either use the import file input (ID: <span class="id">importFile</span>) or the import button inside the export modal (<span class="id">openImportFile</span>).</li>
          </ul>
        </li>
      </ol>
    </section>

    <section id="ui-map" class="card">
      <h2>UI map — controls, IDs and what they do</h2>
      <p class="muted">This list maps every visible control to its DOM id and the precise behavior implemented in the app.</p>

      <h3>Left column — Quick actions & data</h3>
      <table>
        <tr><th>Label</th><th>ID / selector</th><th>Behavior</th></tr>
        <tr><td>+ Add Entry</td><td class="id">#btnAddEntry</td><td>Opens Add Entry modal (<span class="id">#modalAddEntry</span>) prefilled with current datetime.</td></tr>
        <tr><td>Quick Log</td><td class="id">#btnQuickLog</td><td>Opens Quick Log modal (<span class="id">#modalQuickLog</span>).</td></tr>
        <tr><td>Manage Event Types</td><td class="id">#btnManageTypes, #btnManageTypes2</td><td>Opens Types manager (ID: <span class="id">#modalManageTypes</span>) where types can be edited, added, or deleted.</td></tr>
        <tr><td>Reminders</td><td class="id">#btnReminders</td><td>Opens the Reminders modal (ID: <span class="id">#modalReminders</span>). Feature gated by setting <span class="id">settingReminders</span>.</td></tr>
        <tr><td>Export / Import</td><td class="id">#btnExport, #btnExport2, #btnImport, #importFile</td><td>Open export modal or open file dialog for JSON import.</td></tr>
        <tr><td>Clear All</td><td class="id">#btnClearAll</td><td>Removes all saved localStorage keys after a confirmation prompt.</td></tr>
      </table>

      <h3>Right column — Chart & Entries</h3>
      <table>
        <tr><th>Element</th><th>ID</th><th>Behavior / Notes</th></tr>
        <tr><td>Weekly chart canvas</td><td class="id">#weekChart</td><td>Custom-drawn bar chart summarizing last 7 days; updates after each add/import/delete.</td></tr>
        <tr><td>Entries table</td><td class="id">#entriesTable / #entriesBody</td><td>Shows all saved entries (newest first). Each row has action buttons wired to view/delete.</td></tr>
        <tr><td>Collapse / Clear</td><td class="id">#toggleCollapse, #btnClearEntries</td><td>Toggle hides table body or clears only entries (not types/settings).</td></tr>
      </table>

      <h3>Modals (IDs)</h3>
      <ul>
        <li><span class="id">#modalAddEntry</span> — Add Entry</li>
        <li><span class="id">#modalQuickLog</span> — Quick Log</li>
        <li><span class="id">#modalManageTypes</span> — Manage Event Types</li>
        <li><span class="id">#modalReminders</span> — Reminders</li>
        <li><span class="id">#modalSettings</span> — Settings</li>
        <li><span class="id">#modalExport</span> — Export / Import</li>
        <li><span class="id">#modalViewEntry</span> — View a single entry</li>
      </ul>

      <h3>Settings toggles (IDs)</h3>
      <p class="muted">These are the persistent settings available in the Settings modal (will be saved to localStorage):</p>
      <table>
        <tr><th>Toggle</th><th>ID</th><th>What it does</th></tr>
        <tr><td>Enable Mood field</td><td class="id">#settingMood</td><td>Show/hide mood inputs in Add Entry and Quick Log.</td></tr>
        <tr><td>Enable Severity field</td><td class="id">#settingSeverity</td><td>Show/hide severity input; severity is intended for 'action' types.</td></tr>
        <tr><td>Enable Reminders</td><td class="id">#settingReminders</td><td>Controls visibility and scheduling of reminders (uses Notifications API if available).</td></tr>
        <tr><td>Enable Export/Import</td><td class="id">#settingExport</td><td>Shows/hides Export buttons.</td></tr>
        <tr><td>Compact UI</td><td class="id">#settingCompact</td><td>Toggles compact layout CSS class on body.</td></tr>
      </table>
    </section>

    <section id="modals" class="card">
      <h2>Modal details — fields, validation, and flow</h2>

      <h3>Add Entry modal (<span class="id">#modalAddEntry</span>)</h3>
      <div class="example">
        <strong>Fields:</strong>
        <ul>
          <li><span class="id">entryDate</span> — datetime-local, defaults to now.</li>
          <li><span class="id">entryType</span> — select populated from saved types.</li>
          <li><span class="id">entryMood</span> — text input, emoji picker available (<span class="id">openEmojiPicker</span> / <span class="id">emojiPicker</span>).</li>
          <li><span class="id">entrySeverity</span> — number (1–10).</li>
          <li><span class="id">entryDuration</span> — number (minutes).</li>
          <li><span class="id">entryNotes</span> — free text.</li>
        </ul>
        <strong>Save behavior:</strong> click <span class="id">#btnSaveEntry</span>, an entry object is created and prepended to the entries array and persisted to localStorage under the entries key.
      </div>

      <h3>Manage Event Types (<span class="id">#modalManageTypes</span>)</h3>
      <p class="muted">Types are objects with <code>id</code>, <code>name</code>, and <code>action</code> boolean. Action types are treated specially (severity relevance, labeling).</p>
      <ul>
        <li>Rename: edit the input and click the local Save button next to that type.</li>
        <li>Delete: removes type from the types list; existing entries that reference the type keep their raw type id (no automatic remap).</li>
        <li>Add new type: use <span class="id">#newTypeName</span>, check <span class="id">#newTypeAction</span> if it's an action, then click <span class="id">#btnAddType</span>.</li>
      </ul>
      <details>
        <summary>Developer note: how new type id is generated</summary>
        The id is a sanitized slug plus a timestamp chunk, so collisions are extremely unlikely. Example generation logic uses `Date.now()` and `.toString(36)`.
      </details>

      <h3>Reminders (<span class="id">#modalReminders</span>)</h3>
      <p>Set a time (HH:MM) and enable reminders. When enabled, the app checks every minute. If Notifications permission is granted it will show a Notification; otherwise it falls back to an <code>alert()</code>.</p>
      <p class="warn">Browser tabs may be suspended when backgrounded; reminders rely on the tab being active or the browser providing background wakeups. Do not rely on this for urgent alerts.</p>

      <h3>Export / Import (<span class="id">#modalExport</span>)</h3>
      <ul>
        <li>CSV export: downloads a CSV file with headers: <code>timestamp,type,mood,severity,duration,notes</code>.</li>
        <li>JSON export: downloads the raw entries array as JSON.</li>
        <li>Import: expects an array of entry objects. The importer validates presence of <code>timestamp</code> and <code>type</code>, and will prompt you to append (default) instead of replacing.</li>
      </ul>
    </section>

    <section id="data" class="card">
      <h2>Data model & storage</h2>
      <p class="muted">All persistent data is saved to <code>localStorage</code> under versioned keys. Changing <code>APP_VERSION</code> in the app script will effectively isolate data to a new set of keys.</p>

      <h3>Keys</h3>
      <table>
        <tr><th>Key constant</th><th>localStorage key</th><th>Contents</th></tr>
        <tr><td>ENTRIES</td><td class="id">LOCALJOURNAL_v1_ENTRIES</td><td>Array of entry objects</td></tr>
        <tr><td>TYPES</td><td class="id">LOCALJOURNAL_v1_TYPES</td><td>Array of type objects</td></tr>
        <tr><td>REMINDER</td><td class="id">LOCALJOURNAL_v1_REMINDER</td><td>Object {time,enabled}</td></tr>
        <tr><td>SETTINGS</td><td class="id">LOCALJOURNAL_v1_SETTINGS</td><td>Object of UI toggles</td></tr>
      </table>

      <h3>Entry object shape</h3>
      <pre>{
  "id": "e_1678abcd",
  "timestamp": "2025-10-01T14:30:00.000Z",
  "type": "nssi_ideation",
  "mood": "😞",
  "severity": 4,
  "duration": 15,
  "notes": "Contextual notes..."
}</pre>

      <h3>Safety & privacy</h3>
      <p class="muted">All data is stored locally — no network requests — but files created by Export can be shared. If you clear localStorage using the Clear All button, data cannot be recovered unless you exported it earlier.</p>
    </section>

    <section id="tips" class="card">
      <h2>Tips, troubleshooting & developer notes</h2>

      <h3>Common troubleshooting</h3>
      <ul>
        <li><strong>Entries not saving?</strong> Check that your browser allows localStorage for the page and that you're not in a strict private window that disables storage.</li>
        <li><strong>Import shows validation error</strong> — the importer expects an <code>Array</code> at the root and each item must have <code>timestamp</code> and <code>type</code>. If your JSON uses a different shape, convert it before import.</li>
        <li><strong>Notifications don't appear</strong> — ensure you granted Notification permission for the site and the tab is open (browsers may restrict background notifications for untrusted origins).</li>
        <li><strong>Severity not shown for some entries</strong> — severity is displayed only when the selected type is marked <em>action</em>. See the Types manager.</li>
      </ul>

      <h3>Advanced usage & extension points (for developers)</h3>
      <ol>
        <li><strong>Change storage versioning</strong> — update <code>APP_VERSION</code> constant to isolate new data sets.</li>
        <li><strong>Custom export:</strong> The export functions use a simple CSV/JSON blob download. Hook <code>exportCSV()</code> or <code>exportJSON()</code> to pipe data elsewhere (e.g., to a server) if you add auth/networking.</li>
        <li><strong>Type remapping:</strong> Deleting a type leaves existing entries referencing the old id. A migration routine could map or normalize legacy ids after a type rename/delete.</li>
        <li><strong>Tests & automation:</strong> Many DOM hooks are id-based and simple to target in integration tests (Cypress / Playwright). Key hooks: <span class="id">#btnSaveEntry</span>, <span class="id">#importFile</span>, <span class="id">#entriesBody</span>.</li>
      </ol>

      <h3>Keyboard & accessibility notes</h3>
      <p class="muted">The app uses standard inputs and buttons but does not currently implement custom keyboard shortcuts. Modals are shown/hidden by toggling a backdrop element which has ARIA attributes set; further accessibility improvements could include focus trapping and ARIA labels on action buttons.</p>

      <h3>Safety: content note</h3>
      <p class="warn">The default type list in the app includes sensitive categories (e.g., self-harm related types). If you or your users are collecting highly sensitive information, ensure appropriate safeguards: exit paths, disclaimers, or professional support links. The app does not transmit data off-device.</p>
    </section>

    <section class="card">
      <h2>Quick index of selectors</h2>
      <p class="muted">Copy/paste friendly ID list for developers and testers.</p>
      <pre>
#btnAddEntry
#btnQuickLog
#btnManageTypes
#btnReminders
#btnExport, #btnExport2
#importFile
#entriesTable, #entriesBody
#weekChart
#modalAddEntry, #modalQuickLog, #modalManageTypes, #modalReminders, #modalSettings, #modalExport, #modalViewEntry
#entryDate, #entryType, #entryMood, #entrySeverity, #entryDuration, #entryNotes
#quickDate, #quickType, #quickMood
#newTypeName, #newTypeAction, #btnAddType
#reminderTime, #enableReminders
#settingMood, #settingSeverity, #settingReminders, #settingExport, #settingCompact
      </pre>
    </section>

    <footer>
      <div class="muted">Generated guide — intended to be a comprehensive developer & user reference for the application contained in your uploaded file. If you'd like, I can:
        <ul>
          <li>Embed this guide into your app as a help panel or a route like <code>/help</code>.</li>
          <li>Generate a printable PDF version.</li>
          <li>Produce concise "Quick Tips" HTML suitable for new users (2-page cheat sheet).</li>
        </ul>
      </div>
    </footer>
  </div>
</body>
</html>