/* Document library and editor, image gallery, image editor. * * Split out of style.css for maintainability, not for performance: this file * is loaded eagerly from index.html immediately after style.css, so the rules * land in the cascade in exactly the order they had inside the single file. * Nothing here is lazy-loaded. * * LOAD ORDER IS PART OF THE CONTRACT. The tags in static/index.html and * the PRECACHE list in static/sw.js must both list the stylesheets in this * order: * 1. static/style.css * 2. static/css/documents-gallery-editor.css * 3. static/css/email-calendar-notes-tasks.css * * Rules were moved verbatim. A rule stays in style.css when its selector group * covers more than one panel, when the class is shared design language used by * modules outside this panel, or when moving it would change which of two * equally specific rules wins. */ /* Document library search-term highlight — clear, high-contrast. */ mark.doclib-search-hl { background: var(--accent, #e8a830); color: var(--bg, #1a1a1a); border-radius: 2px; padding: 0 2px; font-weight: 600; } /* Research bulk bar — right-align the action buttons (keep All + count on the left). Cancel now lives on the Select toggle, so Archive anchors. */ #doclib-research-bulk #doclib-research-bulk-archive { margin-left: auto; } /* Drafts bulk bar defaults to justify-content:flex-end (whole row hugs the right). Reset it so All + count sit on the left and only the action button is pushed right — matching every other bulk bar. */ #gallery-editor-drafts-bulk { justify-content: flex-start; } .doc-divider.doc-divider-handle-idle .doc-divider-collapse { opacity: 0; pointer-events: none; } .doc-divider:hover .doc-divider-collapse { opacity: 0.92; } /* Smooth entrance — slide in from the left + fade up so it doesn't snap into place when fullscreen activates. The chevron's vertical centering uses translateY(-50%), so the animation has to keep that part. */ @keyframes doc-fs-chevron-in { from { opacity: 0; transform: translateY(-50%) translateX(-18px); } to { opacity: 0.85; transform: translateY(-50%) translateX(0); } } .doc-editor-pane.doc-pane-leaving { pointer-events: none; } @keyframes doc-pane-leave { from { transform: translateX(0); opacity: 1; } to { transform: translateX(24px); opacity: 0; } } .doc-tab-scroll.is-at-left { -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 18px), transparent 100%); mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 18px), transparent 100%); } .doc-tab-scroll.is-at-right { -webkit-mask-image: linear-gradient(to right, transparent 0, #000 18px, #000 100%); mask-image: linear-gradient(to right, transparent 0, #000 18px, #000 100%); } .doc-tab-scroll.is-at-left.is-at-right { -webkit-mask-image: none; mask-image: none; } .doc-tab-scroll::-webkit-scrollbar { display: none; } #doc-tab-right, #doc-tab-left { position: relative; top: 3px; } /* Ghost tab shown in the empty state (new, not-yet-saved document). Muted + italic so it reads as a placeholder, and non-interactive so clicking it can't hit the tab handlers (it has no data-doc-id). */ .doc-tab.doc-tab-ghost { /* New, not-yet-saved doc tab. It already carries .active, so it shows the accent underline like any active tab — that's all we want. The old dashed border + italic/dim "pending" styling looked weird, so they're gone. */ pointer-events: none; } .doc-tab.active::after { content: ''; position: absolute; bottom: 0; left: 0; right: 0; height: 2px; background: var(--red); } @keyframes doc-stream-pulse { 0%, 100% { opacity: 0.5; } 50% { opacity: 1; } } .doc-updated-flash { animation: doc-update-flash 0.6s ease-out; } @keyframes doc-update-flash { 0% { box-shadow: inset 0 0 0 2px var(--accent); } 100% { box-shadow: inset 0 0 0 2px transparent; } } .doc-langpicker-trigger.doc-langpicker-email-compact { width: 28px; min-width: 28px; padding: 0 0 0 6px; justify-content: flex-start; gap: 0; } /* The "T" icon stays centered in the fixed-size button so it grows symmetrically (from the center) instead of jumping around as the size changes. The S/M/L letter is pinned to the bottom-right corner, absolutely positioned so it never shifts the icon either. */ #doc-fontsize-btn { transform: translateY(-1px); } #doc-fontsize-btn svg { flex: 0 0 auto; } .doc-overflow-wrapper { order: -1; } .doc-overflow-toggle { opacity: 0.5; } .doc-md-toolbar.md-preview-active, .doc-md-toolbar.md-write-active { overflow: visible; -webkit-mask-image: none; mask-image: none; z-index: 3; } .doc-md-toolbar #doc-render-view-toggle .md-view-opt { height: 28px; } /* Some toolbar buttons baked in svg{opacity:0.7} via inline styles, which compounded with the button's own opacity to look almost invisible. Force the inline svg opacity back to 1 inside the toolbar — the button wrapper's 0.85 is the only fade we need. */ .doc-md-toolbar button svg[style*="opacity"] { opacity: 1 !important; } /* No black tap-flash / focus background on the doc toolbar + tab controls — they're icon buttons, the opacity change is the only feedback we want. */ .doc-md-toolbar button, .doc-tab-new, .doc-tab-arrow, .doc-tab-play { -webkit-tap-highlight-color: transparent; } /* Pull the icon down toward the "sign" label so they read as one unit. */ #doc-pdf-add-sign-btn svg { transform: translateY(2px); } .doc-outline-count { opacity: 0.48; font-variant-numeric: tabular-nums; } .doc-outline-target { animation: doc-outline-target-flash 1.05s ease-out; } @keyframes doc-outline-target-flash { 0%, 28% { background-color: color-mix(in srgb, var(--accent, var(--red)) 24%, transparent); } 100% { background-color: transparent; } } .doc-rich-slash-count { opacity: 0.48; font-variant-numeric: tabular-nums; } .doc-rich-slash-label { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } /* Find marks live in the syntax-highlight overlay, which sits at z-index:0 under a transparent textarea — so they're always visible through the text layer. The previous color-mix variant could compute to near-invisible on themes with dark/desaturated accents; forced solid colors + !important so it ALWAYS pops. */ mark.doc-find-mark { background: var(--accent) !important; color: var(--bg) !important; border-radius: 2px; padding: 0 1px; box-shadow: 0 0 0 1px var(--accent); } .doc-editor-highlight::-webkit-scrollbar { display: none; } /* Arrow pointing toward the editor */ .doc-suggestion-card::before { content: ''; position: absolute; top: 16px; left: -10px; width: 18px; height: 18px; background: var(--panel); border-left: 2px solid var(--accent); border-bottom: 2px solid var(--accent); transform: rotate(45deg); z-index: 1; } .doc-suggestion-close::before { content: ''; width: 10px; height: 10px; display: block; background: currentColor; -webkit-mask: url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 10 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2 2L8 8M8 2L2 8' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; mask: url("data:image/svg+xml,%3Csvg width='10' height='10' viewBox='0 0 10 10' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M2 2L8 8M8 2L2 8' stroke='black' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E") center / contain no-repeat; } .doc-suggestion-accept:hover { filter: brightness(1.15); } .doc-editor-wrap.animating::after { content: ''; position: absolute; top: 6px; right: 8px; width: 6px; height: 6px; border-radius: 50%; background: var(--red); animation: doc-pulse 0.8s ease-in-out infinite; z-index: 3; pointer-events: none; } @keyframes doc-pulse { 0%, 100% { opacity: 0.3; transform: scale(0.8); } 50% { opacity: 1; transform: scale(1.2); } } .doc-diff-content { } @media (hover: none) { .doc-preview-hover-edit { opacity: 1; pointer-events: auto; transform: none; } } #doclib-research-search { position: relative; top: -1.5px; } /* Restore sits on the right of the Delete in archive previews. */ .doclib-chat-restore-btn { margin-left: auto; } /* Delete + Archive pin to the left of the actions row; the `margin-right: auto` on the last left-side button (Archive) pushes Copy + Open to the right. Delete sits furthest left. */ .doclib-chat-archive-btn { margin-right: auto; } @keyframes doclib-expand { from { opacity: 0.5; transform: translateY(4px); } to { opacity: 1; transform: translateY(0); } } /* Hide the section headers while a card is expanded (full-screen reader). */ .doclib-grid:has(.doclib-card-expanded) > .skills-section-header { display: none; } .skill-card:not(.doclib-card-expanded) .skill-card-tags { display: none; } .doclib-chip-scroll-frame > .chip-scroll-strip:empty { display: none; } .skill-card.doclib-card-expanded .skill-kebab-btn { display: none; } .skill-card.doclib-card-expanded .skill-chevron-up { display: inline-flex; } /* Size the expanded skill card to its content (footer sits right under the preview) but cap at the modal height so a long SKILL.md scrolls instead of overflowing. The inherited `.doclib-card-expanded { flex: 1 }` forced the card to fill the whole modal, which left a big empty void between a short skill's text and the footer. */ .skill-card.doclib-card-expanded { flex: 0 1 auto !important; max-height: 100% !important; } .doclib-inline-load-more::before { display: none; } #doclib-selected-count { color: color-mix(in srgb, var(--fg) 50%, transparent); font-size: 10px; } .gallery-modal-content:has(#gallery-editor-container[style*="flex"]) .gallery-editor-landing { width: 100%; min-height: 0; box-sizing: border-box; } #gallery-bulk-count, #gallery-editor-drafts-bulk-count { top: -1px !important; } #gallery-select-btn { position: relative; top: 4px !important; font-size: 12px; padding: 10px 11px 12px; min-width: 76px; justify-content: center; } #gallery-albums-search { top: -4px; } #gallery-albums-select-btn { top: -4px !important; } #gallery-bulk-delete, #gallery-albums-bulk-delete, #gallery-editor-drafts-bulk-delete { color: var(--color-error, #f44) !important; } .gallery-detail-image video { max-width: 100%; max-height: 70vh; display: block; } .gallery-card:hover .gallery-fav-btn { opacity: 1; } .gallery-card:hover .gallery-dl-btn { opacity: 1; } @media (hover: none) { .gallery-dl-btn { opacity: 0.55; } } /* Space the user's tag chips off the "add tag" input below them. */ #gallery-user-tag-chips { margin-bottom: 4px; } .gallery-user-chip:hover .gallery-tag-x { opacity: 0.85; } @keyframes gallery-skeleton-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } } .gallery-card:hover .gallery-card-overlay, .gallery-card.gallery-card-focus .gallery-card-overlay { opacity: 1; } /* Strong accent ring on the whole photo when selected. Paint it as a foreground pseudo-element so the thumbnail cannot cover the feedback. */ .gallery-card:has(.gallery-select-dot.selected) { border-color: var(--accent-primary, var(--red)); } .gallery-card:has(.gallery-select-dot.selected)::after { content: ''; position: absolute; inset: 0; z-index: 3; border: 3px solid var(--accent-primary, var(--red)); border-radius: inherit; box-sizing: border-box; pointer-events: none; } .gallery-card:has(.gallery-select-dot.selected) .gallery-select-dot { z-index: 4; } .gallery-detail-action.danger:hover { border-color: var(--color-error, #e55); } .gallery-detail-image img, .gallery-detail-image video, .gallery-detail-img-frame img, .gallery-detail-img-frame video { max-width: 100%; max-height: 100%; border-radius: 6px; object-fit: contain; display: block; } .gallery-detail-image:hover .gallery-detail-nav { opacity: 0.85; } @media (min-width: 769px) { .gallery-modal-content:has(#gallery-detail[style*="flex"]) { height: 92vh; } .gallery-modal-content:has(#gallery-detail[style*="flex"]) > .modal-body, .gallery-images-container:has(> #gallery-detail[style*="flex"]), #gallery-images-container:has(> #gallery-detail[style*="flex"]) > #gallery-detail { height: 100%; min-height: 0; } } .gallery-detail-image:hover .gallery-detail-rotate { opacity: 0.85; } .gallery-detail-nav-disabled { opacity: 0 !important; pointer-events: none; } @media (hover: none) { .gallery-detail-nav { opacity: 0.7; } } .gallery-detail-inline-link:hover { text-decoration: underline; } .gallery-detail-section { margin-bottom: 12px; } .gallery-tag-input-wrap .gallery-tag-input { padding-right: 24px; } .gallery-name-wrap:focus-within .gallery-name-enter { display: inline-flex; } .gallery-name-wrap:focus-within .gallery-detail-name-input { padding-right: 28px; } .gallery-album-cover img { width: 100%; height: 100%; object-fit: cover; display: block; } .gallery-editor-landing p { margin: 0; opacity: 0.6; font-size: 13px; max-width: 320px; } .gallery-editor-landing-actions .gallery-select-btn:hover { opacity: 1; } /* Saved-project selection uses the same bulk-bar rhythm as Photos. */ #gallery-editor-drafts-bulk { margin-top: 0; } .gallery-editor-draft-card.selected { outline: 2px solid var(--accent, var(--red)); outline-offset: -2px; } .gallery-editor-draft-card.select-mode { cursor: pointer; } .gallery-drafts-view-toggle button svg { display: block; position: static; transform: none; } .gallery-editor-drafts-grid.list-view { display: flex; flex-direction: column; gap: 4px; } .gallery-editor-drafts-grid.list-view .gallery-editor-draft-card { display: grid; grid-template-columns: 44px minmax(0, 1fr) 24px; align-items: center; gap: 9px; min-height: 48px; padding: 4px 6px; } .gallery-editor-drafts-grid.list-view .gallery-editor-draft-delete-x { display: none; } .gallery-editor-draft-card:focus-visible { outline: 2px solid var(--accent, var(--red)); outline-offset: 2px; } .gallery-editor-draft-card:hover .gallery-editor-draft-delete { opacity: 1; } .ge-topbar.ge-topbar-menu-open { z-index: 10006; } /* Toolbar (left) */ @keyframes ge-layer-action-flash { from { box-shadow: inset 0 0 0 2px var(--red); background-color: color-mix(in srgb, var(--red) 24%, transparent); } to { box-shadow: inset 0 0 0 2px transparent; } } .ge-layer-action-flash { animation: ge-layer-action-flash 650ms ease-out; } @media (prefers-reduced-motion: reduce) { .ge-layer-action-flash { animation-duration: 1ms; } } .ge-tool-btn .ge-tool-label { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } .ge-tool-btn:hover::after { content: ''; position: absolute; inset: 0 2px 0 -2px; background: color-mix(in srgb, var(--fg) 8%, transparent); border-radius: 6px; z-index: -1; pointer-events: none; } .ge-tool-btn.active::before { content: ''; position: absolute; /* Highlight pill shifted 2 px left of the button bounds so it sits under the icon + label (which are also nudged left). Same total width as before — just slid. */ inset: 0 2px 0 -2px; background: color-mix(in srgb, var(--red) 18%, transparent); border-radius: 6px; z-index: 0; pointer-events: none; } .ge-btn-ai:hover .ge-btn-ai-mark { opacity: 1; } .ge-tool-btn.has-selection .ge-tool-clear { display: inline-flex; } .ge-canvas-area.ge-rulers-visible { padding: 18px 0 0 18px; box-sizing: border-box; } .ge-main-canvas { touch-action: none; } .ge-canvas-area.ge-pan-ready, .ge-canvas-area.ge-pan-ready .ge-main-canvas { cursor: grab !important; } .ge-canvas-area.ge-panning, .ge-canvas-area.ge-panning .ge-main-canvas { cursor: grabbing !important; user-select: none; } .ge-ai-command-collapsed .ge-ai-command-toggle { display: inline-flex; } .ge-ai-command-collapsed .ge-ai-command-head, .ge-ai-command-collapsed .ge-ai-command-form, .ge-ai-command-collapsed .ge-ai-command-suggestions, .ge-ai-command-collapsed .ge-ai-command-status { display: none; } @media (hover: none) { .ge-ai-command-collapsed { bottom: 8px; opacity: 0.72; } } .ge-ai-command-clear[hidden] { display: none; } .ge-ai-command-busy .ge-ai-command-run::after { content: ''; width: 12px; height: 12px; border: 2px solid color-mix(in srgb, #fff 42%, transparent); border-top-color: #fff; border-radius: 50%; animation: ge-ai-command-spin 0.7s linear infinite; } @keyframes ge-ai-command-spin { to { transform: rotate(360deg); } } .ge-ai-command-suggestions[hidden] { display: none; } .ge-ai-command-status:empty { display: none; } /* Each shortcut row: key chips + description. The key chips are usually chained with "+" so we use a small horizontal gap between siblings, plus a larger left margin on the trailing text via the kbd:last-of-type sibling rule — keeps "Ctrl+Shift+D Deselect" readable instead of glued. */ .ge-shortcuts-col > div { display: flex; align-items: center; flex-wrap: wrap; gap: 4px; padding: 4px 0; opacity: 0.85; line-height: 1.5; } /* Push the description text away from the last kbd by adding margin to any text node that follows a kbd. Flex+wrap handles wrap on narrow. */ .ge-shortcuts-col > div kbd + kbd { margin-left: 0; } .ge-shortcuts-col > div kbd:last-of-type { margin-right: 6px; } .ge-shortcuts-card kbd, #ge-shortcuts-popover kbd { display: inline-flex; align-items: center; justify-content: center; font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 10px; font-weight: 600; padding: 2px 6px; border: 1px solid color-mix(in srgb, var(--accent, #cc6a3a) 55%, transparent); border-bottom-width: 2px; border-radius: 4px; background: color-mix(in srgb, var(--accent, #cc6a3a) 14%, transparent); color: var(--accent, #cc6a3a); min-width: 18px; line-height: 1.4; } .ge-quick-mask-bar[hidden] { display: none; } .ge-marquee-dimensions[hidden] { display: none; } .ge-layer-geometry-section .ge-section-title { display: flex; align-items: center; gap: 6px; min-width: 0; } .ge-layer-geometry-grid input::-webkit-inner-spin-button, .ge-layer-geometry-grid input::-webkit-outer-spin-button { appearance: none; } #ge-brush-controls select, #ge-eyedropper-section select { height: 26px; min-width: 0; border: 1px solid var(--border); border-radius: 4px; background: var(--bg); color: var(--fg); font: inherit; } .ge-gradient-extra-stop .ge-text-field { min-width: 0; } .ge-shape-gradient-add-stop { align-self: flex-start; } .ge-text-font-field { grid-column: span 1; } #ge-text-rasterize { align-self: flex-end; } .ge-shape-types .ge-text-toggle { flex: 1 1 25%; } #ge-shape-rasterize { align-self: flex-end; } .ge-direct-text-editor:focus { outline: 1px solid color-mix(in srgb, var(--red) 55%, transparent); } .ge-transform-popup.ge-transform-popup-dragging .ge-transform-popup-head { cursor: grabbing; } /* Force the title to take all middle space so the [_][×] cluster stays pinned to the right edge. */ .ge-transform-popup-head .ge-adj-title { flex: 1 1 auto !important; } .ge-transform-popup-minimised .ge-transform-popup-body, .ge-transform-popup-minimised .ge-transform-popup-hint { display: none; } .ge-transform-popup-input::-webkit-outer-spin-button, .ge-transform-popup-input::-webkit-inner-spin-button { -webkit-appearance: none; appearance: none; margin: 0; display: none; } .ge-transform-position-field .ge-transform-popup-input { width: 68px; } .ge-transform-input-locked { opacity: 0.4; cursor: not-allowed; } .ge-transform-input-locked + .ge-transform-spin { display: none; } .ge-transform-preserve-field[hidden] { display: none; } /* Hide the controls wrapper entirely when every tool section inside is hidden — otherwise the padding + border draws an empty band above the layers panel even when no tool needs sliders/buttons. */ .ge-controls:not(:has(> *:not([style*="display: none"]):not([style*="display:none"]))) { display: none; } /* Strip the native chrome (border + padding around the swatch in each engine) so the visible color fills the circle. */ .ge-color-picker::-webkit-color-swatch-wrapper { padding: 0; } .ge-color-picker::-webkit-color-swatch { border: none; border-radius: 50%; } .ge-color-picker::-moz-color-swatch { border: none; border-radius: 50%; } .ge-color-picker.cp-swatch-input::selection { background: transparent; } .ge-size-slider::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 9px; height: 9px; border-radius: 50%; background: var(--red); border: none; cursor: pointer; } .ge-size-slider:hover::-webkit-slider-thumb, .ge-size-slider.is-using::-webkit-slider-thumb, .ge-size-slider:active::-webkit-slider-thumb { width: 16px; height: 16px; } .ge-size-slider::-moz-range-thumb { width: 9px; height: 9px; border-radius: 50%; background: var(--red); border: none; cursor: pointer; } .ge-size-slider:hover::-moz-range-thumb, .ge-size-slider.is-using::-moz-range-thumb, .ge-size-slider:active::-moz-range-thumb { width: 16px; height: 16px; } .ge-eraser-row label > span[id$="-label"]:hover { background: color-mix(in srgb, var(--fg) 10%, transparent); } .ge-eraser-row > span[id$="-label"].ge-slider-value:hover { background: color-mix(in srgb, var(--fg) 10%, transparent); opacity: 1; } .ge-merge-menu[hidden] { display: none; } /* Inpaint Brush size slider — slightly larger thumb than the rest of the panel since it's the primary interactive control. */ #ge-inpaint-brush-slider::-webkit-slider-thumb { width: 12px; height: 12px; } #ge-inpaint-brush-slider:hover::-webkit-slider-thumb, #ge-inpaint-brush-slider.is-using::-webkit-slider-thumb, #ge-inpaint-brush-slider:active::-webkit-slider-thumb { width: 18px; height: 18px; } #ge-inpaint-brush-slider::-moz-range-thumb { width: 12px; height: 12px; } #ge-inpaint-brush-slider:hover::-moz-range-thumb, #ge-inpaint-brush-slider.is-using::-moz-range-thumb, #ge-inpaint-brush-slider:active::-moz-range-thumb { width: 18px; height: 18px; } .ge-adj-popup .ge-adj-title { flex: 1 1 auto; } .ge-adj-popup .ge-adj-head:active { cursor: grabbing; } .ge-fx-dock-label { overflow: hidden; text-overflow: ellipsis; } .ge-history-head:active { cursor: grabbing; } @keyframes ge-canvas-spin { to { transform: rotate(360deg); } } .ge-inline-swatch::-webkit-color-swatch-wrapper { padding: 0; } .ge-inline-swatch::-webkit-color-swatch { border: none; border-radius: 2px; } .ge-inline-swatch::-moz-color-swatch { border: none; border-radius: 2px; } .ge-adj-cb-row .ge-adj-cb-dot { width: 10px; height: 10px; border-radius: 50%; display: inline-block; flex-shrink: 0; box-shadow: 0 0 0 1px color-mix(in srgb, var(--fg) 20%, transparent); } .ge-adj-cb-tone-picker { margin: 0 0 8px; } .ge-adj-hist-details { margin-bottom: 8px; } .ge-adj-hist-details > summary { font-size: 11px; color: var(--fg-muted); cursor: pointer; padding: 4px 0; list-style: none; user-select: none; } .ge-adj-hist-details > summary::-webkit-details-marker { display: none; } .ge-adj-hist-details > summary::before { content: '▸ '; display: inline-block; transition: transform 0.12s; } .ge-mask-sub-item.active .ge-layer-name { opacity: 1; font-style: normal; font-weight: 600; } .ge-mask-sub-item.active .ge-mask-inline-thumb { opacity: 1; } /* Opacity preview — translucent disk */ #ge-eraser-preview-opacity { opacity: 0.5; } /* Flow preview — dotted ring to suggest discrete stamping */ #ge-eraser-preview-flow { background: none; border: 2px dotted var(--fg); opacity: 0.7; width: 12px; height: 12px; } /* Softness preview — blurred edge */ #ge-eraser-preview-softness { background: radial-gradient(circle, var(--fg) 0%, var(--fg) 30%, transparent 75%); opacity: 0.7; } /* Wand feather preview — solid disk that visibly softens at its edge as the user drags the Feather slider. JS sets --feather-blur. */ #ge-wand-feather-preview { filter: blur(var(--feather-blur, 0px)); opacity: 0.8; } .ge-mask-vis-btn.visible:hover { opacity: 1; } .ge-topbar .ge-btn, .ge-topbar .ge-btn-sm { text-transform: uppercase; } .ge-stacked-btn .ge-stacked-glyph { font-size: 14px; line-height: 1; display: inline-flex; align-items: center; justify-content: center; height: 14px; } .ge-layer-selection-bar[hidden] { display: none; } .ge-layer-selection-bar .ge-icon-btn:hover { opacity: 1; } .ge-save-menu[hidden] { display: none; } .ge-stacked-btn .ge-stacked-glyph .ge-save-state-icon[hidden] { display: none !important; } .ge-stacked-btn .ge-stacked-glyph .ge-save-state-icon:not([hidden]) { display: block; } .ge-resize-menu[hidden], .ge-edge-menu[hidden], .ge-view-menu[hidden], .ge-image-menu[hidden], .ge-selection-menu[hidden], .ge-filter-menu[hidden] { display: none; } .ge-selection-save-row .ge-icon-btn { width: 28px; height: 27px; } .ge-export-matte .ge-color-picker { width: 28px; height: 28px; } .ge-export-footer > div { display: flex; gap: 6px; } .ge-export-estimate { opacity: 0.6; font-variant-numeric: tabular-nums; } .ge-canvas-prompt-custom-label { margin-top: 14px; } .ge-canvas-anchor::after { content: ''; position: absolute; inset: 6px; border-radius: 1px; background: color-mix(in srgb, var(--fg) 38%, transparent); } .ge-canvas-anchor.active::after { background: var(--red); } .ge-canvas-lock-option input { accent-color: var(--red); } .ge-canvas-preset-icon { margin-bottom: 1px; } /* Center grip dots so the handle reads as draggable. */ .ge-panel-resize::before { content: ''; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: 2px; height: 24px; background: color-mix(in srgb, var(--fg) 35%, transparent); border-radius: 2px; } .ge-slider-bubble[hidden] { display: none; } /* Tail pointing DOWN at the slider (bubble sits above). */ .ge-slider-bubble::after { content: ''; position: absolute; left: 50%; bottom: -4px; transform: translateX(-50%); width: 8px; height: 8px; background: var(--red); clip-path: polygon(0 0, 100% 0, 50% 100%); } .ge-layer-thumb canvas { display: block; border-radius: 4px; } .ge-layers-merge-menu[hidden] { display: none; } .ge-layer-item:not(.active) .ge-layer-inline-thumb { opacity: 0.86; } .ge-layer-opacity-row .ge-layer-lock-btn { flex: 0 0 24px; width: 24px; } .ge-layers-list > .ge-layer-item:not(.ge-adj-sub-item):not(.ge-mask-sub-item) > .ge-layer-controls { grid-column: 1 / -1; grid-row: 3; } .ge-layer-item.grouped { padding-left: calc(20px + (var(--layer-group-depth, 1) - 1) * 14px); } .ge-layer-vis.visible:hover { opacity: 1; } .ge-layer-item.clipped .ge-layer-name { display: flex; align-items: center; gap: 4px; } /* Shrink the slider thumb — the native default is ~16-20 px which looks massive next to a 3 px track in the compact layer row. */ .ge-layer-opacity::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 9px; height: 9px; border-radius: 50%; background: var(--red); border: none; cursor: pointer; /* Match the track: shrink only after a 0.5s grace period. */ transition: width 0.12s ease 0.5s, height 0.12s ease 0.5s; } .ge-layer-opacity::-moz-range-thumb { width: 9px; height: 9px; border-radius: 50%; background: var(--red); border: none; cursor: pointer; transition: width 0.12s ease 0.5s, height 0.12s ease 0.5s; } .ge-layer-opacity:hover::-webkit-slider-thumb, .ge-layer-opacity:active::-webkit-slider-thumb, .ge-layer-opacity.dragging::-webkit-slider-thumb, .ge-layer-opacity:hover::-moz-range-thumb, .ge-layer-opacity:active::-moz-range-thumb, .ge-layer-opacity.dragging::-moz-range-thumb { transition: width 0.12s ease 0s, height 0.12s ease 0s; } .ge-layer-controls .ge-mask-density { width: 26px; min-width: 24px; height: 4px; flex: 0 0 26px; align-self: center; } .ge-mask-properties > summary { width: 30px; height: 30px; display: inline-flex; align-items: center; justify-content: center; list-style: none; cursor: pointer; color: var(--fg); border: 1px solid transparent; border-radius: 4px; } .ge-mask-properties > summary::-webkit-details-marker { display: none; } .ge-mask-sub-item:has(.ge-mask-properties[open]) { position: relative; z-index: 50; } .ge-mask-property-row output { text-align: right; opacity: .7; } .ge-layers-list > .ge-layer-item:not(.ge-adj-sub-item):not(.ge-mask-sub-item) > .ge-layer-controls, .ge-layers-list > .ge-layer-group-row > .ge-layer-controls { display: none; } .ge-layer-tools[hidden] { display: none; } .ge-layer-tools .ge-layer-btn { min-width: 26px; } @media (max-width: 700px) { /* Preserve the compact grip while giving long-press reorder a usable touch target. */ .ge-layer-drag { width: 28px; min-height: 30px; margin-left: -6px; margin-right: -4px; } } .ge-layer-align-menu .ge-layer-lock-option { grid-template-columns: minmax(0, 1fr); } .ge-crop-apply input[type="number"]::-webkit-outer-spin-button, .ge-crop-apply input[type="number"]::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; } .ge-brush-cursor::after { content: ''; position: absolute; top: 50%; left: 50%; width: 3px; height: 3px; margin: -1.5px 0 0 -1.5px; background: rgba(255,255,255,0.8); border-radius: 50%; } /* Marks remain solid so they pop through the otherwise-invisible overlay; outlined extra-bright for the currently-focused one. */ body.doc-find-active mark.doc-find-mark { background: var(--accent) !important; color: var(--bg) !important; } body.doc-find-active mark.doc-find-mark.current { background: var(--accent) !important; box-shadow: 0 0 0 2px var(--fg) !important; outline: 1px solid var(--fg) !important; } .doc-email-header:not(.doc-email-header-collapsed) .doc-email-collapse-summary { opacity: 0.45; } .doc-email-header.doc-email-header-collapsed { gap: 0; padding-top: 5px; padding-bottom: 5px; } .doc-email-header.doc-email-header-collapsed .doc-email-fields { display: none; } /* Documents footer — X + Undo stay on the LEFT, Copy/Export group pushed to the RIGHT. Email composer keeps its original flex-end layout. */ #doc-actions-footer { justify-content: flex-start; } .doc-save-button[data-save-state="dirty"] .doc-save-state-dirty, .doc-save-button[data-save-state="saving"] .doc-save-state-saving, .doc-save-button[data-save-state="saved"] .doc-save-state-saved, .doc-save-button[data-save-state="error"] .doc-save-state-error { display: block; } .doc-save-button[data-save-state="saving"] .doc-save-state-saving { animation: doc-save-spin 800ms linear infinite; } @keyframes doc-save-spin { to { transform: rotate(360deg); } } @media (prefers-reduced-motion: reduce) { .doc-save-button[data-save-state="saving"] .doc-save-state-saving { animation: none; } } .doc-stats-popover[hidden] { display: none; } .doc-stats-row strong { font-weight: 600; font-variant-numeric: tabular-nums; } .doc-email-richbody:empty::before { content: "Write your email\2026"; opacity: 0.4; pointer-events: none; } @media (max-width: 768px) { .doc-rich-empty-import { top: 106px; } } .doc-email-richbody.richtext-mode:empty::before { content: "Start writing\2026"; } .doc-email-richbody.richtext-mode ul, .doc-email-richbody.richtext-mode ol { padding-left: 1.75em; } .doc-email-richbody.richtext-mode ul:not(.rich-checklist) > li, .doc-email-richbody.richtext-mode ol > li { padding-inline-start: 0.2em; } .doc-email-richbody.richtext-mode pre code { padding: 0; border: 0; background: transparent; font: inherit; } .doc-email-richbody figure.richtext-image .richtext-image-caption { margin-top: 6px; max-width: 100%; color: color-mix(in srgb, var(--fg) 68%, transparent); font-size: 0.84em; line-height: 1.4; text-align: center; overflow-wrap: anywhere; } .doc-email-richbody a { color: var(--accent, #4af); } .doc-email-richbody blockquote { margin: 6px 0; padding-left: 10px; border-left: 3px solid var(--border); opacity: 0.8; } .doc-email-richbody p { margin: 0.5em 0; } #doc-email-more-btn svg { opacity: 0.8; } @media (min-width: 769px) { #doc-email-header #doc-email-collapse-btn.doc-email-collapse-btn { display: none !important; } #doc-email-header.doc-email-header-collapsed .doc-email-fields { display: flex !important; } } .doclib-section-title-icon { width: 14px; height: 14px; margin-right: 6px; color: var(--accent, var(--red)); vertical-align: -2px; }