/* shared/elevation.css — admin-elevation toggle in the tool header. Renders only for users with admin scope (handled by elevation.js; the placeholder is `.hidden` by default). When visible, sits left of the theme button — sudo-style affordance for opting into admin powers. */ .elevation-toggle { display: inline-flex; align-items: center; gap: 0.3rem; font-size: 0.78rem; color: var(--text-muted); user-select: none; cursor: pointer; padding: 0.15rem 0.45rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); transition: background 0.12s, border-color 0.12s, color 0.12s; } .elevation-toggle:hover { background: var(--bg-hover); border-color: var(--border-dark); } .elevation-toggle input[type="checkbox"] { margin: 0; cursor: pointer; accent-color: var(--danger); } .elevation-toggle__label { cursor: pointer; letter-spacing: 0.02em; } /* Active state — when elevation is ON, the toggle reads as "armed" so the user can't miss that admin powers are currently live. :has(:checked) lets us style the wrapper based on the inner checkbox without JS. */ .elevation-toggle:has(input:checked) { background: rgba(220, 53, 69, 0.12); border-color: var(--danger); color: var(--danger); font-weight: 600; } /* Page-wide chrome when admin mode is active. The toggle alone is easy to miss; these add an inescapable visual cue: 1. Thin red border around the entire viewport — peripheral- vision reminder regardless of which tool / scroll position. 2. Sticky banner across the top with a one-click "Drop admin" button so the user can disarm without hunting for the toggle. Both rendered ONLY when the zddc-elevate cookie is set; the shared/elevation.js init() syncs the body class on every page load and tears it down when elevation is cleared. Frame uses fixed positioning + pointer-events:none so it doesn't reflow content or steal clicks. An inset outline on was tried first but overdrew content in tools whose root layout butts right up to the viewport edge (browse split-pane, archive grid). */ body.is-elevated::after { content: ""; position: fixed; inset: 0; border: 3px solid var(--danger, #dc3545); pointer-events: none; z-index: 9200; /* above banner (9100) so the frame paints on top */ } .elevation-banner { display: flex; align-items: center; gap: 0.75rem; padding: 0.4rem 0.9rem; background: rgba(220, 53, 69, 0.95); color: #fff; font-size: 0.85rem; font-weight: 500; letter-spacing: 0.01em; position: sticky; top: 0; z-index: 9100; /* above modal-overlay (9000) so it's never hidden */ box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18); } .elevation-banner__dot { width: 0.5rem; height: 0.5rem; background: #fff; border-radius: 50%; box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); animation: elev-pulse 1.6s infinite; flex-shrink: 0; } @keyframes elev-pulse { 0% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0.7); } 70% { box-shadow: 0 0 0 8px rgba(255, 255, 255, 0); } 100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); } } .elevation-banner__msg { flex: 1 1 auto; } .elevation-banner__off { background: rgba(255, 255, 255, 0.18); border: 1px solid rgba(255, 255, 255, 0.7); color: #fff; padding: 0.18rem 0.65rem; border-radius: var(--radius, 4px); font-size: 0.78rem; font-weight: 600; letter-spacing: 0.02em; cursor: pointer; flex-shrink: 0; } .elevation-banner__off:hover { background: rgba(255, 255, 255, 0.3); }