diff --git a/web/app.js b/web/app.js
index a34351d..5d2904e 100644
--- a/web/app.js
+++ b/web/app.js
@@ -636,14 +636,45 @@
const affHtml = affs.map(a => `${AFF_LABELS[a]}`).join('');
return `
-
${escHtml(title)}
-
—
-
${preview}
-
- ${affHtml}
- ${tags}
- ${e.pinned ? '
★' : ''}
- ${e.use_count > 0 ? `
${e.use_count}×` : ''}
+
+
${escHtml(title)}
+
—
+
${preview}
+
+ ${affHtml}
+ ${tags}
+ ${e.pinned ? '★' : ''}
+ ${e.use_count > 0 ? `${e.use_count}×` : ''}
+
+
+
+
+ ${renderInlineDetail(e)}
+
+
+
`;
+ }
+
+ function renderInlineDetail(e) {
+ const tags = (e.tags || []).map(t => `
#${t}`).join('');
+ let actions = '';
+ actions += `
`;
+ if (!e.card_type) {
+ actions += `
`;
+ actions += `
`;
+ }
+ if (e.card_type) {
+ actions += `
`;
+ } else {
+ actions += `
`;
+ }
+ return `
+
${renderMd(e.body || '')}
+ ${tags ? `
${tags}
` : ''}
+
${actions}
+
+
+
`;
}
@@ -668,11 +699,18 @@
}
return `
-
${glyph}
- ${label}
- ${time}
-
${tags}${cardBadge}
-
${useBadge}
+
+ ${glyph}
+ ${label}
+ ${time}
+ ${tags}${cardBadge}
+ ${useBadge}
+
+
+
+ ${renderInlineDetail(e)}
+
+
`;
}
@@ -1100,6 +1138,20 @@
// ========== Actions ==========
function selectEntity(idx) {
+ if (isMobileBreakpoint()) {
+ const prev = state.selectedIndex;
+ if (prev === idx) {
+ state.selectedIndex = -1;
+ } else {
+ state.selectedIndex = idx;
+ }
+ $$('.entity-item.selected, .card-row.selected').forEach(el => el.classList.remove('selected'));
+ if (state.selectedIndex >= 0) {
+ const target = $(`.entity-item[data-index="${state.selectedIndex}"], .card-row[data-index="${state.selectedIndex}"]`);
+ if (target) target.classList.add('selected');
+ }
+ return;
+ }
state.selectedIndex = idx;
state.peekMode = 'preview';
state.runChecked = new Set();
@@ -1401,6 +1453,38 @@
if (idx >= 0) { state.selectedIndex = idx; renderEntityList(); renderDetailPane(); }
showToast(e.pinned ? 'unpinned' : 'pinned');
},
+
+ togglePeekFull() {
+ if (isMobileBreakpoint()) {
+ this.expandInline();
+ return;
+ }
+ const pane = $('#detail-pane');
+ pane.classList.toggle('peek-full');
+ const btn = pane.querySelector('.peek-mobile-btn');
+ if (btn) btn.textContent = pane.classList.contains('peek-full') ? '↓' : '↑';
+ },
+
+ expandInline() {
+ const sel = $(`.entity-item.selected, .card-row.selected`);
+ if (!sel) return;
+ sel.classList.toggle('exp-full');
+ const btn = sel.querySelector('.exp-toolbar .peek-mobile-btn');
+ if (btn) btn.textContent = sel.classList.contains('exp-full') ? '↓' : '↑';
+ },
+
+ dismissPeek() {
+ if (isMobileBreakpoint()) {
+ const sel = $(`.entity-item.selected, .card-row.selected`);
+ if (sel) sel.classList.remove('selected', 'exp-full');
+ state.selectedIndex = -1;
+ return;
+ }
+ const pane = $('#detail-pane');
+ pane.classList.remove('visible', 'peek-full');
+ state.selectedIndex = -1;
+ renderEntityList();
+ },
};
// ========== Promote modal ==========
@@ -1451,12 +1535,26 @@
return;
}
- if (ev.key === 'Escape' && $('main').classList.contains('focus-peek')) {
- exitFocusPeek();
- state.selectedIndex = -1;
- renderEntityList();
- renderDetailPane();
- return;
+ if (ev.key === 'Escape') {
+ if (isMobileBreakpoint()) {
+ if (state.selectedIndex >= 0) {
+ const sel = $(`.entity-item.selected, .card-row.selected`);
+ if (sel) sel.classList.remove('selected', 'exp-full');
+ state.selectedIndex = -1;
+ return;
+ }
+ }
+ const pane = $('#detail-pane');
+ if ($('main').classList.contains('focus-peek')) {
+ exitFocusPeek();
+ }
+ if (pane.classList.contains('visible')) {
+ pane.classList.remove('visible', 'peek-full');
+ state.selectedIndex = -1;
+ renderEntityList();
+ renderDetailPane();
+ return;
+ }
}
const sel = state.entities[state.selectedIndex];
@@ -1540,7 +1638,16 @@
localStorage.setItem('nib:' + cls, m.classList.contains(cls) ? '1' : '');
}
+ function isMobileBreakpoint() {
+ return window.matchMedia('(max-width: 900px)').matches;
+ }
+
function toggleZen() {
+ if (isMobileBreakpoint()) {
+ if (state.selectedIndex >= 0) nibApp.togglePeekFull();
+ return;
+ }
+
const m = $('main');
if (m.classList.contains('focus-peek')) {
diff --git a/web/style.css b/web/style.css
index 2e3863a..07fb835 100644
--- a/web/style.css
+++ b/web/style.css
@@ -375,28 +375,72 @@ main.focus-peek .resize-handle { visibility: hidden; }
}
.entity-item {
+ cursor: pointer;
+ border-left: 2px solid transparent;
+ transition: background var(--t-fast), border-left-color var(--t-fast);
+}
+
+.entity-head {
display: flex;
align-items: center;
gap: 8px;
padding: 5px 16px 5px 20px;
- cursor: pointer;
- border-left: 2px solid transparent;
min-height: 32px;
- transition: background var(--t-fast), border-left-color var(--t-fast);
}
.entity-item:hover { background: var(--surf); }
.entity-item.selected { background: var(--surf); border-left-color: var(--accent); }
+.entity-exp { display: none; }
+
+.entity-exp-clip { overflow: hidden; }
+
+.exp-inner {
+ padding: .6rem 1rem .7rem calc(20px + 14px + 8px);
+ border-top: 1px solid var(--border);
+}
+
+.exp-body {
+ font-family: var(--mono);
+ font-size: 11px;
+ color: var(--text);
+ line-height: 1.7;
+ white-space: pre-wrap;
+ word-break: break-word;
+ margin-bottom: .5rem;
+ display: -webkit-box;
+ -webkit-line-clamp: 3;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+}
+
+.entity-item.exp-full .exp-body {
+ -webkit-line-clamp: unset;
+ overflow: visible;
+}
+
+.exp-tags { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: .5rem; }
+
+.exp-acts { display: flex; flex-wrap: wrap; gap: 4px; }
+
+.exp-toolbar {
+ display: none;
+ justify-content: space-between;
+ margin-top: .5rem;
+ padding-top: .5rem;
+ border-top: 1px solid var(--border);
+}
+
.entity-item.is-card {
background: var(--surf);
margin: 2px 10px;
border-radius: var(--r2);
border: 1px solid var(--border);
border-left-width: 1px;
- padding: 7px 12px;
}
+.entity-item.is-card .entity-head { padding: 7px 12px; }
+
.entity-item.is-card:hover { border-color: var(--muted); }
.entity-item.is-card.selected { border-color: var(--accent); background: var(--a-bg); }
@@ -556,20 +600,23 @@ main.focus-peek .resize-handle { visibility: hidden; }
/* ── CARD ROWS ──────────────────────────────────────── */
.card-row {
- display: flex;
- align-items: center;
- gap: 7px;
- padding: 9px 12px 9px 14px;
margin: 2px 10px;
background: var(--surf);
border: 1px solid var(--border);
border-radius: var(--r2);
cursor: pointer;
- min-height: 40px;
position: relative;
transition: border-color var(--t-fast), background var(--t-fast);
}
+.card-head {
+ display: flex;
+ align-items: center;
+ gap: 7px;
+ padding: 9px 12px 9px 14px;
+ min-height: 40px;
+}
+
.card-row:hover { border-color: var(--muted); }
.card-row.selected { border-color: var(--accent); background: var(--a-bg); }
.card-row.pinned { border-left: 2px solid var(--accent); }
@@ -785,6 +832,21 @@ main.focus-peek .resize-handle { visibility: hidden; }
overflow: hidden;
}
+.peek-mobile-btn {
+ font-family: var(--mono);
+ font-size: 14px;
+ color: var(--muted);
+ background: none;
+ border: 1px solid var(--border);
+ border-radius: 4px;
+ width: 28px;
+ height: 28px;
+ cursor: pointer;
+ transition: color var(--t-fast), border-color var(--t-fast);
+}
+
+.peek-mobile-btn:hover { color: var(--accent); border-color: var(--accent); }
+
.peek-scroll {
flex: 1;
overflow-y: auto;
@@ -1443,8 +1505,17 @@ kbd { background: var(--raised); border: 1px solid var(--border); border-radius:
/* ── RESPONSIVE ─────────────────────────────────────── */
@media (max-width: 900px) {
- main { grid-template-columns: 1fr; }
- #tag-rail { display: none; }
+ main,
+ main.hide-rail,
+ main.hide-peek,
+ main.hide-rail.hide-peek,
+ main.focus-peek {
+ grid-template-columns: 1fr !important;
+ transition: none !important;
+ }
+ #tag-rail { display: none !important; }
+ .resize-handle { display: none !important; }
+ #entity-panel { overflow: auto; }
#detail-pane {
position: fixed;
inset: 0;
@@ -1457,5 +1528,31 @@ kbd { background: var(--raised); border: 1px solid var(--border); border-radius:
transition: transform var(--t-base);
z-index: 50;
}
- #detail-pane.visible { transform: translateY(0); }
+ #detail-pane { display: none !important; }
+ .entity-exp {
+ display: grid;
+ grid-template-rows: 0fr;
+ transition: grid-template-rows .2s ease;
+ }
+ .entity-item.selected .entity-exp,
+ .card-row.selected .entity-exp { grid-template-rows: 1fr; }
+ .entity-item.selected .exp-toolbar,
+ .card-row.selected .exp-toolbar { display: flex; }
+ .entity-item.exp-full,
+ .entity-item.is-card.exp-full,
+ .card-row.exp-full {
+ position: fixed;
+ inset: 0;
+ z-index: 60;
+ background: var(--bg);
+ overflow-y: auto;
+ border: none;
+ margin: 0;
+ border-radius: 0;
+ }
+ .entity-item.exp-full .entity-exp,
+ .card-row.exp-full .entity-exp { grid-template-rows: 1fr; }
+ .entity-item.exp-full .exp-inner,
+ .card-row.exp-full .exp-inner { padding-top: 1rem; padding-bottom: 2rem; }
+ main.focus-peek #entity-panel { display: block; overflow: auto; min-width: 0; }
}