/** * Heartbeat widget styles. Bundled with the widget's JS (Vite * emits a separate `widget-heartbeat[.min].css`); the script * registration enqueues this CSS alongside the JS handle so it * loads on demand the same way the JS does. */ .os-widget-heartbeat { display: flex; flex-direction: column; gap: 8px; /* Only side padding here — the framework's `card-body` ships * with `padding: 16px` so vertical chrome already exists. * Adding more on top creates the dead-space-below-the-bar * problem. */ padding: 0 12px; user-select: none; -webkit-user-select: none; box-sizing: border-box; height: 100%; width: 100%; overflow: hidden; } /* Push the meta row (and the bar that follows it) to the BOTTOM * of the widget container — any vertical slack accumulates as * extra breathing room around the heart, not as dead space * below the progress bar. */ .os-widget-heartbeat__meta { margin-top: auto; } /* Override the framework card-body's default `padding: 16px` — * the heartbeat widget owns its own layout and that padding * eats real estate the progress bar needs. */ .os-widgets__card-body.os-widget-heartbeat { padding: 8px; min-height: 0; flex: 1 1 auto; } /* Card-level flex so the body fills the card cleanly. Scoped to * cards hosting this widget so others keep their block layout. */ .os-widgets__card.os-widgets__card--heartbeat { display: flex; flex-direction: column; overflow: hidden; } .os-widget-heartbeat__stage { position: relative; display: block; /* Stage height matches the available vertical room exactly so * the big-beat halo (the concentric glow rings around the * heart, which grow on each WP heartbeat tick) has the most * space possible without overflowing into the meta/bar row. * * Card 230 * − chrome 32 (6 + 6 padding + 20 px close icon) * − body padding 16 (8 + 8, this widget's override) * − widget padding 0 (zero vertical — see container rule) * − meta row 16 * − bar 10 * − 2 × 8 px gaps 16 * ──────────────────── * stage = 140 px * * The heart + halo geometry in index.ts is tuned so that at * the big-beat peak (heart × 1.55, halo × 1.15) the whole * lighting effect fits comfortably inside this 140 × ~270 box * without the outer ring colliding with the stage edges. */ flex: 0 0 140px; height: 140px; width: 100%; overflow: hidden; contain: strict; } .os-widget-heartbeat__stage canvas { display: block; width: 100% !important; height: 100% !important; max-width: 100%; max-height: 100%; } .os-widget-heartbeat__meta { display: flex; align-items: baseline; justify-content: space-between; font-size: 11px; color: rgba( 255, 255, 255, 0.7 ); letter-spacing: 0.04em; text-transform: uppercase; padding: 0 2px; } .os-widget-heartbeat__label { font-weight: 600; } .os-widget-heartbeat__remaining { font-variant-numeric: tabular-nums; font-size: 13px; color: #ff8ba3; letter-spacing: 0.02em; text-transform: none; font-weight: 600; } .os-widget-heartbeat__bar { position: relative; height: 10px; border-radius: 5px; background: rgba( 255, 255, 255, 0.10 ); overflow: hidden; box-shadow: inset 0 1px 2px rgba( 0, 0, 0, 0.35 ), inset 0 0 0 1px rgba( 255, 255, 255, 0.04 ); } .os-widget-heartbeat__bar-fill { position: absolute; left: 0; top: 0; bottom: 0; width: 0%; border-radius: 5px; background: linear-gradient( 90deg, #ff8ba3 0%, #ff4d6d 60%, #ff2d5b 100% ); box-shadow: 0 0 10px rgba( 255, 77, 109, 0.65 ), inset 0 1px 0 rgba( 255, 255, 255, 0.35 ), inset 0 -1px 0 rgba( 0, 0, 0, 0.18 ); } /* Compact mode — right-click → "Show heart" toggled off. */ .os-widget-heartbeat--no-heart .os-widget-heartbeat__stage { display: none; } .os-widget-heartbeat--no-heart { justify-content: center; } .os-widget-heartbeat--fallback .os-widget-heartbeat__fallback { display: flex; align-items: center; justify-content: center; height: 100%; font-size: 12px; color: rgba( 255, 255, 255, 0.6 ); text-align: center; padding: 12px; }