import { style } from '@vanilla-extract/css'; import { color, toRem } from 'folds'; import { VOJO_HORSESHOE_RADIUS_PX } from '../../styles/horseshoe'; // Outer container — anchor for the two absolutely-positioned panes // (`appBody` and `silhouette`). Same shape as the settings-sheet // container, see that file for the full rationale. export const container = style({ position: 'relative', display: 'flex', flex: 1, flexDirection: 'column', minWidth: 0, minHeight: 0, overflow: 'hidden', }); // Holds the wrapped chat column. Stays put — clip-path carves the // bottom edge so virtualized timeline rows aren't re-measured // mid-gesture. `backgroundColor` opaque so the void colour painted // on the container doesn't bleed through any transparent slivers // in the wrapped tree (e.g. between bubble rows). export const appBody = style({ position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, display: 'flex', flexDirection: 'column', minWidth: 0, minHeight: 0, backgroundColor: color.Background.Container, willChange: 'clip-path', }); // The viewer sheet's surface. `Background.Container` (deepest Dawn // tone) so the image floats on a near-black backdrop — closest to // the legacy `` viewer's full-screen dark scrim. Rounded // top corners (same radius as the tab curtains) with `overflow: // hidden` clip the header / image to the curve; the carved corners // expose the app's dark background behind, so the rounding reads // without re-introducing a black void gap. export const silhouette = style({ position: 'absolute', bottom: 0, left: 0, right: 0, display: 'flex', flexDirection: 'column', overflow: 'hidden', backgroundColor: color.Background.Container, borderTopLeftRadius: toRem(VOJO_HORSESHOE_RADIUS_PX), borderTopRightRadius: toRem(VOJO_HORSESHOE_RADIUS_PX), willChange: 'height', }); // Top-anchored — handle + viewer body reveal top-down as silhouette // grows. Android nav-bar clearance is owned by `MainActivity.java`'s // WindowInsets listener (the WebView is already sized above the nav // bar), so no `padding-bottom: env(...)` here — that would stack on // top of the native padding and lift the download / share row above // its visible host. export const panelContent = style({ position: 'absolute', top: 0, left: 0, right: 0, boxSizing: 'border-box', display: 'flex', flexDirection: 'column', }); // 20px drag-to-close band. The ONLY drag-to-close origin — touches // on the viewer body below this strip drive zoom / pan / swipe and // MUST NOT initiate a close gesture. `touchAction: none` blocks // browser-native scroll on this strip. export const panelHandle = style({ flexShrink: 0, height: toRem(20), display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'grab', touchAction: 'none', userSelect: 'none', selectors: { '&:active': { cursor: 'grabbing' }, }, }); // Darker than `Background.Container` would make the grabber // disappear — use `SurfaceVariant.Container` so the bar reads // against the dark viewer bg. Mirror of the settings handle's // step-up against `SurfaceVariant.Container` (where it uses the // deeper `Background.Container`). export const panelHandleBar = style({ width: toRem(36), height: toRem(4), borderRadius: toRem(4), backgroundColor: color.SurfaceVariant.Container, }); export const panelBody = style({ flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0, minWidth: 0, });