mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 15:02:20 +02:00
style-part-01..08 were arbitrary 6,000-line cuts, so the names said nothing and a reader had no way to guess which file held a rule. The original stylesheet turns out to be roughly area-grouped already, so cutting where the content changes rather than every 6,000 lines produces boundaries worth naming. Classifying every top-level rule by selector prefix and smoothing over a 40-rule window gives 17 stable runs: agent-chat, compare, memory, documents, admin-settings, skills, gallery, cookbook, tasks, image-editor, email, notes, calendar, research. The numeric prefix stays because load order is load-bearing, and it also disambiguates the areas that appear twice: the original interleaves, and merging non-adjacent blocks of the same area would reorder the cascade. The names describe where a file sits, not a claim that it holds every rule for that area or only rules for it. The header in each file says so, because that is the misreading this naming invites. Reconstruction was checked against lab's style.css before rewriting: identical after whitespace normalisation, all 47,528 lines accounted for. The computed style baseline still reproduces exactly.
4063 lines
118 KiB
CSS
4063 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-checkbox-agent {
|
||
display: inline-flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
width: 14px;
|
||
height: 14px;
|
||
padding: 0;
|
||
margin: 0 1px;
|
||
border: 0;
|
||
background: transparent;
|
||
color: var(--accent, var(--red));
|
||
box-shadow: none;
|
||
cursor: pointer;
|
||
opacity: 0;
|
||
transition: opacity 0.12s, color 0.12s;
|
||
}
|
||
.note-checkbox-agent:hover {
|
||
background: transparent;
|
||
opacity: 1 !important;
|
||
}
|
||
.note-checkbox-agent.is-agent-stream-complete {
|
||
color: #50fa7b;
|
||
opacity: 0.9;
|
||
}
|
||
.note-checkbox-agent svg {
|
||
display: block;
|
||
}
|
||
|
||
.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;
|
||
}
|