mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 15:02:20 +02:00
Integrate lab fff55a78 into PR #40 (cc25d5ba). Lab's modular email backend/frontend, modular settings, split stylesheets (static/style.css stays deleted), procfs compatibility, and request-scoped TurnContract authority win; PR #40's routing classifiers, editor/email/task features, and style.css changes are ported into lab's module and stylesheet homes. Integration fixes: - settings/api.js imports ui.js under its canonical versioned URL - browser observations keep legacy CAPTCHA/access-block evidence - artifact turns do not re-trigger broad-web research recovery - env reference documents PR test-tool variables; page regenerated PR #40 defects surfaced by lab gates and fixed here: - web_fetch generic schema drops top-level anyOf (OpenAI contract); the compact preview contract still requires url or urls - get_weather registered as a brokered network read - new lazy editor modules precached for offline use - SearXNG pin mirrored into GPU standalone compose files - image model picker again skips offline endpoints Tests updated where PR #40 changed behaviour on purpose, and PR tests moved onto lab's document_source helpers.
4036 lines
118 KiB
CSS
4036 lines
118 KiB
CSS
/* 15-notes - part of the former static/style.css.
|
||
*
|
||
* The stylesheet is split by area, but the split is mechanical: rules were
|
||
* moved verbatim and NOT regrouped. The numeric prefix is the load order, and
|
||
* that order is what preserves the cascade. A rule sits in the file its
|
||
* original position fell into, so an area's rules are not all in its file and
|
||
* a file is not only that area's rules.
|
||
*
|
||
* Do not reorder the <link> tags in static/index.html, and do not move a rule
|
||
* between files: with 1,151 redeclarations and 1,886 !important in this
|
||
* cascade, either can change which declaration wins.
|
||
*
|
||
* static/index.html and the PRECACHE list in static/sw.js must agree on this
|
||
* order. tests/test_static_stylesheet_manifest.py and
|
||
* tests/test_css_computed_style_snapshot.py fail if that drifts.
|
||
*/
|
||
body.notes-drag-mode .note-card {
|
||
cursor: grab;
|
||
transform: scale(0.985);
|
||
filter: saturate(0.7);
|
||
opacity: 0.92;
|
||
position: relative;
|
||
overflow: hidden;
|
||
transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.3, 1),
|
||
filter 0.18s ease,
|
||
opacity 0.18s ease;
|
||
}
|
||
@media (max-width: 768px) {
|
||
body.notes-drag-mode .note-card {
|
||
filter: none;
|
||
opacity: 0.96;
|
||
box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent, var(--red)) 28%, transparent);
|
||
}
|
||
body.notes-drag-mode .note-card::after {
|
||
display: none;
|
||
}
|
||
}
|
||
/* Placeholder — same footprint as the lifted card, dotted outline so
|
||
the drop target is visible while the card follows the finger. */
|
||
.note-card-placeholder {
|
||
background: color-mix(in srgb, var(--fg) 5%, transparent);
|
||
border: 2px dashed color-mix(in srgb, var(--fg) 25%, transparent);
|
||
border-radius: 8px;
|
||
box-sizing: border-box;
|
||
flex-shrink: 0;
|
||
transition: width 0.18s ease, height 0.18s ease;
|
||
}
|
||
|
||
|
||
/* ── Fullscreen single-note edit overlay ──────────────── */
|
||
.note-fullscreen-overlay {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 10500;
|
||
background: var(--bg);
|
||
display: flex;
|
||
flex-direction: column;
|
||
opacity: 0;
|
||
/* Bigger zoom range so the transition reads as a real "tile expands
|
||
into a page" motion. transform-origin is set per-tile by JS. */
|
||
transform: scale(0.45);
|
||
transform-origin: center center;
|
||
transition: opacity 0.28s ease, transform 0.32s cubic-bezier(0.18, 0.74, 0.24, 1.06);
|
||
will-change: transform, opacity;
|
||
}
|
||
.note-fullscreen-overlay.open {
|
||
opacity: 1;
|
||
transform: scale(1);
|
||
}
|
||
.note-fullscreen-overlay.closing {
|
||
opacity: 0;
|
||
transform: scale(0.7);
|
||
transition: opacity 0.22s ease, transform 0.22s cubic-bezier(0.4, 0, 0.6, 1);
|
||
}
|
||
.note-fullscreen-header {
|
||
flex-shrink: 0;
|
||
padding: 8px 12px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
border-bottom: 1px solid var(--border);
|
||
}
|
||
.note-fullscreen-actions {
|
||
margin-left: auto;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
/* Compact the relocated Archive/Delete buttons so two of them fit
|
||
alongside the back chevron without crowding. */
|
||
.note-fullscreen-actions .note-form-text-btn {
|
||
padding: 8px 12px;
|
||
font-size: 12px;
|
||
border-radius: 8px;
|
||
}
|
||
.note-fullscreen-actions .note-form-text-btn svg {
|
||
width: 14px;
|
||
height: 14px;
|
||
margin-right: 4px;
|
||
}
|
||
.note-fullscreen-back {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 40px; height: 40px;
|
||
background: none;
|
||
border: none;
|
||
color: var(--fg);
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
.note-fullscreen-back:active {
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
}
|
||
.note-fullscreen-body {
|
||
flex: 1;
|
||
min-height: 0;
|
||
overflow-y: auto;
|
||
padding: 8px 14px 24px;
|
||
}
|
||
/* The reused .note-form inside the fullscreen overlay should breathe —
|
||
it was originally sized to slot into a grid cell. */
|
||
.note-fullscreen-body .note-form {
|
||
max-width: 720px;
|
||
margin: 0 auto;
|
||
border: none;
|
||
box-shadow: none;
|
||
background: transparent;
|
||
}
|
||
|
||
/* Bigger touch targets inside the fullscreen overlay. The default form
|
||
is tuned for the grid-card context (tiny icons fit a 200px wide
|
||
tile); on a phone-sized full-bleed page we want chunky thumb-sized
|
||
controls. */
|
||
.note-fullscreen-back svg {
|
||
width: 28px;
|
||
height: 28px;
|
||
}
|
||
.note-fullscreen-overlay .note-form-type-pill svg {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
.note-fullscreen-overlay .note-cl-row {
|
||
padding: 8px 0;
|
||
gap: 8px;
|
||
align-items: center;
|
||
}
|
||
.note-fullscreen-overlay .note-cl-grip {
|
||
font-size: 22px;
|
||
line-height: 1;
|
||
padding: 6px 8px;
|
||
opacity: 0.5;
|
||
cursor: grab;
|
||
touch-action: none;
|
||
user-select: none;
|
||
/* Pull 4px toward the left edge of the row. */
|
||
margin-left: -4px;
|
||
}
|
||
.note-fullscreen-overlay .note-cl-dot {
|
||
width: 16px;
|
||
height: 16px;
|
||
border-width: 2px;
|
||
border-radius: 50%;
|
||
flex-shrink: 0;
|
||
position: relative;
|
||
/* Generous invisible tap target around the visible dot */
|
||
}
|
||
/* Filled checkmark glyph when the row is marked done — gives a clear
|
||
visual cue beyond the colored fill. Nudged up 2px so it sits
|
||
centered in the smaller dot. */
|
||
.note-fullscreen-overlay .note-cl-row.done .note-cl-dot::after {
|
||
content: '';
|
||
position: absolute;
|
||
left: 2px; top: 1px;
|
||
width: 8px; height: 4px;
|
||
border-left: 2px solid #fff;
|
||
border-bottom: 2px solid #fff;
|
||
transform: rotate(-45deg);
|
||
}
|
||
.note-fullscreen-overlay .note-cl-rm {
|
||
width: 40px;
|
||
height: 40px;
|
||
font-size: 28px;
|
||
line-height: 1;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
opacity: 0.7;
|
||
/* Nudge 4px further toward the right edge of the row. */
|
||
margin-right: -4px;
|
||
}
|
||
/* Lifted row + placeholder while dragging a checklist item. Mirrors
|
||
the card-drag look so the two interactions feel consistent. */
|
||
.note-cl-row-dragging {
|
||
box-shadow: 0 12px 28px rgba(0,0,0,0.4);
|
||
background: var(--bg);
|
||
border-radius: 8px;
|
||
opacity: 0.98;
|
||
}
|
||
.note-cl-row-placeholder {
|
||
background: color-mix(in srgb, var(--fg) 5%, transparent);
|
||
border: 2px dashed color-mix(in srgb, var(--fg) 22%, transparent);
|
||
border-radius: 6px;
|
||
margin: 4px 0;
|
||
box-sizing: border-box;
|
||
transition: height 0.16s ease;
|
||
}
|
||
.note-fullscreen-overlay .note-form-text-btn {
|
||
padding: 10px 16px;
|
||
font-size: 14px;
|
||
}
|
||
.note-fullscreen-overlay .note-form-text-btn svg {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
/* + Add and the camera/photo button share a row inside checklists, so
|
||
they're both within thumb reach when editing items. The whole row
|
||
reads as a single dashed "tap to add" surface — tapping ANYWHERE
|
||
on it triggers + Add (the photo button stays its own target). */
|
||
.note-fullscreen-overlay .note-cl-add-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
gap: 8px;
|
||
margin-top: 10px;
|
||
padding: 4px 8px 4px 4px;
|
||
border: 1px solid color-mix(in srgb, var(--fg) 22%, transparent);
|
||
border-radius: 10px;
|
||
cursor: pointer;
|
||
transition: background 0.12s ease, border-color 0.12s ease;
|
||
}
|
||
.note-fullscreen-overlay .note-cl-add-row:active {
|
||
background: color-mix(in srgb, var(--fg) 6%, transparent);
|
||
border-color: color-mix(in srgb, var(--fg) 36%, transparent);
|
||
}
|
||
.note-fullscreen-overlay .note-cl-add-row .note-cl-add {
|
||
flex: 1;
|
||
justify-content: flex-start;
|
||
background: transparent;
|
||
border: none;
|
||
}
|
||
.note-fullscreen-overlay .note-cl-add-row .note-form-photo-btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
width: auto;
|
||
height: 36px;
|
||
padding: 0 12px 0 10px;
|
||
border-radius: 8px;
|
||
/* No border / no background — the surrounding +Add row provides the
|
||
bordered container, the camera is just an icon inside it. */
|
||
border: none;
|
||
background: transparent;
|
||
}
|
||
|
||
/* Read-mode overlay shown over the textarea for plain notes. Renders
|
||
linkified content so URLs are tappable. Click anywhere off a link
|
||
to flip to edit mode (focuses the underlying textarea). */
|
||
.note-form-content-reader {
|
||
font-size: 15px;
|
||
line-height: 1.55;
|
||
padding: 10px 6px;
|
||
white-space: pre-wrap;
|
||
word-wrap: break-word;
|
||
color: var(--fg);
|
||
cursor: text;
|
||
min-height: 40px;
|
||
}
|
||
|
||
/* Per-row read mode for todo items — replaces the bare <input> with a
|
||
clickable linkified span when the value contains a URL. */
|
||
.note-fullscreen-overlay .note-cl-text-reader {
|
||
flex: 1;
|
||
padding: 7px 6px;
|
||
font-size: 14px;
|
||
line-height: 1.4;
|
||
min-height: 32px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
word-break: break-word;
|
||
color: var(--fg);
|
||
cursor: text;
|
||
}
|
||
.note-fullscreen-overlay .note-cl-row.done .note-cl-text-reader {
|
||
opacity: 0.5;
|
||
text-decoration: line-through;
|
||
}
|
||
.note-fullscreen-overlay .note-form-icon-btn svg {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
|
||
|
||
/* Tags input is JS-relocated into the bottom actions row, pinned
|
||
left of Cancel/Update. Style it as a dashed pill so it reads as
|
||
metadata rather than another control. */
|
||
.note-fullscreen-overlay .note-form-actions-group .note-form-label {
|
||
flex: 1 1 auto;
|
||
min-width: 0;
|
||
font-size: 13px;
|
||
padding: 8px 10px;
|
||
margin: 0 auto 0 0;
|
||
background: transparent;
|
||
border: 1px dashed color-mix(in srgb, var(--fg) 16%, transparent);
|
||
border-radius: 6px;
|
||
text-align: left;
|
||
}
|
||
|
||
.note-fullscreen-overlay .note-color-picker { order: 1; }
|
||
.note-fullscreen-overlay .note-form-type-seg {
|
||
order: 3;
|
||
margin-left: auto; /* shove right */
|
||
/* The overlay enlarges the pills (padding 10px), but the base seg is only
|
||
28px tall with overflow:hidden — which clipped them. Grow the track so
|
||
the bigger touch targets fit. */
|
||
height: 40px;
|
||
border-radius: 12px;
|
||
}
|
||
.note-fullscreen-overlay .note-form-actions-group {
|
||
order: 4;
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin-top: 6px;
|
||
}
|
||
|
||
.notes-mobile-grabber { display: none; }
|
||
/* Notes panel: mounted like a window, docked to the right on desktop. */
|
||
.notes-pane-backdrop {
|
||
position: fixed;
|
||
inset: 0;
|
||
z-index: 200;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: transparent;
|
||
backdrop-filter: none;
|
||
-webkit-backdrop-filter: none;
|
||
pointer-events: none;
|
||
animation: notes-backdrop-fade-in 180ms ease both;
|
||
}
|
||
.notes-pane-backdrop .notes-pane {
|
||
pointer-events: auto;
|
||
}
|
||
.notes-pane-backdrop:has(.notes-pane.modal-right-docked),
|
||
.notes-pane-backdrop:has(.notes-pane.modal-left-docked) {
|
||
background: transparent;
|
||
backdrop-filter: none;
|
||
-webkit-backdrop-filter: none;
|
||
pointer-events: none;
|
||
}
|
||
.notes-pane-backdrop:has(.notes-pane.modal-right-docked) .notes-pane,
|
||
.notes-pane-backdrop:has(.notes-pane.modal-left-docked) .notes-pane {
|
||
pointer-events: auto;
|
||
}
|
||
.notes-pane-backdrop:has(.notes-pane.notes-window-fullscreen) {
|
||
background: transparent;
|
||
backdrop-filter: none;
|
||
-webkit-backdrop-filter: none;
|
||
}
|
||
.notes-pane {
|
||
display: flex;
|
||
flex-direction: column;
|
||
background: var(--panel);
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
overflow: hidden;
|
||
width: min(880px, 92vw);
|
||
height: min(80vh, 820px);
|
||
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.45);
|
||
box-sizing: border-box;
|
||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
letter-spacing: -0.015em;
|
||
/* Smooth open: scale up + fade in from the centre. */
|
||
animation: notes-pane-enter 200ms cubic-bezier(0.22, 0.61, 0.36, 1) both;
|
||
transform-origin: center center;
|
||
will-change: transform, opacity;
|
||
}
|
||
.notes-pane.modal-right-docked {
|
||
border-left: 1px solid var(--border);
|
||
border-radius: 0;
|
||
box-shadow: -4px 0 14px rgba(0, 0, 0, 0.18);
|
||
transition: none !important;
|
||
}
|
||
.notes-pane.modal-left-docked {
|
||
border-right: 1px solid var(--border);
|
||
border-radius: 0;
|
||
box-shadow: 4px 0 14px rgba(0, 0, 0, 0.18);
|
||
transition: none !important;
|
||
}
|
||
.notes-pane-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
justify-content: space-between;
|
||
padding: 0 0 6px;
|
||
margin: 10px 10px 0;
|
||
border-bottom: 1px solid var(--border);
|
||
background: inherit;
|
||
flex-shrink: 0;
|
||
flex-wrap: nowrap;
|
||
min-height: 30px;
|
||
overflow: hidden;
|
||
}
|
||
|
||
/* Archive mode — sepia tint over the panel + a header strip so it's clearly
|
||
a different view. Active reminders sort + glow rules don't apply here. */
|
||
.notes-pane-archive {
|
||
background: color-mix(in srgb, #b48a4a 6%, var(--bg));
|
||
}
|
||
.notes-pane-archive .notes-pane-header {
|
||
background: color-mix(in srgb, #b48a4a 12%, var(--bg));
|
||
border-bottom-color: color-mix(in srgb, #b48a4a 35%, var(--border));
|
||
}
|
||
.notes-pane-archive .notes-pane-body {
|
||
background: color-mix(in srgb, #b48a4a 4%, var(--bg));
|
||
}
|
||
/* Smooth the archive↔active swap so the colour tint eases in/out instead
|
||
of snapping. Covers the pane, its header, and its body. */
|
||
.notes-pane,
|
||
.notes-pane .notes-pane-header,
|
||
.notes-pane .notes-pane-body {
|
||
transition: background 0.28s ease, border-color 0.28s ease;
|
||
}
|
||
.notes-pane-archive .notes-pane-title::after {
|
||
content: 'Archive';
|
||
margin-left: 8px;
|
||
padding: 2px 8px 2px 22px;
|
||
font-size: 9px;
|
||
font-weight: 700;
|
||
letter-spacing: 1px;
|
||
text-transform: uppercase;
|
||
color: #b48a4a;
|
||
background-color: color-mix(in srgb, #b48a4a 18%, transparent);
|
||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23b48a4a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='2' y='3' width='20' height='5' rx='1'/%3E%3Cpath d='M4 8v11a2 2 0 002 2h12a2 2 0 002-2V8'/%3E%3Cpath d='M10 12h4'/%3E%3C/svg%3E");
|
||
background-repeat: no-repeat;
|
||
background-position: 6px center;
|
||
background-size: 11px 11px;
|
||
border: 1px solid color-mix(in srgb, #b48a4a 45%, transparent);
|
||
border-radius: 10px;
|
||
vertical-align: middle;
|
||
}
|
||
.notes-pane-archive .note-card {
|
||
background: color-mix(in srgb, #b48a4a 8%, var(--panel));
|
||
border-color: color-mix(in srgb, #b48a4a 25%, var(--border));
|
||
}
|
||
.notes-pane-header .doc-action-icon-btn {
|
||
flex-shrink: 0;
|
||
}
|
||
.notes-pane-header .notes-pane-title {
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
min-width: 0;
|
||
flex-shrink: 1;
|
||
}
|
||
.notes-pane-footer {
|
||
padding: 6px 8px;
|
||
border-top: 1px solid var(--border);
|
||
background: var(--panel);
|
||
flex-shrink: 0;
|
||
display: flex;
|
||
gap: 6px;
|
||
}
|
||
.notes-new-btn {
|
||
background: none;
|
||
border: 1px dashed color-mix(in srgb, var(--accent) 40%, transparent);
|
||
color: color-mix(in srgb, var(--fg) 50%, transparent);
|
||
border-radius: 6px;
|
||
padding: 6px 0;
|
||
flex: 1;
|
||
cursor: pointer;
|
||
font-size: 11px;
|
||
font-family: inherit;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 4px;
|
||
transition: border-color 0.15s, color 0.15s;
|
||
}
|
||
.notes-new-btn:hover {
|
||
border-color: var(--accent);
|
||
color: var(--fg);
|
||
}
|
||
.notes-pane-title {
|
||
/* Match the other tool headers (.modal-header h4). */
|
||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
font-size: 1rem;
|
||
font-weight: 600;
|
||
letter-spacing: -0.03em;
|
||
color: var(--red);
|
||
white-space: nowrap;
|
||
height: 24px;
|
||
line-height: 22px;
|
||
padding: 0 6px;
|
||
margin: 6px 0 0 0;
|
||
display: inline-block;
|
||
vertical-align: middle;
|
||
/* Optical nudge — sits 1px above its row baseline on desktop, more on mobile
|
||
where the surrounding controls are taller. Overridden in the mobile
|
||
media block below. */
|
||
position: relative;
|
||
top: -1px;
|
||
box-sizing: border-box;
|
||
}
|
||
@media (max-width: 768px) {
|
||
.notes-pane-title { top: -4px; }
|
||
.notes-pane-title svg {
|
||
position: relative;
|
||
top: -2px;
|
||
}
|
||
/* Mobile header is tight — keep Archive / Toggle View icon-only. */
|
||
.notes-header-btn-label { display: none; }
|
||
.notes-header-text-btn { width: 32px !important; padding: 0 !important; }
|
||
}
|
||
.notes-header-btn-label {
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
line-height: 1;
|
||
letter-spacing: 0.2px;
|
||
white-space: nowrap;
|
||
}
|
||
.notes-header-text-btn {
|
||
width: auto !important;
|
||
padding: 0 8px !important;
|
||
}
|
||
.notes-pane-body {
|
||
flex: 1;
|
||
overflow-y: auto;
|
||
scroll-behavior: smooth;
|
||
padding: 10px 8px 8px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 6px;
|
||
scrollbar-width: thin;
|
||
}
|
||
.notes-pane-body > .doclib-chip-scroll-frame:has(> .notes-labels-bar) {
|
||
/* The shared Library wrapper grows to fill available flex space. Notes
|
||
needs this to remain a content-height toolbar or it can create a huge
|
||
blank gap above the cards after filtering/re-rendering. */
|
||
flex: 0 0 auto;
|
||
width: 100%;
|
||
}
|
||
|
||
.note-card.note-card-sliding-out {
|
||
transform: translateX(120%);
|
||
opacity: 0;
|
||
transition: transform 0.32s ease-in, opacity 0.32s ease-in;
|
||
pointer-events: none;
|
||
}
|
||
|
||
/* ⋯ corner menu button (replaced the copy corner button) */
|
||
.note-card-corner-menu {
|
||
background: none;
|
||
border: none;
|
||
color: var(--fg);
|
||
cursor: pointer;
|
||
padding: 2px;
|
||
opacity: 0.5;
|
||
transition: opacity 0.15s;
|
||
display: inline-flex;
|
||
}
|
||
.note-card-corner-menu:hover { opacity: 0.9; }
|
||
/* Dropdown spawned by the ⋯ menu */
|
||
.note-corner-menu-dropdown {
|
||
background: var(--panel);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
box-shadow: 0 8px 24px rgba(0,0,0,0.3);
|
||
padding: 4px;
|
||
min-width: 168px;
|
||
font-size: 12px;
|
||
animation: ncm-pop 0.12s ease-out both;
|
||
}
|
||
@keyframes ncm-pop { from { opacity: 0; transform: scale(0.96); } to { opacity: 1; transform: scale(1); } }
|
||
.note-corner-menu-dropdown .ncm-item {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 9px;
|
||
width: 100%;
|
||
background: none;
|
||
border: none;
|
||
color: var(--fg);
|
||
font-family: inherit;
|
||
font-size: 12px;
|
||
text-align: left;
|
||
padding: 8px 10px;
|
||
border-radius: 6px;
|
||
cursor: pointer;
|
||
}
|
||
.note-corner-menu-dropdown .ncm-item:hover {
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
}
|
||
|
||
.note-card {
|
||
/* Same tint that .doclib-card uses so a default (uncolored) note
|
||
visually separates from the panel background it sits on. */
|
||
background: color-mix(in srgb, var(--fg) 3%, transparent);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
/* Extra right padding so the corner buttons (pin / edit / copy / done)
|
||
never collide with the title, and a min-height so an empty/short
|
||
note is still tall enough to fit that row of corner controls. */
|
||
padding: 10px 14px;
|
||
padding-right: 30px;
|
||
min-height: 64px;
|
||
cursor: default;
|
||
transition: background 0.15s;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
/* Keep drawings/images clipped to the card so they can't spill outside it —
|
||
but allow a small overhang (the pin bubble sits at right:-8px and would
|
||
otherwise be cropped). overflow-clip-margin extends the clip-box without
|
||
letting full images bleed past. */
|
||
overflow: clip;
|
||
overflow-clip-margin: 14px;
|
||
/* Don't shrink inside the flex-column list pane — otherwise cards squish to
|
||
fit (clipped/too short) and the container never overflows, so it won't
|
||
scroll. Keeping natural height makes the list overflow → scrollable. */
|
||
flex-shrink: 0;
|
||
}
|
||
.note-card:hover:not([class*="note-color-"]) {
|
||
background: color-mix(in srgb, var(--fg) 6%, transparent);
|
||
}
|
||
.note-card { position: relative; }
|
||
.note-card-image { max-width: 100%; }
|
||
|
||
/* Mobile: bigger, more legible note cards + a sticky quick-add bar so you can
|
||
add a to-do without scrolling back up; and keep media inside the card. */
|
||
@media (max-width: 768px) {
|
||
.note-card { padding: 14px 16px; padding-right: 34px; min-height: 84px; font-size: 15px; }
|
||
.note-card-image { max-height: 260px; max-width: 100%; object-fit: cover; }
|
||
/* Sticky create-todo bar — pin it to the top of the scrolling list pane.
|
||
Safe now that the cards no longer shrink (the list actually overflows). */
|
||
.notes-quick-add {
|
||
position: sticky;
|
||
top: -8px;
|
||
z-index: 12;
|
||
flex-shrink: 0;
|
||
margin-top: 0;
|
||
box-shadow: 0 -8px 0 8px var(--panel), 0 8px 0 0 var(--panel);
|
||
}
|
||
}
|
||
.note-card-pinned {
|
||
border-top: 2px solid color-mix(in srgb, var(--fg) 30%, transparent);
|
||
}
|
||
.note-card.note-card-reminder-fired {
|
||
animation: note-reminder-pulse 1.2s ease-in-out 2;
|
||
}
|
||
/* Sticky outside glow — applied to the exact note whose reminder fired.
|
||
It stays until the user interacts with that card. */
|
||
.note-card.note-card-reminder-fired-sticky {
|
||
position: relative;
|
||
outline: 1px solid color-mix(in srgb, var(--accent, var(--red)) 36%, transparent);
|
||
outline-offset: 2px;
|
||
animation: note-reminder-glow 1.6s ease-in-out infinite;
|
||
}
|
||
|
||
/* Hover-only buttons (Google Keep style) */
|
||
.note-card-select,
|
||
.note-card-pin {
|
||
position: absolute;
|
||
top: -8px;
|
||
background: var(--bg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 50%;
|
||
width: 18px;
|
||
height: 18px;
|
||
padding: 0;
|
||
cursor: pointer;
|
||
display: none;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--fg);
|
||
opacity: 0.7;
|
||
z-index: 2;
|
||
transition: opacity 0.15s, transform 0.15s, background 0.15s;
|
||
}
|
||
/* Pencil + checkmark glyphs both have empty space along the top of their
|
||
24×24 viewBox, so flex-centering leaves them sitting visually high.
|
||
Nudge the inner SVG down a touch to compensate. */
|
||
.note-card-edit-corner svg,
|
||
.note-card-done svg {
|
||
position: relative;
|
||
top: 0.5px;
|
||
}
|
||
.note-card-edit-corner {
|
||
position: absolute;
|
||
/* Both Edit + Done at top-right: Edit on the left (right:40px),
|
||
Done on the right (right:6px). */
|
||
top: 6px; right: 40px;
|
||
width: 28px; height: 28px;
|
||
/* Fully invisible at rest. Materializes (with a solid panel fill blocking
|
||
any text underneath) only when the card is hovered or the button is
|
||
focused. Same rule on touch — opacity stays 0 until the card is tapped
|
||
to expose actions. */
|
||
background: transparent;
|
||
border: 1px solid transparent;
|
||
border-radius: 50%;
|
||
cursor: pointer; padding: 0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--fg); opacity: 0;
|
||
touch-action: manipulation;
|
||
transition: opacity 0.15s, background 0.15s, border-color 0.15s;
|
||
z-index: 2;
|
||
}
|
||
.note-card:hover .note-card-edit-corner {
|
||
opacity: 0.85;
|
||
background: var(--panel);
|
||
border-color: color-mix(in srgb, var(--fg) 18%, transparent);
|
||
}
|
||
.note-card-edit-corner:hover,
|
||
.note-card-edit-corner:focus-visible {
|
||
opacity: 1 !important;
|
||
background: color-mix(in srgb, var(--accent) 18%, var(--panel)) !important;
|
||
border-color: color-mix(in srgb, var(--accent) 50%, var(--border)) !important;
|
||
}
|
||
@media (hover: none) {
|
||
.note-card-edit-corner {
|
||
opacity: 0.7;
|
||
background: var(--panel);
|
||
border-color: color-mix(in srgb, var(--fg) 18%, transparent);
|
||
}
|
||
}
|
||
/* Copy corner — bottom-right counterpart to the edit/done corner buttons.
|
||
Round, subtle, hover-reveal on desktop and always faintly visible on
|
||
touch so mobile users can tap it without needing hover. */
|
||
.note-card-copy-corner {
|
||
position: absolute;
|
||
bottom: 6px;
|
||
right: 6px;
|
||
top: auto;
|
||
width: 26px;
|
||
height: 26px;
|
||
background: transparent;
|
||
border: 1px solid transparent;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
padding: 0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--fg);
|
||
opacity: 0;
|
||
touch-action: manipulation;
|
||
transition: opacity 0.15s, background 0.15s, border-color 0.15s;
|
||
z-index: 2;
|
||
}
|
||
.note-card:hover .note-card-copy-corner {
|
||
opacity: 0.7;
|
||
background: var(--panel);
|
||
border-color: color-mix(in srgb, var(--fg) 18%, transparent);
|
||
}
|
||
.note-card-copy-corner:hover,
|
||
.note-card-copy-corner:focus-visible {
|
||
opacity: 1 !important;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 18%, var(--panel)) !important;
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 50%, var(--border)) !important;
|
||
}
|
||
@media (hover: none) {
|
||
.note-card-copy-corner {
|
||
opacity: 0.6;
|
||
background: var(--panel);
|
||
border-color: color-mix(in srgb, var(--fg) 18%, transparent);
|
||
}
|
||
}
|
||
/* Unarchive corner reuses the pencil's spot in archive view. */
|
||
.note-card-unarchive-corner:hover,
|
||
.note-card-unarchive-corner:focus-visible {
|
||
background: color-mix(in srgb, var(--accent) 22%, transparent) !important;
|
||
border-color: color-mix(in srgb, var(--accent) 50%, var(--border)) !important;
|
||
color: var(--accent);
|
||
}
|
||
|
||
/* "Done" pill in the bottom-right of every active note card. Visible-only on
|
||
hover (and always on touch) so it's clearly readable but doesn't clutter
|
||
the grid at rest. Distinct from the edit pencil so it's obvious what it
|
||
does — green checkmark + label, not just an icon. */
|
||
/* Matches .note-card-edit-corner footprint (22×22 circle), just anchored
|
||
to the bottom-right corner instead of top-right. */
|
||
.note-card-done {
|
||
position: absolute;
|
||
top: 6px;
|
||
right: 6px;
|
||
width: 28px;
|
||
height: 28px;
|
||
background: transparent;
|
||
border: 1px solid transparent;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
padding: 0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--green, #98c379);
|
||
opacity: 0;
|
||
touch-action: manipulation;
|
||
transition: opacity 0.15s, background 0.15s, border-color 0.15s;
|
||
z-index: 2;
|
||
}
|
||
.note-card:hover .note-card-done {
|
||
opacity: 0.85;
|
||
background: var(--panel);
|
||
border-color: color-mix(in srgb, var(--fg) 18%, transparent);
|
||
}
|
||
.note-card-done:hover,
|
||
.note-card-done:focus-visible {
|
||
opacity: 1 !important;
|
||
background: color-mix(in srgb, var(--green, #98c379) 22%, var(--panel)) !important;
|
||
border-color: color-mix(in srgb, var(--green, #98c379) 50%, var(--border)) !important;
|
||
}
|
||
@media (hover: none) {
|
||
.note-card-done {
|
||
opacity: 0.7;
|
||
background: var(--panel);
|
||
border-color: color-mix(in srgb, var(--fg) 18%, transparent);
|
||
}
|
||
}
|
||
|
||
/* Copy corner — bottom-right of the card. Same opaque-fill pattern as
|
||
trash/unarchive so the underlying text/image never bleeds through. */
|
||
.note-card-corner-copy {
|
||
position: absolute;
|
||
bottom: 6px;
|
||
right: 6px;
|
||
width: 28px;
|
||
height: 28px;
|
||
background: var(--panel);
|
||
border: 1px solid color-mix(in srgb, var(--fg) 18%, transparent);
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
padding: 0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--fg);
|
||
visibility: hidden;
|
||
touch-action: manipulation;
|
||
transition: background 0.15s, border-color 0.15s, color 0.15s;
|
||
z-index: 2;
|
||
}
|
||
.note-card-corner-copy svg { position: relative; top: 1px; opacity: 0.85; transition: opacity 0.15s; }
|
||
.note-card-corner-copy:hover,
|
||
.note-card-corner-copy:focus-visible {
|
||
background: color-mix(in srgb, var(--accent) 18%, var(--panel));
|
||
border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
|
||
color: var(--accent);
|
||
}
|
||
.note-card-corner-copy:hover svg { opacity: 1; }
|
||
@media (hover: none) {
|
||
.note-card-corner-copy { visibility: visible; }
|
||
.note-card-corner-copy svg { opacity: 0.7; }
|
||
}
|
||
|
||
/* ── Archive view corners — trash (top-left) + unarchive (top-right) ── */
|
||
/* Background fill stays fully opaque (var(--panel)) so the note text or
|
||
image behind doesn't bleed through. Visibility is gated by `visibility`
|
||
+ a faded ICON instead of `opacity` on the whole button. */
|
||
.note-card-corner-trash,
|
||
.note-card-corner-unarchive {
|
||
position: absolute;
|
||
top: 6px;
|
||
width: 28px;
|
||
height: 28px;
|
||
background: var(--panel);
|
||
border: 1px solid color-mix(in srgb, var(--fg) 18%, transparent);
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
padding: 0;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
color: var(--fg);
|
||
visibility: hidden;
|
||
touch-action: manipulation;
|
||
transition: background 0.15s, border-color 0.15s, color 0.15s;
|
||
z-index: 2;
|
||
}
|
||
.note-card-corner-trash svg,
|
||
.note-card-corner-unarchive svg { opacity: 0.85; transition: opacity 0.15s; }
|
||
.note-card-corner-trash:hover,
|
||
.note-card-corner-trash:focus-visible {
|
||
background: color-mix(in srgb, var(--red) 18%, var(--panel));
|
||
border-color: color-mix(in srgb, var(--red) 50%, var(--border));
|
||
color: var(--red);
|
||
}
|
||
.note-card-corner-trash:hover svg,
|
||
.note-card-corner-unarchive:hover svg { opacity: 1; }
|
||
.note-card-corner-unarchive:hover,
|
||
.note-card-corner-unarchive:focus-visible {
|
||
background: color-mix(in srgb, var(--accent) 18%, var(--panel));
|
||
border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
|
||
color: var(--accent);
|
||
}
|
||
@media (hover: none) {
|
||
.note-card-corner-trash,
|
||
.note-card-corner-unarchive { visibility: visible; }
|
||
.note-card-corner-trash svg,
|
||
.note-card-corner-unarchive svg { opacity: 0.7; }
|
||
}
|
||
|
||
/* ─── Auto-AI ✨ chip on note cards ─────────────────────────────────── */
|
||
.note-card-ai-chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
margin-left: 6px;
|
||
padding: 2px 8px;
|
||
border-radius: 999px;
|
||
font-size: 11px;
|
||
font-weight: 500;
|
||
font-family: inherit;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 14%, transparent);
|
||
border: 1px solid color-mix(in srgb, var(--accent, var(--red)) 35%, transparent);
|
||
color: var(--accent, var(--red));
|
||
cursor: pointer;
|
||
transition: background 0.12s, transform 0.12s, box-shadow 0.12s;
|
||
vertical-align: middle;
|
||
}
|
||
.note-card-ai-chip:hover {
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 22%, transparent);
|
||
transform: translateY(-1px);
|
||
box-shadow: 0 2px 6px color-mix(in srgb, var(--accent, var(--red)) 30%, transparent);
|
||
}
|
||
.note-card-ai-chip svg {
|
||
flex-shrink: 0;
|
||
animation: note-ai-shine 2.4s ease-in-out infinite;
|
||
}
|
||
.note-card-ai-solving {
|
||
cursor: default;
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
border-color: color-mix(in srgb, var(--fg) 18%, transparent);
|
||
color: color-mix(in srgb, var(--fg) 70%, transparent);
|
||
}
|
||
.note-card-ai-solving svg { animation: spin 0.9s linear infinite; filter: none; }
|
||
.note-card-ai-done { background: color-mix(in srgb, var(--accent, var(--red)) 8%, transparent); }
|
||
.note-card-ai-done svg { animation: none; }
|
||
#notes-auto-ai-toggle.active { color: var(--accent, var(--red)); }
|
||
|
||
/* ─── AI improve button (note form header) ───────────────────────────── */
|
||
.note-form-improve-btn {
|
||
width: 38px !important;
|
||
height: 38px !important;
|
||
color: var(--accent, var(--red));
|
||
}
|
||
.note-form-improve-btn svg {
|
||
width: 22px !important;
|
||
height: 22px !important;
|
||
animation: note-ai-shine 2.4s ease-in-out infinite;
|
||
}
|
||
.note-form-improve-btn.busy svg {
|
||
animation: spin 0.9s linear infinite;
|
||
filter: none;
|
||
}
|
||
|
||
.note-card:hover .note-card-select,
|
||
.note-card:hover .note-card-pin,
|
||
.note-card-selected .note-card-select,
|
||
.note-card-pinned .note-card-pin {
|
||
display: flex;
|
||
}
|
||
.note-card-select:hover, .note-card-pin:hover {
|
||
opacity: 1;
|
||
transform: scale(1.15);
|
||
background: color-mix(in srgb, var(--accent) 15%, var(--bg));
|
||
}
|
||
.note-card-pin.active {
|
||
display: flex;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 12%, var(--bg));
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 45%, var(--border));
|
||
color: var(--accent, var(--red));
|
||
opacity: 1;
|
||
}
|
||
.note-card-selected .note-card-select {
|
||
background: var(--accent);
|
||
border-color: var(--accent);
|
||
color: #fff;
|
||
opacity: 1;
|
||
}
|
||
|
||
/* Select-mode checkbox on cards (mirrors docs library) */
|
||
.note-card-cb {
|
||
position: absolute;
|
||
top: 6px;
|
||
left: 6px;
|
||
z-index: 3;
|
||
margin: 0;
|
||
}
|
||
.note-card-selectmode {
|
||
padding-left: 28px;
|
||
cursor: pointer;
|
||
}
|
||
.note-card-selectmode:hover { background: color-mix(in srgb, var(--fg) 3%, transparent) !important; }
|
||
|
||
@media (max-width: 768px) {
|
||
body.notes-mobile-mode .note-card-selectmode {
|
||
animation: notes-select-jiggle 0.34s cubic-bezier(0.42, 0, 0.58, 1) infinite;
|
||
transform-origin: 50% 50%;
|
||
}
|
||
body.notes-mobile-mode .note-card-selectmode:nth-child(2n) {
|
||
animation-delay: -0.08s;
|
||
}
|
||
/* Keep the subtle edit-mode cue only on Notes and Gallery. */
|
||
:is(
|
||
body.gallery-selecting .gallery-card
|
||
) {
|
||
animation: notes-select-jiggle 0.34s cubic-bezier(0.42, 0, 0.58, 1) infinite;
|
||
transform-origin: 50% 50%;
|
||
}
|
||
:is(
|
||
body.gallery-selecting .gallery-card:nth-child(2n)
|
||
) { animation-delay: -0.11s; }
|
||
}
|
||
@media (prefers-reduced-motion: reduce) {
|
||
body.notes-mobile-mode .note-card-selectmode,
|
||
body.gallery-selecting .gallery-card { animation: none; }
|
||
}
|
||
|
||
/* Bottom action row — hidden everywhere. The archive/delete actions and the
|
||
color picker now live inside the edit form (click the pencil corner). */
|
||
.note-card-actions { display: none; }
|
||
.note-agent-menu {
|
||
background: var(--panel, var(--bg));
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
box-shadow: 0 4px 16px rgba(0,0,0,0.3);
|
||
padding: 4px 0;
|
||
min-width: 140px;
|
||
font-size: 12px;
|
||
}
|
||
.note-card-colors {
|
||
display: flex;
|
||
gap: 3px;
|
||
}
|
||
/* Re-asserted AFTER the base rule above so the mobile-hide actually
|
||
wins the cascade — earlier @media (hover:none) block was being
|
||
overridden because the unconditional display:flex rule came later. */
|
||
@media (hover: none) {
|
||
.note-card-colors { display: none; }
|
||
}
|
||
.note-card-color-dot {
|
||
width: 12px;
|
||
height: 12px;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
border: 1.5px solid color-mix(in srgb, var(--fg) 20%, transparent);
|
||
transition: transform 0.15s, border-color 0.15s;
|
||
}
|
||
.note-card-color-dot:hover {
|
||
transform: scale(1.25);
|
||
border-color: var(--fg);
|
||
}
|
||
.note-card-color-dot.active {
|
||
border-color: var(--fg);
|
||
border-width: 2px;
|
||
}
|
||
.note-card-action {
|
||
background: none;
|
||
border: none;
|
||
cursor: pointer;
|
||
padding: 3px;
|
||
color: var(--fg);
|
||
opacity: 0.4;
|
||
display: flex;
|
||
align-items: center;
|
||
border-radius: 3px;
|
||
transition: opacity 0.15s, background 0.15s;
|
||
}
|
||
|
||
/* Note image */
|
||
.note-card-image {
|
||
width: 100%;
|
||
max-height: 180px;
|
||
object-fit: cover;
|
||
border-radius: 4px;
|
||
margin: 4px 0;
|
||
display: block;
|
||
}
|
||
.note-form-image-wrap {
|
||
position: relative;
|
||
margin: 4px 0;
|
||
}
|
||
.note-form-image {
|
||
width: 100%;
|
||
max-height: 200px;
|
||
object-fit: cover;
|
||
border-radius: 4px;
|
||
display: block;
|
||
/* Images are draggable=true by default; that catches the mousedown
|
||
and beats the X button to the click. Disabling drag at the CSS
|
||
level (the -webkit-user-drag prop) keeps the X button reliably
|
||
clickable even if the JS forgets to set draggable="false" on the
|
||
element. Unprefixed user-drag was never standardized — Firefox
|
||
drops it with a warning. */
|
||
-webkit-user-drag: none;
|
||
user-select: none;
|
||
}
|
||
.note-form-image-rm {
|
||
position: absolute;
|
||
top: 6px;
|
||
right: 6px;
|
||
z-index: 5;
|
||
background: rgba(0,0,0,0.65);
|
||
border: none;
|
||
color: #fff;
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
font-size: 20px;
|
||
line-height: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.note-form-photo-btn {
|
||
flex: 0 0 auto;
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
width: auto;
|
||
min-width: 32px;
|
||
height: 32px;
|
||
padding: 0 6px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 3px;
|
||
opacity: 1;
|
||
transition: opacity 0.15s, border-color 0.15s, background 0.15s;
|
||
}
|
||
.note-form-photo-btn:hover { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
|
||
|
||
/* Quick-add bar (always at top) */
|
||
.notes-quick-add {
|
||
display: flex;
|
||
align-items: center;
|
||
transform: translateY(-2px);
|
||
gap: 4px;
|
||
background: var(--panel);
|
||
border: 1px solid color-mix(in srgb, var(--accent, var(--red)) 35%, var(--border));
|
||
border-radius: 6px;
|
||
/* Toggle pill sits at the very left of the bar — no inset padding. The
|
||
pill's own border provides visual breathing room from the wrapper edge. */
|
||
padding: 4px 6px 4px 4px;
|
||
margin-top: 2px;
|
||
margin-bottom: 8px;
|
||
transition: border-color 0.15s, box-shadow 0.15s, background 0.15s;
|
||
/* Subtle idle glow so the field reads as "you can type here" without
|
||
the user having to click it first. Fades out the moment the user
|
||
hovers or focuses it. */
|
||
animation: notes-quick-pulse 2.8s ease-in-out infinite;
|
||
}
|
||
.notes-quick-add:hover {
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 55%, var(--border));
|
||
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, var(--red)) 18%, transparent);
|
||
animation: none;
|
||
}
|
||
.notes-quick-add:focus-within {
|
||
border-color: var(--accent, var(--red));
|
||
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, var(--red)) 25%, transparent);
|
||
background: color-mix(in srgb, var(--fg) 3%, var(--panel));
|
||
animation: none;
|
||
}
|
||
.notes-quick-input {
|
||
flex: 1;
|
||
background: transparent;
|
||
border: none;
|
||
outline: none;
|
||
color: var(--fg);
|
||
caret-color: var(--accent, var(--red));
|
||
font-family: inherit;
|
||
font-size: 12px;
|
||
padding: 6px 0;
|
||
}
|
||
.notes-quick-icon {
|
||
background: none;
|
||
border: none;
|
||
color: var(--fg);
|
||
opacity: 0.45;
|
||
cursor: pointer;
|
||
padding: 5px;
|
||
border-radius: 4px;
|
||
display: flex;
|
||
align-items: center;
|
||
transition: opacity 0.15s, background 0.15s;
|
||
}
|
||
.notes-quick-icon:hover {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
}
|
||
/* 2-pill Note/Todo toggle in the quick-add bar — same look as the form's
|
||
type-seg but slimmer to fit the compact row. */
|
||
.notes-quick-type-seg {
|
||
display: inline-flex;
|
||
height: 28px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
overflow: hidden;
|
||
position: relative;
|
||
flex-shrink: 0;
|
||
/* Negative order pushes the toggle BEFORE the wrapper's ::before caret
|
||
hint, so the blinking | sits between the toggle and the input rather
|
||
than at the far-left edge. */
|
||
order: -1;
|
||
}
|
||
.notes-quick-type-seg::before {
|
||
content: '';
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
width: 50%;
|
||
height: 100%;
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent);
|
||
border-radius: 6px;
|
||
transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
z-index: 0;
|
||
}
|
||
.notes-quick-type-pill {
|
||
background: none;
|
||
border: none;
|
||
color: color-mix(in srgb, var(--fg) 40%, transparent);
|
||
cursor: pointer;
|
||
padding: 0 11px;
|
||
font-family: inherit;
|
||
transition: color 0.2s;
|
||
white-space: nowrap;
|
||
height: 100%;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
.notes-quick-type-pill svg {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
.notes-quick-type-pill:not(.active):hover {
|
||
color: color-mix(in srgb, var(--fg) 65%, transparent);
|
||
}
|
||
.notes-quick-type-pill.active,
|
||
.notes-quick-type-pill.active:hover,
|
||
.notes-quick-type-pill.active:focus {
|
||
color: var(--fg);
|
||
cursor: default;
|
||
}
|
||
/* Mobile: thumb-sized Note/Todo toggle. The 22px desktop pill is too
|
||
small to hit reliably on a phone. */
|
||
@media (max-width: 768px) {
|
||
.notes-quick-type-seg {
|
||
height: 36px;
|
||
border-radius: 10px;
|
||
}
|
||
.notes-quick-type-seg::before {
|
||
border-radius: 9px;
|
||
}
|
||
.notes-quick-type-pill {
|
||
padding: 0 14px;
|
||
}
|
||
.notes-quick-type-pill svg {
|
||
width: 17px;
|
||
height: 17px;
|
||
}
|
||
/* Match the input + photo button heights to the bigger toggle so the
|
||
row reads as one consistent bar. */
|
||
.notes-quick-input {
|
||
height: 36px;
|
||
font-size: 15px;
|
||
}
|
||
.notes-quick-icon {
|
||
padding: 9px;
|
||
}
|
||
.notes-quick-icon svg {
|
||
width: 18px;
|
||
height: 18px;
|
||
}
|
||
}
|
||
.notes-empty-msg {
|
||
text-align: center;
|
||
/* 0.4 dropped this empty-state text to ~2.8:1; 0.65 keeps it readable
|
||
(WCAG AA) while staying visibly secondary. */
|
||
opacity: 0.65;
|
||
padding: 30px 20px;
|
||
font-size: 11px;
|
||
}
|
||
|
||
/* Loading skeleton */
|
||
.notes-skeleton {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
margin-top: 4px;
|
||
}
|
||
.notes-skeleton-card {
|
||
height: 72px;
|
||
border-radius: 6px;
|
||
border: 1px solid var(--border);
|
||
background: linear-gradient(
|
||
90deg,
|
||
color-mix(in srgb, var(--fg) 4%, transparent) 0%,
|
||
color-mix(in srgb, var(--fg) 10%, transparent) 50%,
|
||
color-mix(in srgb, var(--fg) 4%, transparent) 100%
|
||
);
|
||
background-size: 200% 100%;
|
||
animation: notes-skeleton-shimmer 1.4s ease-in-out infinite;
|
||
}
|
||
|
||
/* Type toggle (note vs todo) */
|
||
.note-form-type-row {
|
||
display: flex;
|
||
gap: 4px;
|
||
margin-top: -2px;
|
||
}
|
||
/* Reminder bell button */
|
||
/* Mobile-only: bell icon in the note editor is accent-coloured so it pops as
|
||
the primary "set a reminder" affordance. The Archive button is hidden — the
|
||
Update (✓) button morphs into an Archive action when the user opens a note
|
||
and clicks without making any edits (see notes.js `archive-mode` toggle). */
|
||
@media (max-width: 768px) {
|
||
.note-form-remind-btn { color: var(--accent, var(--red)) !important; }
|
||
.note-form-remind-btn > svg { color: var(--accent, var(--red)); }
|
||
.note-form-archive-btn { display: none !important; }
|
||
.notes-pane #notes-archive-toggle { display: none !important; }
|
||
.note-form-save.archive-mode {
|
||
color: var(--accent, var(--red)) !important;
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 50%, transparent) !important;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 10%, transparent) !important;
|
||
}
|
||
}
|
||
.note-form-remind-btn {
|
||
flex: 0 0 auto;
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
border-radius: 4px;
|
||
width: 32px;
|
||
height: 32px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
opacity: 1;
|
||
position: relative;
|
||
top: -2px;
|
||
transition: opacity 0.15s, border-color 0.15s, background 0.15s, color 0.15s;
|
||
}
|
||
.note-form-remind-btn:hover { opacity: 1; border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
|
||
.note-form-remind-btn.has-date { color: var(--accent); border-color: var(--accent); }
|
||
|
||
/* Calendar event form + notes form: jingle the little bell when the user
|
||
picks a reminder. Anchored near the top of the bell so the swing reads
|
||
as the bell clanging side-to-side. */
|
||
.cal-remind-bell,
|
||
.note-form-remind-btn > svg {
|
||
transform-origin: 50% 4px;
|
||
transition: transform 0.1s ease;
|
||
}
|
||
.cal-remind-bell.jingling,
|
||
.note-form-remind-btn > svg.jingling {
|
||
animation: cal-bell-jingle 0.65s cubic-bezier(0.36, 0, 0.66, -0.56) both;
|
||
}
|
||
@media (prefers-reduced-motion: reduce) {
|
||
.cal-remind-bell.jingling,
|
||
.note-form-remind-btn > svg.jingling { animation: none; }
|
||
}
|
||
|
||
/* Reminder tag inside form */
|
||
.note-form-reminder-tags {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 4px;
|
||
}
|
||
.note-reminder-tag {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
background: color-mix(in srgb, var(--accent) 14%, transparent);
|
||
color: var(--accent);
|
||
border: none;
|
||
border-radius: 12px;
|
||
padding: 4px 4px 4px 9px;
|
||
font-size: 10px;
|
||
font-family: inherit;
|
||
cursor: pointer;
|
||
font-weight: 500;
|
||
}
|
||
.note-reminder-tag:hover { background: color-mix(in srgb, var(--accent) 22%, transparent); }
|
||
.note-reminder-tag-x {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 14px;
|
||
height: 14px;
|
||
border-radius: 50%;
|
||
background: color-mix(in srgb, var(--accent) 25%, transparent);
|
||
font-size: 12px;
|
||
line-height: 1;
|
||
position: relative;
|
||
top: -2px;
|
||
}
|
||
.note-reminder-tag-x:hover { background: var(--red); color: #fff; }
|
||
|
||
/* Reminder tag on card */
|
||
.note-card-reminder {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
background: color-mix(in srgb, var(--accent) 12%, transparent);
|
||
color: var(--accent);
|
||
font-size: 9px;
|
||
font-weight: 500;
|
||
padding: 2px 7px;
|
||
border-radius: 10px;
|
||
align-self: flex-start;
|
||
margin-top: 2px;
|
||
}
|
||
.note-card-reminder.overdue {
|
||
background: color-mix(in srgb, var(--red) 18%, transparent);
|
||
color: var(--red);
|
||
}
|
||
|
||
/* Reminder dropdown menu */
|
||
.note-reminder-menu {
|
||
position: fixed;
|
||
background: var(--bg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
box-shadow: 0 6px 24px rgba(0,0,0,0.25);
|
||
/* Above the fullscreen note overlay (z-index: 10500) — otherwise the
|
||
reminder picker opens hidden behind it on mobile and reads as
|
||
"broken". */
|
||
z-index: 12000;
|
||
min-width: 220px;
|
||
padding: 6px 0;
|
||
font-family: inherit;
|
||
font-size: 12px;
|
||
}
|
||
.note-reminder-menu-title {
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
text-transform: uppercase;
|
||
opacity: 0.5;
|
||
padding: 6px 14px 4px;
|
||
letter-spacing: 0.5px;
|
||
}
|
||
.note-reminder-menu-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
background: none;
|
||
border: none;
|
||
color: var(--fg);
|
||
font-family: inherit;
|
||
font-size: 12px;
|
||
padding: 7px 14px;
|
||
cursor: pointer;
|
||
text-align: left;
|
||
transition: background 0.1s;
|
||
}
|
||
.note-reminder-menu-item:hover { background: color-mix(in srgb, var(--fg) 6%, transparent); }
|
||
.note-reminder-menu-item.active { color: var(--accent); }
|
||
.note-reminder-menu-sub {
|
||
font-size: 10px;
|
||
opacity: 0.5;
|
||
margin-left: 12px;
|
||
}
|
||
.note-reminder-menu-check { color: var(--accent); font-size: 12px; }
|
||
.note-reminder-menu-divider {
|
||
height: 1px;
|
||
background: var(--border);
|
||
margin: 4px 0;
|
||
}
|
||
.note-reminder-menu-picker {
|
||
padding: 6px 14px 8px;
|
||
}
|
||
.note-reminder-date-input {
|
||
width: 100%;
|
||
background: color-mix(in srgb, var(--fg) 5%, transparent);
|
||
border: 1px solid var(--border);
|
||
border-radius: 4px;
|
||
color: var(--fg);
|
||
font-family: inherit;
|
||
font-size: 12px;
|
||
padding: 6px 8px;
|
||
outline: none;
|
||
color-scheme: dark light;
|
||
box-sizing: border-box;
|
||
}
|
||
.note-reminder-date-input:focus { border-color: var(--accent); }
|
||
.note-reminder-menu-confirm {
|
||
font-weight: 600;
|
||
color: var(--accent);
|
||
justify-content: center;
|
||
}
|
||
.note-reminder-menu-confirm.disabled,
|
||
.note-reminder-menu-confirm[disabled] {
|
||
opacity: 0.4;
|
||
cursor: not-allowed;
|
||
color: var(--fg);
|
||
}
|
||
.note-reminder-menu-arrow {
|
||
opacity: 0.5;
|
||
margin-left: 8px;
|
||
font-size: 14px;
|
||
line-height: 1;
|
||
}
|
||
.note-reminder-menu-back {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
width: 100%;
|
||
background: none;
|
||
border: none;
|
||
color: var(--fg);
|
||
font-family: inherit;
|
||
font-size: 11px;
|
||
opacity: 0.7;
|
||
padding: 6px 12px;
|
||
cursor: pointer;
|
||
text-align: left;
|
||
transition: opacity 0.1s, background 0.1s;
|
||
}
|
||
.note-reminder-menu-back:hover { opacity: 1; background: color-mix(in srgb, var(--fg) 6%, transparent); }
|
||
.note-reminder-menu-arrow-back {
|
||
font-size: 14px;
|
||
line-height: 1;
|
||
}
|
||
.note-reminder-menu-sublabel {
|
||
font-size: 10px;
|
||
opacity: 0.5;
|
||
padding: 6px 14px 2px;
|
||
letter-spacing: 0.3px;
|
||
}
|
||
.note-reminder-weekday-row {
|
||
display: flex;
|
||
gap: 4px;
|
||
padding: 4px 12px 8px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.note-reminder-day-chip {
|
||
flex: 1 1 0;
|
||
min-width: 24px;
|
||
height: 28px;
|
||
background: color-mix(in srgb, var(--fg) 5%, transparent);
|
||
border: 1px solid var(--border);
|
||
border-radius: 4px;
|
||
color: var(--fg);
|
||
font-family: inherit;
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: background 0.1s, border-color 0.1s, color 0.1s;
|
||
padding: 0;
|
||
}
|
||
.note-reminder-day-chip:hover {
|
||
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
||
border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
|
||
}
|
||
.note-reminder-day-chip.active {
|
||
background: var(--accent);
|
||
border-color: var(--accent);
|
||
color: #fff;
|
||
}
|
||
|
||
.note-form-type-btn,
|
||
.note-form-type-toggle {
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
width: 32px;
|
||
height: 32px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
opacity: 1;
|
||
transition: opacity 0.15s, background 0.15s, border-color 0.15s;
|
||
}
|
||
.note-form-type-toggle:hover { opacity: 1; border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
|
||
.note-form-type-toggle[data-type="todo"] { color: var(--accent); }
|
||
|
||
/* Note | Todo | Draw segmented toggle — mirrors .mode-toggle (agent/chat) */
|
||
.note-form-type-seg {
|
||
display: inline-flex;
|
||
height: 32px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 10px;
|
||
overflow: hidden;
|
||
position: relative;
|
||
flex-shrink: 0;
|
||
}
|
||
.note-form-type-pill {
|
||
background: none;
|
||
border: none;
|
||
color: color-mix(in srgb, var(--fg) 40%, transparent);
|
||
cursor: pointer;
|
||
padding: 0 12px;
|
||
font-size: 13px;
|
||
font-weight: 500;
|
||
font-family: inherit;
|
||
transition: color 0.2s;
|
||
white-space: nowrap;
|
||
height: 100%;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
position: relative;
|
||
z-index: 1;
|
||
}
|
||
.note-form-type-pill:not(.active):hover { color: color-mix(in srgb, var(--fg) 60%, transparent); }
|
||
.note-form-type-pill.active,
|
||
.note-form-type-pill.active:hover,
|
||
.note-form-type-pill.active:focus {
|
||
color: var(--fg);
|
||
cursor: default;
|
||
}
|
||
@media (max-width: 480px) {
|
||
.note-form-type-pill span { display: none; }
|
||
.note-form-type-pill { padding: 0 8px; }
|
||
}
|
||
|
||
.note-card-action:hover {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent);
|
||
}
|
||
.note-card-delete:hover { color: var(--red); }
|
||
|
||
/* Tag/label */
|
||
.note-card-label {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 4px;
|
||
margin-top: 2px;
|
||
}
|
||
.note-card-label-chip {
|
||
border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border));
|
||
background: color-mix(in srgb, var(--accent) 10%, transparent);
|
||
color: var(--accent);
|
||
border-radius: 999px;
|
||
padding: 2px 6px;
|
||
font: inherit;
|
||
font-size: 9px;
|
||
font-weight: 600;
|
||
line-height: 1.2;
|
||
cursor: pointer;
|
||
}
|
||
.note-card-label-chip:hover {
|
||
background: color-mix(in srgb, var(--accent) 18%, transparent);
|
||
border-color: color-mix(in srgb, var(--accent) 60%, var(--border));
|
||
}
|
||
|
||
/* Search bar */
|
||
.notes-search-bar {
|
||
padding: 6px 8px;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
.notes-select-trigger {
|
||
position: relative;
|
||
top: 3px;
|
||
flex-shrink: 0;
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
font-family: inherit;
|
||
font-size: 11px;
|
||
height: 30px;
|
||
padding: 0 12px;
|
||
cursor: pointer;
|
||
opacity: 0.75;
|
||
transition: opacity 0.15s, border-color 0.15s, background 0.15s, color 0.15s;
|
||
}
|
||
.notes-select-trigger:hover { opacity: 1; border-color: color-mix(in srgb, var(--accent) 50%, var(--border)); }
|
||
.notes-select-trigger.active {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--accent) 18%, transparent);
|
||
color: var(--accent);
|
||
border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
|
||
}
|
||
.notes-search-bar .memory-search-input {
|
||
flex: 1;
|
||
min-width: 0;
|
||
height: 30px;
|
||
min-height: 30px;
|
||
font-size: 11px;
|
||
padding: 0 10px 0 28px;
|
||
background-color: var(--bg);
|
||
background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%23e06c75' stroke-opacity='0.85' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><circle cx='11' cy='11' r='8'/><line x1='21' y1='21' x2='16.65' y2='16.65'/></svg>");
|
||
background-repeat: no-repeat;
|
||
background-position: 9px center;
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
color: var(--fg);
|
||
font-family: inherit;
|
||
outline: none;
|
||
transition: border-color 0.15s, background-color 0.15s;
|
||
}
|
||
.notes-search-bar .memory-search-input:focus {
|
||
border-color: var(--red);
|
||
}
|
||
|
||
/* Grid view: true CSS Grid plus JS-computed row spans, so cards masonry-pack
|
||
vertically without the jumpy rebalancing of CSS columns. */
|
||
.notes-pane.notes-view-grid .notes-pane-body {
|
||
display: grid;
|
||
grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
|
||
grid-auto-rows: 4px;
|
||
grid-auto-flow: dense;
|
||
gap: 0 8px;
|
||
padding: 10px 8px 8px;
|
||
overflow-x: hidden;
|
||
align-items: start;
|
||
align-content: start;
|
||
}
|
||
.notes-pane.notes-view-grid .note-card {
|
||
margin: 0 0 8px;
|
||
min-width: 0;
|
||
max-width: 100%;
|
||
overflow-wrap: anywhere;
|
||
word-break: break-word;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
.notes-pane.notes-view-grid .note-form,
|
||
.notes-pane.notes-view-grid .notes-quick-add {
|
||
grid-column: 1 / -1;
|
||
margin-bottom: 0;
|
||
grid-row-end: span 16;
|
||
}
|
||
/* Edit form in grid view: span the full row and size naturally — same shape
|
||
as the new-note form. The earlier max-width: 380px + max-height: 220px
|
||
inner-scroll combo read as a tiny popup floating in a wider panel and
|
||
didn't actually fit the form's content. */
|
||
.notes-pane.notes-view-grid .note-form {
|
||
width: 100%;
|
||
max-width: none;
|
||
margin-left: 0;
|
||
margin-right: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
/* Pinned section break: the first unpinned card jumps to column 1, leaving
|
||
any leftover cell in the pinned row empty. Reads as a visual divider
|
||
between pinned and unpinned without needing a separator element. */
|
||
.notes-pane.notes-view-grid .note-card-pinned + .note-card:not(.note-card-pinned) {
|
||
grid-column-start: 1;
|
||
}
|
||
/* Mobile: 2-lane masonry via the CSS-Grid row-span trick. Each card spans
|
||
N tiny rows (4px each) based on its measured height; the grid auto-places
|
||
cards into the two columns so left/right lanes flow independently — no
|
||
row alignment between them. JS in notes.js sets `grid-row-end: span N`
|
||
on every card after render. Pure CSS multi-column was tried but its
|
||
`column-span: all` interaction with sticky positioning broke clicks on
|
||
the quick-add bar (Firefox mobile). */
|
||
@media (max-width: 768px) {
|
||
.notes-pane.notes-view-grid .notes-pane-body {
|
||
display: grid;
|
||
grid-template-columns: repeat(2, 1fr);
|
||
grid-auto-rows: 4px;
|
||
grid-auto-flow: dense;
|
||
gap: 0 8px;
|
||
align-content: start;
|
||
}
|
||
.notes-pane.notes-view-grid .note-card {
|
||
margin: -8px 0 6px;
|
||
transform: translateY(-12px);
|
||
/* grid-row-end set inline by JS (_applyMasonry) */
|
||
}
|
||
/* Full-width quick-add + edit form. Quick-add stays sticky at top so
|
||
the user can always reach it; it's NOT inside the masonry pack. */
|
||
.notes-pane.notes-view-grid .notes-label-toggle,
|
||
.notes-pane.notes-view-grid .notes-labels-bar,
|
||
.notes-pane.notes-view-grid .doclib-chip-scroll-frame:has(> .notes-labels-bar),
|
||
.notes-pane.notes-view-grid .notes-quick-add,
|
||
.notes-pane.notes-view-grid .note-form {
|
||
grid-column: 1 / -1;
|
||
}
|
||
.notes-pane.notes-view-grid .notes-label-toggle { grid-row: span 8; }
|
||
.notes-pane.notes-view-grid .notes-labels-bar { grid-row: span 16; }
|
||
.notes-pane.notes-view-grid .doclib-chip-scroll-frame:has(> .notes-labels-bar) { grid-row: span 16; }
|
||
.notes-pane.notes-view-grid .notes-quick-add { grid-row: span 12; }
|
||
.notes-pane.notes-view-grid .note-form {
|
||
width: 100%;
|
||
max-width: none;
|
||
margin-left: 0;
|
||
margin-right: 0;
|
||
box-sizing: border-box;
|
||
grid-row: auto / span 64;
|
||
}
|
||
.notes-pane.notes-view-grid .note-form:has(.note-form-type-seg.is-draw) {
|
||
grid-row: auto / span 152;
|
||
}
|
||
.notes-pane.notes-view-grid .note-form.note-form-new {
|
||
transform: translateY(-28px);
|
||
}
|
||
.notes-pane.notes-view-grid .notes-labels-bar {
|
||
padding-top: 0;
|
||
margin-top: -6px;
|
||
margin-bottom: 0;
|
||
}
|
||
.notes-pane.notes-view-grid .notes-quick-add {
|
||
margin-top: -32px;
|
||
margin-bottom: 4px;
|
||
}
|
||
/* Pinned-section break: first unpinned card jumps to column 1. */
|
||
.notes-pane.notes-view-grid .note-card-pinned + .note-card:not(.note-card-pinned) {
|
||
grid-column-start: 1;
|
||
}
|
||
}
|
||
|
||
/* Label filter bar */
|
||
.notes-label-toggle {
|
||
align-self: flex-start;
|
||
margin: -6px 8px 2px;
|
||
top: 0;
|
||
}
|
||
.notes-search-bar .notes-label-toggle {
|
||
align-self: center;
|
||
flex: 0 0 auto;
|
||
height: 30px;
|
||
margin: 0;
|
||
top: 4px;
|
||
padding: 0 10px;
|
||
border-radius: 6px;
|
||
font-size: 11px;
|
||
white-space: nowrap;
|
||
}
|
||
.notes-pane-body .doclib-chip-scroll-arrow.right {
|
||
top: calc(50% - 6px) !important;
|
||
}
|
||
.doclib-chip-scroll-frame:has(> #tasks-filter-chips) .doclib-chip-scroll-arrow {
|
||
top: calc(50% - 9px) !important;
|
||
}
|
||
|
||
@media (max-width: 768px) {
|
||
#doclib-modal .doclib-lang-chips {
|
||
position: relative;
|
||
top: -2px;
|
||
}
|
||
#doclib-chats-tidy-btn,
|
||
#doclib-chats-select-btn,
|
||
#doclib-arc-select-btn,
|
||
#doclib-research-tidy-btn,
|
||
#doclib-research-select-btn,
|
||
#doclib-tidy-btn,
|
||
#doclib-select-btn {
|
||
height: 30px !important;
|
||
min-height: 30px !important;
|
||
box-sizing: border-box;
|
||
}
|
||
}
|
||
|
||
/* Keep filter chips consistent across Skills, Tasks, and the document
|
||
library. Documents use the shared compact chip treatment as the baseline. */
|
||
.skills-summary-chip,
|
||
.memory-cat-chip,
|
||
.doclib-chip {
|
||
height: 23px;
|
||
padding: 0 8px;
|
||
border: 1px solid color-mix(in srgb, var(--fg) 12%, transparent);
|
||
border-radius: 6px;
|
||
background: color-mix(in srgb, var(--fg) 4%, transparent);
|
||
color: color-mix(in srgb, var(--fg) 70%, transparent);
|
||
font-size: 10px;
|
||
line-height: 1;
|
||
font-family: inherit;
|
||
text-transform: none;
|
||
transition: background 0.15s, border-color 0.15s, color 0.15s;
|
||
}
|
||
.skills-summary-chip:hover,
|
||
.memory-cat-chip:hover,
|
||
.doclib-chip:hover {
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
border-color: color-mix(in srgb, var(--fg) 18%, transparent);
|
||
color: color-mix(in srgb, var(--fg) 70%, transparent);
|
||
}
|
||
.skills-summary-chip.active,
|
||
.memory-cat-chip.active,
|
||
.doclib-chip.active {
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 13%, transparent);
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 28%, transparent);
|
||
color: var(--fg);
|
||
}
|
||
.notes-labels-bar {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 4px;
|
||
padding: 0 8px 0;
|
||
margin-top: -6px;
|
||
margin-bottom: -2px;
|
||
}
|
||
.notes-label-chip {
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: color-mix(in srgb, var(--fg) 60%, transparent);
|
||
font-size: 10px;
|
||
padding: 3px 10px;
|
||
border-radius: 10px;
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
transition: background 0.15s, color 0.15s, border-color 0.15s;
|
||
}
|
||
.notes-label-chip:hover {
|
||
color: var(--fg);
|
||
background: color-mix(in srgb, var(--fg) 6%, transparent);
|
||
border-color: color-mix(in srgb, var(--accent) 40%, var(--border));
|
||
}
|
||
.notes-label-chip.active {
|
||
background: color-mix(in srgb, var(--accent) 18%, transparent);
|
||
color: var(--accent);
|
||
border-color: color-mix(in srgb, var(--accent) 60%, transparent);
|
||
font-weight: 600;
|
||
}
|
||
.notes-label-chip-reminders {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 2px;
|
||
}
|
||
.notes-label-chip-count {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
min-width: 14px;
|
||
height: 14px;
|
||
padding: 0 4px;
|
||
border-radius: 7px;
|
||
background: color-mix(in srgb, var(--fg) 12%, transparent);
|
||
color: inherit;
|
||
font-size: 9px;
|
||
font-weight: 600;
|
||
margin-left: 3px;
|
||
}
|
||
.notes-label-chip-reminders.active .notes-label-chip-count {
|
||
background: color-mix(in srgb, var(--accent) 30%, transparent);
|
||
color: var(--accent);
|
||
}
|
||
.notes-label-chip-reminders.active.negated {
|
||
background: color-mix(in srgb, var(--red, #e55) 14%, transparent);
|
||
color: var(--red, #e55);
|
||
border-color: color-mix(in srgb, var(--red, #e55) 50%, transparent);
|
||
}
|
||
.notes-label-chip-reminders.active.negated .notes-label-chip-count {
|
||
background: color-mix(in srgb, var(--red, #e55) 25%, transparent);
|
||
color: var(--red, #e55);
|
||
}
|
||
.notes-label-clear-past {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
color: var(--red, #e55);
|
||
border-color: color-mix(in srgb, var(--red, #e55) 45%, var(--border));
|
||
}
|
||
.notes-label-clear-past:hover {
|
||
color: var(--red, #e55);
|
||
background: color-mix(in srgb, var(--red, #e55) 12%, transparent);
|
||
border-color: color-mix(in srgb, var(--red, #e55) 65%, var(--border));
|
||
}
|
||
/* Today + Goals filter chips — share styling, tint with a warm accent so
|
||
they read as "long-term work" alongside the cool reminder chip. */
|
||
.notes-label-chip-today,
|
||
.notes-label-chip-goals {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 2px;
|
||
}
|
||
.notes-label-chip-today.active,
|
||
.notes-label-chip-goals.active {
|
||
background: color-mix(in srgb, var(--accent-warm) 22%, transparent);
|
||
color: var(--accent-warm);
|
||
border-color: color-mix(in srgb, var(--accent-warm) 60%, transparent);
|
||
}
|
||
.notes-label-chip-today.active .notes-label-chip-count,
|
||
.notes-label-chip-goals.active .notes-label-chip-count {
|
||
background: color-mix(in srgb, var(--accent-warm) 30%, transparent);
|
||
color: var(--accent-warm);
|
||
}
|
||
|
||
/* ── Goal cards ──────────────────────────────────────────────────────── */
|
||
/* A goal note is structurally a checklist (note_type='goal') but visually
|
||
marked with a small Goal pill in the corner + a slightly warmer accent
|
||
so users can spot it at a glance among regular todos. */
|
||
.note-card-goal {
|
||
border-left: 3px solid color-mix(in srgb, var(--accent-warm) 80%, transparent);
|
||
}
|
||
.note-goal-pill {
|
||
position: absolute;
|
||
top: 6px;
|
||
left: 8px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 3px;
|
||
padding: 2px 7px 2px 5px;
|
||
background: color-mix(in srgb, var(--accent-warm) 18%, transparent);
|
||
color: var(--accent-warm);
|
||
border-radius: 999px;
|
||
font-size: 9px;
|
||
font-weight: 600;
|
||
letter-spacing: 0.04em;
|
||
text-transform: uppercase;
|
||
line-height: 1;
|
||
z-index: 2;
|
||
}
|
||
/* Description blurb above the checklist on goal cards */
|
||
.note-goal-desc {
|
||
font-size: 12px;
|
||
opacity: 0.7;
|
||
margin: 4px 0 6px;
|
||
white-space: pre-wrap;
|
||
line-height: 1.4;
|
||
}
|
||
|
||
/* ── Goal form (Break-down editor) ───────────────────────────────────── */
|
||
.note-form-goal {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
}
|
||
.note-form-goal-desc {
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
color: var(--fg);
|
||
font-family: inherit;
|
||
font-size: 13px;
|
||
padding: 8px 10px;
|
||
resize: vertical;
|
||
min-height: 60px;
|
||
}
|
||
.note-form-goal-desc:focus {
|
||
outline: none;
|
||
border-color: color-mix(in srgb, var(--accent-warm) 60%, var(--border));
|
||
}
|
||
.note-form-goal-actions {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
}
|
||
.note-form-goal-ai {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
background: color-mix(in srgb, var(--accent-warm) 16%, transparent);
|
||
color: var(--accent-warm);
|
||
border: 1px solid color-mix(in srgb, var(--accent-warm) 45%, transparent);
|
||
border-radius: 6px;
|
||
padding: 5px 10px;
|
||
font-size: 12px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
transition: background 0.15s, border-color 0.15s;
|
||
}
|
||
.note-form-goal-ai:hover:not(:disabled) {
|
||
background: color-mix(in srgb, var(--accent-warm) 26%, transparent);
|
||
border-color: color-mix(in srgb, var(--accent-warm) 65%, transparent);
|
||
}
|
||
.note-form-goal-hint {
|
||
font-size: 11px;
|
||
opacity: 0.55;
|
||
}
|
||
|
||
/* ── Today view ──────────────────────────────────────────────────────── */
|
||
.notes-today-wrap {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
margin: 4px 0 12px;
|
||
}
|
||
.notes-today-header {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
letter-spacing: 0.06em;
|
||
text-transform: uppercase;
|
||
color: var(--accent-warm);
|
||
padding: 6px 10px 4px;
|
||
}
|
||
.notes-today-list {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 6px;
|
||
}
|
||
.notes-today-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 10px 12px;
|
||
background: var(--panel, var(--bg));
|
||
border: 1px solid var(--border);
|
||
border-left: 3px solid color-mix(in srgb, var(--accent-warm) 70%, transparent);
|
||
border-radius: 8px;
|
||
transition: opacity 0.2s, transform 0.2s;
|
||
}
|
||
.notes-today-row .note-check-dot {
|
||
flex-shrink: 0;
|
||
width: 18px;
|
||
height: 18px;
|
||
border-radius: 50%;
|
||
border: 2px solid color-mix(in srgb, var(--fg) 40%, transparent);
|
||
cursor: pointer;
|
||
transition: background 0.15s, border-color 0.15s;
|
||
}
|
||
.notes-today-row .note-check-dot:hover {
|
||
border-color: var(--accent-warm);
|
||
background: color-mix(in srgb, var(--accent-warm) 20%, transparent);
|
||
}
|
||
.notes-today-row.done .note-check-dot {
|
||
background: var(--accent-warm);
|
||
border-color: var(--accent-warm);
|
||
}
|
||
.notes-today-text {
|
||
flex: 1;
|
||
min-width: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 2px;
|
||
}
|
||
.notes-today-title {
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
color: var(--accent-warm);
|
||
letter-spacing: 0.03em;
|
||
cursor: pointer;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
.notes-today-step {
|
||
font-size: 14px;
|
||
color: var(--fg);
|
||
line-height: 1.35;
|
||
}
|
||
.notes-today-progress {
|
||
flex-shrink: 0;
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
opacity: 0.6;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.notes-empty {
|
||
text-align: center;
|
||
padding: 32px 16px;
|
||
font-size: 13px;
|
||
opacity: 0.55;
|
||
font-style: italic;
|
||
}
|
||
|
||
/* Bulk action bar */
|
||
.notes-bulk-info {
|
||
font-size: 10px;
|
||
opacity: 0.6;
|
||
margin-left: 4px;
|
||
}
|
||
|
||
/* Form label input */
|
||
.note-form-label {
|
||
background: transparent;
|
||
border: 1px dashed color-mix(in srgb, var(--border) 60%, transparent);
|
||
color: var(--fg);
|
||
font-size: 11px;
|
||
padding: 3px 6px;
|
||
border-radius: 4px;
|
||
outline: none;
|
||
width: 80px;
|
||
font-family: inherit;
|
||
opacity: 0.6;
|
||
transition: opacity 0.15s, border-color 0.15s;
|
||
}
|
||
.note-form-label:hover, .note-form-label:focus { opacity: 1; border-color: var(--border); }
|
||
@keyframes noteLabelFlash {
|
||
0% { background: color-mix(in srgb, var(--accent) 35%, transparent); }
|
||
100% { background: transparent; }
|
||
}
|
||
|
||
.note-card-header {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
justify-content: space-between;
|
||
gap: 6px;
|
||
}
|
||
.note-card-title {
|
||
font-size: 13px;
|
||
font-weight: 600;
|
||
cursor: pointer;
|
||
flex: 1;
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.note-content-preview {
|
||
font-size: 12px;
|
||
opacity: 0.6;
|
||
line-height: 1.4;
|
||
/* Roomy preview: up to ~14 lines. Content is also sliced to 600 chars
|
||
client-side, so cards still stay reasonable in the list. */
|
||
max-height: 240px;
|
||
overflow: hidden;
|
||
cursor: pointer;
|
||
white-space: pre-wrap;
|
||
word-break: break-word;
|
||
}
|
||
|
||
.note-pin-btn {
|
||
background: none;
|
||
border: none;
|
||
cursor: pointer;
|
||
padding: 2px;
|
||
flex-shrink: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
.note-pin-dot {
|
||
width: 7px;
|
||
height: 7px;
|
||
border-radius: 50%;
|
||
border: 1.5px solid color-mix(in srgb, var(--fg) 25%, transparent);
|
||
transition: all 0.15s;
|
||
}
|
||
.note-pin-btn:hover .note-pin-dot { border-color: var(--fg); }
|
||
.note-pin-btn.active .note-pin-dot {
|
||
background: var(--accent);
|
||
border-color: var(--accent);
|
||
}
|
||
.note-x-btn {
|
||
background: none;
|
||
border: none;
|
||
cursor: pointer;
|
||
padding: 2px;
|
||
flex-shrink: 0;
|
||
color: var(--fg);
|
||
opacity: 0.25;
|
||
display: flex;
|
||
align-items: center;
|
||
transition: opacity 0.15s, color 0.15s;
|
||
}
|
||
.note-x-btn:hover {
|
||
opacity: 0.9;
|
||
color: var(--red);
|
||
}
|
||
/* Inline due date next to title */
|
||
.note-due-inline {
|
||
font-size: 9px;
|
||
padding: 1px 6px;
|
||
border-radius: 3px;
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
color: color-mix(in srgb, var(--fg) 60%, transparent);
|
||
opacity: 0.7;
|
||
white-space: nowrap;
|
||
flex-shrink: 0;
|
||
align-self: center;
|
||
}
|
||
.note-due-inline.note-due-overdue {
|
||
background: color-mix(in srgb, var(--red) 18%, transparent);
|
||
color: var(--red);
|
||
opacity: 1;
|
||
font-weight: 600;
|
||
}
|
||
.note-card:active { cursor: grabbing; }
|
||
/* Dragged card = "drop preview" — it already sits at the swap-target slot,
|
||
so making it the most visible card on screen tells the user exactly where
|
||
the note will land on release. */
|
||
.note-card.dragging {
|
||
opacity: 0.92;
|
||
cursor: grabbing;
|
||
transform: scale(1.03) rotate(-0.6deg);
|
||
box-shadow: 0 14px 32px rgba(0,0,0,0.4), 0 0 0 2px var(--accent, var(--red));
|
||
border-color: var(--accent, var(--red)) !important;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 6%, var(--panel)) !important;
|
||
z-index: 10;
|
||
position: relative;
|
||
/* Let elementFromPoint see THROUGH the dragged card so the swap detector
|
||
can find the sibling underneath the finger. Without this, in single-row
|
||
(list view) the dragged card follows the finger and forever occludes
|
||
anything else, so no swap ever fires. The body-level touchmove listener
|
||
still receives events regardless. */
|
||
pointer-events: none;
|
||
}
|
||
.notes-pane-body.drag-active .note-card:not(.dragging) {
|
||
transition: transform 0.22s cubic-bezier(0.34, 1.2, 0.64, 1), border-color 0.15s, opacity 0.15s;
|
||
opacity: 0.78;
|
||
}
|
||
.notes-pane-body.drag-active .note-card:not(.dragging):hover {
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 50%, var(--border));
|
||
opacity: 1;
|
||
}
|
||
|
||
/* Checklist drag grip */
|
||
.note-cl-grip {
|
||
cursor: grab;
|
||
opacity: 0.2;
|
||
font-size: 9px;
|
||
letter-spacing: -2px;
|
||
user-select: none;
|
||
flex-shrink: 0;
|
||
width: 14px;
|
||
height: 14px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: opacity 0.15s;
|
||
}
|
||
.note-cl-row.dragging {
|
||
opacity: 0.4;
|
||
background: color-mix(in srgb, var(--accent) 8%, transparent);
|
||
border-radius: 4px;
|
||
}
|
||
.note-cl-row.drop-before {
|
||
box-shadow: 0 -2px 0 0 var(--accent);
|
||
}
|
||
.note-cl-row.drop-after {
|
||
box-shadow: 0 2px 0 0 var(--accent);
|
||
}
|
||
|
||
.note-card-footer {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
margin-top: 2px;
|
||
}
|
||
|
||
.note-delete-btn {
|
||
background: none;
|
||
border: none;
|
||
color: var(--fg);
|
||
opacity: 0.2;
|
||
cursor: pointer;
|
||
padding: 2px;
|
||
transition: opacity 0.15s;
|
||
}
|
||
.note-delete-btn:hover { opacity: 0.8; color: var(--red); }
|
||
.note-archive-btn {
|
||
background: none; border: none; color: var(--fg); opacity: 0.2; cursor: pointer; padding: 2px; transition: opacity 0.15s;
|
||
}
|
||
|
||
/* Checklist preview — cap height so cards with 30 items don't push the
|
||
grid layout into oblivion; the inner list scrolls inside the card. */
|
||
.note-checklist-preview {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 0;
|
||
min-height: 18px;
|
||
max-height: 240px;
|
||
overflow-y: auto;
|
||
/* Let wheel/touch scrolling continue into the Notes pane when this nested
|
||
checklist is already at its top or bottom. */
|
||
overscroll-behavior-y: auto;
|
||
/* Card has padding-right:30px reserved for the top-corner edit/done/pin
|
||
buttons — but those sit above the checklist, not next to it. Pull the
|
||
checklist back into that reserved gutter so todo text can extend
|
||
further right. The copy button (bottom-right, 28×28) only appears on
|
||
hover; leave just enough room (last row) so it doesn't hide the final
|
||
item's tail. */
|
||
margin-right: -22px;
|
||
padding-right: 4px;
|
||
}
|
||
.note-cl-quickadd {
|
||
/* In flow now (was position:absolute), rendered AFTER the reminder badge
|
||
so the "+ Add item" input sits underneath the reminder instead of
|
||
overlapping it. Slight right inset keeps clear of the bottom-right
|
||
copy button on hover. */
|
||
display: block;
|
||
padding-top: 2px;
|
||
padding-right: 32px;
|
||
margin-top: 2px;
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
transition: opacity 0.15s;
|
||
}
|
||
.note-cl-quickadd-input {
|
||
width: 100%;
|
||
background: transparent;
|
||
border: none;
|
||
border-top: 1px dashed color-mix(in srgb, var(--border) 60%, transparent);
|
||
color: var(--fg);
|
||
font-size: 11px;
|
||
font-family: inherit;
|
||
padding: 4px 2px 2px;
|
||
outline: none;
|
||
opacity: 0.6;
|
||
transition: opacity 0.15s, border-color 0.15s;
|
||
}
|
||
.note-cl-quickadd-input:focus { opacity: 1; border-top-color: var(--border); }
|
||
.note-checkbox {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
font-size: 11px;
|
||
cursor: pointer;
|
||
/* Vertical padding stays 0 so short single-line rows pack tightly.
|
||
Left padding bumped so the dot's hover-scale (1.15x) doesn't clip
|
||
against the card edge. */
|
||
padding: 0 4px 0 8px;
|
||
line-height: 1.25;
|
||
border-radius: 4px;
|
||
user-select: none;
|
||
-webkit-tap-highlight-color: transparent;
|
||
}
|
||
.note-checkbox:hover {
|
||
background: color-mix(in srgb, var(--fg) 5%, transparent);
|
||
}
|
||
.note-check-text { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
||
.note-link {
|
||
color: var(--accent-primary, var(--red));
|
||
text-decoration: underline;
|
||
word-break: break-all;
|
||
}
|
||
.note-link:hover { opacity: 0.8; }
|
||
.note-checkbox-edit, .note-checkbox-rm {
|
||
flex: 0 0 auto;
|
||
background: transparent;
|
||
border: none;
|
||
color: var(--fg);
|
||
opacity: 0;
|
||
cursor: pointer;
|
||
padding: 2px;
|
||
border-radius: 3px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-left: 2px;
|
||
transition: opacity 0.12s, background 0.12s, color 0.12s;
|
||
}
|
||
.note-checkbox-rm:hover { opacity: 1 !important; color: var(--red); background: color-mix(in srgb, var(--red) 12%, transparent); }
|
||
.note-checkbox-edit:hover { opacity: 1 !important; color: var(--accent, var(--blue)); background: color-mix(in srgb, var(--accent, var(--blue)) 12%, transparent); }
|
||
.note-check-text[contenteditable="true"] {
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
outline: 1px solid var(--accent, var(--blue));
|
||
border-radius: 2px;
|
||
cursor: text;
|
||
padding: 0 2px;
|
||
margin: 0 -2px;
|
||
}
|
||
.note-check-dot {
|
||
width: 16px;
|
||
height: 16px;
|
||
border-radius: 50%;
|
||
border: 1.75px solid color-mix(in srgb, var(--fg) 35%, transparent);
|
||
/* Solid panel fill so the dot reads as a tappable target even when an
|
||
image or colored card background sits behind it. */
|
||
background: var(--panel);
|
||
flex-shrink: 0;
|
||
position: relative;
|
||
/* Anchor the hover/active scale to the LEFT edge so the dot grows
|
||
rightward only. Default center origin pushed the scaled dot off the
|
||
left of the card (the parent .note-checklist-preview has overflow:auto
|
||
and clips horizontally as a side-effect of overflow-y:auto). */
|
||
transform-origin: left center;
|
||
transition: background 0.2s, border-color 0.2s, transform 0.15s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
}
|
||
.notes-select-mode .note-checkbox:hover { background: transparent; }
|
||
.notes-select-mode .note-checkbox:hover .note-check-dot { transform: none; border-color: color-mix(in srgb, var(--fg) 35%, transparent); }
|
||
.note-checkbox:hover .note-check-dot {
|
||
border-color: var(--accent);
|
||
transform: scale(1.15);
|
||
}
|
||
.note-checkbox.done .note-check-dot {
|
||
background: var(--accent);
|
||
border-color: var(--accent);
|
||
animation: note-check-pop 0.35s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
}
|
||
.note-check-text {
|
||
transition: opacity 0.25s;
|
||
line-height: 1.3;
|
||
padding-right: 4px;
|
||
word-break: break-word;
|
||
}
|
||
|
||
/* Due date badge */
|
||
.note-due-badge {
|
||
font-size: 10px;
|
||
padding: 1px 6px;
|
||
border-radius: 4px;
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent);
|
||
color: var(--fg);
|
||
opacity: 0.6;
|
||
}
|
||
.note-due-overdue {
|
||
background: color-mix(in srgb, var(--red) 20%, transparent);
|
||
color: var(--red);
|
||
opacity: 1;
|
||
font-weight: 600;
|
||
}
|
||
|
||
/* Color classes — theme-aware via color-mix with --panel */
|
||
.note-color-red { background: color-mix(in srgb, var(--red) 18%, var(--panel)); border-color: color-mix(in srgb, var(--red) 30%, var(--border)); }
|
||
.note-color-orange { background: color-mix(in srgb, #d19a66 18%, var(--panel)); border-color: color-mix(in srgb, #d19a66 30%, var(--border)); }
|
||
.note-color-yellow { background: color-mix(in srgb, var(--hl-string) 18%, var(--panel)); border-color: color-mix(in srgb, var(--hl-string) 30%, var(--border)); }
|
||
.note-color-green { background: color-mix(in srgb, #98c379 18%, var(--panel)); border-color: color-mix(in srgb, #98c379 30%, var(--border)); }
|
||
.note-color-blue { background: color-mix(in srgb, var(--hl-function) 18%, var(--panel)); border-color: color-mix(in srgb, var(--hl-function) 30%, var(--border)); }
|
||
.note-color-purple { background: color-mix(in srgb, var(--hl-keyword) 18%, var(--panel)); border-color: color-mix(in srgb, var(--hl-keyword) 30%, var(--border)); }
|
||
|
||
|
||
/* Standard notes use a small identity palette when no color was selected.
|
||
The variation is deliberately limited to the card tint, top edge, and
|
||
title accent so the notes still read as one collection. */
|
||
.note-card.note-standard {
|
||
border-top-width: 3px;
|
||
background: color-mix(in srgb, var(--note-accent) 7%, var(--panel));
|
||
border-color: color-mix(in srgb, var(--note-accent) 24%, var(--border));
|
||
box-shadow: inset 0 2px 0 0 color-mix(in srgb, var(--note-accent) 72%, transparent);
|
||
}
|
||
.note-card.note-standard:hover {
|
||
background: color-mix(in srgb, var(--note-accent) 11%, var(--panel));
|
||
}
|
||
.note-card.note-standard .note-card-title {
|
||
color: color-mix(in srgb, var(--note-accent) 82%, var(--fg));
|
||
}
|
||
.note-card.note-standard .note-card-label-chip {
|
||
border-color: color-mix(in srgb, var(--note-accent) 38%, var(--border));
|
||
background: color-mix(in srgb, var(--note-accent) 10%, transparent);
|
||
color: color-mix(in srgb, var(--note-accent) 86%, var(--fg));
|
||
}
|
||
|
||
/* Color picker dots */
|
||
.note-color-picker {
|
||
display: flex;
|
||
gap: 5px;
|
||
align-items: center;
|
||
}
|
||
.note-color-dot {
|
||
width: 16px;
|
||
height: 16px;
|
||
border-radius: 50%;
|
||
cursor: pointer;
|
||
border: 2px solid transparent;
|
||
transition: border-color 0.15s, transform 0.15s;
|
||
flex-shrink: 0;
|
||
}
|
||
.note-color-dot:hover { transform: scale(1.15); }
|
||
.note-color-dot.active {
|
||
border-color: var(--fg);
|
||
}
|
||
|
||
/* Note form */
|
||
.note-form {
|
||
background: var(--panel);
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
padding: 12px 14px;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 8px;
|
||
margin-bottom: 10px;
|
||
transition: background 0.2s, border-color 0.2s;
|
||
/* Container so the action buttons can collapse to icons when the note
|
||
card is narrow (see .note-form-collapsible). */
|
||
container-type: inline-size;
|
||
container-name: noteform;
|
||
}
|
||
@media (max-width: 768px) {
|
||
.notes-pane:not(.notes-view-grid) .note-form.note-form-new {
|
||
transform: translateY(6px);
|
||
}
|
||
}
|
||
/* Label sits after the icon in each action button */
|
||
.note-form-text-btn .nft-label { margin-left: 5px; }
|
||
/* Never let the action buttons spill outside the card */
|
||
.note-form-actions-group { flex-wrap: wrap; row-gap: 6px; }
|
||
/* When the note card is narrow, collapse Archive / Delete / Cancel to
|
||
icon-only (their text label hides; tooltip via title= remains). The
|
||
Save/Update button is NOT collapsible — it always keeps its label and
|
||
stays last. */
|
||
@container noteform (max-width: 360px) {
|
||
.note-form-collapsible .nft-label { display: none; }
|
||
.note-form-collapsible { padding-left: 9px; padding-right: 9px; }
|
||
}
|
||
.note-form.note-color-red { background: color-mix(in srgb, var(--red) 18%, var(--panel)) !important; border-color: color-mix(in srgb, var(--red) 30%, var(--border)) !important; }
|
||
.note-form.note-color-orange { background: color-mix(in srgb, #d19a66 18%, var(--panel)) !important; border-color: color-mix(in srgb, #d19a66 30%, var(--border)) !important; }
|
||
.note-form.note-color-yellow { background: color-mix(in srgb, var(--hl-string) 18%, var(--panel)) !important; border-color: color-mix(in srgb, var(--hl-string) 30%, var(--border)) !important; }
|
||
.note-form.note-color-green { background: color-mix(in srgb, #98c379 18%, var(--panel)) !important; border-color: color-mix(in srgb, #98c379 30%, var(--border)) !important; }
|
||
.note-form.note-color-blue { background: color-mix(in srgb, var(--hl-function) 18%, var(--panel)) !important; border-color: color-mix(in srgb, var(--hl-function) 30%, var(--border)) !important; }
|
||
.note-form.note-color-purple { background: color-mix(in srgb, var(--hl-keyword) 18%, var(--panel)) !important; border-color: color-mix(in srgb, var(--hl-keyword) 30%, var(--border)) !important; }
|
||
.note-form-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
padding-right: 0;
|
||
}
|
||
.note-form-header .note-form-remind-btn {
|
||
margin-right: -7px; /* align bell center with X-button column on todo rows */
|
||
position: relative;
|
||
top: -2px;
|
||
}
|
||
.note-form-title {
|
||
flex: 1;
|
||
min-width: 0;
|
||
background: transparent;
|
||
border: none;
|
||
border-bottom: 1px solid var(--border);
|
||
color: var(--fg);
|
||
font-size: 14px;
|
||
font-weight: 600;
|
||
padding: 4px 0;
|
||
outline: none;
|
||
}
|
||
.note-form-title:focus { border-color: var(--fg); }
|
||
.note-form-header { position: relative; }
|
||
.note-form-header .note-form-due {
|
||
position: absolute;
|
||
width: 1px;
|
||
height: 1px;
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
border: 0;
|
||
padding: 0;
|
||
margin: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
}
|
||
.note-form-due-btn {
|
||
flex: 0 0 auto;
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
border-radius: 4px;
|
||
width: 26px;
|
||
height: 26px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
opacity: 0.85;
|
||
transition: opacity 0.15s, border-color 0.15s, background 0.15s;
|
||
}
|
||
.note-form-due-btn:hover { opacity: 1; border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
|
||
.note-form-due-btn.has-date {
|
||
opacity: 1;
|
||
border-style: solid;
|
||
background: color-mix(in srgb, var(--accent) 18%, transparent);
|
||
border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
|
||
}
|
||
|
||
.note-type-toggle {
|
||
display: flex;
|
||
gap: 4px;
|
||
}
|
||
.note-type-btn {
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
font-size: 11px;
|
||
padding: 3px 10px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
opacity: 0.5;
|
||
transition: opacity 0.15s, background 0.15s;
|
||
}
|
||
.note-type-btn.active {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent);
|
||
}
|
||
|
||
.note-form-content {
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
font-size: 12px;
|
||
padding: 8px;
|
||
border-radius: 4px;
|
||
resize: vertical;
|
||
/* Roomier default so editing a note isn't cramped; JS auto-grow takes
|
||
it further as you type. */
|
||
min-height: 120px;
|
||
line-height: 1.5;
|
||
font-family: inherit;
|
||
outline: none;
|
||
}
|
||
.note-form-content:focus { border-color: var(--fg); }
|
||
|
||
.note-form-meta {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.note-form-meta .note-color-picker { gap: 3px; }
|
||
.note-form-actions-group {
|
||
display: flex;
|
||
gap: 6px;
|
||
align-items: center;
|
||
/* Take the full width of the meta row so Archive/Delete can sit on the
|
||
LEFT side and the spacer pushes Cancel + Update to the right edge. */
|
||
flex: 1 1 auto;
|
||
flex-shrink: 0;
|
||
flex-wrap: nowrap;
|
||
}
|
||
.note-form-actions-spacer { flex: 1 1 auto; }
|
||
/* Unified text+icon action button — used for Archive, Delete, Cancel, Update
|
||
so all 4 read as a matched set. Matches the existing .note-form-save
|
||
sizing/padding via the rules at ~25023. */
|
||
.note-form-text-btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: color-mix(in srgb, var(--fg) 6%, transparent);
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
border-radius: 6px;
|
||
padding: 5px 12px;
|
||
font-size: 12px;
|
||
font-family: inherit;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: background 0.12s, border-color 0.12s, color 0.12s;
|
||
white-space: nowrap;
|
||
}
|
||
.note-form-text-btn:hover {
|
||
background: color-mix(in srgb, var(--fg) 14%, transparent);
|
||
border-color: color-mix(in srgb, var(--fg) 28%, var(--border));
|
||
}
|
||
.note-form-text-btn.note-form-save {
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 18%, transparent);
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 45%, var(--border));
|
||
color: var(--accent, var(--red));
|
||
font-weight: 600;
|
||
}
|
||
.note-form-text-btn.note-form-save:hover {
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 28%, transparent);
|
||
}
|
||
.note-form-text-btn.danger:hover {
|
||
background: color-mix(in srgb, var(--red) 14%, transparent);
|
||
border-color: color-mix(in srgb, var(--red) 45%, var(--border));
|
||
color: var(--red);
|
||
}
|
||
.note-form-icon-btn {
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
width: 38px;
|
||
height: 38px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
opacity: 0.65;
|
||
transition: opacity 0.15s, border-color 0.15s, background 0.15s, color 0.15s;
|
||
}
|
||
/* Force the inner icons to render at the inline-attribute size — some other
|
||
stylesheets clamp `svg { width: ... }` globally and that shrinks them. */
|
||
.note-form-icon-btn svg { width: 31px !important; height: 31px !important; }
|
||
.note-form-icon-btn:hover { opacity: 1; border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, transparent); }
|
||
.note-form-delete-btn:hover { color: var(--red); border-color: color-mix(in srgb, var(--red) 50%, var(--border)); background: color-mix(in srgb, var(--red) 8%, transparent); }
|
||
|
||
/* Draw mode — canvas + small toolbar */
|
||
.note-form-draw-wrap {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 6px;
|
||
position: relative;
|
||
}
|
||
/* X overlay on the canvas — appears only when a photo is loaded as the
|
||
background (via _wireCanvas). Clicking it restores the theme surface. */
|
||
.note-form-draw-bg-rm {
|
||
position: absolute;
|
||
top: 8px;
|
||
right: 8px;
|
||
z-index: 3;
|
||
width: 28px;
|
||
height: 28px;
|
||
border: none;
|
||
border-radius: 50%;
|
||
background: rgba(0, 0, 0, 0.6);
|
||
color: #fff;
|
||
font-size: 18px;
|
||
line-height: 1;
|
||
cursor: pointer;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
}
|
||
.note-form-draw-bg-rm:hover { background: rgba(0, 0, 0, 0.8); }
|
||
/* Draw mode hides the note's background-color picker and the standalone
|
||
image preview — they don't make sense alongside a canvas. Uses :has() so
|
||
it kicks in whenever the type-seg flips to .is-draw, in addition to the
|
||
JS that sets display:none. */
|
||
.note-form:has(.note-form-type-seg.is-draw) .note-color-picker,
|
||
.note-form:has(.note-form-type-seg.is-draw) .note-form-image-wrap {
|
||
display: none !important;
|
||
}
|
||
.note-form-canvas {
|
||
background: var(--panel, var(--bg));
|
||
border: 1px solid var(--border);
|
||
border-radius: 6px;
|
||
touch-action: none;
|
||
max-width: 100%;
|
||
cursor: crosshair;
|
||
}
|
||
.note-form-draw-toolbar {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.note-form-draw-tool {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
height: 26px;
|
||
}
|
||
/* Color picker rendered as a flat circular swatch — the native chrome around
|
||
<input type=color> would clash with the rest of the toolbar. */
|
||
.note-form-draw-color {
|
||
appearance: none;
|
||
-webkit-appearance: none;
|
||
width: 24px;
|
||
height: 24px;
|
||
border-radius: 50%;
|
||
border: 1px solid color-mix(in srgb, var(--fg) 25%, transparent);
|
||
background: none;
|
||
cursor: pointer;
|
||
padding: 0;
|
||
overflow: hidden;
|
||
box-sizing: border-box;
|
||
flex: 0 0 24px;
|
||
}
|
||
.note-form-draw-size-wrap { width: 110px; display: inline-flex; align-items: center; }
|
||
.note-form-photo-plus {
|
||
font-size: 16px;
|
||
line-height: 1;
|
||
font-weight: 600;
|
||
opacity: 0.8;
|
||
}
|
||
/* Mirrors .gallery-editor-container input[type=range] — slim pill track that
|
||
grows on interaction, red circular thumb. */
|
||
.note-form-draw-size {
|
||
-webkit-appearance: none;
|
||
appearance: none;
|
||
width: 100%;
|
||
height: 4px;
|
||
background: color-mix(in srgb, var(--fg) 25%, transparent);
|
||
border-radius: 999px;
|
||
accent-color: var(--red);
|
||
cursor: pointer;
|
||
transition: height 0.15s ease;
|
||
}
|
||
/* Brush | Eraser segmented toggle — sliding pill, same recipe as Note/Todo. */
|
||
.note-form-draw-be {
|
||
display: inline-flex;
|
||
height: 32px;
|
||
/* Accent-colored box around the whole control so it's instantly readable
|
||
as "switch is on", and the sliding pill inside indicates which side. */
|
||
border: 2px solid var(--accent);
|
||
border-radius: 10px;
|
||
overflow: hidden;
|
||
position: relative;
|
||
flex-shrink: 0;
|
||
background: color-mix(in srgb, var(--fg) 5%, transparent);
|
||
}
|
||
.note-form-draw-be-btn {
|
||
background: none;
|
||
border: none;
|
||
color: color-mix(in srgb, var(--fg) 50%, transparent);
|
||
cursor: pointer;
|
||
padding: 0 8px;
|
||
width: 34px;
|
||
height: 100%;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: relative;
|
||
z-index: 1;
|
||
transition: color 0.18s;
|
||
}
|
||
.note-form-draw-be-btn:hover { color: var(--fg); }
|
||
/* Active side picks up the theme accent so brush vs eraser is unmistakable. */
|
||
.note-form-draw-be-btn.active { color: var(--accent-primary, var(--red)); }
|
||
|
||
.note-form-draw-text,
|
||
.note-form-draw-line,
|
||
.note-form-draw-circle,
|
||
.note-form-draw-undo {
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
cursor: pointer;
|
||
border-radius: 4px;
|
||
height: 32px;
|
||
width: 34px;
|
||
font-family: inherit;
|
||
font-size: 14px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
opacity: 0.7;
|
||
position: relative;
|
||
transition: opacity 0.15s, border-color 0.15s, background 0.15s;
|
||
}
|
||
.note-form-draw-text { font-weight: 700; font-family: Georgia, serif; font-size: 16px; }
|
||
.note-form-draw-undo.has-undo {
|
||
opacity: 1;
|
||
color: var(--accent-primary, var(--red));
|
||
border-color: color-mix(in srgb, var(--accent-primary, var(--red)) 55%, var(--border));
|
||
background: color-mix(in srgb, var(--accent-primary, var(--red)) 12%, transparent);
|
||
}
|
||
.note-form-draw-undo:disabled {
|
||
opacity: 0.35;
|
||
cursor: default;
|
||
}
|
||
/* Size badge in the bottom-right of T — empty until a size is chosen. */
|
||
.note-form-draw-text-badge {
|
||
position: absolute;
|
||
right: 3px;
|
||
bottom: 1px;
|
||
font-family: inherit;
|
||
font-weight: 700;
|
||
font-size: 8px;
|
||
line-height: 1;
|
||
letter-spacing: 0.3px;
|
||
/* Bare --accent is undefined here, was rendering invisible — use the
|
||
defined accent so the S/M/L size badge actually shows in theme colour. */
|
||
color: var(--accent-primary, var(--red));
|
||
}
|
||
.note-form-draw-shape-badge {
|
||
position: absolute;
|
||
right: 3px;
|
||
bottom: 1px;
|
||
font-family: inherit;
|
||
font-weight: 700;
|
||
font-size: 8px;
|
||
line-height: 1;
|
||
letter-spacing: 0.3px;
|
||
color: var(--accent-primary, var(--red));
|
||
}
|
||
.note-form-draw-text:hover,
|
||
.note-form-draw-line:hover,
|
||
.note-form-draw-circle:hover,
|
||
.note-form-draw-undo:hover {
|
||
opacity: 1;
|
||
border-color: var(--accent);
|
||
background: color-mix(in srgb, var(--accent) 8%, transparent);
|
||
}
|
||
.note-form-draw-text.active,
|
||
.note-form-draw-line.active,
|
||
.note-form-draw-circle.active {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--accent) 18%, transparent);
|
||
color: var(--accent);
|
||
border-color: color-mix(in srgb, var(--accent) 50%, var(--border));
|
||
}
|
||
.note-form-due {
|
||
background: transparent;
|
||
border: 1px dashed color-mix(in srgb, var(--border) 60%, transparent);
|
||
color: var(--fg);
|
||
font-size: 11px;
|
||
padding: 3px 6px;
|
||
border-radius: 4px;
|
||
outline: none;
|
||
opacity: 0.4;
|
||
transition: opacity 0.15s, border-color 0.15s;
|
||
}
|
||
.note-form-due:hover, .note-form-due:focus { opacity: 0.9; border-color: var(--border); }
|
||
|
||
.note-form-actions {
|
||
display: flex;
|
||
gap: 6px;
|
||
justify-content: flex-end;
|
||
}
|
||
.note-form-save,
|
||
.note-form-cancel,
|
||
.note-form-archive {
|
||
background: transparent;
|
||
border: 1px solid var(--border);
|
||
color: var(--fg);
|
||
font-size: 11px;
|
||
padding: 4px 12px;
|
||
border-radius: 4px;
|
||
cursor: pointer;
|
||
transition: background 0.15s;
|
||
}
|
||
.note-form-save { background: color-mix(in srgb, var(--fg) 12%, transparent); font-weight: 600; }
|
||
.note-form-save:hover { background: color-mix(in srgb, var(--fg) 20%, transparent); }
|
||
.note-form-cancel:hover { background: color-mix(in srgb, var(--fg) 8%, transparent); }
|
||
.note-form-archive:hover { background: color-mix(in srgb, var(--fg) 8%, transparent); }
|
||
|
||
/* Checklist inputs in form */
|
||
.note-checklist-inputs {
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 4px;
|
||
}
|
||
.note-cl-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 6px;
|
||
}
|
||
.note-cl-dot {
|
||
width: 8px;
|
||
height: 8px;
|
||
border-radius: 50%;
|
||
border: 1.5px solid color-mix(in srgb, var(--fg) 30%, transparent);
|
||
flex-shrink: 0;
|
||
cursor: pointer;
|
||
transition: all 0.15s;
|
||
}
|
||
.note-cl-dot:hover { border-color: var(--fg); transform: scale(1.2); }
|
||
.note-cl-row.done .note-cl-dot {
|
||
background: var(--accent);
|
||
border-color: var(--accent);
|
||
}
|
||
.note-cl-row.done .note-cl-text {
|
||
opacity: 0.4;
|
||
background: linear-gradient(currentColor, currentColor) no-repeat;
|
||
background-size: 0 1px;
|
||
background-position: 0 calc(50% - 1px);
|
||
animation: cl-strike 0.32s ease-out forwards;
|
||
transition: opacity 0.2s ease;
|
||
}
|
||
/* Draws the strikethrough line left-to-right when the row is marked
|
||
done, instead of snapping it in full-width on the same frame. */
|
||
@keyframes cl-strike {
|
||
to { background-size: 100% 1px; }
|
||
}
|
||
.note-cl-text {
|
||
background: transparent;
|
||
border: none;
|
||
border-bottom: 1px solid var(--border);
|
||
color: var(--fg);
|
||
font-size: 12px;
|
||
padding: 3px 0 3px 3px;
|
||
flex: 1 1 auto;
|
||
width: auto;
|
||
min-width: 0;
|
||
outline: none;
|
||
}
|
||
.note-cl-text:focus { border-color: var(--fg); }
|
||
.note-cl-rm {
|
||
background: none;
|
||
border: none;
|
||
color: var(--fg);
|
||
opacity: 0.3;
|
||
cursor: pointer;
|
||
font-size: 14px;
|
||
padding: 0;
|
||
width: 24px;
|
||
height: 14px;
|
||
flex-shrink: 0;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: flex-end;
|
||
line-height: 1;
|
||
}
|
||
.note-cl-rm:hover { opacity: 0.8; color: var(--red); }
|
||
.note-cl-add {
|
||
background: none;
|
||
border: none;
|
||
color: var(--fg);
|
||
opacity: 0.4;
|
||
cursor: pointer;
|
||
font-size: 11px;
|
||
padding: 4px 0;
|
||
text-align: left;
|
||
}
|
||
|
||
/* ── Calendar ── */
|
||
.cal-modal-content { width:min(680px, 94vw); max-height:88vh; overflow-x:hidden; position:relative; }
|
||
#calendar-modal .cal-modal-content { animation: none; }
|
||
/* Was overflow-y:auto with grid + day-detail flowing naturally. Now uses a
|
||
true splitter layout: the body is a flex column that doesn't scroll
|
||
itself; the grid takes the remaining space and scrolls if needed; the
|
||
day-detail has an explicit height (driven by the splitter drag via
|
||
--cal-detail-h) and shrinks the grid visually as it grows. */
|
||
#cal-body { display:flex; flex-direction:column; gap:8px; overflow:hidden; padding:0; min-height:0; }
|
||
#cal-body > .cal-grid { flex: 1 1 auto; min-height: 120px; overflow-y: auto; overflow-x: hidden; }
|
||
@media (max-width: 768px) {
|
||
/* Let the calendar pane shrink to nothing on mobile so the day-detail
|
||
splitter can be dragged all the way to the top, hiding the calendar
|
||
entirely. Without min-height:0 the grid (or the week-wrap below)
|
||
refuses to shrink past its built-in floor. */
|
||
#cal-body > .cal-grid,
|
||
#cal-body > .cal-wk-wrap {
|
||
min-height: 0;
|
||
max-height: none;
|
||
}
|
||
/* Let the week grid fill the calendar pane and scroll its hours internally
|
||
instead of overflowing #cal-body (which clips it and feels cramped). */
|
||
#cal-body > .cal-wk-wrap {
|
||
flex: 1 1 auto;
|
||
overflow: auto;
|
||
}
|
||
}
|
||
.cal-toolbar { display:flex; align-items:center; gap:6px; margin-bottom:7px; flex-wrap:wrap; line-height:1; max-width:100%; row-gap:6px; }
|
||
|
||
/* Quick-add bar: natural-language event creation. Sits directly under
|
||
the toolbar; focused with `Q`; opens the bespoke form pre-filled. */
|
||
.cal-quickadd-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 8px;
|
||
margin: 0 0 8px;
|
||
padding: 1px 10px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
background: color-mix(in srgb, var(--fg) 3%, var(--bg));
|
||
transition: border-color 0.15s, background 0.15s;
|
||
position: relative;
|
||
}
|
||
/* Two-tone placeholder hint: "Quick add" in accent, the example in grey, both
|
||
at one low opacity. Overlays the (empty) input; hidden once the user types. */
|
||
.cal-quickadd-hint {
|
||
position: absolute;
|
||
left: 10px;
|
||
right: 10px;
|
||
top: 50%;
|
||
transform: translateY(-50%);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
font-size: 12px;
|
||
color: var(--fg);
|
||
opacity: 0.5;
|
||
pointer-events: none;
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
}
|
||
.cal-quickadd-hint .qa-hint-accent { color: var(--accent, var(--red)); }
|
||
/* ↵ enter glyph in the hint — makes it obvious the field submits on Enter. */
|
||
.cal-quickadd-hint .qa-hint-enter { margin-left: auto; flex: 0 0 auto; color: var(--accent, var(--red)); opacity: 0.8; }
|
||
/* Cycling example text fades out before swap, then fades back in. */
|
||
.cal-quickadd-hint .qa-hint-example {
|
||
display: block;
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
font-style: italic;
|
||
transition: opacity 0.18s ease;
|
||
}
|
||
.cal-quickadd-hint .qa-hint-example.qa-hint-fade { opacity: 0; }
|
||
.cal-title-hint {
|
||
position: absolute;
|
||
left: 0;
|
||
top: 50%;
|
||
transform: translateY(calc(-50% - 2px));
|
||
display: none;
|
||
align-items: center;
|
||
gap: 7px;
|
||
font-size: 18px;
|
||
line-height: 1.2;
|
||
white-space: nowrap;
|
||
pointer-events: none;
|
||
color: color-mix(in srgb, var(--fg) 42%, transparent);
|
||
}
|
||
.cal-hero-title:placeholder-shown ~ .cal-title-hint { display: inline-flex; }
|
||
.cal-title-hint .cal-title-enter-ico { color: var(--accent, var(--red)); flex-shrink: 0; }
|
||
/* Pure-CSS toggle: hide the hint as soon as the field has real text (no
|
||
per-keystroke JS, so typing never triggers a re-render / focus loss). */
|
||
.cal-quickadd-input:not(:placeholder-shown) ~ .cal-quickadd-hint { display: none; }
|
||
.cal-quickadd-row:focus-within {
|
||
border-color: color-mix(in srgb, var(--accent, var(--fg)) 55%, var(--border));
|
||
background: color-mix(in srgb, var(--fg) 5%, var(--bg));
|
||
}
|
||
.cal-quickadd-icon {
|
||
color: color-mix(in srgb, var(--accent, var(--fg)) 80%, transparent);
|
||
display: inline-flex;
|
||
align-items: center;
|
||
flex-shrink: 0;
|
||
opacity: 0.7;
|
||
}
|
||
.cal-quickadd-input {
|
||
flex: 1;
|
||
min-width: 0;
|
||
background: transparent;
|
||
border: none;
|
||
outline: none;
|
||
color: var(--fg);
|
||
font-family: inherit;
|
||
font-size: 12px;
|
||
height: 22px;
|
||
padding: 0;
|
||
}
|
||
.cal-quickadd-status {
|
||
font-size: 10px;
|
||
opacity: 0.55;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
.cal-toolbar > *, .cal-toolbar-nav > *, .cal-toolbar-right > * { vertical-align:middle; }
|
||
.cal-toolbar-nav { display:inline-flex; align-items:center; gap:4px; flex-wrap:wrap; }
|
||
.cal-toolbar-right {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: flex-start;
|
||
gap: 6px;
|
||
flex: 1 1 100%;
|
||
width: 100%;
|
||
margin-left: 0;
|
||
margin-top: 6px;
|
||
flex-wrap: wrap;
|
||
}
|
||
.cal-title { font-size:13px; font-weight:600; white-space:nowrap; height:24px; line-height:30px; padding:0 6px; display:inline-block; vertical-align:middle; box-sizing:border-box; }
|
||
.cal-toolbar-clock {
|
||
margin-left: 8px;
|
||
color: var(--accent, var(--red));
|
||
font-size: 11px;
|
||
font-weight: 600;
|
||
font-variant-numeric: tabular-nums;
|
||
}
|
||
button.cal-nav { background:color-mix(in srgb, var(--fg) 6%, transparent); border:1px solid var(--border); color:var(--fg); border-radius:5px; padding:0 8px; height:24px; line-height:22px; cursor:pointer; font-size:11px; font-family:inherit; box-sizing:border-box; vertical-align:middle; }
|
||
button.cal-nav:hover { background:color-mix(in srgb, var(--fg) 12%, transparent); }
|
||
button.cal-nav.cal-toolbar-arrow {
|
||
display: none;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 24px;
|
||
padding: 0;
|
||
border: 1px solid color-mix(in srgb, var(--fg) 14%, transparent);
|
||
border-radius: 50%;
|
||
background: color-mix(in srgb, var(--bg) 86%, var(--fg) 14%);
|
||
color: var(--accent, var(--red));
|
||
box-shadow: 0 6px 18px rgba(0,0,0,0.16);
|
||
font-size: 18px;
|
||
line-height: 1;
|
||
opacity: 0.84;
|
||
}
|
||
.cal-toolbar-arrow-glyph {
|
||
position: relative;
|
||
top: -1px;
|
||
line-height: 1;
|
||
}
|
||
@media (max-width: 768px) {
|
||
button.cal-nav.cal-toolbar-arrow { display: inline-flex !important; }
|
||
.cal-toolbar-nav {
|
||
flex: 1 1 100%;
|
||
width: 100%;
|
||
min-width: 0;
|
||
}
|
||
#cal-next { margin-left: auto; }
|
||
}
|
||
.cal-week-start-toggle {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 0;
|
||
width: max-content;
|
||
padding: 0;
|
||
height: 24px;
|
||
box-sizing: border-box;
|
||
border: 1px solid var(--border);
|
||
border-radius: 5px;
|
||
background: color-mix(in srgb, var(--fg) 4%, transparent);
|
||
}
|
||
.cal-week-start-btn {
|
||
box-sizing: border-box;
|
||
height: 22px !important;
|
||
min-height: 22px !important;
|
||
margin-top: 0 !important;
|
||
padding: 0 7px;
|
||
border: 1px solid transparent;
|
||
border-radius: 4px;
|
||
background: transparent;
|
||
color: color-mix(in srgb, var(--fg) 68%, transparent);
|
||
cursor: pointer;
|
||
font-family: inherit;
|
||
font-size: 10px;
|
||
line-height: 20px;
|
||
transition: background 0.12s ease, border-color 0.12s ease, color 0.12s ease;
|
||
}
|
||
.cal-settings-actions {
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
width: 100%;
|
||
}
|
||
#cal-settings-panel .cal-week-start-toggle {
|
||
display: flex;
|
||
margin-left: auto;
|
||
}
|
||
.cal-settings-sync-status {
|
||
position: relative;
|
||
top: 2px;
|
||
font-size: 11px;
|
||
opacity: 0.6;
|
||
}
|
||
.cal-settings-sync-status.is-error {
|
||
color: var(--red);
|
||
opacity: 1;
|
||
}
|
||
.cal-week-start-btn:hover {
|
||
color: var(--fg);
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
}
|
||
.cal-week-start-btn.active,
|
||
.cal-week-start-btn.active:hover {
|
||
color: var(--fg);
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 40%, var(--border));
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 16%, transparent);
|
||
}
|
||
.cal-side-nav {
|
||
position: absolute;
|
||
top: var(--cal-side-nav-y, 50%);
|
||
transform: translateY(-50%);
|
||
width: 32px;
|
||
height: 32px;
|
||
border-radius: 50%;
|
||
border: 1px solid color-mix(in srgb, var(--fg) 14%, transparent);
|
||
background: color-mix(in srgb, var(--bg) 86%, var(--fg) 14%);
|
||
color: var(--accent, var(--red));
|
||
box-shadow: 0 6px 18px rgba(0,0,0,0.16);
|
||
cursor: pointer;
|
||
z-index: 6;
|
||
opacity: 0;
|
||
pointer-events: none;
|
||
font-family: inherit;
|
||
font-size: 24px;
|
||
line-height: 28px;
|
||
padding: 0 0 3px;
|
||
transition: opacity 0.12s ease, background 0.12s ease, transform 0.12s ease;
|
||
}
|
||
.cal-modal-content:hover .cal-side-nav,
|
||
.cal-side-nav:focus-visible {
|
||
opacity: 0.84;
|
||
pointer-events: auto;
|
||
}
|
||
.cal-side-nav:hover {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--bg) 76%, var(--fg) 24%);
|
||
transform: translateY(-50%) scale(1.04);
|
||
}
|
||
button.cal-today-btn { font-size:10px; opacity:0.5; }
|
||
button.cal-add-btn { background:var(--accent); color:#fff; border:none; border-radius:50%; width:24px; height:24px; line-height:22px; font-size:18px; cursor:pointer; flex-shrink:0; padding:0; box-sizing:border-box; font-family:inherit; vertical-align:middle; text-align:center; }
|
||
button.cal-add-btn.cal-add-btn-text {
|
||
width:auto; min-width:0;
|
||
background: color-mix(in srgb, var(--fg) 8%, transparent);
|
||
color: var(--fg);
|
||
border: 1px solid var(--border);
|
||
border-radius: 12px;
|
||
padding: 0 10px 0 6px;
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 4px;
|
||
height: 24px;
|
||
line-height: 1;
|
||
margin-top: 0;
|
||
transition: background 0.15s, border-color 0.15s;
|
||
}
|
||
button.cal-add-btn.cal-add-btn-text:hover {
|
||
background: color-mix(in srgb, var(--fg) 14%, transparent);
|
||
border-color: var(--accent);
|
||
opacity: 1;
|
||
}
|
||
.cal-add-plus {
|
||
font-size: 16px;
|
||
line-height: 1;
|
||
color: var(--accent, var(--red));
|
||
font-weight: 500;
|
||
display: inline-block;
|
||
transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1);
|
||
padding-bottom: 2px;
|
||
}
|
||
button.cal-add-btn.cal-add-btn-text:hover .cal-add-plus {
|
||
transform: rotate(180deg);
|
||
}
|
||
.cal-add-label { font-size:11px; font-weight:600; line-height:1; opacity:0.85; }
|
||
/* Small variant of the toolbar's +New button. Inherits the .cal-add-btn-text
|
||
styles (pill with "+" + "New" + spring-rotate on the +), so the
|
||
animation is identical. Just shrunk a bit. */
|
||
button.cal-add-btn.cal-add-btn-text.cal-add-btn-sm {
|
||
height: 20px;
|
||
border-radius: 10px;
|
||
/* At rest: tight, equal padding around the "+" so it sits centred
|
||
with no trailing gap. On hover the right pad and the flex gap grow
|
||
to make room for the revealed "New". */
|
||
padding: 0 5px;
|
||
gap: 0;
|
||
transition: padding 0.25s ease, gap 0.25s ease, background 0.15s, border-color 0.15s;
|
||
}
|
||
/* Don't touch .cal-add-plus on the small variant — the toolbar +New is
|
||
the reference and we want the same rotation centre / motion. The label
|
||
is shrunk and hidden until hover so the pill is compact at rest. */
|
||
button.cal-add-btn.cal-add-btn-text.cal-add-btn-sm .cal-add-label {
|
||
font-size: 10px;
|
||
max-width: 0;
|
||
margin-left: 0;
|
||
opacity: 0;
|
||
overflow: hidden;
|
||
white-space: nowrap;
|
||
transition: max-width 0.25s ease, opacity 0.18s ease, margin-left 0.25s ease;
|
||
}
|
||
button.cal-add-btn.cal-add-btn-text.cal-add-btn-sm:hover .cal-add-label {
|
||
max-width: 40px;
|
||
margin-left: 3px;
|
||
opacity: 0.85;
|
||
}
|
||
.cal-add-btn:hover { opacity:0.85; }
|
||
|
||
/* Mobile: bump the +New pill and the +/- zoom buttons up to a tap-friendly
|
||
size so they're easy to hit with a thumb. */
|
||
@media (max-width: 768px) {
|
||
/* Toolbar +New (relocated by JS into the quickadd row on mobile) */
|
||
button.cal-add-btn.cal-add-btn-text {
|
||
height: 36px;
|
||
border-radius: 18px;
|
||
padding: 0 14px 0 12px;
|
||
gap: 6px;
|
||
flex-shrink: 0;
|
||
}
|
||
/* Day-detail +New: just a "+" on mobile — drop the label entirely. */
|
||
button.cal-add-btn.cal-add-btn-text.cal-add-btn-sm {
|
||
width: 28px;
|
||
height: 28px;
|
||
border-radius: 50%;
|
||
padding: 0;
|
||
gap: 0;
|
||
justify-content: center;
|
||
}
|
||
button.cal-add-btn.cal-add-btn-text.cal-add-btn-sm .cal-add-label {
|
||
display: none;
|
||
}
|
||
button.cal-add-btn.cal-add-btn-text.cal-add-btn-sm .cal-add-plus {
|
||
font-size: 18px;
|
||
padding-bottom: 0;
|
||
}
|
||
.cal-add-plus { font-size: 22px; padding-bottom: 1px; }
|
||
.cal-add-label { font-size: 13px; }
|
||
.cal-wk-zoom {
|
||
width: 36px;
|
||
height: 36px;
|
||
font-size: 20px;
|
||
border-radius: 8px;
|
||
opacity: 0.85;
|
||
}
|
||
/* The +New button sits as a sibling of the quickadd row inside a flex
|
||
wrapper, so it's clearly outside the input's bordered box. The row
|
||
itself keeps its own styling. */
|
||
.cal-quickadd-wrap {
|
||
display: flex;
|
||
align-items: stretch;
|
||
gap: 8px;
|
||
margin: 0 0 8px;
|
||
}
|
||
.cal-quickadd-wrap > #cal-quickadd-row {
|
||
flex: 1;
|
||
min-width: 0;
|
||
margin: 0;
|
||
}
|
||
.cal-quickadd-wrap > .cal-add-btn-text {
|
||
align-self: stretch;
|
||
flex-shrink: 0;
|
||
}
|
||
/* Nudge the "+" glyph up one pixel on the round day-detail button so it
|
||
sits visually centred inside the circle. */
|
||
button.cal-add-btn.cal-add-btn-text.cal-add-btn-sm .cal-add-plus {
|
||
transform: translateY(-1px);
|
||
}
|
||
/* Event form: bigger Create / Cancel buttons so they're easy to tap. */
|
||
.cal-form-actions button.cal-btn {
|
||
height: 44px;
|
||
padding: 0 20px;
|
||
font-size: 14px;
|
||
border-radius: 8px;
|
||
min-width: 96px;
|
||
}
|
||
/* Left-align the day/month + tags row in the day-detail panel and
|
||
the calendar/category chip row so they sit flush against the
|
||
left edge on a narrow screen. */
|
||
.cal-detail-header {
|
||
justify-content: flex-start;
|
||
gap: 12px;
|
||
}
|
||
.cal-filters {
|
||
justify-content: flex-start;
|
||
}
|
||
}
|
||
|
||
/* Refresh button spin — driven by JS toggling .cal-syncing on the button.
|
||
transform-box + transform-origin keep the rotation pivoted at the SVG's
|
||
own centre so it spins in place instead of orbiting / drifting up. */
|
||
#cal-sync svg,
|
||
#email-lib-refresh-btn svg { display: block; transform-box: fill-box; transform-origin: 50% 50%; }
|
||
/* Brief checkmark flash after a refresh completes. Lasts ~900ms in JS;
|
||
the small bounce + accent color give a clear "done" cue. */
|
||
#cal-sync.cal-sync-done svg,
|
||
#email-lib-refresh-btn.email-lib-refresh-done svg {
|
||
color: var(--accent, #2ea043);
|
||
animation: refresh-check-pop 0.32s ease-out;
|
||
}
|
||
@keyframes refresh-check-pop {
|
||
0% { transform: scale(0.55); opacity: 0.4; }
|
||
60% { transform: scale(1.18); opacity: 1; }
|
||
100% { transform: scale(1); opacity: 1; }
|
||
}
|
||
#cal-sync.cal-syncing svg,
|
||
#email-lib-refresh-btn.email-lib-refreshing svg { animation: spin 0.6s linear infinite; }
|
||
.email-undone-toggle.active,
|
||
.email-attach-toggle.active {
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 18%, transparent);
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 50%, transparent);
|
||
color: var(--accent, var(--red));
|
||
font-weight: 600;
|
||
}
|
||
/* Hide the gallery-style reader-btn labels on desktop — only the mobile
|
||
@media block re-displays them under each icon. Desktop keeps compact
|
||
icon-only reader buttons. */
|
||
.reader-btn-label {
|
||
display: inline-block;
|
||
font-size: 9px;
|
||
font-weight: 500;
|
||
line-height: 1;
|
||
letter-spacing: 0.02em;
|
||
white-space: nowrap;
|
||
opacity: 0.85;
|
||
}
|
||
|
||
/* Inline attachment-filter toggle nested inside the search input. The
|
||
input has padding-right:34px set inline so its text doesn't slide
|
||
under the button. */
|
||
.email-search-wrap { display: flex; align-items: center; }
|
||
/* Keep the email search input and the adjacent "Select" button identical in
|
||
height regardless of base-vs-mobile overrides — pin both explicitly. */
|
||
.email-search-row .memory-search-input {
|
||
height: 32px;
|
||
min-height: 32px;
|
||
box-sizing: border-box;
|
||
}
|
||
.email-search-row .email-search-select-btn {
|
||
height: 32px;
|
||
min-height: 32px;
|
||
box-sizing: border-box;
|
||
margin-top: 6px;
|
||
flex-shrink: 0;
|
||
}
|
||
/* Select moved into the dropdown row — dock it to the right and match the
|
||
selects' vertical nudge (.memory-sort-select has top:3px). */
|
||
.memory-category-filters .email-filter-select-btn,
|
||
.memory-category-filters .email-filter-refresh-btn {
|
||
position: relative;
|
||
top: 3px;
|
||
flex-shrink: 0;
|
||
}
|
||
.memory-category-filters .email-filter-refresh-btn {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 0 8px;
|
||
}
|
||
.memory-category-filters .email-reminders-clear-btn {
|
||
position: relative;
|
||
top: -2px;
|
||
flex-shrink: 0;
|
||
}
|
||
.email-attach-toggle-inline {
|
||
position: absolute !important;
|
||
right: 4px !important;
|
||
top: 50%;
|
||
transform: translateY(calc(-50% - 5px));
|
||
width: 26px !important;
|
||
height: 26px !important;
|
||
padding: 0 !important;
|
||
display: inline-flex !important;
|
||
align-items: center !important;
|
||
justify-content: center !important;
|
||
border-radius: 6px !important;
|
||
background: transparent !important;
|
||
border: none !important;
|
||
opacity: 0.55;
|
||
}
|
||
.email-attach-toggle-inline:hover {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent) !important;
|
||
}
|
||
.email-attach-toggle-inline.active {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 16%, transparent) !important;
|
||
color: var(--accent, var(--red)) !important;
|
||
}
|
||
/* Inline undone-toggle nested inside the search input, sits LEFT of the
|
||
attach toggle. Same visual treatment. */
|
||
.email-undone-toggle-inline {
|
||
position: absolute !important;
|
||
right: 34px !important;
|
||
top: 50%;
|
||
transform: translateY(calc(-50% - 3px));
|
||
width: 26px !important;
|
||
height: 26px !important;
|
||
padding: 0 !important;
|
||
display: inline-flex !important;
|
||
align-items: center !important;
|
||
justify-content: center !important;
|
||
border-radius: 6px !important;
|
||
background: transparent !important;
|
||
border: none !important;
|
||
opacity: 0.55;
|
||
}
|
||
.email-reminder-toggle-inline {
|
||
position: absolute !important;
|
||
right: 64px !important;
|
||
top: 50%;
|
||
transform: translateY(calc(-50% - 3px));
|
||
width: 26px !important;
|
||
height: 26px !important;
|
||
padding: 0 !important;
|
||
display: inline-flex !important;
|
||
align-items: center !important;
|
||
justify-content: center !important;
|
||
border-radius: 6px !important;
|
||
background: transparent !important;
|
||
border: none !important;
|
||
opacity: 0.55;
|
||
}
|
||
.email-reminder-toggle-inline:hover {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent) !important;
|
||
}
|
||
.email-reminder-toggle-inline.active {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 16%, transparent) !important;
|
||
color: var(--accent, var(--red)) !important;
|
||
}
|
||
.email-undone-toggle-inline:hover {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--fg) 10%, transparent) !important;
|
||
}
|
||
.email-undone-toggle-inline.active {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 16%, transparent) !important;
|
||
color: var(--accent, var(--red)) !important;
|
||
}
|
||
/* Round (circular) toggles in the search bar, matching the app's default icon
|
||
buttons. Always fully visible (not dimmed until hover). */
|
||
.email-attach-toggle-inline,
|
||
.email-undone-toggle-inline,
|
||
.email-reminder-toggle-inline { border-radius: 50% !important; opacity: 1 !important; }
|
||
.email-search-options-btn {
|
||
position: absolute !important;
|
||
right: 5px !important;
|
||
top: 50% !important;
|
||
transform: translateY(calc(-50% - 5px));
|
||
width: 26px !important;
|
||
height: 26px !important;
|
||
min-width: 26px !important;
|
||
padding: 0 !important;
|
||
display: inline-flex !important;
|
||
align-items: center !important;
|
||
justify-content: center !important;
|
||
border-radius: 999px !important;
|
||
background: transparent !important;
|
||
border: 0 !important;
|
||
color: inherit !important;
|
||
opacity: 0.7;
|
||
z-index: 2;
|
||
}
|
||
.email-search-options-btn:hover,
|
||
.email-search-options-btn.active {
|
||
opacity: 1;
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 14%, transparent) !important;
|
||
color: var(--accent, var(--red)) !important;
|
||
}
|
||
.email-search-options-menu {
|
||
position: absolute;
|
||
top: calc(100% + 2px);
|
||
right: 0;
|
||
z-index: 75;
|
||
min-width: 140px;
|
||
padding: 4px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 8px;
|
||
background: var(--panel, var(--bg));
|
||
box-shadow: 0 8px 24px rgba(0,0,0,0.3);
|
||
}
|
||
.email-search-options-title {
|
||
padding: 5px 9px 4px;
|
||
color: var(--fg-muted, var(--fg));
|
||
font-size: 10px;
|
||
font-weight: 600;
|
||
opacity: 0.65;
|
||
white-space: nowrap;
|
||
}
|
||
.email-search-options-menu button {
|
||
width: 100%;
|
||
border: 0;
|
||
background: transparent;
|
||
color: var(--fg);
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
height: auto;
|
||
min-height: 0;
|
||
padding: 6px 8px;
|
||
border-radius: 8px;
|
||
font-family: inherit;
|
||
font-size: 11px;
|
||
font-weight: 400;
|
||
line-height: normal;
|
||
letter-spacing: normal;
|
||
text-align: left;
|
||
cursor: pointer;
|
||
}
|
||
.email-search-options-menu button:hover,
|
||
.email-search-options-menu button.active {
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 10%, transparent);
|
||
color: var(--accent, var(--red));
|
||
}
|
||
.email-search-option-icon {
|
||
width: 14px;
|
||
height: 14px;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex: 0 0 auto;
|
||
opacity: 0.5;
|
||
}
|
||
.email-search-option-icon svg { width: 14px; height: 14px; }
|
||
.email-search-date-panel {
|
||
width: 220px;
|
||
padding: 6px 7px 5px;
|
||
border-top: 1px solid color-mix(in srgb, var(--border) 65%, transparent);
|
||
}
|
||
.email-search-date-panel input {
|
||
width: 100%;
|
||
height: 26px;
|
||
box-sizing: border-box;
|
||
padding: 2px 6px;
|
||
border: 1px solid var(--border);
|
||
border-radius: 5px;
|
||
outline: none;
|
||
background: var(--bg);
|
||
color: var(--fg);
|
||
font: inherit;
|
||
}
|
||
.email-search-date-panel input:focus { border-color: var(--accent, var(--red)); }
|
||
.email-search-date-actions { display: flex; justify-content: flex-end; gap: 5px; }
|
||
.email-search-options-menu .email-search-date-actions [data-email-date-apply] {
|
||
color: var(--accent, var(--red));
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 12%, transparent);
|
||
}
|
||
@media (max-width: 768px) {
|
||
.email-search-options-menu button {
|
||
min-height: 44px;
|
||
padding: 12px 12px !important;
|
||
font-size: 14px !important;
|
||
gap: 10px !important;
|
||
}
|
||
.email-search-options-menu .email-search-option-icon {
|
||
width: 18px;
|
||
height: 18px;
|
||
}
|
||
.email-search-options-menu .email-search-option-icon svg {
|
||
width: 16px;
|
||
height: 16px;
|
||
}
|
||
}
|
||
/* Mobile: enlarge the icons inside the inline search-bar toggles
|
||
(done / attachment / reminders) — buttons themselves stay the same,
|
||
only the SVG glyph scales up so it's tappable + visible. */
|
||
@media (max-width: 768px) {
|
||
.email-filter-btn {
|
||
height: 30px;
|
||
min-height: 30px;
|
||
font-size: 12px;
|
||
top: -6px;
|
||
padding: 0 9px;
|
||
}
|
||
.email-folder-btn {
|
||
top: -4px;
|
||
}
|
||
|
||
#email-lib-folder,
|
||
.memory-category-filters .email-filter-select-btn,
|
||
.memory-category-filters .email-filter-refresh-btn,
|
||
.memory-category-filters .email-filter-settings-btn {
|
||
height: 30px !important;
|
||
min-height: 30px !important;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.memory-category-filters .email-filter-refresh-btn,
|
||
.memory-category-filters .email-filter-settings-btn {
|
||
width: 30px;
|
||
padding: 0 !important;
|
||
}
|
||
.memory-category-filters .email-filter-settings-btn > svg {
|
||
width: 15px;
|
||
height: 15px;
|
||
}
|
||
|
||
.email-search-row .memory-search-input {
|
||
height: 38px;
|
||
min-height: 38px;
|
||
}
|
||
|
||
#email-lib-chip-bar {
|
||
padding-right: 42px !important;
|
||
padding-left: 30px !important;
|
||
gap: 5px !important;
|
||
}
|
||
|
||
.email-lib-chip-bar-icon {
|
||
width: 14px !important;
|
||
height: 14px !important;
|
||
left: 9px !important;
|
||
}
|
||
|
||
#email-lib-search {
|
||
font-size: 14px !important;
|
||
min-width: 88px !important;
|
||
top: 0 !important;
|
||
}
|
||
|
||
#email-lib-search::placeholder {
|
||
font-size: 14px !important;
|
||
}
|
||
|
||
#email-lib-chip-bar.has-email-lib-pills #email-lib-search {
|
||
min-width: 24px !important;
|
||
flex: 1 1 24px !important;
|
||
}
|
||
|
||
.email-lib-pill {
|
||
min-height: 24px !important;
|
||
height: 24px !important;
|
||
line-height: 24px !important;
|
||
font-size: 12px !important;
|
||
padding: 0 6px 0 8px !important;
|
||
max-width: 180px !important;
|
||
}
|
||
|
||
.email-lib-pill svg {
|
||
width: 14px !important;
|
||
height: 14px !important;
|
||
}
|
||
|
||
.email-lib-pill-x {
|
||
font-size: 13px !important;
|
||
top: -4.5px !important;
|
||
}
|
||
|
||
.email-lib-filter-pill {
|
||
min-height: 24px !important;
|
||
height: 24px !important;
|
||
line-height: 24px !important;
|
||
gap: 4px !important;
|
||
padding: 0 6px 0 8px !important;
|
||
}
|
||
|
||
.email-lib-filter-pill .email-lib-pill-icon {
|
||
width: 17px !important;
|
||
height: 17px !important;
|
||
}
|
||
|
||
.email-lib-filter-pill svg {
|
||
width: 18px !important;
|
||
height: 18px !important;
|
||
}
|
||
|
||
.email-lib-filter-pill .email-lib-pill-x {
|
||
font-size: 13px !important;
|
||
top: -4.5px !important;
|
||
}
|
||
|
||
.email-tags-toggle-inline {
|
||
right: 6px;
|
||
height: 28px !important;
|
||
min-width: 42px;
|
||
padding: 0 8px !important;
|
||
font-size: 11px !important;
|
||
transform: translateY(calc(-50% - 3px));
|
||
}
|
||
|
||
.email-attach-toggle-inline {
|
||
right: 56px !important;
|
||
width: 32px !important;
|
||
height: 32px !important;
|
||
transform: translateY(calc(-50% - 3px));
|
||
}
|
||
|
||
.email-undone-toggle-inline {
|
||
right: 92px !important;
|
||
width: 32px !important;
|
||
height: 32px !important;
|
||
transform: translateY(calc(-50% - 3px));
|
||
}
|
||
|
||
.email-reminder-toggle-inline {
|
||
right: 128px !important;
|
||
width: 32px !important;
|
||
height: 32px !important;
|
||
transform: translateY(calc(-50% - 3px));
|
||
}
|
||
|
||
.email-attach-toggle-inline svg,
|
||
.email-undone-toggle-inline svg,
|
||
.email-reminder-toggle-inline svg,
|
||
.email-filter-refresh-btn svg {
|
||
width: 16px !important;
|
||
height: 16px !important;
|
||
}
|
||
}
|
||
.email-accounts-row {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10px;
|
||
padding: 0 0 6px;
|
||
}
|
||
.email-accounts-row .doclib-desc { flex-shrink: 0; }
|
||
/* Only the direct-child compose button gets pushed right; nested chips
|
||
inside #email-lib-accounts pack to the left as normal flex items. */
|
||
.email-accounts-row > .memory-toolbar-btn { flex-shrink: 0; margin-left: auto; }
|
||
.email-account-chip {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
gap: 5px;
|
||
}
|
||
.email-account-chip.email-account-has-unread {
|
||
border-color: color-mix(in srgb, var(--accent, var(--red)) 42%, var(--border));
|
||
background: color-mix(in srgb, var(--accent, var(--red)) 10%, transparent);
|
||
color: color-mix(in srgb, var(--accent, var(--red)) 86%, var(--fg));
|
||
}
|
||
.email-account-unread-dot {
|
||
width: 6px;
|
||
height: 6px;
|
||
border-radius: 999px;
|
||
background: var(--accent, var(--red));
|
||
box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent, var(--red)) 14%, transparent);
|
||
flex: 0 0 auto;
|
||
}
|
||
.email-account-chip-label {
|
||
min-width: 0;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
}
|
||
.email-account-unread-count {
|
||
font-size: 9px;
|
||
line-height: 1;
|
||
font-weight: 700;
|
||
color: var(--accent, var(--red));
|
||
opacity: 0.9;
|
||
position: relative;
|
||
top: 0;
|
||
}
|
||
.email-account-away-label {
|
||
color: var(--accent, var(--red));
|
||
font-size: 9px;
|
||
font-weight: 700;
|
||
line-height: 1;
|
||
flex: 0 0 auto;
|
||
}
|
||
.email-accounts-loading-whirlpool {
|
||
width: 14px;
|
||
height: 14px;
|
||
margin: 3px 4px 0 1px;
|
||
display: inline-flex;
|
||
flex: 0 0 auto;
|
||
}
|
||
.email-accounts-loading-label {
|
||
font-size: 10px;
|
||
opacity: 0.55;
|
||
position: relative;
|
||
top: 2px;
|
||
white-space: nowrap;
|
||
}
|
||
.email-loading-with-label {
|
||
/* Fill the email list grid so the spinner lands in the middle of the
|
||
email window rather than the top of the empty list section. */
|
||
position: absolute;
|
||
inset: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 8px;
|
||
text-align: center;
|
||
pointer-events: none;
|
||
}
|
||
.date-section-header {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 7px;
|
||
padding: 8px 9px 4px;
|
||
color: color-mix(in srgb, var(--fg) 58%, transparent);
|
||
font-size: 10px;
|
||
font-weight: 700;
|
||
letter-spacing: 0;
|
||
line-height: 1.2;
|
||
text-transform: uppercase;
|
||
user-select: none;
|
||
}
|
||
.date-section-header::after {
|
||
content: '';
|
||
flex: 1 1 auto;
|
||
height: 1px;
|
||
background: color-mix(in srgb, var(--border) 72%, transparent);
|
||
}
|
||
#session-list .date-section-header {
|
||
padding-left: 10px;
|
||
padding-right: 8px;
|
||
cursor: pointer;
|
||
}
|
||
#session-list .date-section-header.collapsed {
|
||
color: color-mix(in srgb, var(--fg) 36%, transparent);
|
||
}
|
||
#session-list .date-section-header.collapsed::after {
|
||
opacity: 0.45;
|
||
}
|
||
#session-list .date-section-header:focus-visible {
|
||
outline: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
|
||
outline-offset: 2px;
|
||
border-radius: 5px;
|
||
}
|
||
/* Bootstrap row shown while the session list hydrates, and on load failure.
|
||
Reads as a normal list row but is not selectable. */
|
||
.session-list-bootstrap {
|
||
cursor: default;
|
||
pointer-events: none;
|
||
}
|
||
#email-lib-grid .date-section-header {
|
||
padding: 10px 5px 3px;
|
||
}
|
||
#email-lib-modal .email-lib-sync-status {
|
||
flex: 0 0 auto;
|
||
min-height: 14px;
|
||
padding: 1px 4px 0;
|
||
font-size: 10.5px;
|
||
line-height: 1.2;
|
||
text-align: center;
|
||
opacity: 0.58;
|
||
color: var(--muted-text, currentColor);
|
||
white-space: nowrap;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
position: relative;
|
||
top: 4px;
|
||
}
|