diff --git a/src/style.css b/src/style.css
index 1286ed1..e88fcfe 100644
--- a/src/style.css
+++ b/src/style.css
@@ -8,7 +8,16 @@ body {
color: #222;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
- overflow-x: hidden;
+ overflow: hidden;
+}
+
+#app-content {
+ position: fixed;
+ top: 36px;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ overflow-y: auto;
}
/* ── Titlebar ── */
@@ -78,8 +87,7 @@ body {
flex-direction: column;
align-items: center;
justify-content: center;
- height: 100vh;
- padding-top: 36px;
+ height: 100%;
background: #1a1b2e;
}
@@ -206,6 +214,23 @@ body {
z-index: 99;
overflow: hidden;
}
+
+.sidebar__scroll {
+ flex: 1;
+ min-height: 0;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+}
+
+.sidebar__footer {
+ flex-shrink: 0;
+ display: flex;
+ flex-direction: column;
+ padding: 4px 0 8px;
+ border-top: 1px solid rgba(255,255,255,0.06);
+}
+
.sidebar__title-block {
margin: 32px 24px 8px;
flex-shrink: 0;
@@ -233,7 +258,7 @@ body {
.sidebar__menu {
list-style: none;
margin: 0;
- padding: 8px 0 48px 0;
+ padding: 8px 0;
flex: 1;
overflow-y: auto;
}
@@ -379,12 +404,12 @@ body {
/* ── Content ── */
.content {
margin-left: 264px;
- padding-top: 84px;
+ padding-top: 48px;
padding-right: 72px;
padding-bottom: 96px;
padding-left: 72px;
max-width: 1080px;
- min-height: 100vh;
+ min-height: 100%;
background: #fff;
}
@@ -459,11 +484,8 @@ body {
/* ── Customize CSS button ── */
.btn-customize-css {
- position: fixed;
- bottom: 60px;
- left: 12px;
- width: 240px;
- z-index: 100;
+ width: calc(100% - 24px);
+ margin: 4px 12px 0;
background: transparent;
color: rgba(255,255,255,0.7);
border: 1px solid rgba(255,255,255,0.15);
@@ -626,11 +648,7 @@ body {
/* ── Back button ── */
.btn-back {
- position: fixed;
- bottom: 24px;
- left: 0;
- width: 264px;
- z-index: 98;
+ width: 100%;
background: transparent;
color: rgba(255,255,255,0.45);
border: none;
@@ -641,7 +659,6 @@ body {
cursor: pointer;
text-align: left;
transition: color 0.2s;
- z-index: 100;
}
.btn-back:hover { color: #ff5577; }
@@ -651,7 +668,7 @@ body {
left: -300px;
transition: left 0.2s cubic-bezier(0.09, 0.46, 0.45, 0.94);
}
- .content { margin-left: 0; padding: 68px 24px 64px; }
+ .content { margin-left: 0; padding: 32px 24px 64px; }
}
@media screen and (max-width: 540px) {
.content { padding: 68px 16px 48px; }
diff --git a/src/ui/reader.js b/src/ui/reader.js
index 9b74170..15df362 100644
--- a/src/ui/reader.js
+++ b/src/ui/reader.js
@@ -4,6 +4,37 @@ const win = window.__TAURI__.window.getCurrentWindow();
const titlebarTitle = document.getElementById('titlebar-title');
const content = document.querySelector('#content');
+function resolveRelativePath(currentFile, href) {
+ const sep = currentFile.includes('\\') ? '\\' : '/';
+ const dir = currentFile.split(sep).slice(0, -1).join(sep);
+ const parts = [...dir.split(sep), ...href.split('/')];
+ const resolved = [];
+ for (const part of parts) {
+ if (part === '..') resolved.pop();
+ else if (part !== '.') resolved.push(part);
+ }
+ return resolved.join(sep);
+}
+
+function wireLinks(filePath, mode, sidebarEl) {
+ content.querySelectorAll('a[href]').forEach(a => {
+ const href = a.getAttribute('href');
+ if (!href || href.startsWith('#')) return;
+
+ if (/^https?:\/\//.test(href)) {
+ a.setAttribute('target', '_blank');
+ a.setAttribute('rel', 'noopener noreferrer');
+ return;
+ }
+
+ a.addEventListener('click', async e => {
+ e.preventDefault();
+ const resolved = resolveRelativePath(filePath, href);
+ await loadPage(resolved, mode, sidebarEl);
+ });
+ });
+}
+
export async function loadPage(filePath, mode, sidebarEl) {
try {
const html = await convertFile(filePath);
@@ -27,6 +58,8 @@ export async function loadPage(filePath, mode, sidebarEl) {
}
}
}
+
+ wireLinks(filePath, mode, sidebarEl);
} catch (err) {
content.innerHTML = `
Impossible de charger le fichier : ${err}
`;
}