/* 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 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 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,");
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
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;
}