joplock/public/styles.css
igor 4b9e1bba1c fix(mobile): allow zoom, stop sticky hover, calm touch and motion
- one viewport meta for every page: zoom is no longer blocked
  (user-scalable=no also stopped pinch zoom on Android; WCAG 1.4.4) and
  interactive-widget=resizes-content makes Android resize for the
  keyboard. iOS already ignored the old tags.
- viewport.js does not pin the scroll while the page is pinch-zoomed,
  or it would fight the user's panning
- 38 pure :hover rules moved into @media (hover: hover): iOS emulates
  hover on a tap and left the tapped toolbar button or row highlighted.
  Reveal-on-hover rules with touch fallbacks are untouched, and a test
  fails if a bare :hover rule is added
- touch block: no tap flash, selection or callout on controls (long-
  pressing a row no longer opens the loupe), touch-action: manipulation
  so a quick second tap does not zoom; fields and the editor keep selection
- prefers-reduced-motion block (loading ring keeps turning)
- /diag defaults now mirror the app, with ?zoom=0 / ?iw=0 to compare

Full mobile and desktop suites pass.
2026-10-13 15:11:21 +13:00

4501 lines
105 KiB
CSS

/* ===== Self-hosted monospace font ===== */
@font-face {
font-family: 'Cascadia Mono';
src: url('/fonts/CascadiaMono-Regular.woff2') format('woff2');
font-weight: 400;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: 'Cascadia Mono';
src: url('/fonts/CascadiaMono-Bold.woff2') format('woff2');
font-weight: 700;
font-style: normal;
font-display: swap;
}
/* ===== Theme: Matrix (black & green) ===== */
.theme-matrix {
--bg: #080c08;
--theme-color: #08110b;
--bg-side: #0d140d;
--bg-list: #0b120b;
--bg-editor: #050905;
--bg-elevated: rgba(255,255,255,0.02);
--bg-input: rgba(50,255,112,0.06);
--bg-hover: rgba(50,255,112,0.08);
--bg-active: rgba(50,255,112,0.16);
--overlay: rgba(0,0,0,0.45);
--shadow: rgba(0,0,0,0.25);
--text: #e8fbe8;
--text-dim: #6a9a6a;
--text-muted: #6a9a6a;
--text-heading: #e0ffe0;
--text-on-accent: #041006;
--accent: #32ff70;
--border: rgba(50,255,112,0.12);
--border-focus: rgba(50,255,112,0.4);
--danger: #ff5555;
--toolbar-bg: #0d140d;
--scrollbar: rgba(50,255,112,0.15);
--statusbar-bg: #060a06;
color-scheme: dark;
}
/* ===== Theme: Matrix Blue ===== */
.theme-matrix-blue {
--bg: #06090d;
--theme-color: #071019;
--bg-side: #0b1220;
--bg-list: #09101a;
--bg-editor: #04070b;
--bg-elevated: rgba(255,255,255,0.02);
--bg-input: rgba(84,172,255,0.07);
--bg-hover: rgba(84,172,255,0.09);
--bg-active: rgba(84,172,255,0.17);
--overlay: rgba(0,0,0,0.45);
--shadow: rgba(0,0,0,0.25);
--text: #e6f5ff;
--text-dim: #6b91aa;
--text-muted: #6b91aa;
--text-heading: #dff4ff;
--text-on-accent: #041019;
--accent: #54acff;
--border: rgba(84,172,255,0.14);
--border-focus: rgba(84,172,255,0.42);
--danger: #ff6b6b;
--toolbar-bg: #0b1220;
--scrollbar: rgba(84,172,255,0.18);
--statusbar-bg: #050910;
color-scheme: dark;
}
/* ===== Theme: Matrix Purple ===== */
.theme-matrix-purple {
--bg: #09070d;
--theme-color: #100815;
--bg-side: #130d1d;
--bg-list: #100a18;
--bg-editor: #06040a;
--bg-elevated: rgba(255,255,255,0.02);
--bg-input: rgba(184,92,255,0.07);
--bg-hover: rgba(184,92,255,0.09);
--bg-active: rgba(184,92,255,0.17);
--overlay: rgba(0,0,0,0.45);
--shadow: rgba(0,0,0,0.25);
--text: #f5e9ff;
--text-dim: #9a72b4;
--text-muted: #9a72b4;
--text-heading: #f4e2ff;
--text-on-accent: #14081b;
--accent: #b85cff;
--border: rgba(184,92,255,0.14);
--border-focus: rgba(184,92,255,0.42);
--danger: #ff6b8a;
--toolbar-bg: #130d1d;
--scrollbar: rgba(184,92,255,0.18);
--statusbar-bg: #09060f;
color-scheme: dark;
}
/* ===== Theme: Matrix Amber ===== */
.theme-matrix-amber {
--bg: #0d0a05;
--theme-color: #130d06;
--bg-side: #1a1309;
--bg-list: #151007;
--bg-editor: #090602;
--bg-elevated: rgba(255,255,255,0.02);
--bg-input: rgba(255,191,64,0.07);
--bg-hover: rgba(255,191,64,0.09);
--bg-active: rgba(255,191,64,0.17);
--overlay: rgba(0,0,0,0.45);
--shadow: rgba(0,0,0,0.25);
--text: #fff5dd;
--text-dim: #b39355;
--text-muted: #b39355;
--text-heading: #ffefc7;
--text-on-accent: #171002;
--accent: #ffbf40;
--border: rgba(255,191,64,0.14);
--border-focus: rgba(255,191,64,0.42);
--danger: #ff7a45;
--toolbar-bg: #1a1309;
--scrollbar: rgba(255,191,64,0.18);
--statusbar-bg: #0c0803;
color-scheme: dark;
}
/* ===== Theme: Matrix Orange ===== */
.theme-matrix-orange {
--bg: #0d0805;
--theme-color: #140a06;
--bg-side: #1b1009;
--bg-list: #160d07;
--bg-editor: #090502;
--bg-elevated: rgba(255,255,255,0.02);
--bg-input: rgba(255,138,61,0.07);
--bg-hover: rgba(255,138,61,0.09);
--bg-active: rgba(255,138,61,0.17);
--overlay: rgba(0,0,0,0.45);
--shadow: rgba(0,0,0,0.25);
--text: #fff0e6;
--text-dim: #b98465;
--text-muted: #b98465;
--text-heading: #ffe4d1;
--text-on-accent: #180c05;
--accent: #ff8a3d;
--border: rgba(255,138,61,0.14);
--border-focus: rgba(255,138,61,0.42);
--danger: #ff6b5e;
--toolbar-bg: #1b1009;
--scrollbar: rgba(255,138,61,0.18);
--statusbar-bg: #0c0703;
color-scheme: dark;
}
/* ===== Theme: Dark Grey ===== */
.theme-dark-grey {
--bg: #090909;
--theme-color: #0b0b0b;
--bg-side: #141414;
--bg-list: #101010;
--bg-editor: #060606;
--bg-elevated: rgba(255,255,255,0.03);
--bg-input: rgba(255,255,255,0.06);
--bg-hover: rgba(255,255,255,0.08);
--bg-active: rgba(255,255,255,0.14);
--overlay: rgba(0,0,0,0.45);
--shadow: rgba(0,0,0,0.25);
--text: #ededed;
--text-dim: #9a9a9a;
--text-muted: #8d8d8d;
--text-heading: #f6f6f6;
--text-on-accent: #101010;
--accent: #b8b8b8;
--border: rgba(255,255,255,0.12);
--border-focus: rgba(255,255,255,0.35);
--danger: #ff6b6b;
--toolbar-bg: #121212;
--scrollbar: rgba(255,255,255,0.15);
--statusbar-bg: #070707;
color-scheme: dark;
}
/* ===== Theme: Grey ===== */
.theme-grey {
--bg: #222222;
--theme-color: #0d0d0d;
--bg-side: #0d0d0d;
--bg-list: #0d0d0d;
--bg-editor: #222222;
--bg-elevated: rgba(255,255,255,0.05);
--bg-input: rgba(255,255,255,0.06);
--bg-hover: rgba(255,255,255,0.08);
--bg-active: rgba(255,255,255,0.12);
--overlay: rgba(0,0,0,0.5);
--shadow: rgba(0,0,0,0.3);
--text: #e0e0e0;
--text-dim: #8a8a8a;
--text-muted: #7a7a7a;
--text-heading: #ffffff;
--text-on-accent: #ffffff;
--accent: #4a6572;
--border: rgba(255,255,255,0.10);
--border-focus: rgba(255,255,255,0.30);
--danger: #ef5350;
--toolbar-bg: #222222;
--scrollbar: rgba(255,255,255,0.12);
--statusbar-bg: #0d0d0d;
color-scheme: dark;
}
/* ===== Theme: Fruit (Apple Notes) ===== */
.theme-fruit {
--bg: #f5f5f0;
--theme-color: #f5f5f0;
--bg-side: #f0f0eb;
--bg-list: #ffffff;
--bg-editor: #ffffff;
--bg-elevated: rgba(0,0,0,0.03);
--bg-input: rgba(0,0,0,0.04);
--bg-hover: rgba(0,0,0,0.04);
--bg-active: rgba(0,0,0,0.06);
--overlay: rgba(0,0,0,0.2);
--shadow: rgba(0,0,0,0.08);
--text: #1c1c1e;
--text-dim: #6e6e73;
--text-muted: #8e8e93;
--text-heading: #000000;
--text-on-accent: #ffffff;
--accent: #c8a02e;
--border: rgba(0,0,0,0.08);
--border-focus: rgba(0,0,0,0.20);
--danger: #ff3b30;
--toolbar-bg: #f0f0eb;
--scrollbar: rgba(0,0,0,0.12);
--statusbar-bg: #e8e8e3;
color-scheme: light;
}
/* ===== Theme: Dark Fruit (Apple Notes dark) ===== */
.theme-dark-fruit {
--bg: #000000;
--theme-color: #000000;
--bg-side: #1c1c1e;
--bg-list: #2c2c2e;
--bg-editor: #000000;
--bg-elevated: rgba(255,255,255,0.05);
--bg-input: rgba(255,255,255,0.06);
--bg-hover: rgba(255,255,255,0.06);
--bg-active: rgba(255,255,255,0.10);
--overlay: rgba(0,0,0,0.5);
--shadow: rgba(0,0,0,0.4);
--text: #e5e5e5;
--text-dim: #8e8e93;
--text-muted: #6e6e73;
--text-heading: #ffffff;
--text-on-accent: #000000;
--accent: #c8a02e;
--border: rgba(255,255,255,0.08);
--border-focus: rgba(255,255,255,0.25);
--danger: #ff453a;
--toolbar-bg: #1c1c1e;
--scrollbar: rgba(255,255,255,0.12);
--statusbar-bg: #000000;
color-scheme: dark;
}
/* ===== Theme: Dark Red ===== */
.theme-dark-red {
--bg: #0b0607;
--theme-color: #0d0708;
--bg-side: #170d0e;
--bg-list: #130b0c;
--bg-editor: #080505;
--bg-elevated: rgba(255,255,255,0.03);
--bg-input: rgba(220,80,70,0.08);
--bg-hover: rgba(220,80,70,0.10);
--bg-active: rgba(220,80,70,0.18);
--overlay: rgba(0,0,0,0.5);
--shadow: rgba(0,0,0,0.3);
--text: #f0e0dc;
--text-dim: #b07070;
--text-muted: #966060;
--text-heading: #ffe4e0;
--text-on-accent: #1a0808;
--accent: #e05555;
--border: rgba(220,80,70,0.16);
--border-focus: rgba(220,80,70,0.40);
--danger: #ff6b6b;
--toolbar-bg: #150d0d;
--scrollbar: rgba(220,80,70,0.18);
--statusbar-bg: #0b0606;
color-scheme: dark;
}
/* ===== Theme: Dark (blue-gray) ===== */
.theme-dark {
--bg: #1d2024;
--theme-color: #1d2024;
--bg-side: #263238;
--bg-list: #2c3540;
--bg-editor: #1d2024;
--bg-elevated: rgba(255,255,255,0.02);
--bg-input: rgba(255,255,255,0.06);
--bg-hover: rgba(255,255,255,0.06);
--bg-active: rgba(100,149,237,0.25);
--overlay: rgba(0,0,0,0.45);
--shadow: rgba(0,0,0,0.25);
--text: #cdd8e0;
--text-dim: #8a9baa;
--text-muted: #8a9baa;
--text-heading: #e0e8f0;
--text-on-accent: #ffffff;
--accent: #6c9eff;
--border: rgba(255,255,255,0.08);
--border-focus: rgba(100,149,237,0.5);
--danger: #ff5555;
--toolbar-bg: #263238;
--scrollbar: rgba(255,255,255,0.1);
--statusbar-bg: #1a1e22;
color-scheme: dark;
}
/* ===== Theme: Light ===== */
.theme-light {
--bg: #ffffff;
--theme-color: #f0f4f8;
--bg-side: #f0f4f8;
--bg-list: #ffffff;
--bg-editor: #ffffff;
--bg-elevated: rgba(0,0,0,0.03);
--bg-input: rgba(0,0,0,0.04);
--bg-hover: rgba(0,0,0,0.04);
--bg-active: rgba(100,149,237,0.15);
--overlay: rgba(0,0,0,0.45);
--shadow: rgba(0,0,0,0.18);
--text: #32363a;
--text-dim: #6c757d;
--text-muted: #6c757d;
--text-heading: #1d2024;
--text-on-accent: #ffffff;
--accent: #0066cc;
--border: rgba(0,0,0,0.09);
--border-focus: rgba(0,102,204,0.4);
--danger: #dc3545;
--toolbar-bg: #f7f7f7;
--scrollbar: rgba(0,0,0,0.12);
--statusbar-bg: #e8ecf0;
color-scheme: light;
}
/* ===== Theme: Joplin OLED Dark ===== */
.theme-oled-dark {
--bg: #000000;
--theme-color: #000000;
--bg-side: #0f2051;
--bg-list: #000000;
--bg-editor: #000000;
--bg-elevated: rgba(255,255,255,0.02);
--bg-input: rgba(255,255,255,0.06);
--bg-hover: rgba(255,255,255,0.06);
--bg-active: rgba(120,139,195,0.22);
--overlay: rgba(0,0,0,0.55);
--shadow: rgba(0,0,0,0.35);
--text: #dddddd;
--text-dim: #777777;
--text-muted: #777777;
--text-heading: #ffffff;
--text-on-accent: #ffffff;
--accent: #788bc3;
--border: #3d444e;
--border-focus: #788bc3;
--danger: #ff4444;
--toolbar-bg: #0f2051;
--scrollbar: rgba(255,255,255,0.12);
--statusbar-bg: #000000;
color-scheme: dark;
}
/* ===== Theme: Joplin Solarized Light ===== */
.theme-solarized-light {
--bg: #fdf6e3;
--theme-color: #fdf6e3;
--bg-side: #002b36;
--bg-list: #fdf6e3;
--bg-editor: #fdf6e3;
--bg-elevated: #eee8d5;
--bg-input: rgba(0,43,54,0.06);
--bg-hover: rgba(38,139,210,0.08);
--bg-active: #eee8d5;
--overlay: rgba(0,43,54,0.35);
--shadow: rgba(0,43,54,0.18);
--text: #657b83;
--text-dim: #839496;
--text-muted: #839496;
--text-heading: #073642;
--text-on-accent: #ffffff;
--accent: #268bd2;
--border: #eee8d5;
--border-focus: #268bd2;
--danger: #dc322f;
--toolbar-bg: #eee8d5;
--scrollbar: rgba(101,123,131,0.18);
--statusbar-bg: #eee8d5;
color-scheme: light;
}
/* ===== Theme: Joplin Solarized Dark ===== */
.theme-solarized-dark {
--bg: #002b36;
--theme-color: #002b36;
--bg-side: #073642;
--bg-list: #002b36;
--bg-editor: #002b36;
--bg-elevated: #073642;
--bg-input: rgba(147,161,161,0.08);
--bg-hover: rgba(42,161,152,0.14);
--bg-active: #073642;
--overlay: rgba(0,43,54,0.55);
--shadow: rgba(0,0,0,0.28);
--text: #839496;
--text-dim: #657b83;
--text-muted: #657b83;
--text-heading: #93a1a1;
--text-on-accent: #002b36;
--accent: #268bd2;
--border: #586e75;
--border-focus: #2aa198;
--danger: #dc322f;
--toolbar-bg: #073642;
--scrollbar: rgba(131,148,150,0.18);
--statusbar-bg: #012732;
color-scheme: dark;
}
/* ===== Theme: Joplin Nord ===== */
.theme-nord {
--bg: #2e3440;
--theme-color: #2e3440;
--bg-side: #434c5e;
--bg-list: #2e3440;
--bg-editor: #2e3440;
--bg-elevated: #434c5e;
--bg-input: rgba(216,222,233,0.08);
--bg-hover: rgba(129,161,193,0.12);
--bg-active: #81a1c1;
--overlay: rgba(46,52,64,0.55);
--shadow: rgba(46,52,64,0.32);
--text: #e5e9f0;
--text-dim: #d8dee9;
--text-muted: #d8dee9;
--text-heading: #eceff4;
--text-on-accent: #2e3440;
--accent: #88c0d0;
--border: rgba(129,161,193,0.20);
--border-focus: #81a1c1;
--danger: #bf616a;
--toolbar-bg: #3b4252;
--scrollbar: rgba(216,222,233,0.18);
--statusbar-bg: #3b4252;
color-scheme: dark;
}
/* ===== Theme: Joplin Dracula ===== */
.theme-dracula {
--bg: #282a36;
--theme-color: #282a36;
--bg-side: #21222c;
--bg-list: #282a36;
--bg-editor: #282a36;
--bg-elevated: #44475a;
--bg-input: rgba(248,248,242,0.06);
--bg-hover: rgba(189,147,249,0.12);
--bg-active: #44475a;
--overlay: rgba(40,42,54,0.55);
--shadow: rgba(0,0,0,0.3);
--text: #f8f8f2;
--text-dim: #6272a4;
--text-muted: #6272a4;
--text-heading: #f8f8f2;
--text-on-accent: #282a36;
--accent: #8be9fd;
--border: rgba(189,147,249,0.18);
--border-focus: #bd93f9;
--danger: #ff5555;
--toolbar-bg: #21222c;
--scrollbar: rgba(248,248,242,0.18);
--statusbar-bg: #21222c;
color-scheme: dark;
}
/* ===== Theme: Swamp Thing ===== */
.theme-swamp-thing {
--bg: #1a1e1a;
--theme-color: #1a1e1a;
--bg-side: #141814;
--bg-list: #1a1e1a;
--bg-editor: #1a1e1a;
--bg-elevated: #2a332a;
--bg-input: rgba(105,255,148,0.06);
--bg-hover: rgba(105,255,148,0.12);
--bg-active: #2a332a;
--overlay: rgba(26,30,26,0.55);
--shadow: rgba(0,0,0,0.3);
--text: #f0f5f0;
--text-dim: #627a64;
--text-muted: #627a64;
--text-heading: #f0f5f0;
--text-on-accent: #1a1e1a;
--accent: #69ff94;
--border: rgba(105,255,148,0.12);
--border-focus: rgba(105,255,148,0.40);
--danger: #ff5555;
--toolbar-bg: #141814;
--scrollbar: rgba(240,245,240,0.18);
--statusbar-bg: #141814;
color-scheme: dark;
}
/* ===== Theme: Fireball ===== */
.theme-fireball {
--bg: #1e1a16;
--theme-color: #1e1a16;
--bg-side: #181410;
--bg-list: #1e1a16;
--bg-editor: #1e1a16;
--bg-elevated: #332820;
--bg-input: rgba(255,140,40,0.07);
--bg-hover: rgba(255,140,40,0.12);
--bg-active: #332820;
--overlay: rgba(30,26,22,0.55);
--shadow: rgba(0,0,0,0.3);
--text: #f5f0eb;
--text-dim: #807060;
--text-muted: #807060;
--text-heading: #f5f0eb;
--text-on-accent: #1e1a16;
--accent: #ff8c28;
--border: rgba(255,140,40,0.14);
--border-focus: rgba(255,140,40,0.42);
--danger: #ff5555;
--toolbar-bg: #181410;
--scrollbar: rgba(245,240,235,0.18);
--statusbar-bg: #181410;
color-scheme: dark;
}
/* ===== Theme: Joplin Aritim Dark ===== */
.theme-aritim-dark {
--bg: #10151a;
--theme-color: #10151a;
--bg-side: #141a21;
--bg-list: #141a21;
--bg-editor: #10151a;
--bg-elevated: #141a21;
--bg-input: rgba(211,218,227,0.06);
--bg-hover: rgba(43,82,120,0.12);
--bg-active: #2b5278;
--overlay: rgba(16,21,26,0.58);
--shadow: rgba(0,0,0,0.34);
--text: #d3dae3;
--text-dim: #666a73;
--text-muted: #666a73;
--text-heading: #d3dae3;
--text-on-accent: #d3dae3;
--accent: #5a95c5;
--border: #141a21;
--border-focus: #2b5278;
--danger: #d66500;
--toolbar-bg: #141a21;
--scrollbar: rgba(211,218,227,0.16);
--statusbar-bg: #141a21;
color-scheme: dark;
}
/* ===== Theme: Earth ===== */
.theme-earth {
--bg: #1a1610;
--theme-color: #1e1a12;
--bg-side: #262018;
--bg-list: #221e16;
--bg-editor: #161310;
--bg-elevated: rgba(255,255,255,0.03);
--bg-input: rgba(180,150,90,0.08);
--bg-hover: rgba(180,150,90,0.10);
--bg-active: rgba(180,150,90,0.18);
--overlay: rgba(0,0,0,0.45);
--shadow: rgba(0,0,0,0.30);
--text: #e8dcc8;
--text-dim: #9a8b6e;
--text-muted: #8a7b5e;
--text-heading: #f0e8d8;
--text-on-accent: #1a1408;
--accent: #b4964a;
--border: rgba(180,150,90,0.14);
--border-focus: rgba(180,150,90,0.40);
--danger: #c46040;
--toolbar-bg: #262018;
--scrollbar: rgba(180,150,90,0.18);
--statusbar-bg: #141210;
color-scheme: dark;
}
/* ===== Reset ===== */
*,*::before,*::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
html.mobile-no-page-scroll,
body.mobile-no-page-scroll {
overflow: hidden !important;
height: 100dvh;
}
body {
--font-size-note: 15px;
--font-size-markdown: 14px;
--font-size-code: 12px;
--statusbar-height: 28px;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
font-size: 13px;
line-height: 1.4;
color: var(--text);
background: var(--bg);
}
body.app-shell {
display: flex;
flex-direction: column;
min-height: 100vh;
min-height: 100dvh;
overflow: hidden;
}
/* While mobile shell editor is active, freeze outer page scrolling so only the
editor content scrolls. This avoids dual-scroll behavior on iOS Safari. */
body.mobile-shell-active {
overscroll-behavior: none;
overflow: hidden;
position: fixed;
inset: 0;
width: 100%;
}
body.note-body-monospace,
body.note-body-monospace .editor-preview {
font-family: 'Cascadia Mono','SF Mono',Consolas,'Liberation Mono',Menlo,monospace;
}
.editor-preview {
font-family: var(--font-family-note, inherit);
}
button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; border: none; background: none; }
/* ===== 3-Column App Layout ===== */
.app {
display: flex;
flex: 1;
min-height: 0;
overflow: hidden;
}
.mobile-nav-backdrop { display: none; }
.nav-toggle-btn {
display: inline-flex;
width: 30px;
height: 30px;
align-items: center;
justify-content: center;
border-radius: 0;
background: transparent;
border: 1px solid var(--border);
color: var(--text);
font-size: 16px;
cursor: pointer;
flex-shrink: 0;
}
.nav-reopen-btn {
display: none;
position: absolute;
left: 6px;
top: 6px;
width: 30px;
height: 30px;
align-items: center;
justify-content: center;
border-radius: 0;
background: var(--bg-side);
border: 1px solid var(--border);
color: var(--text);
font-size: 16px;
cursor: pointer;
z-index: 5;
}
body.nav-collapsed .col-nav { display: none; }
body.nav-collapsed .nav-reopen-btn { display: inline-flex; }
body.nav-collapsed .editor-titlebar { padding-left: 42px; }
.col-nav {
display: flex;
flex-direction: column;
width: 320px;
min-width: 320px;
background: var(--bg-side);
border-right: 1px solid var(--border);
min-width: 0;
height: 100%;
}
.nav-panel-header {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 10px;
height: 44px;
box-sizing: border-box;
border-bottom: 1px solid var(--border);
background: var(--bg-side);
flex-shrink: 0;
}
.nav-panel-header .btn { padding: 4px 6px; }
.nav-search-form {
display: flex;
align-items: center;
gap: 6px;
flex: 1;
}
.nav-items {
flex: 1;
overflow-y: auto;
padding: 6px;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-elevated);
}
.nav-folder {
margin-bottom: 2px;
border: 0;
border-radius: 0;
overflow: visible;
background: transparent;
}
.nav-folder.active {
background: var(--bg-active);
}
.nav-folder-row {
display: flex;
align-items: center;
gap: 6px;
padding: 7px 8px;
cursor: pointer;
}
/* Nested notebooks: each level indents by 14px (capped server-side at 8
* levels via --nav-depth). Every collapse/expand rule below uses the child
* combinator, because a descendant selector would let a collapsed child's
* state leak into an expanded parent (and vice versa). */
.nav-folder > .nav-folder-row {
padding-left: calc(8px + var(--nav-depth, 0) * 14px);
}
.nav-folder-children { display: block; }
/* Pinned notebooks: a small pin before the title (sidebar) / after it (mobile). */
.nav-pin-icon,
.mobile-pin-icon {
display: inline-flex;
flex-shrink: 0;
width: 12px;
height: 12px;
color: var(--accent);
opacity: 0.85;
}
.nav-pin-icon svg,
.mobile-pin-icon svg { width: 100%; height: 100%; }
.nav-pin-icon { margin-right: 2px; }
.mobile-pin-icon { width: 14px; height: 14px; }
/* Notebook order switch: shows the CURRENT order; <body data-folder-sort> decides which label. */
.sort-on-recent { display: none; }
body[data-folder-sort="recent"] .sort-on-alpha { display: none; }
body[data-folder-sort="recent"] .sort-on-recent { display: inline; }
/* The header is a fixed-width flex row: let the search box shrink so the switch and the "+" always fit. */
.nav-search-form { min-width: 0; }
.nav-search-form .notelist-search { min-width: 0; flex: 1 1 auto; }
.nav-sort-btn { flex-shrink: 0; min-width: 40px; font-size: 11px; padding-left: 5px; padding-right: 5px; white-space: nowrap; }
.mobile-sort-btn { font-size: 13px; font-weight: 600; min-width: 44px; }
/* Drag a notebook onto another to nest it (desktop). */
.nav-folder.nav-dragging > .nav-folder-row { opacity: 0.45; }
.nav-folder-row.nav-drop-target {
background: color-mix(in srgb, var(--accent) 22%, transparent);
outline: 2px solid var(--accent);
outline-offset: -2px;
}
.nav-drop-root {
display: none;
margin: 4px 8px 6px;
padding: 8px;
border: 1px dashed var(--border-focus, var(--accent));
border-radius: 4px;
font-size: 12px;
text-align: center;
color: var(--text-dim);
}
body.nav-dragging-folder.nav-drag-nested .nav-drop-root { display: block; }
.nav-drop-root.nav-drop-active {
border-style: solid;
background: color-mix(in srgb, var(--accent) 22%, transparent);
color: var(--text);
}
.nav-folder.collapsed > .nav-folder-children { display: none; }
.nav-folder-toggle {
width: 18px;
height: 18px;
display: inline-flex;
align-items: center;
justify-content: center;
color: var(--text-dim);
font-size: 14px;
transition: transform 0.12s;
flex-shrink: 0;
transform: rotate(90deg);
}
.nav-folder-toggle-placeholder { visibility: hidden; }
.nav-folder.collapsed > .nav-folder-row > .nav-folder-toggle { transform: rotate(0deg); }
.nav-folder-title {
flex: 1;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: 14px;
font-weight: 600;
color: var(--accent);
}
.nav-share-icon {
font-size: 14px;
margin-right: 4px;
opacity: 0.7;
}
.theme-matrix .nav-folder-title,
.theme-matrix .sidebar-item-name {
color: #7ee787;
}
:is(.theme-matrix, .theme-matrix-blue, .theme-matrix-purple, .theme-matrix-amber, .theme-matrix-orange) .notelist-item-title,
:is(.theme-matrix, .theme-matrix-blue, .theme-matrix-purple, .theme-matrix-amber, .theme-matrix-orange) .nav-folder .sidebar-item-icon,
:is(.theme-matrix, .theme-matrix-blue, .theme-matrix-purple, .theme-matrix-amber, .theme-matrix-orange) .sidebar-item-icon {
color: #e0ffe0;
}
.nav-folder .sidebar-item-icon {
font-size: 14px;
width: 18px;
height: 18px;
color: currentColor;
}
.nav-folder-add {
flex-shrink: 0;
width: 20px;
height: 20px;
font-size: 14px;
}
.nav-folder-notes {
padding: 0 0 4px;
border-top: 0;
}
.nav-folder.collapsed > .nav-folder-notes { display: none; }
.nav-folder-notes .notelist-item {
padding: 7px 10px 7px calc(34px + var(--nav-depth, 0) * 14px);
border-bottom: none;
background: transparent;
}
.folder-context-menu {
position: fixed;
z-index: 40;
min-width: 160px;
padding: 4px;
border: 1px solid var(--border);
border-radius: 0;
/* It floats over the sidebar AND the editor, so it must be opaque. --bg-elevated alone is
* a ~2% tint in most themes (see-through); lay it over the solid sidebar colour so the
* theme's look is kept without letting the content behind show through. */
background-color: var(--bg-side);
background-image: linear-gradient(var(--bg-elevated), var(--bg-elevated));
box-shadow: 0 10px 30px var(--shadow);
/* a very short window: scroll the menu instead of letting items fall off the screen */
max-height: calc(100vh - 16px);
max-height: calc(100dvh - 16px);
overflow-y: auto;
}
.folder-context-menu[hidden],
.folder-modal-backdrop[hidden],
.folder-modal[hidden],
.history-modal[hidden] {
display: none;
}
.folder-context-item {
display: block;
width: 100%;
padding: 8px 10px;
border-radius: 0;
text-align: left;
color: var(--text);
}
@media (hover: hover) {
.folder-context-item:hover {
background: var(--bg-hover);
}
}
/* display:block above beats the UA [hidden] rule; vault notebooks hide the
* "New sub-notebook" / "Move" entries with it. */
.folder-context-item[hidden],
.mobile-ctx-btn[hidden] { display: none; }
/* Notebook pickers (new notebook "Inside", move "Move into") */
.folder-parent-label {
display: block;
margin: 0.75rem 0 0.25rem;
font-size: 12px;
color: var(--text-muted);
}
.folder-parent-select {
width: 100%;
max-width: 100%;
text-overflow: ellipsis;
}
.folder-parent-select option:disabled { color: var(--text-muted); }
.folder-context-item.danger {
color: var(--danger);
}
.folder-modal-backdrop {
position: fixed;
inset: 0;
background: var(--overlay);
z-index: 1000;
}
.folder-modal {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
z-index: 1001;
}
.folder-modal-card {
display: grid;
gap: 12px;
width: min(360px, 100%);
padding: 16px;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-side);
box-shadow: 0 10px 30px var(--shadow);
}
.folder-modal-title {
margin: 0;
font-size: 16px;
color: var(--text-heading);
}
.folder-modal-actions {
display: flex;
justify-content: flex-end;
gap: 8px;
}
/* ===== Upload Modal ===== */
.upload-modal-card {
width: min(440px, 100%);
gap: 14px;
padding: 18px;
}
.upload-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
}
.upload-close-btn {
font-size: 18px;
padding: 2px 6px;
line-height: 1;
border-radius: 0;
color: var(--text-dim);
background: transparent;
border: none;
cursor: pointer;
}
@media (hover: hover) {
.upload-close-btn:hover { color: var(--text); background: var(--bg-hover); }
}
.upload-drop-zone {
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
padding: 24px 16px;
border: 2px dashed var(--border);
border-radius: 0;
text-align: center;
transition: border-color 0.15s, background 0.15s;
background: var(--bg);
}
.upload-drop-zone.drag-over {
border-color: var(--accent);
background: color-mix(in srgb, var(--accent) 8%, var(--bg));
}
.upload-drop-icon {
font-size: 32px;
line-height: 1;
opacity: 0.7;
}
.upload-drop-text {
margin: 0;
font-size: 14px;
color: var(--text-dim);
}
.upload-drop-or {
margin: 0;
font-size: 12px;
color: var(--text-dim);
opacity: 0.6;
}
.upload-file-list {
display: flex;
flex-direction: column;
gap: 6px;
max-height: 180px;
overflow-y: auto;
}
.upload-file-item {
display: flex;
align-items: center;
gap: 10px;
padding: 8px 10px;
border-radius: 0;
background: var(--bg);
border: 1px solid var(--border);
transition: background 0.15s;
}
.upload-file-item.done { border-color: var(--accent); }
.upload-file-item.error { border-color: var(--danger); opacity: 0.8; }
.upload-file-name {
flex: 1;
font-size: 13px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--text);
}
.upload-file-size {
font-size: 11px;
color: var(--text-dim);
flex-shrink: 0;
}
.upload-file-status {
font-size: 11px;
font-weight: 600;
flex-shrink: 0;
min-width: 48px;
text-align: right;
}
.upload-file-status.ok { color: var(--accent); }
.upload-file-status.err { color: var(--danger); }
.upload-progress-bar {
width: 100%;
height: 3px;
border-radius: 0;
background: var(--border);
overflow: hidden;
margin-top: 4px;
}
.upload-progress-bar-fill {
height: 100%;
background: var(--accent);
transition: width 0.2s;
border-radius: 0;
}
.upload-file-del {
flex-shrink: 0;
width: 22px;
height: 22px;
padding: 0;
border: none;
border-radius: 0;
background: transparent;
color: var(--text-dim);
font-size: 16px;
line-height: 1;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
@media (hover: hover) {
.upload-file-del:hover { color: var(--danger); background: var(--bg-hover); }
}
.trash-folder-empty {
flex-shrink: 0;
color: var(--danger);
}
.empty-trash-warning {
margin: 0;
line-height: 1.45;
}
/* ===== Code Block Modal ===== */
/* ===== Code Modal (full-screen panel) ===== */
.code-modal-panel[hidden] { display: none; }
.code-modal-panel {
position: fixed;
inset: 0;
z-index: 50;
display: flex;
align-items: stretch;
justify-content: center;
background: var(--bg);
padding: 24px;
gap: 0;
}
.code-modal-inner {
display: flex;
flex-direction: column;
flex: 1;
max-width: 960px;
padding: 20px;
gap: 12px;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-side);
box-shadow: 0 18px 40px var(--shadow);
}
.code-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.code-modal-title {
margin: 0;
font-size: 16px;
color: var(--text-heading);
}
.code-lang-select {
width: auto;
min-width: 140px;
padding: 4px 8px;
font-size: 13px;
}
.code-input {
flex: 1;
min-height: 0;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-editor);
overflow: hidden;
}
.code-input .cm-editor {
height: 100%;
}
.code-input .cm-scroller {
overflow: auto;
}
.code-modal-actions {
display: flex;
gap: 8px;
justify-content: flex-end;
}
/* ===== History Modal ===== */
.history-modal {
position: fixed;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
z-index: 1001;
}
.history-modal-card {
display: flex;
flex-direction: column;
width: min(820px, 100%);
height: min(520px, 85vh);
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-side);
box-shadow: 0 10px 40px var(--shadow);
overflow: hidden;
}
.history-modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: 12px 16px;
border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.history-modal-header .folder-modal-title {
margin: 0;
}
.history-close-btn {
font-size: 14px;
line-height: 1;
}
#history-modal-inner {
display: contents;
}
.history-body {
display: grid;
grid-template-columns: 200px 1fr;
flex: 1;
min-height: 0;
overflow: hidden;
}
.history-list {
overflow-y: auto;
border-right: 1px solid var(--border);
padding: 4px 0;
}
.history-item {
display: flex;
flex-direction: column;
width: 100%;
padding: 8px 12px;
text-align: left;
font-size: 11px;
color: var(--text-dim);
border-bottom: 1px solid var(--border);
gap: 2px;
}
@media (hover: hover) {
.history-item:hover { background: var(--bg-hover); color: var(--text); }
}
.history-item-active { background: var(--bg-active); color: var(--text); }
.history-item-title {
font-size: 10px;
color: var(--text-muted);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.history-preview {
overflow-y: auto;
background: var(--bg-editor);
}
.history-snapshot-content {
height: 100%;
}
.history-snapshot-body {
margin: 0;
padding: 12px 16px;
font-size: 12px;
font-family: 'Cascadia Mono', monospace;
color: var(--text);
white-space: pre-wrap;
word-break: break-word;
line-height: 1.6;
}
.history-actions {
display: flex;
align-items: center;
gap: 8px;
padding: 8px 12px;
border-top: 1px solid var(--border);
flex-shrink: 0;
}
.history-selected-label {
flex: 1;
font-size: 11px;
color: var(--text-muted);
}
.history-empty,
.history-loading {
padding: 24px;
font-size: 12px;
color: var(--text-muted);
text-align: center;
}
.nav-empty {
padding: 6px 10px 8px 34px;
font-size: 11px;
}
.notelist-load-more {
display: block;
width: 100%;
padding: 6px 10px 6px 34px;
font-size: 11px;
color: var(--text-muted);
background: none;
border: none;
text-align: left;
cursor: pointer;
font-family: inherit;
}
@media (hover: hover) {
.notelist-load-more:hover { color: var(--text-primary); background: var(--bg-hover); }
}
.btn-icon-sm {
width: 22px;
height: 22px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
font-size: 16px;
font-weight: 600;
color: var(--text-dim);
transition: background 0.1s;
}
@media (hover: hover) {
.btn-icon-sm:hover { background: var(--bg-hover); color: var(--text); }
}
/* Sidebar items */
.sidebar-item {
display: flex;
align-items: center;
gap: 6px;
width: 100%;
padding: 5px 8px;
border-radius: 0;
text-align: left;
transition: background 0.1s;
margin-bottom: 1px;
}
@media (hover: hover) {
.sidebar-item:hover { background: var(--bg-hover); }
}
.sidebar-item.active { background: var(--bg-active); }
.sidebar-item-icon {
font-size: 14px;
flex-shrink: 0;
width: 20px;
height: 20px;
text-align: center;
display: inline-flex;
align-items: center;
justify-content: center;
color: currentColor;
}
.folder-outline-icon {
width: 20px;
height: 20px;
display: block;
}
.sidebar-item-name {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--accent);
}
.sidebar-item-count {
font-size: 11px;
color: var(--text-dim);
flex-shrink: 0;
min-width: 16px;
text-align: right;
}
.notelist-header {
display: flex;
align-items: center;
gap: 6px;
padding: 8px 10px;
height: 44px;
box-sizing: border-box;
border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.notelist-search {
flex: 1;
padding: 5px 8px;
height: 28px;
box-sizing: border-box;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-input);
outline: none;
font-size: 12px;
}
.notelist-search:focus { border-color: var(--border-focus); }
.nav-search-btn {
flex-shrink: 0;
border: 1px solid var(--border);
background: var(--bg-input);
}
.nav-search-clear {
flex-shrink: 0;
border: 1px solid var(--border);
background: var(--bg-input);
color: var(--text-muted);
cursor: pointer;
font-size: 0.85em;
}
.notelist-items {
overflow-y: auto;
flex: 1;
}
@media (hover: hover) {
.notelist-item:hover { background: var(--bg-hover); }
}
.notelist-item.active { background: var(--bg-active); }
.notelist-item-title {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: var(--text);
min-width: 0;
flex: 1;
}
/* Column 3: Editor */
.col-editor {
flex: 1;
min-width: 0;
background: var(--bg-editor);
display: flex;
flex-direction: column;
overflow: hidden;
}
.editor-empty {
display: flex;
align-items: center;
justify-content: center;
height: 100%;
color: var(--text-dim);
}
.editor-form {
display: flex;
flex-direction: column;
height: 100%;
min-height: 0;
}
/* Read-only editor: dim toolbar + title, block caret + selection so it is
* clear the note cannot be edited. TinyMCE + CM6 also have their own
* contenteditable=false / mode=readonly applied by _applyFormReadonly(). */
.editor-form.editor-readonly .editor-toolbar { opacity: 0.5; pointer-events: none; }
.editor-form.editor-readonly .editor-title { opacity: 0.75; cursor: default; caret-color: transparent; }
.editor-form.editor-readonly .editor-folder-select { opacity: 0.6; cursor: not-allowed; }
.editor-form.editor-readonly .cm-content { caret-color: transparent; }
/* HTML notes (Joplin markup_language 2): rendered, read-only. No editing chrome,
* no markdown/rendered switch (there is only the rendered view). */
.editor-form[data-html-note="1"] #markdown-toggle,
.editor-form[data-html-note="1"] #preview-toggle,
.editor-form[data-html-note="1"] #undo-save-btn,
.editor-form[data-html-note="1"] .editor-toolbar,
.active-html-note #mobile-md-toggle,
.active-html-note #mobile-preview-toggle { display: none !important; }
.editor-form[data-html-note="1"] .editor-title { opacity: 0.85; cursor: default; caret-color: transparent; }
/* Joplin end-to-end encrypted note: locked placeholder only (no form). */
.editor-e2ee {
flex-direction: column;
gap: 10px;
text-align: center;
padding: 40px 20px;
}
.editor-e2ee-hint { font-size: 13px; color: var(--text-muted); }
.notelist-item-e2ee .notelist-item-title,
.mobile-note-row-e2ee .mobile-note-title { opacity: 0.75; font-style: italic; }
.share-readonly-banner {
background: var(--accent);
color: var(--bg);
padding: 4px 12px;
font-size: 12px;
font-weight: 600;
text-align: center;
letter-spacing: 0.5px;
}
.editor-titlebar {
display: flex;
align-items: center;
gap: 8px;
padding: 6px 16px;
height: 44px;
box-sizing: border-box;
border-bottom: 1px solid var(--border);
flex-shrink: 0;
}
.editor-title {
flex: 1;
padding: 0 0;
border: none;
background: transparent;
font-size: 16px;
font-weight: 700;
color: var(--text-heading);
outline: none;
line-height: 28px;
min-height: 28px;
}
.editor-title:empty::before {
content: attr(data-placeholder);
color: var(--text-muted);
pointer-events: none;
}
.editor-folder-select {
padding: 3px 6px;
height: 28px;
box-sizing: border-box;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-side);
color: var(--text);
font-size: 12px;
max-width: 160px;
outline: none;
cursor: pointer;
}
.editor-folder-select:focus { border-color: var(--accent); }
.editor-folder-arrow {
color: var(--text-dim);
font-size: 14px;
margin: 0 2px;
}
/* Toolbar */
.editor-toolbar {
display: none;
align-items: center;
gap: 1px;
padding: 2px 12px 4px;
border-bottom: 1px solid var(--border);
background: color-mix(in srgb, var(--accent) 10%, var(--bg));
flex-shrink: 0;
flex-wrap: wrap;
}
/* Legacy custom toolbar is only used for markdown mode.
Rich mode uses TinyMCE's built-in toolbar on both desktop and mobile. */
body.editor-rich-mode .editor-toolbar {
display: none;
}
body.editor-markdown-mode .editor-toolbar {
display: flex;
}
.tb {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 28px;
height: 26px;
padding: 0 5px;
border-radius: 3px;
font-size: 13px;
color: var(--text-dim);
transition: background 0.1s, color 0.1s;
}
@media (hover: hover) {
.tb:hover { background: var(--bg-hover); color: var(--text); }
}
.tb:focus { outline: none; }
.tb-div {
width: 1px;
height: 16px;
background: var(--border);
margin: 0 4px;
}
/* Export menu */
.export-menu {
position: fixed;
z-index: 500;
min-width: 160px;
background: var(--bg-editor);
border: 1px solid var(--border);
border-radius: 0;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.25);
display: none;
flex-direction: column;
padding: 4px;
}
.export-menu:not([hidden]) { display: flex; }
.export-menu button {
display: block;
width: 100%;
text-align: left;
padding: 6px 10px;
font-size: 13px;
color: var(--text);
border-radius: 4px;
background: transparent;
}
@media (hover: hover) {
.export-menu button:hover { background: var(--bg-hover); }
}
.export-menu .export-menu-cancel { color: var(--text-muted); margin-top: 2px; border-top: 1px solid var(--border); border-radius: 0 0 4px 4px; }
/* Editor body (hidden textarea, used as sync target for form submission) */
.editor-body {
display: none;
flex: 1;
min-height: 0;
resize: none;
border: none;
outline: none;
background: var(--bg);
color: var(--text);
font-family: 'Cascadia Mono', monospace;
font-size: var(--font-size-markdown);
line-height: 1.6;
padding: 16px 20px;
overflow-y: auto;
}
/* CodeMirror host */
.cm-host {
flex: 1;
overflow: hidden;
min-height: 0;
font-size: var(--font-size-markdown);
}
/* TinyMCE host — persistent, positioned by JS over #tinymce-slot */
#tinymce-editor { display: none; }
.tinymce-host {
position: fixed;
z-index: 5;
display: none;
flex-direction: column;
background: var(--bg);
}
.tinymce-host.tinymce-host-visible { display: flex; }
.tinymce-slot {
flex: 1;
min-height: 0;
}
.tox-tinymce,
.tox-tinymce--focused {
flex: 1 !important;
min-height: 0 !important;
height: 100% !important;
border: none !important;
border-radius: 0 !important;
box-shadow: none !important;
outline: none !important;
}
.tox-tinymce .tox-editor-container,
.tox-tinymce .tox-edit-area,
.tox-tinymce .tox-edit-area__iframe {
flex: 1 !important;
min-height: 0 !important;
height: 100% !important;
}
.tox-statusbar { display: none !important; }
.tox .tox-edit-area,
.tox .tox-edit-area__iframe {
background: var(--bg) !important;
}
/* TinyMCE theme integration — toolbar tinted per-theme via accent color */
.tox .tox-toolbar-overlord,
.tox .tox-toolbar,
.tox .tox-toolbar__primary,
.tox .tox-toolbar__overflow {
background-color: color-mix(in srgb, var(--accent) 10%, var(--bg)) !important;
background-image: none !important;
}
.tox .tox-editor-header {
position: sticky !important;
top: 0 !important;
z-index: 10 !important;
background-color: color-mix(in srgb, var(--accent) 10%, var(--bg)) !important;
}
.tox .tox-tbtn {
color: var(--text-dim) !important;
background: transparent !important;
background-color: transparent !important;
background-image: none !important;
border: none !important;
box-shadow: none !important;
}
.tox .tox-tbtn svg {
fill: var(--text-dim) !important;
}
@media (hover: hover) {
.tox .tox-tbtn:hover {
background: var(--bg-hover) !important;
background-color: var(--bg-hover) !important;
color: var(--text) !important;
}
}
@media (hover: hover) {
.tox .tox-tbtn:hover svg {
fill: var(--text) !important;
}
}
.tox .tox-tbtn--active,
.tox .tox-tbtn--enabled,
.tox .tox-tbtn--enabled:hover {
background: var(--bg-active) !important;
background-color: var(--bg-active) !important;
color: var(--accent) !important;
}
.tox .tox-tbtn--active svg,
.tox .tox-tbtn--enabled svg,
.tox .tox-tbtn--enabled:hover svg {
fill: var(--accent) !important;
}
.tox .tox-toolbar__group {
border-right-color: var(--border) !important;
}
/* Select-style toolbar buttons + fields (e.g. "Paragraph" format menu, list
* split-buttons). The oxide-dark skin gives these a default blue background;
* neutralize to match the app theme. */
.tox .tox-tbtn--select,
.tox .tox-split-button,
.tox .tox-tbtn--bespoke,
.tox .tox-listboxfield .tox-listbox--select,
.tox .tox-selectfield select,
.tox .tox-toolbar__primary .tox-split-button .tox-tbtn {
background: transparent !important;
background-color: transparent !important;
background-image: none !important;
color: var(--text-dim) !important;
border-color: var(--border) !important;
}
.tox .tox-tbtn--select:hover,
.tox .tox-split-button:hover,
.tox .tox-tbtn--bespoke:hover,
.tox .tox-split-button:focus,
.tox .tox-tbtn--select:focus {
background: var(--bg-hover) !important;
background-color: var(--bg-hover) !important;
color: var(--text) !important;
}
.tox .tox-tbtn--select.tox-tbtn--active,
.tox .tox-tbtn--select.tox-tbtn--enabled,
.tox .tox-split-button.tox-tbtn--active,
.tox .tox-split-button.tox-tbtn--enabled {
background: var(--bg-active) !important;
background-color: var(--bg-active) !important;
color: var(--accent) !important;
}
.tox .tox-tbtn__select-label,
.tox .tox-tbtn__select-chevron,
.tox .tox-split-button__chevron,
.tox .tox-tbtn--bespoke .tox-tbtn__select-label {
color: var(--text-dim) !important;
}
.tox .tox-tbtn__select-chevron svg,
.tox .tox-split-button__chevron svg {
fill: var(--text-dim) !important;
}
@media (hover: hover) {
.tox .tox-tbtn--select:hover .tox-tbtn__select-label,
.tox .tox-split-button:hover .tox-tbtn__select-chevron svg,
.tox .tox-tbtn--select:hover .tox-tbtn__select-chevron svg {
color: var(--text) !important;
fill: var(--text) !important;
}
}
/* Dropdown menus, context menus, popups */
.tox .tox-menu,
.tox .tox-collection--list,
.tox .tox-collection--toolbar,
.tox .tox-collection--grid {
background: var(--bg-side) !important;
border-color: var(--border) !important;
}
.tox .tox-collection__item {
color: var(--text-dim) !important;
}
.tox .tox-collection__item--active,
.tox .tox-collection__item:hover {
background: var(--bg-hover) !important;
color: var(--text) !important;
}
.tox .tox-collection__item--enabled {
background: var(--bg-active) !important;
color: var(--accent) !important;
}
.tox .tox-collection__group-label {
color: var(--text-muted) !important;
}
/* TinyMCE codesample plugin uses Prism classes; force app theme colors over default blue */
.tox-edit-area pre[class*="language-"],
.tox-edit-area pre.language-markup,
.tox-edit-area pre.language-javascript,
.tox-edit-area pre.language-css,
.tox-edit-area pre.language-html,
.tox-edit-area pre.language-typescript {
background: var(--bg-hover) !important;
border: 1px solid var(--border) !important;
border-radius: 0 !important;
color: var(--text) !important;
}
.tox-edit-area code[class*="language-"] { background: transparent !important; }
.tox-edit-area pre[class*="language-"] > code {
background: transparent !important;
padding: 0 !important;
border-radius: 0 !important;
}
.tox-edit-area pre[class*="language-"] .hljs-keyword,
.tox-edit-area pre[class*="language-"] .hljs-selector-tag,
.tox-edit-area pre[class*="language-"] .hljs-built_in { color: #c678dd !important; }
.tox-edit-area pre[class*="language-"] .hljs-string,
.tox-edit-area pre[class*="language-"] .hljs-attr,
.tox-edit-area pre[class*="language-"] .hljs-addition { color: #98c379 !important; }
.tox-edit-area pre[class*="language-"] .hljs-number,
.tox-edit-area pre[class*="language-"] .hljs-literal,
.tox-edit-area pre[class*="language-"] .hljs-symbol { color: #d19a66 !important; }
.tox-edit-area pre[class*="language-"] .hljs-title,
.tox-edit-area pre[class*="language-"] .hljs-title.function_ { color: #61afef !important; }
.tox-edit-area pre[class*="language-"] .hljs-type,
.tox-edit-area pre[class*="language-"] .hljs-title.class_ { color: #e5c07b !important; }
.tox-edit-area pre[class*="language-"] .hljs-comment,
.tox-edit-area pre[class*="language-"] .hljs-quote { color: var(--text-dim) !important; font-style: italic; }
.cm-host .cm-editor {
height: 100%;
background: transparent;
color: var(--text);
}
.cm-host .cm-editor.cm-focused {
outline: none;
}
/* Underline links in markdown mode */
.cm-host .cm-link,
.cm-host .cm-url {
text-decoration: underline;
}
.cm-host .cm-scroller {
scrollbar-color: var(--border) transparent;
}
.cm-host .cm-placeholder {
color: var(--text-dim);
font-style: italic;
}
/* ===== Markdown mode extras (public/cm-extras.js) ===== */
/* Image previews under `![](:/id)` lines */
.cm-host .cm-jl-imgrow {
display: flex;
flex-wrap: wrap;
gap: 12px;
align-items: flex-start;
padding: 4px 0 10px;
font-family: system-ui, sans-serif;
}
.cm-host .cm-jl-img {
position: relative;
display: inline-block;
max-width: 100%;
line-height: 0;
}
.cm-host .cm-jl-img img {
display: block;
max-width: 100%;
height: auto;
border-radius: 6px;
border: 1px solid var(--border);
background: var(--bg-elevated);
cursor: zoom-in;
user-select: none;
-webkit-user-drag: none;
}
.cm-host .cm-jl-img-natural img { max-height: 360px; width: auto; }
.cm-host .cm-jl-img.loading { min-width: 96px; min-height: 56px; border-radius: 6px; background: var(--bg-elevated); }
.cm-host .cm-jl-img.loading img { opacity: 0; }
.cm-host .cm-jl-img.broken {
padding: 8px 12px;
line-height: 1.4;
font-size: 0.85em;
color: var(--text-dim);
border: 1px dashed var(--border);
border-radius: 6px;
}
.cm-host .cm-jl-img-handle {
position: absolute;
right: -7px;
bottom: -7px;
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--accent);
border: 2px solid var(--bg-editor, var(--bg));
cursor: nwse-resize;
opacity: 0;
transition: opacity 0.12s;
touch-action: none;
z-index: 2;
}
.cm-host .cm-jl-img:hover .cm-jl-img-handle,
.cm-host .cm-jl-img.resizing .cm-jl-img-handle { opacity: 0.95; }
.cm-host .cm-jl-img.resizing img { outline: 2px solid var(--accent); }
@media (hover: none) { .cm-host .cm-jl-img-handle { opacity: 0.85; width: 22px; height: 22px; right: -9px; bottom: -9px; } }
/* Download buttons (same look as the rendered-mode image button) */
.cm-host .cm-jl-img-dl {
position: absolute;
top: 8px;
right: 8px;
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
padding: 0;
font-size: 16px;
line-height: 1;
color: var(--text-heading);
background: var(--bg-elevated);
border: 1px solid var(--border);
border-radius: 999px;
box-shadow: 0 1px 6px rgba(0, 0, 0, 0.28);
cursor: pointer;
opacity: 0.28;
z-index: 2;
transition: opacity 0.18s ease, color 0.18s ease, border-color 0.18s ease, background-color 0.18s ease;
}
.cm-host .cm-jl-img-dl::after,
.cm-host .cm-jl-chip-dl::after { content: "\2B07\FE0F"; }
.cm-host .cm-jl-img:hover .cm-jl-img-dl,
.cm-host .cm-jl-img-dl:hover,
.cm-host .cm-jl-img-dl:focus { opacity: 1; color: #fff; border-color: var(--accent); background: var(--accent); }
.cm-host .cm-jl-img.broken .cm-jl-img-dl,
.cm-host .cm-jl-img.loading .cm-jl-img-dl { display: none; }
@media (hover: none) { .cm-host .cm-jl-img-dl { opacity: 0.9; width: 32px; height: 32px; } }
/* Attachment / note-link chips (replace `[text](:/id)`) */
.cm-host .cm-jl-chip {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 0 9px 0 7px;
margin: 0 1px;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--bg-hover);
color: var(--text);
font-size: 0.92em;
line-height: 1.6;
cursor: pointer;
vertical-align: baseline;
white-space: nowrap;
max-width: 26em;
}
@media (hover: hover) {
.cm-host .cm-jl-chip:hover { border-color: var(--accent); background: var(--bg-active); }
}
.cm-host .cm-jl-chip-dl {
display: none;
align-items: center;
justify-content: center;
width: 1.5em;
height: 1.5em;
margin: 0 -4px 0 0;
padding: 0;
font-size: 0.85em;
line-height: 1;
color: var(--text-dim);
background: transparent;
border: 0;
border-radius: 999px;
cursor: pointer;
}
.cm-host .cm-jl-chip[data-kind="resource"] .cm-jl-chip-dl { display: inline-flex; }
@media (hover: hover) {
.cm-host .cm-jl-chip-dl:hover { color: #fff; background: var(--accent); }
}
.cm-host .cm-jl-chip-label { overflow: hidden; text-overflow: ellipsis; }
.cm-host .cm-jl-chip-icon::before { content: "\1F517"; font-size: 0.9em; }
.cm-host .cm-jl-chip[data-kind="resource"] .cm-jl-chip-icon::before { content: "\1F4CE"; }
.cm-host .cm-jl-chip[data-kind="note"] .cm-jl-chip-icon::before { content: "\1F4C4"; }
/* Clickable task checkboxes */
.cm-host .cm-jl-check {
display: inline-block;
position: relative;
width: 1.05em;
height: 1.05em;
margin: 0 0.15em;
vertical-align: -0.15em;
border: 1.5px solid var(--text-dim);
border-radius: 4px;
cursor: pointer;
box-sizing: border-box;
}
@media (hover: hover) {
.cm-host .cm-jl-check:hover { border-color: var(--accent); }
}
.cm-host .cm-jl-check.checked { background: var(--accent); border-color: var(--accent); }
.cm-host .cm-jl-check.checked::after {
content: "";
position: absolute;
left: 0.28em;
top: 0.04em;
width: 0.28em;
height: 0.55em;
border: solid var(--text-on-accent, #000);
border-width: 0 2px 2px 0;
transform: rotate(45deg);
}
.cm-host .cm-jl-task-done { text-decoration: line-through; color: var(--text-dim); }
/* Fenced code blocks */
.cm-host .cm-jl-codeline { background: var(--bg-elevated); }
.cm-host .cm-jl-codeline-first { border-top-left-radius: 6px; border-top-right-radius: 6px; }
.cm-host .cm-jl-codeline-last { border-bottom-left-radius: 6px; border-bottom-right-radius: 6px; }
.cm-host .cm-jl-copy {
float: right;
margin-left: 8px;
padding: 0 8px;
font: inherit;
font-size: 0.78em;
line-height: 1.6;
color: var(--text-dim);
background: transparent;
border: 1px solid var(--border);
border-radius: 5px;
cursor: pointer;
opacity: 0.55;
}
.cm-host .cm-jl-codeline-first:hover .cm-jl-copy,
.cm-host .cm-jl-copy:focus { opacity: 1; color: var(--text); border-color: var(--accent); }
/* Fold gutter */
.cm-host .cm-foldGutter { width: 18px; }
.cm-host .cm-foldGutter .cm-gutterElement { text-align: center; cursor: pointer; padding: 0; }
.cm-host .cm-jl-fold-marker { opacity: 0; font-size: 0.8em; color: var(--text-dim); transition: opacity 0.12s; }
.cm-host .cm-gutters:hover .cm-jl-fold-marker,
.cm-host .cm-jl-fold-marker.closed { opacity: 0.9; }
@media (hover: hover) {
.cm-host .cm-jl-fold-marker:hover { color: var(--accent); }
}
.cm-host .cm-jl-fold-placeholder {
margin: 0 4px;
padding: 0 6px;
border: 1px solid var(--border);
border-radius: 4px;
background: var(--bg-hover);
color: var(--text-dim);
cursor: pointer;
}
/* Status bar + outline */
.cm-host .cm-panels-bottom {
background: var(--statusbar-bg, var(--bg-side));
border-top: 1px solid var(--border);
color: var(--text-dim);
}
.cm-host .cm-jl-status {
position: relative;
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
padding: 2px 12px;
font-family: system-ui, sans-serif;
font-size: 12px;
line-height: 22px;
}
.cm-host .cm-jl-stat { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cm-host .cm-jl-outline-btn {
font: inherit;
color: var(--text-dim);
background: transparent;
border: 1px solid var(--border);
border-radius: 5px;
padding: 0 8px;
line-height: 18px;
cursor: pointer;
flex: 0 0 auto;
}
@media (hover: hover) {
.cm-host .cm-jl-outline-btn:hover { color: var(--text); border-color: var(--accent); }
}
.cm-host .cm-jl-outline {
position: absolute;
right: 8px;
bottom: 100%;
min-width: 220px;
max-width: min(420px, 90vw);
max-height: 50vh;
overflow-y: auto;
margin-bottom: 4px;
padding: 4px 0;
background: var(--bg-side);
border: 1px solid var(--border);
border-radius: 8px;
box-shadow: 0 8px 24px var(--shadow, rgba(0,0,0,0.3));
z-index: 20;
}
.cm-host .cm-jl-outline[hidden] { display: none; }
.cm-host .cm-jl-outline-item {
display: block;
width: 100%;
text-align: left;
font: inherit;
line-height: 1.5;
padding: 3px 10px;
color: var(--text);
background: transparent;
border: 0;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
@media (hover: hover) {
.cm-host .cm-jl-outline-item:hover { background: var(--bg-hover); }
}
.cm-host .cm-jl-outline-empty { padding: 6px 12px; color: var(--text-dim); }
/* Link hover info */
.cm-tooltip.cm-tooltip-hover {
background: var(--bg-side);
color: var(--text);
border: 1px solid var(--border);
border-radius: 8px;
box-shadow: 0 6px 20px var(--shadow, rgba(0,0,0,0.3));
}
.cm-tooltip.cm-tooltip-hover .cm-jl-tip {
padding: 6px 10px;
font-family: system-ui, sans-serif;
font-size: 13px;
max-width: 340px;
}
.cm-jl-tip-title { color: var(--text); font-weight: 600; word-break: break-word; }
.cm-jl-tip-sub { color: var(--text-dim); font-size: 12px; margin-top: 2px; }
.note-autocomplete-popup,
.cm-tooltip-autocomplete {
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-side);
box-shadow: 0 14px 40px var(--shadow);
overflow: hidden;
max-width: min(560px, calc(100vw - 24px));
max-height: 42vh;
overflow-y: auto;
backdrop-filter: blur(8px);
}
.note-autocomplete-item,
.cm-tooltip-autocomplete ul > li {
padding: 10px 12px;
color: var(--text);
font-size: 13px;
line-height: 1.35;
border-top: 1px solid transparent;
}
.note-autocomplete-item:first-child,
.cm-tooltip-autocomplete ul > li:first-child { border-top: 0; }
.note-autocomplete-item.active,
.cm-tooltip-autocomplete ul > li[aria-selected="true"] {
background: var(--bg-active);
color: var(--text-heading);
}
@media (hover: hover) {
.note-autocomplete-item:hover,
.cm-tooltip-autocomplete ul > li:hover {
background: var(--bg-hover);
}
}
.note-autocomplete-item + .note-autocomplete-item,
.cm-tooltip-autocomplete ul > li + li {
border-top-color: var(--border);
}
/* Preview pane */
.editor-preview {
flex: 1;
padding: 16px 20px;
overflow-y: auto;
font-size: var(--font-size-note);
line-height: 1.7;
color: var(--text);
outline: none;
}
.editor-preview p { margin: 0.75em 0; }
.editor-preview p:first-child { margin-top: 0; }
.editor-preview .md-blank-line { margin: 0.75em 0; }
.editor-preview .md-blank-line br { line-height: 0; font-size: 0; display: block; }
/* Match browser-inserted blank paragraphs to the canonical md-blank-line
spacing. Without this, hitting Enter in rendered mode creates <p><br></p>
or <div><br></div> at full line-height, while the same source re-rendered
from markdown produces md-blank-line divs at paragraph-margin scale. */
.editor-preview p:empty,
.editor-preview p:has(> br:only-child),
.editor-preview div:not([class]):empty,
.editor-preview div:not([class]):has(> br:only-child) {
margin: 0.75em 0;
}
.editor-preview[contenteditable="true"] {
cursor: text;
overflow-anchor: none;
}
.editor-preview h1, .editor-preview h2, .editor-preview h3,
.editor-preview h4, .editor-preview h5, .editor-preview h6 {
color: var(--text-heading);
margin: 1em 0 0.5em;
}
.editor-preview > h1:first-child,
.editor-preview > h2:first-child,
.editor-preview > h3:first-child,
.editor-preview > h4:first-child,
.editor-preview > h5:first-child,
.editor-preview > h6:first-child { margin-top: 0; }
.editor-preview h1 { font-size: 1.8em; }
.editor-preview h2 { font-size: 1.5em; }
.editor-preview h3 { font-size: 1.25em; }
.editor-preview strong { color: var(--text-heading); }
.editor-preview a { color: var(--accent); }
.editor-preview code {
background: var(--bg-hover);
padding: 2px 5px;
border-radius: 0;
font-family: 'Cascadia Mono', monospace;
font-size: var(--font-size-code);
}
.editor-preview pre {
background: #1f2329;
border: 1px solid #343a40;
color: #e6edf3;
padding: 28px 16px 12px;
border-radius: 0;
overflow-x: auto;
margin: 1em 0;
font-family: 'Cascadia Mono', monospace;
font-size: var(--font-size-code);
}
.editor-preview pre code { background: none; padding: 0; color: inherit; }
/* highlight.js token colors (One Dark inspired, matches CM6 theme) */
.editor-preview .hljs-keyword,
.editor-preview .hljs-selector-tag,
.editor-preview .hljs-built_in { color: #c678dd; }
.editor-preview .hljs-string,
.editor-preview .hljs-attr,
.editor-preview .hljs-addition { color: #98c379; }
.editor-preview .hljs-number,
.editor-preview .hljs-literal,
.editor-preview .hljs-symbol { color: #d19a66; }
.editor-preview .hljs-title,
.editor-preview .hljs-title.function_ { color: #61afef; }
.editor-preview .hljs-type,
.editor-preview .hljs-title.class_ { color: #e5c07b; }
.editor-preview .hljs-comment,
.editor-preview .hljs-quote { color: #8b949e; font-style: italic; }
.editor-preview .hljs-variable,
.editor-preview .hljs-template-variable { color: #e06c75; }
.editor-preview .hljs-operator { color: #56b6c2; }
.editor-preview .hljs-property { color: #e06c75; }
.editor-preview .hljs-attribute { color: #d19a66; }
.editor-preview .hljs-meta { color: #8b949e; }
.editor-preview .hljs-deletion { color: #e06c75; }
.editor-preview .hljs-section { color: #61afef; font-weight: bold; }
.editor-preview .hljs-name { color: #e06c75; }
.editor-preview .hljs-selector-class,
.editor-preview .hljs-selector-id { color: #e5c07b; }
.editor-preview .hljs-punctuation { color: #e6edf3; }
.editor-preview blockquote {
border-left: 3px solid var(--accent);
margin: 1em 0;
padding: 4px 16px;
color: var(--text-dim);
}
.editor-preview hr { border: none; border-top: 1px solid var(--border); margin: 1.5em 0; }
.editor-preview ul, .editor-preview ol { padding-left: 1.5em; margin: 0.5em 0; }
.editor-preview li { margin: 0.25em 0; }
.editor-preview table { border-collapse: collapse; width: 100%; margin: 0.8em 0; }
.editor-preview th, .editor-preview td { border: 3px solid var(--border); padding: 6px 10px; text-align: left; }
.editor-preview th { background: var(--bg-hover); font-weight: bold; }
.editor-preview .md-checkbox {
margin: 0.25em 0;
padding-left: 0.9em;
display: flex;
align-items: baseline;
gap: 0.35em;
}
.editor-preview .md-checkbox::before {
content: '';
display: inline-block;
width: 16px;
height: 16px;
border: 1.5px solid var(--accent);
border-radius: 0;
flex-shrink: 0;
background: transparent;
box-sizing: border-box;
}
.editor-preview .md-checkbox.checked::before {
background: var(--accent);
border-color: var(--accent);
content: '✓';
color: var(--bg);
font-size: 11px;
font-weight: bold;
line-height: 16px;
text-align: center;
}
.preview-img { display: block; max-width: 100%; height: auto; border-radius: 0; margin: 12px 0; cursor: default; }
.editor-preview[contenteditable="true"] .preview-img { cursor: nwse-resize; border: 1px solid transparent; }
@media (hover: hover) {
.editor-preview[contenteditable="true"] .preview-img:hover { border-color: var(--accent); opacity: 0.95; }
}
.editor-preview[contenteditable="true"] .preview-img:active { border-color: var(--accent); }
.preview-img-download-wrap {
position: relative;
display: inline-block;
max-width: 100%;
margin: 12px 0;
}
.preview-img-download-wrap .preview-img { margin: 0; }
.preview-img-download-btn {
position: absolute;
top: 8px;
right: 8px;
display: inline-flex;
align-items: center;
justify-content: center;
width: 28px;
height: 28px;
padding: 0;
font-size: 18px;
font-weight: 700;
font-family: inherit;
background: color-mix(in srgb, var(--bg-elevated) 82%, transparent);
color: var(--text-heading);
border: 1px solid var(--border);
border-radius: 999px;
cursor: pointer;
line-height: 1;
z-index: 1;
opacity: 0.28;
backdrop-filter: blur(4px);
box-shadow: 0 1px 6px rgba(0,0,0,0.28);
transition: opacity 0.18s ease, color 0.18s ease, border-color 0.18s ease, background-color 0.18s ease, transform 0.18s ease;
}
.preview-img-download-wrap:hover .preview-img-download-btn,
.preview-img-download-wrap:focus-within .preview-img-download-btn,
.preview-img-download-btn:focus,
.preview-img-download-btn:active {
opacity: 1;
}
.preview-img-download-wrap:hover .preview-img-download-btn,
.preview-img-download-wrap:focus-within .preview-img-download-btn {
color: #fff;
border-color: var(--accent);
background: color-mix(in srgb, var(--accent) 82%, transparent);
transform: scale(1.04);
}
.preview-img-download-btn:hover,
.preview-img-download-btn:focus,
.preview-img-download-btn:active {
color: #fff;
border-color: var(--accent);
background: color-mix(in srgb, var(--accent) 82%, transparent);
transform: scale(1.04);
}
@media (hover: none), (pointer: coarse) {
.preview-img-download-btn {
width: 24px;
height: 24px;
top: 6px;
right: 6px;
font-size: 15px;
opacity: 1;
background: color-mix(in srgb, var(--accent) 80%, transparent);
color: #fff;
border-color: color-mix(in srgb, var(--accent) 70%, var(--border));
}
}
/* --- Resource action sheet (PWA) --- */
.resource-action-backdrop {
position: fixed; inset: 0; z-index: 10010;
background: var(--overlay);
}
.resource-action-sheet {
position: fixed; left: 12px; right: 12px; top: 12px;
z-index: 10011;
display: flex; flex-direction: column; gap: 6px;
padding: 10px;
min-width: 180px;
overflow: auto;
background: var(--bg-side);
border: 1px solid var(--border);
border-radius: 0;
box-shadow: 0 8px 24px rgba(0,0,0,0.45);
}
.resource-action-btn {
appearance: none;
display: block; width: 100%;
padding: 14px 16px;
font-size: 17px; font-weight: 600;
color: var(--text);
background: var(--bg-elevated);
border: 1px solid var(--border);
border-radius: 0;
cursor: pointer;
}
.resource-action-btn:active { background: var(--bg-active); }
.resource-action-btn-cancel { color: var(--text-dim); }
@media (hover: hover) and (pointer: fine) {
.resource-action-backdrop { background: transparent; }
.resource-action-sheet { right: auto; }
}
/* --- Resource viewer (in-app preview: PWA action sheet + desktop image/attachment double-click) --- */
.resource-viewer {
position: fixed; inset: 0; z-index: 10020;
display: flex; flex-direction: column;
background: #000;
}
.resource-viewer-bar {
display: flex; align-items: center; gap: 8px;
padding: 10px 12px;
padding-top: calc(env(safe-area-inset-top, 0px) + 10px);
background: var(--bg-side);
border-bottom: 1px solid var(--border);
}
.resource-viewer-title {
flex: 1; min-width: 0;
color: var(--text);
font-size: 14px;
white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.resource-viewer-btn {
appearance: none;
padding: 8px 14px;
font-size: 14px; font-weight: 600;
color: var(--text);
background: var(--bg-elevated);
border: 1px solid var(--border);
border-radius: 0;
cursor: pointer;
}
.resource-viewer-btn:active { background: var(--bg-active); }
.resource-viewer-body {
flex: 1; min-height: 0;
display: flex; align-items: center; justify-content: center;
overflow: auto;
background: #000;
padding-bottom: env(safe-area-inset-bottom, 0px);
}
.resource-viewer-img { max-width: 100%; max-height: 100%; object-fit: contain; }
.resource-viewer-frame { width: 100%; height: 100%; border: 0; background: #fff; }
.resource-viewer-msg { padding: 20px; color: var(--text); text-align: center; font-size: 15px; }
/* Autosave */
.autosave-ok { color: #5fd38d; font-size: 11px; opacity: 0.9; }
.autosave-edited { color: var(--danger); font-size: 11px; opacity: 0.95; }
.autosave-error { color: var(--danger); font-size: 11px; }
.autosave-saving { color: var(--text-dim); font-size: 11px; opacity: 0.9; }
.autosave-offline { color: var(--danger); font-size: 11px; animation: pulse-offline 2s ease-in-out infinite; }
@keyframes pulse-offline { 0%,100%{opacity:1} 50%{opacity:0.4} }
.is-offline .app-statusbar { background: color-mix(in srgb, var(--danger) 12%, var(--statusbar-bg)); }
/* --- Disconnected overlay (server unreachable) --- */
.disconnected-overlay {
position: fixed;
inset: 0;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
background: #000;
}
.disconnected-logo {
position: absolute;
width: 320px;
height: 320px;
opacity: 0.15;
filter: blur(4px);
pointer-events: none;
}
.disconnected-card {
position: relative;
text-align: center;
max-width: 340px;
width: calc(100% - 32px);
}
.disconnected-icon svg {
width: 48px;
height: 48px;
color: var(--danger);
margin-bottom: 16px;
}
.disconnected-title {
font-size: 18px;
font-weight: 600;
color: #ccc;
margin-bottom: 6px;
}
.disconnected-sub {
font-size: 13px;
color: #888;
margin-bottom: 16px;
}
.disconnected-countdown {
font-size: 13px;
color: #666;
margin-bottom: 16px;
font-variant-numeric: tabular-nums;
animation: pulse-offline 2s ease-in-out infinite;
}
.disconnected-actions {
display: flex;
flex-direction: column;
gap: 8px;
}
.disconnected-retry {
padding: 8px 16px;
border: 1px solid #555;
border-radius: 0;
background: transparent;
color: #ccc;
font-size: 13px;
font-weight: 500;
font-family: inherit;
cursor: pointer;
transition: background 0.15s;
}
@media (hover: hover) {
.disconnected-retry:hover { background: #222; }
}
.disconnected-retry:disabled { opacity: 0.5; cursor: not-allowed; }
.disconnected-logout {
padding: 8px 16px;
border: 1px solid #333;
border-radius: 0;
background: transparent;
color: #666;
font-size: 13px;
font-family: inherit;
cursor: pointer;
transition: color 0.15s, border-color 0.15s;
}
@media (hover: hover) {
.disconnected-logout:hover { color: var(--danger); border-color: var(--danger); }
}
.is-disconnected .app-layout { display: none; }
.is-disconnected #mobile-app { display: none; }
.autosave-conflict { display: inline-flex; align-items: center; gap: 6px; }
/* Full-screen note loading overlay */
#note-loading-overlay {
display: none;
position: fixed;
inset: 0;
z-index: 9999;
background: rgba(0,0,0,0.45);
align-items: center;
justify-content: center;
flex-direction: column;
gap: 20px;
}
#note-loading-overlay.active { display: flex; }
.mobile-loading-note {
display: flex !important;
align-items: center;
justify-content: center;
flex: 1;
}
.note-loading-ring {
width: 72px;
height: 72px;
border-radius: 50%;
border: 6px solid rgba(255,255,255,0.2);
border-top-color: #fff;
will-change: transform;
animation: note-loading-spin 0.8s linear infinite;
}
.note-loading-label {
color: #fff;
font-size: 15px;
letter-spacing: 0.03em;
opacity: 0.9;
}
@keyframes note-loading-spin {
to { transform: rotate(360deg); }
}
.htmx-indicator { display: none; color: var(--text-dim); font-size: 11px; }
.htmx-request .htmx-indicator { display: inline; }
.htmx-request #autosave-status { display: none; }
.note-meta {
color: var(--text-dim);
font-size: 10px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 260px;
}
#editor-panel > #note-meta {
display: none;
}
/* Status bar */
.app-statusbar {
height: var(--statusbar-height);
display: flex;
align-items: center;
gap: 10px;
padding: 0 12px;
background: var(--statusbar-bg);
border-top: 1px solid var(--border);
font-size: 11px;
color: var(--text-dim);
flex-shrink: 0;
}
.status-user { }
.status-spacer { flex: 1; }
.theme-picker {
padding: 2px 4px;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-side);
color: var(--text);
font-size: 11px;
outline: none;
cursor: pointer;
width: auto;
max-width: min(260px, 100%);
flex: 0 1 auto;
}
.theme-picker option {
background: var(--bg-side);
color: var(--text);
}
/* Buttons */
.btn {
display: inline-flex;
align-items: center;
justify-content: center;
padding: 5px 12px;
border-radius: 4px;
border: 1px solid var(--border);
font-weight: 500;
font-size: 12px;
transition: background 0.1s;
text-decoration: none;
white-space: nowrap;
}
.btn[hidden] { display: none; }
@media (hover: hover) {
.btn:hover { background: var(--bg-hover); }
}
.btn-primary {
background: var(--accent);
color: var(--text-on-accent);
border-color: var(--accent);
}
@media (hover: hover) {
.btn-primary:hover {
background: color-mix(in srgb, var(--accent) 88%, #fff);
border-color: color-mix(in srgb, var(--accent) 88%, #fff);
color: var(--text-on-accent);
}
}
.btn.active {
background: var(--bg-active);
border-color: var(--border-focus);
}
.btn-secondary { background: var(--bg-input); }
.btn-sm { padding: 4px 10px; font-size: 12px; }
.btn-icon {
width: 28px;
height: 28px;
padding: 0;
display: flex;
align-items: center;
justify-content: center;
border-radius: 4px;
border: none;
font-size: 14px;
color: var(--text-dim);
transition: background 0.1s;
}
@media (hover: hover) {
.btn-icon:hover { background: var(--bg-hover); }
}
#lock-toggle-btn { color: #FFC107; }
@media (hover: hover) {
#lock-toggle-btn:hover { color: #FFC107; }
}
.btn-icon.active { color: var(--accent); background: var(--bg-active); }
.btn-icon-compact { width: 24px; height: 24px; font-size: 13px; }
.btn-danger-soft { color: var(--danger); }
@media (hover: hover) {
.btn-danger-soft:hover { color: var(--danger); background: color-mix(in srgb, var(--danger) 14%, transparent); }
}
@media (hover: hover) {
.btn-danger:hover { color: var(--danger); }
}
.mode-toggle-btn {
width: auto;
min-width: 52px;
height: 28px;
padding: 0 10px;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 12px;
font-weight: 600;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--bg-input);
color: var(--text-muted);
}
.btn-icon.mode-toggle-btn.active {
color: var(--text-on-accent);
background: var(--accent);
border-color: var(--accent);
}
.empty-hint {
padding: 12px;
color: var(--text-dim);
font-size: 12px;
}
/* Login */
.login-page {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
font-family: 'Cascadia Mono', monospace;
min-height: 100dvh;
}
.login-card { text-align: center; max-width: 360px; width: 100%; }
.login-logo {
display: block;
width: 96px;
height: 96px;
margin: 0 auto 14px;
border-radius: 0;
box-shadow: 0 14px 32px var(--shadow);
}
.login-title {
font-size: 36px;
font-weight: 800;
color: var(--accent);
margin-bottom: 8px;
}
.login-brand {
font-size: 28px;
letter-spacing: 0.16em;
}
.login-sub {
color: var(--text-dim);
margin-bottom: 20px;
}
.login-tagline {
font-size: 13px;
line-height: 1.35;
}
.login-form {
display: flex;
flex-direction: column;
gap: 10px;
}
.login-input {
box-sizing: border-box;
min-width: 0;
max-width: 100%;
padding: 10px 12px;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-side);
color: var(--text);
font-size: 14px;
outline: none;
}
select.login-input {
background-color: var(--bg-side);
color: var(--text);
}
select.login-input option {
background-color: var(--bg-side);
color: var(--text);
}
.login-input:focus {
border-color: var(--accent);
}
.login-btn {
padding: 10px 12px;
font-size: 14px;
margin-top: 4px;
}
.login-error {
color: var(--danger);
font-size: 13px;
min-height: 1.2em;
}
.settings-page {
min-height: 100vh;
padding: calc(28px + env(safe-area-inset-top, 0px)) 20px calc(28px + env(safe-area-inset-bottom, 0px));
min-height: 100dvh;
background: var(--bg);
}
.settings-card {
max-width: 760px;
margin: 0 auto;
padding: 20px;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-side);
box-shadow: 0 18px 40px var(--shadow);
}
.about-info {
display: flex;
flex-direction: column;
gap: 12px;
margin-top: 16px;
}
.about-row {
display: flex;
align-items: baseline;
gap: 12px;
}
.about-label {
font-size: 13px;
color: var(--text-dim);
min-width: 120px;
flex-shrink: 0;
}
.about-value {
font-size: 14px;
color: var(--text);
}
.about-link {
color: var(--accent);
text-decoration: none;
}
@media (hover: hover) {
.about-link:hover {
text-decoration: underline;
}
}
.settings-header {
display: flex;
justify-content: space-between;
gap: 16px;
align-items: flex-start;
margin-bottom: 18px;
}
.settings-title {
margin: 0;
font-size: 28px;
color: var(--text-heading);
}
.settings-sub,
.settings-section-sub {
margin: 6px 0 0;
color: var(--text-dim);
}
.settings-section {
padding-top: 18px;
margin-top: 18px;
border-top: 1px solid var(--border);
}
.status-settings-link {
text-decoration: none;
flex-shrink: 0;
width: 42px;
height: 42px;
font-size: 21px;
position: relative;
top: 1px;
}
.settings-section-title {
margin: 0 0 8px;
font-size: 18px;
color: var(--text-heading);
}
.settings-grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 16px;
margin-top: 16px;
}
.settings-form {
display: grid;
gap: 16px;
}
.settings-field {
display: grid;
gap: 8px;
color: var(--text);
/* Grid cells stretch to the tallest cell in their row; without this the
rows inside a field stretch too and a <select> balloons to fill it. */
align-content: start;
}
.settings-checkbox {
align-content: start;
}
/* A field that needs the whole row (e.g. a group of checkboxes). */
.settings-field-wide {
grid-column: 1 / -1;
}
.settings-checkbox-group {
display: flex;
flex-wrap: wrap;
gap: 8px 28px;
}
.settings-actions {
display: flex;
justify-content: flex-end;
}
.settings-security-card {
margin-top: 14px;
padding: 16px;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-elevated);
}
.settings-mfa-status,
.settings-secret {
margin: 0 0 12px;
}
.settings-mfa-status .badge { vertical-align: middle; margin-right: 8px; }
.settings-qr {
display: block;
width: 200px;
height: 200px;
max-width: 100%;
margin: 16px 0;
border-radius: 0;
background: #fff;
padding: 12px;
}
.settings-mfa-row {
display: flex;
gap: 8px;
align-items: center;
margin-top: 8px;
}
.settings-mfa-row .login-input {
flex: 1;
max-width: 160px;
}
.settings-mfa-setup .settings-mfa-row { margin-bottom: 12px; }
.settings-mfa-cancel { margin-top: 12px; }
.settings-mfa-global {
margin-top: 16px;
background: color-mix(in srgb, var(--accent) 10%, transparent);
border: 1px solid var(--accent);
}
.badge-warning { background: color-mix(in srgb, #f59e0b 20%, transparent); color: #f59e0b; }
/* AI profile cards */
.ai-profiles-bar {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
margin-top: 14px;
max-width: 100%;
}
.ai-profiles-bar-label {
display: flex;
align-items: center;
flex: 1 1 260px;
gap: 8px;
min-width: 0;
font-size: 13px;
color: var(--text-muted);
}
.ai-active-select {
width: 200px;
max-width: 200px;
}
.ai-profiles {
display: grid;
gap: 10px;
margin-top: 12px;
min-width: 0;
}
.ai-profile-card {
min-width: 0;
max-width: 100%;
box-sizing: border-box;
padding: 12px 14px;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-elevated);
}
.ai-profile-card-active {
border-color: var(--accent);
}
.ai-profile-header {
display: flex;
align-items: center;
gap: 8px;
margin-bottom: 10px;
flex-wrap: wrap;
}
.ai-profile-name-input {
flex: 1 1 180px;
min-width: 120px;
}
.ai-profile-provider-select {
flex: 1 1 150px;
width: 150px;
max-width: 150px;
min-width: 0;
}
.ai-profile-body {
display: grid;
gap: 8px;
min-width: 0;
}
.ai-profile-field {
display: grid;
gap: 4px;
min-width: 0;
font-size: 13px;
color: var(--text-muted);
}
.ai-profile-field .login-input {
width: 100%;
}
.ai-profile-field .settings-field-hint,
.ai-profile-field code {
max-width: 100%;
overflow-wrap: anywhere;
word-break: break-word;
}
.ai-profile-field > span:first-child {
font-size: 11px;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--text-muted);
}
.ai-profile-actions {
display: flex;
align-items: center;
gap: 10px;
margin-top: 4px;
}
.ai-test-result {
font-size: 13px;
color: var(--text-muted);
}
.ai-test-ok { color: var(--accent); }
.ai-test-fail { color: #ef4444; }
.logout-progress {
display: grid;
gap: 6px;
margin-top: 18px;
text-align: left;
}
.logout-step {
padding: 8px 0;
border: 0;
border-bottom: 1px solid var(--border);
border-radius: 0;
background: transparent;
color: var(--text-dim);
text-align: left;
cursor: pointer;
}
.logout-step.done {
color: var(--text);
}
.logout-step-check {
float: right;
color: #4caf50;
font-weight: 700;
}
.logout-detail {
display: none;
padding: 0 0 8px;
color: var(--text-dim);
font-size: 13px;
line-height: 1.5;
}
.logout-detail.open {
display: block;
}
.login-password-wrap {
position: relative;
display: flex;
}
.login-password-wrap .login-input {
flex: 1;
padding-right: 36px;
}
.login-eye {
position: absolute;
right: 4px;
top: 50%;
transform: translateY(-50%);
background: none;
border: none;
cursor: pointer;
font-size: 18px;
padding: 4px;
line-height: 1;
opacity: 0.6;
}
@media (hover: hover) {
.login-eye:hover {
opacity: 1;
}
}
.login-totp {
opacity: 0.7;
font-size: 14px;
}
.login-totp:focus {
opacity: 1;
}
/* Scrollbar — standard props (Firefox, modern Chromium/Safari) + WebKit
pseudo-elements (older Chromium/Safari) so every scrollable panel in the
app (note list, sidebars, modals, etc.) gets the same thin, theme-colored
scrollbar as the markdown editor (.cm-scroller). */
body { scrollbar-width: thin; scrollbar-color: var(--scrollbar) transparent; }
::-webkit-scrollbar { width: 6px; height: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scrollbar); border-radius: 0; }
/* Responsive */
@media (max-width: 768px) {
body { font-size: 12px; }
body { --statusbar-height: 36px; }
/* Prevent iOS auto-zoom: all inputs must be >= 16px */
input, select, textarea { font-size: 16px !important; }
html, body { overflow-x: hidden; }
.login-page {
padding: calc(20px + env(safe-area-inset-top, 0px)) 16px 20px;
align-items: flex-start;
}
.login-card {
max-width: 320px;
margin: 0 auto;
}
.login-logo { width: 108px; height: 108px; margin-bottom: 16px; }
.login-title { font-size: 36px; }
.login-brand { font-size: 24px; }
.login-sub { margin-bottom: 20px; font-size: 18px; line-height: 1.45; }
.login-tagline { font-size: 12px; line-height: 1.3; }
.login-input,
.login-btn { font-size: 18px; }
.login-input { padding: 12px 14px; }
.login-btn { width: 100%; min-height: 52px; padding: 14px 18px; font-size: 20px; font-weight: 700; }
.app { display: block; position: relative; height: calc(100vh - var(--statusbar-height) - env(safe-area-inset-bottom, 0px) - 22px); }
body.mobile-nav-open { overflow: hidden; }
.nav-toggle-btn { display: none; }
.nav-reopen-btn {
display: inline-flex;
position: fixed;
top: env(safe-area-inset-top, 6px);
left: 8px;
z-index: 15;
}
body.nav-collapsed .nav-reopen-btn,
body:not(.nav-collapsed) .nav-reopen-btn { display: inline-flex; }
.mobile-nav-backdrop {
display: block;
position: fixed;
inset: 0;
background: var(--overlay);
opacity: 0;
pointer-events: none;
transition: opacity 0.18s;
z-index: 18;
}
.mobile-nav-backdrop.open {
opacity: 1;
pointer-events: auto;
}
.col-nav {
display: flex;
position: fixed;
left: 0;
top: 0;
bottom: calc(var(--statusbar-height) + env(safe-area-inset-bottom, 0px) + 22px);
width: min(88vw, 360px);
max-width: 100%;
flex-direction: column;
background: var(--bg-side);
transform: translateX(-100%);
transition: transform 0.18s ease;
z-index: 20;
box-shadow: 10px 0 30px var(--shadow);
}
.col-nav.open { transform: translateX(0); }
body.nav-collapsed .col-nav { display: flex; }
.col-editor { height: 100%; min-height: 0; }
.nav-panel-header { padding: 10px; gap: 5px; }
.nav-items { padding: 8px; }
.nav-folder-row { padding: 8px; }
.nav-folder > .nav-folder-row { padding-left: calc(8px + var(--nav-depth, 0) * 14px); }
.nav-folder-notes .notelist-item { padding: 8px 10px 8px calc(32px + var(--nav-depth, 0) * 14px); }
.editor-titlebar {
padding: 6px 8px 6px 62px;
gap: 4px;
flex-wrap: nowrap;
align-items: center;
}
.editor-title {
flex: 1 1 auto;
min-width: 0;
font-size: 13px;
line-height: 1.2;
padding: 0;
min-height: 1.2em;
order: 1;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.editor-folder-select {
max-width: 110px;
font-size: 11px;
padding: 2px 5px;
order: 1;
}
.editor-folder-arrow { margin: 0; font-size: 12px; order: 1; }
#autosave-status,
#autosave-indicator { margin-left: auto; font-size: 10px; order: 1; }
.btn,
.btn-sm { padding: 4px 8px; font-size: 11px; }
.login-btn { font-size: 20px; }
.btn-icon { width: 26px; height: 26px; font-size: 13px; order: 1; }
.editor-title-mobile-readonly {
pointer-events: none;
}
.editor-toolbar {
flex-wrap: nowrap;
overflow-x: auto;
overflow-y: hidden;
padding: 10px 12px;
gap: 6px;
-webkit-overflow-scrolling: touch;
}
.editor-toolbar::-webkit-scrollbar { height: 3px; }
.editor-toolbar .tb { min-width: 46px; height: 46px; padding: 0 12px; font-size: 18px; border-radius: 10px; flex: 0 0 auto; }
.editor-toolbar .tb-div { margin: 0 5px; height: 24px; flex: 0 0 auto; }
.editor-toolbar .tb[data-format="h1"],
.editor-toolbar .tb[data-format="h2"] { display: none; }
.cm-host .cm-content {
padding: 10px 12px;
}
.editor-preview {
padding: 10px 12px;
font-size: var(--font-size-note-mobile, var(--font-size-note));
line-height: 1.7;
}
.editor-preview h1 { font-size: 1.45em; }
.editor-preview h2 { font-size: 1.28em; }
.editor-preview h3 { font-size: 1.15em; }
.app-statusbar {
height: var(--statusbar-height);
gap: 6px;
padding: 0 8px calc(env(safe-area-inset-bottom, 0px) + 18px);
font-size: 10px;
}
.status-user {
max-width: 40vw;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.theme-picker { padding: 1px 3px; font-size: 10px; }
}
/* --- Mobile app (only shown on mobile) --- */
.mobile-app {
display: none;
}
.mobile-fab {
display: none;
}
@media (max-width: 768px) {
/* Hide desktop layout on mobile */
.app, .nav-reopen-btn, .mobile-nav-backdrop { display: none !important; }
.app-statusbar { display: none; }
#mobile-editor-body #note-meta { display: none !important; }
#mobile-editor-body > #note-meta {
display: none !important;
height: 0 !important;
min-height: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
}
/* Show mobile app */
.mobile-app {
display: flex;
position: fixed;
inset: 0;
overflow: hidden;
background: var(--bg);
}
/* Each screen fills the container */
.mobile-screen {
position: absolute;
inset: 0;
display: none;
flex-direction: column;
background: var(--bg);
pointer-events: none;
}
.mobile-screen-active {
display: flex;
pointer-events: auto;
}
/* Header bar */
.mobile-header {
display: flex;
align-items: center;
height: calc(44px + env(safe-area-inset-top, 0px));
padding-top: env(safe-area-inset-top, 0px);
padding-left: 4px;
padding-right: 4px;
background: var(--bg-side);
border-bottom: 1px solid var(--border);
flex-shrink: 0;
gap: 4px;
}
.mobile-header-title {
flex: 1;
min-width: 0;
font-size: 17px;
font-weight: 600;
color: var(--text);
padding: 0 8px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mobile-editor-title-editable[contenteditable="true"] {
cursor: text;
outline: none;
border-bottom: 1px solid transparent;
transition: border-color 0.15s;
}
.mobile-editor-title-editable[contenteditable="true"]:focus {
border-bottom-color: var(--accent);
white-space: normal;
overflow: visible;
text-overflow: clip;
}
.mobile-editor-title-editable:empty:before {
content: attr(data-placeholder);
color: var(--text-muted, #888);
pointer-events: none;
}
.mobile-header-btn {
background: none;
border: none;
color: var(--accent);
font-size: 22px;
line-height: 1;
padding: 6px 10px;
cursor: pointer;
flex-shrink: 0;
font-family: inherit;
}
.mobile-editor-search-header {
padding-left: 8px;
padding-right: 8px;
}
.mobile-editor-search-input {
flex: 1;
min-width: 0;
height: 34px;
padding: 0 10px;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--bg-input);
color: var(--text);
font: inherit;
}
.mobile-editor-search-input:focus {
outline: none;
border-color: var(--border-focus);
}
.mobile-search-nav-counter {
flex-shrink: 0;
min-width: 40px;
text-align: center;
font-size: 12px;
font-variant-numeric: tabular-nums;
color: var(--text);
}
.mobile-search-nav-btn {
width: 34px;
height: 34px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid var(--border);
border-radius: 50%;
background: var(--bg-input);
color: var(--text);
font-size: 16px;
}
.mobile-mode-toggle {
width: 34px;
height: 34px;
padding: 0;
display: inline-flex;
align-items: center;
justify-content: center;
border: 1px solid var(--border);
border-radius: 50%;
background: var(--bg-input);
color: var(--text-muted);
font-size: 11px;
font-weight: 600;
flex-shrink: 0;
}
.mobile-header-btn.mobile-mode-toggle.active {
background: var(--accent);
border-color: var(--accent);
color: var(--text-on-accent);
}
.mobile-back-btn {
font-size: 28px;
padding: 2px 8px;
position: relative;
z-index: 1;
}
.mobile-editor-status {
flex-shrink: 0;
font-size: 12px;
color: var(--text-muted);
min-width: 3.5em;
text-align: right;
}
.mobile-editor-status .autosave-ok,
.mobile-editor-status .autosave-edited,
.mobile-editor-status .autosave-error,
.mobile-editor-status .autosave-saving {
font-size: 12px;
opacity: 1;
}
/* Screen body */
.mobile-screen-body {
flex: 1;
overflow-y: auto;
-webkit-overflow-scrolling: touch;
overscroll-behavior: contain;
}
/* The folder and note lists end clear of the floating "+" (56px tall, 20px above the
bottom edge, so 76px) plus breathing room and the home indicator. Without this the last
row's count / "+" / chevron (or "Load more") sit under the button and cannot be scrolled
out from beneath it. Scoped to the two list bodies: the editor body shares
.mobile-screen-body and must not get padding. */
#mobile-folders-body,
#mobile-notes-body {
padding-bottom: calc(96px + env(safe-area-inset-bottom, 0px));
}
/* Editor body must not scroll at the outer level — TinyMCE scrolls internally.
overflow:hidden + overscroll-behavior:none kills iOS rubber-band on the shell. */
.mobile-editor-body {
display: flex;
flex-direction: column;
overflow: hidden;
overscroll-behavior: none;
min-width: 0;
position: relative;
}
.mobile-editor-body .col-editor,
.mobile-editor-body > form {
flex: 1;
display: flex;
flex-direction: column;
min-height: 0;
min-width: 0;
position: absolute;
inset: 0;
width: 100%;
}
.mobile-editor-body > form > * {
min-height: 0;
}
/* Folder rows */
.mobile-folder-row {
display: flex;
align-items: center;
flex-wrap: nowrap;
width: 100%;
background: none;
border: none;
border-bottom: 1px solid var(--border);
padding: 14px 16px;
gap: 10px;
cursor: pointer;
color: var(--text);
font-size: 15px;
font-family: inherit;
text-align: left;
}
.mobile-folder-row:active { background: var(--bg-hover); }
/* display:flex above beats the UA [hidden] rule, so restate it. */
.mobile-folder-row[hidden] { display: none; }
/* Nested notebooks: indent per level (capped at 4 by the server). */
.mobile-folder-row { padding-left: calc(16px + var(--m-depth, 0) * 18px); }
/* Chevron is its own 44px-tall tap target; the row itself still opens the notes. */
.mobile-folder-toggle {
display: inline-flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
width: 28px;
align-self: stretch;
margin: -14px 0 -14px -8px;
color: var(--text-muted);
font-size: 16px;
transition: transform 0.12s;
}
.mobile-folder-toggle-placeholder { visibility: hidden; }
.mobile-folder-row.expanded > .mobile-folder-toggle { transform: rotate(90deg); }
.mobile-folder-icon { font-size: 16px; flex-shrink: 0; color: var(--accent); }
.mobile-folder-title { flex: 1 1 auto; min-width: 0; }
.mobile-folder-count { color: var(--text-muted); font-size: 13px; flex-shrink: 0; }
.mobile-vault-folder-lock {
flex-shrink: 0;
display: inline-flex;
align-items: center;
justify-content: center;
padding: 0;
line-height: 1;
font-size: 16px;
}
.mobile-folder-add {
color: var(--accent);
font-size: 24px;
line-height: 1;
padding: 0 6px;
flex-shrink: 0;
}
.mobile-folder-arrow { color: var(--text-muted); font-size: 20px; flex-shrink: 0; }
/* Note rows */
.mobile-note-row {
display: flex;
align-items: center;
width: 100%;
background: none;
border: none;
border-bottom: 1px solid var(--border);
padding: 14px 16px;
gap: 10px;
cursor: pointer;
color: var(--text);
font-size: 15px;
font-family: inherit;
text-align: left;
}
.mobile-note-row:active { background: var(--bg-hover); }
.mobile-note-title { flex: 1; }
.mobile-note-arrow { color: var(--text-muted); font-size: 20px; }
/* Editor inside mobile */
.mobile-editor-body .editor-titlebar {
padding: 8px 12px;
flex-wrap: nowrap;
}
.mobile-editor-body .editor-folder-select,
.mobile-editor-body .editor-folder-arrow,
.mobile-editor-body #mobile-delete-btn {
display: none;
}
.mobile-hidden-folder-select {
display: none !important;
}
.mobile-editor-body .editor-title {
font-size: 15px;
}
.mobile-editor-body .cm-host .cm-content,
.mobile-editor-body .editor-preview {
font-size: var(--font-size-note-mobile, var(--font-size-note));
}
.mobile-editor-body .cm-host,
.mobile-editor-body .editor-preview {
flex: 1;
min-height: 0;
height: 0;
}
/* FAB */
.mobile-fab {
position: fixed;
bottom: calc(20px + env(safe-area-inset-bottom, 0px));
right: 20px;
width: 56px;
height: 56px;
border-radius: 50%;
background: var(--accent);
color: #000;
font-size: 28px;
line-height: 1;
border: none;
cursor: pointer;
display: none;
align-items: center;
justify-content: center;
z-index: 100;
box-shadow: 0 4px 16px var(--shadow);
}
.mobile-fab-menu-backdrop {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.2);
z-index: 109;
}
.mobile-fab-menu {
position: fixed;
right: 20px;
bottom: calc(88px + env(safe-area-inset-bottom, 0px));
background: var(--bg-side);
border: 1px solid var(--border);
border-radius: 0;
box-shadow: 0 8px 24px var(--shadow);
z-index: 110;
min-width: 180px;
overflow: hidden;
}
.mobile-fab-menu-btn {
display: block;
width: 100%;
background: none;
border: none;
text-align: left;
padding: 18px 20px;
font: inherit;
font-size: 18px;
color: var(--text);
min-height: 56px;
}
.mobile-fab-menu-btn:active { background: var(--bg-hover); }
.mobile-fab-menu-cancel {
border-top: 1px solid var(--border);
color: var(--text-muted);
}
/* Context menu bottom sheet */
.mobile-ctx-backdrop {
position: fixed;
inset: 0;
background: rgba(0,0,0,0.45);
z-index: 200;
}
.mobile-ctx-sheet {
position: fixed;
left: 0; right: 0; bottom: 0;
background: var(--bg-side);
border-radius: 0;
padding: 8px 0 calc(16px + env(safe-area-inset-bottom, 0px));
z-index: 201;
box-shadow: 0 -4px 24px var(--shadow);
animation: mobileCtxSlideUp 0.2s cubic-bezier(0.4,0,0.2,1);
}
@keyframes mobileCtxSlideUp {
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
.mobile-ctx-title {
font-size: 15px;
color: var(--text-muted);
text-align: center;
padding: 10px 16px 14px;
border-bottom: 1px solid var(--border);
margin-bottom: 4px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.mobile-ctx-meta {
font-size: 12px;
color: var(--text-dim);
text-align: center;
padding: 6px 16px 10px;
border-bottom: 1px solid var(--border);
margin-bottom: 4px;
}
.mobile-ctx-btn {
display: block;
width: 100%;
background: none;
border: none;
color: var(--text);
font-size: 18px;
font-family: inherit;
text-align: left;
padding: 16px 20px;
cursor: pointer;
min-height: 56px;
}
.mobile-ctx-btn:active { background: var(--bg-hover); }
.mobile-ctx-btn:disabled {
opacity: 0.55;
}
.mobile-ctx-btn-cancel {
color: var(--text-muted);
border-top: 1px solid var(--border);
margin-top: 4px;
}
.mobile-folder-picker-sheet {
max-height: min(70vh, 520px);
display: flex;
flex-direction: column;
}
.mobile-folder-picker-list {
overflow-y: auto;
-webkit-overflow-scrolling: touch;
padding-bottom: 4px;
}
.mobile-folder-picker-btn.is-current {
color: var(--text-muted);
}
}
/* Forced UI mode overrides (user setting) */
body.force-mobile .app,
body.force-mobile .nav-reopen-btn,
body.force-mobile .mobile-nav-backdrop,
body.force-mobile .app-statusbar { display: none !important; }
body.force-mobile #mobile-editor-body #note-meta { display: none !important; }
body.force-mobile #mobile-editor-body > #note-meta {
display: none !important;
height: 0 !important;
min-height: 0 !important;
margin: 0 !important;
padding: 0 !important;
overflow: hidden !important;
}
body.force-mobile .mobile-editor-body {
position: relative;
}
body.force-mobile .mobile-editor-body > form {
position: absolute;
inset: 0;
width: 100%;
}
body.force-mobile .mobile-app {
display: flex !important;
position: fixed;
inset: 0;
overflow: hidden;
background: var(--bg);
}
body.force-mobile .mobile-fab { display: flex; }
/* While a soft keyboard is up, public/viewport.js sizes the shell to the visible area and keeps it
at the top of that area (and pins the page scroll at 0). iOS then has nothing to scroll into
view, so the header and the markdown toolbar stay on screen. Outside that state .mobile-app is
inset:0 exactly as before. */
html[data-keyboard] .mobile-app,
html[data-keyboard] body.force-mobile .mobile-app {
top: var(--app-top, 0px);
bottom: auto;
height: var(--app-height);
}
/* Hide the custom toolbar in mobile rich (TinyMCE) mode — applies at any viewport width.
TinyMCE's own built-in toolbar is rendered inside the editor host instead.
In markdown/preview mode body.mobile-markdown-mode is set, restoring it. */
#mobile-editor-body .editor-toolbar {
display: none;
}
body.mobile-markdown-mode #mobile-editor-body .editor-toolbar {
display: flex;
}
body.force-desktop .mobile-app { display: none !important; }
body.force-desktop .mobile-fab { display: none !important; }
body.force-desktop .app { display: flex !important; }
body.force-desktop .app-statusbar { display: flex !important; }
/* Disable mobile screen slide transitions during resize to prevent glitching */
body.resizing .mobile-screen,
body.resizing .mobile-screen-active,
body.resizing .mobile-screen-left,
body.resizing .mobile-screen-right { transition: none !important; }
/* Mobile locked editor */
@media (max-width: 768px) {
.editor-locked {
padding: 60px 20px;
}
.editor-locked-password {
max-width: 100%;
font-size: 16px;
}
}
.settings-tabs {
display: flex;
gap: 2px;
border-bottom: 1px solid var(--border);
margin-bottom: 0;
padding: 0 0 0 0;
}
.settings-tab {
background: none;
border: none;
border-bottom: 2px solid transparent;
color: var(--text-muted);
cursor: pointer;
font-size: 13px;
padding: 8px 16px;
font-family: inherit;
transition: color 0.15s, border-color 0.15s;
margin-bottom: -1px;
}
@media (hover: hover) {
.settings-tab:hover { color: var(--text); }
}
.settings-tab.active { color: var(--accent); border-bottom-color: var(--accent); font-weight: 600; }
.settings-tab-panel { display: none; }
.settings-tab-panel.active { display: block; }
@media (max-width: 768px) {
.settings-page {
padding: calc(16px + env(safe-area-inset-top, 0px)) 12px calc(20px + env(safe-area-inset-bottom, 0px));
}
.settings-card {
width: 100%;
padding: 16px;
border-radius: 0;
overflow: hidden;
}
.settings-header {
flex-direction: column;
align-items: stretch;
gap: 12px;
}
.settings-header .btn {
align-self: flex-start;
}
.settings-tabs {
display: grid;
grid-template-columns: 1fr;
gap: 6px;
border-bottom: 0;
margin: 0 0 12px;
}
.settings-tab {
width: 100%;
padding: 12px 14px;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-elevated);
text-align: left;
font-size: 16px;
margin-bottom: 0;
}
.settings-tab.active {
border-color: var(--accent);
background: var(--bg-active);
}
.settings-grid {
grid-template-columns: 1fr;
}
.settings-actions {
justify-content: stretch;
}
.settings-actions .btn,
.settings-actions .btn-primary {
width: 100%;
}
.ai-profiles-bar {
display: grid;
grid-template-columns: 1fr 1fr;
align-items: stretch;
}
.ai-profiles-bar-label {
grid-column: 1 / -1;
display: grid;
grid-template-columns: auto minmax(0, 1fr);
align-items: center;
}
.ai-active-select {
width: 100%;
max-width: 100%;
}
.ai-profiles-bar .btn {
width: 100%;
}
.ai-profile-header {
display: grid;
grid-template-columns: minmax(0, 1fr);
align-items: stretch;
}
.ai-profile-name-input,
.ai-profile-provider-select,
.ai-profile-header .btn {
width: 100%;
max-width: 100%;
}
.ai-profile-header .badge {
justify-self: start;
}
}
/* --- Flash messages --- */
.settings-flash {
margin: 0 0 12px 0;
padding: 8px 14px;
border-radius: 0;
font-size: 13px;
font-weight: 500;
}
.settings-flash-ok { background: color-mix(in srgb, var(--accent) 18%, transparent); color: var(--accent); border: 1px solid color-mix(in srgb, var(--accent) 40%, transparent); }
.settings-flash-err { background: color-mix(in srgb, var(--danger) 18%, transparent); color: var(--danger); border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent); }
/* --- Admin table --- */
.admin-table-wrap { overflow-x: auto; }
.admin-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
margin-top: 8px;
}
.admin-table th, .admin-table td {
text-align: left;
padding: 7px 10px;
border-bottom: 1px solid var(--border);
}
.admin-table th { color: var(--text-muted); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; }
.admin-table tr:last-child td { border-bottom: none; }
@media (hover: hover) {
.admin-table tr:hover td { background: color-mix(in srgb, var(--accent) 6%, transparent); }
}
.admin-actions-cell { white-space: nowrap; }
.admin-inline-form { display: inline; margin: 0; }
.admin-backup-actions { display: inline-flex; align-items: center; gap: 6px; }
/* --- Badges --- */
.badge { display: inline-block; padding: 2px 7px; border-radius: 0; font-size: 11px; font-weight: 600; }
.badge-ok { background: color-mix(in srgb, var(--accent) 20%, transparent); color: var(--accent); }
.badge-off { background: color-mix(in srgb, var(--text-muted) 20%, transparent); color: var(--text-muted); }
.badge-mfa { background: color-mix(in srgb, #8b5cf6 20%, transparent); color: #a78bfa; margin-left: 4px; }
/* --- Admin user modal --- */
.admin-modal {
border: none;
border-radius: 0;
padding: 0;
background: var(--bg-elevated);
color: var(--text);
max-width: 420px;
width: calc(100% - 32px);
max-height: calc(100vh - 32px);
max-height: calc(100dvh - 32px);
overflow: hidden;
box-shadow: 0 8px 32px rgba(0,0,0,0.4);
}
.admin-modal::backdrop {
background: rgba(0,0,0,0.6);
backdrop-filter: blur(4px);
}
.admin-modal-content {
display: flex;
flex-direction: column;
max-height: calc(100vh - 32px);
max-height: calc(100dvh - 32px);
overflow-y: auto;
}
.admin-modal-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 16px 20px;
border-bottom: 1px solid var(--border);
}
.admin-modal-header h3 {
margin: 0;
font-size: 18px;
font-weight: 600;
}
.admin-modal-close {
background: none;
border: none;
font-size: 28px;
line-height: 1;
color: var(--text-muted);
cursor: pointer;
padding: 0 4px;
}
@media (hover: hover) {
.admin-modal-close:hover { color: var(--text); }
}
.admin-modal-user {
display: flex;
flex-direction: column;
gap: 4px;
padding: 16px 20px;
background: var(--bg-side);
border-bottom: 1px solid var(--border);
}
.admin-modal-user strong { font-size: 16px; }
.admin-modal-user span { font-size: 14px; color: var(--text-muted); }
.admin-modal-user .badge { align-self: flex-start; margin-top: 4px; }
.admin-modal-actions {
padding: 16px 20px;
display: flex;
flex-direction: column;
gap: 16px;
}
.admin-modal-form {
display: flex;
flex-direction: column;
gap: 8px;
}
.admin-modal-label {
font-weight: 600;
font-size: 14px;
}
.admin-modal-hint {
font-size: 13px;
color: var(--text-muted);
margin: 0 0 4px 0;
}
.admin-modal-row {
display: flex;
gap: 8px;
}
.admin-modal-row .login-input { flex: 1; }
.admin-modal-divider {
height: 1px;
background: var(--border);
margin: 4px 0;
}
.admin-modal-footer {
padding: 12px 20px 16px;
border-top: 1px solid var(--border);
}
.btn-block { width: 100%; }
/* Admin TOTP reveal */
.admin-totp-details { margin-top: 8px; }
.admin-totp-details > summary { cursor: pointer; }
.admin-totp-reveal {
margin-top: 12px;
padding: 12px;
background: var(--bg-side);
border-radius: 0;
text-align: center;
}
.admin-totp-qr {
width: 140px;
height: 140px;
background: #fff;
border-radius: 0;
padding: 8px;
margin-bottom: 8px;
}
.admin-totp-seed {
display: block;
font-size: 12px;
word-break: break-all;
color: var(--text-muted);
}
/* --- Code block copy button --- */
.editor-preview pre { position: relative; }
.pre-copy-btn {
position: sticky;
top: 6px;
float: right;
margin: -22px 0 8px 12px;
z-index: 1;
padding: 2px 8px;
font-size: 11px;
font-family: inherit;
background: var(--bg-elevated);
color: var(--text-muted);
border: 1px solid var(--border);
border-radius: 4px;
cursor: pointer;
opacity: 0;
transition: opacity 0.15s, color 0.15s;
line-height: 1.6;
}
@media (hover: hover) {
.editor-preview pre:hover .pre-copy-btn { opacity: 1; }
}
@media (hover: hover) {
.pre-copy-btn:hover { color: var(--accent); border-color: var(--accent); }
}
mark.search-highlight {
background: #ffe066;
color: #111;
border-radius: 0;
padding: 0 1px;
}
.theme-light mark.search-highlight { background: #ffe066; color: #111; }
.search-nav-bar {
display: flex;
align-items: center;
gap: 4px;
padding: 3px 8px;
background: #ffe066;
border-bottom: 1px solid #e6c800;
color: #111;
flex-shrink: 0;
}
.search-nav-bar[hidden] { display: none; }
.search-nav-counter { min-width: 48px; font-variant-numeric: tabular-nums; }
.search-nav-btn {
background: none;
border: 1px solid #b8960a;
border-radius: 0;
color: #111;
cursor: pointer;
font-size: 11px;
line-height: 1;
padding: 2px 5px;
}
@media (hover: hover) {
.search-nav-btn:hover { border-color: #333; background: rgba(0,0,0,0.08); }
}
.search-nav-close { margin-left: auto; }
/* Remote-update bar reuses .search-nav-bar layout; this rule lets the message
take the remaining space so the action buttons pack to the right. */
.remote-update-bar .remote-update-text { flex: 1; }
mark.search-highlight-active {
background: #ff9800;
color: #111;
border-radius: 0;
padding: 0 1px;
}
/* --- Encryption UI --- */
.note-lock-icon {
font-size: 13px;
margin-right: 4px;
opacity: 0.7;
flex-shrink: 0;
display: inline-flex;
align-items: center;
color: #FFC107;
}
.note-lock-icon.note-lock-unlocked {
color: var(--accent);
opacity: 0.9;
}
.notelist-item {
display: flex;
align-items: center;
width: 100%;
padding: 8px 12px;
text-align: left;
border-bottom: 1px solid var(--border);
transition: background 0.1s;
}
.editor-locked {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex: 1;
gap: 12px;
padding: 40px 20px;
min-height: 200px;
}
.editor-locked-icon {
font-size: 48px;
opacity: 0.5;
color: #FFC107;
}
.editor-locked-icon .vault-svg-icon {
width: 48px;
height: 48px;
}
.editor-locked-text {
font-size: 16px;
color: var(--text-dim);
}
.editor-locked-password {
width: 100%;
max-width: 280px;
padding: 10px 14px;
border: 1px solid var(--border);
border-radius: 0;
background: var(--bg-input, var(--bg-hover));
color: var(--text);
font-size: 15px;
text-align: center;
}
.editor-locked-password:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 20%, transparent);
}
.editor-locked-btn {
min-width: 120px;
}
.editor-locked-actions {
display: flex;
gap: 8px;
justify-content: center;
flex-wrap: wrap;
}
.editor-locked-error {
color: var(--danger, #e06c75);
font-size: 13px;
min-height: 18px;
}
.autosave-encrypted {
color: var(--accent);
font-size: 11px;
opacity: 0.8;
}
.lock-modal-warning {
font-size: 13px;
color: var(--danger, #e06c75);
margin: 0 0 8px;
line-height: 1.4;
}
.lock-modal-checkbox {
display: flex;
align-items: center;
gap: 6px;
font-size: 13px;
color: var(--text-dim);
margin: 4px 0;
cursor: pointer;
}
.lock-modal-error {
color: var(--danger, #e06c75);
font-size: 13px;
min-height: 18px;
}
#tb-remove-lock, #tb-change-password {
font-size: 11px;
white-space: nowrap;
}
/* Vault folder styles */
.nav-folder-vault > .nav-folder-row {
/* subtle accent to distinguish vault folders */
}
.vault-folder-lock {
font-size: 14px;
opacity: 0.85;
background: none;
border: none;
cursor: pointer;
padding: 0 2px;
color: #FFC107;
line-height: 1;
flex-shrink: 0;
}
@media (hover: hover) {
.vault-folder-lock:hover {
opacity: 1;
color: #FFC107;
}
}
/* SVG lock icons */
.vault-svg-icon {
width: 1em;
height: 1em;
display: inline-block;
vertical-align: -0.125em;
}
/* Mobile lock icon in note row */
.mobile-note-row .note-lock-icon {
font-size: 13px;
margin-right: 6px;
}
/* Link-copied toast */
#link-copied-toast {
position: fixed;
z-index: 99999;
background: var(--accent);
color: #fff;
font-size: 13px;
padding: 4px 10px;
border-radius: 0;
pointer-events: none;
opacity: 0;
transform: translate(-50%, -120%);
transition: opacity 0.15s;
}
#link-copied-toast.visible {
opacity: 1;
}
/* ===== Touch devices =====
Controls are not text: a long press on a row, a tab or a button opens no loupe or link callout,
and a quick second tap does not zoom the page (pinch zoom stays; WCAG 1.4.4). Note text, fields
and the editors keep selection. */
@media (hover: none) and (pointer: coarse) {
html {
-webkit-text-size-adjust: 100%;
text-size-adjust: 100%;
-webkit-tap-highlight-color: transparent;
}
a,
button,
input,
select,
textarea,
summary,
label,
[role="button"],
[role="tab"],
.mobile-folder-row,
.mobile-note-row,
.nav-folder-row,
.notelist-item {
touch-action: manipulation;
-webkit-tap-highlight-color: transparent;
}
.mobile-header,
.mobile-folder-row,
.mobile-note-row,
.mobile-fab,
.mobile-fab-menu,
.mobile-ctx-sheet,
.editor-toolbar,
.nav-folder-row,
.notelist-item,
.settings-tab,
button,
[role="button"],
[role="tab"],
summary {
-webkit-user-select: none;
user-select: none;
-webkit-touch-callout: none;
}
input,
textarea,
[contenteditable],
.cm-content {
-webkit-user-select: text;
user-select: text;
}
}
/* Reduced motion: no slides, fades or pulses. The loading ring is progress, not decoration, so it
keeps turning. */
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
transition-duration: 0.01ms !important;
transition-delay: 0s !important;
scroll-behavior: auto !important;
}
*:not(.note-loading-ring) {
animation: none !important;
}
}