Automerge backed Markdown editor for the Atmosphere
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189/* Mobile formatting toolbar - appears below editor on narrow viewports */
/* Toolbar height: 32px buttons + 1px border-top = 33px. * Used to bound the action-row shadows; layout reserves the measured height. */:root { --formatting-toolbar-height: 33px;}
.formatting-toolbar { position: fixed; isolation: isolate; left: var(--ribbon-width); right: 0; bottom: 0; background-color: var(--bg-secondary); border-top: 1px solid var(--border-color); overflow: hidden; z-index: 99;}
.formatting-toolbar__scroller { display: flex; align-items: center; gap: 1px; /* No vertical padding: 32px buttons fill the toolbar height edge-to-edge * so hover/active fills are flush with the bar. Horizontal padding only. */ padding-left: 0.5rem; padding-right: 0.5rem; overflow-x: auto; -webkit-overflow-scrolling: touch;}
.formatting-toolbar__scroll-shadow { position: absolute; top: 0; /* Bound the shadow to the 32px action row. */ height: calc(var(--formatting-toolbar-height) - 1px); width: 28px; pointer-events: none; opacity: 0; transition: opacity 0.15s ease-out; z-index: 1;}
.formatting-toolbar__scroll-shadow--left { left: 0; background: linear-gradient(to right, rgba(0, 0, 0, 0.42), transparent);}
.formatting-toolbar__scroll-shadow--right { right: 0; background: linear-gradient(to left, rgba(0, 0, 0, 0.42), transparent);}
.formatting-toolbar[data-scroll-shadow-left="true"] .formatting-toolbar__scroll-shadow--left { opacity: 1;}
.formatting-toolbar[data-scroll-shadow-right="true"] .formatting-toolbar__scroll-shadow--right { opacity: 1;}
@media (max-width: 767px) { /* Follow the ribbon's width animation when the sidebar mode changes. */ .formatting-toolbar { transition: left 0.15s ease-out; }}
/* Mobile is always enabled. Respect the user's desktop visibility setting. */@media (min-width: 768px) { .formatting-toolbar:not([data-show-desktop="true"]) { display: none; }
/* Desktop with toolbar visible: * * 1. Offset left edge to avoid overlapping the ribbon and sidebar. * --toolbar-left-offset is computed in AppShell.tsx and set as an * inline CSS variable on .app-shell: * - 0px when ribbon is hidden * - var(--ribbon-width) when only ribbon is visible * - var(--ribbon-width) + sidebarWidth when both are visible * * 2. Offset right edge to avoid overlapping the right panel. * --toolbar-right-offset is set to rightPanelWidth when expanded, * 0px when collapsed. * * 3. Keep the toolbar pinned to the viewport bottom like mobile, but * constrain it horizontally to the editor lane so it clears the * ribbon/sidebar/right-panel chrome. * * The `transition` matches the 0.15s ease-out used by .app-shell-sidebar * and .app-shell-right-panel (AppShell.css). Without this, the toolbar * snaps to its final position instantly while the panels animate, briefly * re-introducing the original overlap bug for ~150ms. * * The transition is suppressed during sidebar/right-panel resize drags * (when .app-shell has data-resizing="true") so the toolbar tracks the * cursor in real time instead of lagging 150ms behind. * * `prefers-reduced-motion` is honored by the rule below. * * Bug fix: #213 — formatting toolbar overlaps settings icon on desktop. */ .formatting-toolbar[data-show-desktop="true"] { left: var(--toolbar-left-offset, 0px); right: var(--toolbar-right-offset, 0px); width: auto; bottom: 0; transition: left 0.15s ease-out, right 0.15s ease-out; }
/* Suppress transition during resize drag — the toolbar should track * the sidebar edge in real time, not lag behind it. ResizeHandle.tsx * sets data-resizing="true" on the active handle during pointermove. */ .app-shell:has(.resize-handle[data-resizing="true"]) .formatting-toolbar[data-show-desktop="true"] { transition: none; }}
/* Honor reduced-motion preference. Applies in any viewport (desktop or * mobile) — though the desktop rule is where it matters most. */@media (prefers-reduced-motion: reduce) { .formatting-toolbar, .formatting-toolbar[data-show-desktop="true"] { transition: none; }}
/* Hide when not focused */.formatting-toolbar[data-visible="false"] { display: none;}
/* Hide in Read mode — editing is disabled, no formatting actions available */.formatting-toolbar[data-mode="read"] { display: none;}
/* Hide when there are no visible actions (e.g., no file open, or all actions hidden) */.formatting-toolbar[data-empty="true"] { display: none;}
.formatting-toolbar__button { display: flex; align-items: center; justify-content: center; width: 32px; height: 32px; background: none; border: 1px solid transparent; /* Square — matches the rectilinear chrome. */ border-radius: 0; color: var(--text-secondary); cursor: pointer; flex-shrink: 0; transition: background-color 0.15s, color 0.15s, border-color 0.15s; -webkit-tap-highlight-color: transparent;}
.formatting-toolbar__button:hover { background-color: var(--bg-tertiary); color: var(--text-primary);}
.formatting-toolbar__button:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px;}
.formatting-toolbar__button:active { background-color: var(--bg-active); border-color: var(--border-color);}
.formatting-toolbar__button svg { width: 16px; height: 16px;}
.formatting-toolbar__divider { width: 1px; height: 16px; background-color: var(--border-color); margin: 0 2px; flex-shrink: 0;}