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