mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-06 06:52:20 +02:00
Last step of splitting static/style.css by panel. This moves the cookbook, deep research, memory and settings rules that can move into static/css/cookbook-research-memory-settings.css. After the three steps style.css still holds the shell and every rule whose move would change the cascade, which on this branch is most of the file. Eager ordered links, verbatim moves, no rendering change.
963 lines
32 KiB
CSS
963 lines
32 KiB
CSS
/* 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 <link> 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
|
||
* 4. static/css/cookbook-research-memory-settings.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 <input type="color"> 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;
|
||
}
|