Skip to main content

PLAYER_CSS

Constant PLAYER_CSS 

Source
pub const PLAYER_CSS: &str = "/* beecast-player chrome + terminal palette (see the crate README).\n   Clean-room, MIT like the rest of beecast. Semantic chrome tokens (--beecast-*) are the\n   stable theming surface; --sp-* covers the terminal palette and remains independently\n   themeable. Internal .sp-* classes are not a public API. */\n\n/* Semantic theme tokens (Phase 8). Defaults map to the classic dark chrome. */\n.beecast-player {\n  --beecast-color-surface: #121417;\n  --beecast-color-surface-raised: rgba(255, 255, 255, 0.04);\n  --beecast-color-text: #cdd3dc;\n  --beecast-color-text-muted: rgba(205, 211, 220, 0.8);\n  --beecast-color-accent: #6a9ded;\n  --beecast-color-focus: rgba(88, 166, 255, 0.5);\n  --beecast-color-marker: #d5b45e;\n  --beecast-color-live: #78bd65;\n  --beecast-color-error: #e05f65;\n  --beecast-control-height: 44px;\n  --beecast-radius: 4px;\n  --beecast-font-ui: 13px/1.2 ui-sans-serif, system-ui, sans-serif;\n  --beecast-font-terminal: 13px/1.25 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;\n\n  /* Terminal palette */\n  --sp-bg: var(--beecast-color-surface);\n  --sp-fg: var(--beecast-color-text);\n  --sp-c0: #1c1f24; --sp-c1: #e05f65; --sp-c2: #78bd65; --sp-c3: #d5b45e;\n  --sp-c4: #6a9ded; --sp-c5: #bd7bd8; --sp-c6: #55b8c2; --sp-c7: #b8bfc9;\n  --sp-c8: #596273; --sp-c9: #ff8188; --sp-c10: #98d989; --sp-c11: #f0d182;\n  --sp-c12: #8fb7ff; --sp-c13: #d99df0; --sp-c14: #7fd6df; --sp-c15: #eef1f5;\n\n  display: flex;\n  flex-direction: column;\n  min-height: 0;\n  box-sizing: border-box;\n  background: var(--sp-bg);\n  color: var(--sp-fg);\n  border-radius: var(--beecast-radius);\n  outline: none;\n  overflow: hidden;\n}\n\n/* Built-in themes */\n.beecast-player[data-theme=\"light\"] {\n  --beecast-color-surface: #f4f5f7;\n  --beecast-color-surface-raised: rgba(0, 0, 0, 0.04);\n  --beecast-color-text: #1c1f24;\n  --beecast-color-text-muted: rgba(28, 31, 36, 0.75);\n  --beecast-color-accent: #3b6fd4;\n  --beecast-color-focus: rgba(59, 111, 212, 0.45);\n  --beecast-color-marker: #b8860b;\n  --beecast-color-live: #3d8b40;\n  --sp-bg: #f4f5f7;\n  --sp-fg: #1c1f24;\n}\n\n@media (prefers-color-scheme: light) {\n  .beecast-player[data-theme=\"system\"] {\n    --beecast-color-surface: #f4f5f7;\n    --beecast-color-surface-raised: rgba(0, 0, 0, 0.04);\n    --beecast-color-text: #1c1f24;\n    --beecast-color-text-muted: rgba(28, 31, 36, 0.75);\n    --beecast-color-accent: #3b6fd4;\n    --beecast-color-focus: rgba(59, 111, 212, 0.45);\n    --beecast-color-marker: #b8860b;\n    --beecast-color-live: #3d8b40;\n    --sp-bg: #f4f5f7;\n    --sp-fg: #1c1f24;\n  }\n}\n\n.beecast-player:focus-visible { box-shadow: 0 0 0 2px var(--beecast-color-focus); }\n.beecast-player.arrival-flash { animation: beecast-arrival 900ms ease-out; }\n@keyframes beecast-arrival { from { box-shadow: 0 0 0 3px var(--beecast-color-focus); } to { box-shadow: none; } }\n\n/* Stage grows into leftover height; bar stays at the bottom. Content-sized mounts still\n   size to the terminal (flex:1 with an indefinite parent collapses to content). */\n.sp-stage {\n  position: relative;\n  flex: 1 1 auto;\n  min-height: 0;\n  min-width: 0;\n  width: 100%;\n  display: flex;\n  flex-direction: column;\n  align-items: center;\n  justify-content: center;\n}\n\n/* Fullscreen (and wrap-fullscreen when scsh fullscreens the outer .cast): fill the\n   viewport, center the terminal in the stage, pin the control bar at the bottom \u{2014}\n   no margin-auto gap between the terminal and the bar. */\n.beecast-player:fullscreen,\n:fullscreen .beecast-player {\n  width: 100%; height: 100%; border-radius: 0;\n}\n.beecast-player:fullscreen .sp-bar,\n:fullscreen .beecast-player .sp-bar {\n  position: relative;\n  z-index: 20;\n  box-sizing: border-box;\n  padding-right: 0.35rem; /* keep 1\u{d7} / \u{26f6} from kissing the edge after scale */\n}\n.beecast-player [hidden] { display: none !important; }\n\n.sp-screen-box { overflow: hidden; position: relative; flex: 0 0 auto; }\n\n/* Center play overlay: soft dim + a geometric `|>` (SVG bar + chevron, equal height). */\n.sp-overlay {\n  position: absolute; inset: 0; z-index: 3;\n  display: flex; align-items: center; justify-content: center;\n  background: rgba(0, 0, 0, 0.42);\n  cursor: pointer;\n}\n.sp-overlay:focus-visible {\n  outline: 2px solid var(--beecast-color-accent);\n  outline-offset: -4px;\n}\n.sp-bigplay {\n  margin: 0;\n  display: flex;\n  align-items: center;\n  justify-content: center;\n  width: 7rem;\n  height: 7rem;\n  color: #fff;\n  opacity: 0.92;\n  filter: drop-shadow(0 0 1px rgba(0, 0, 0, 0.9)) drop-shadow(0 4px 18px rgba(0, 0, 0, 0.65));\n  transition: opacity 0.15s, transform 0.15s;\n  user-select: none;\n}\n.sp-bigplay-icon {\n  display: block;\n  width: 100%;\n  height: 100%;\n}\n.sp-overlay:hover .sp-bigplay,\n.sp-overlay:focus-visible .sp-bigplay {\n  opacity: 1;\n  transform: scale(1.06);\n}\n@media (prefers-reduced-motion: reduce) {\n  .beecast-player.arrival-flash { animation: none; outline: 2px solid var(--beecast-color-accent); }\n  .sp-toast { transition: none; }\n  .sp-bigplay { transition: none; }\n  .sp-overlay:hover .sp-bigplay,\n  .sp-overlay:focus-visible .sp-bigplay { transform: none; }\n}\n\n/* Off-screen snapshot for accessibility=\"snapshot\" \u{2014} readable, not a live region. */\n.sp-a11y {\n  position: absolute;\n  width: 1px; height: 1px;\n  padding: 0; margin: -1px;\n  overflow: hidden;\n  clip: rect(0, 0, 0, 0);\n  white-space: pre;\n  border: 0;\n}\n\n.sp-chapters {\n  position: absolute; top: 0; right: 0; bottom: 0; z-index: 4;\n  width: min(320px, 60%);\n  overflow-y: auto;\n  background: rgba(9, 11, 15, 0.92);\n  border-left: 1px solid rgba(255, 255, 255, 0.14);\n  font: 12px/1.45 ui-sans-serif, system-ui, sans-serif;\n  padding: 8px;\n  display: flex;\n  flex-direction: column;\n  gap: 6px;\n  box-sizing: border-box;\n  pointer-events: auto;\n}\n/* Tall + wide mounts (and fullscreen): dock chapters beside the terminal instead of\n   overlaying it. The list stretches full stage height; the terminal stays centered. */\n.beecast-player.sp-chapters-dock .sp-stage {\n  flex-direction: row;\n  align-items: center;\n  justify-content: flex-start;\n}\n.beecast-player.sp-chapters-dock .sp-screen-box {\n  flex: 1 1 auto;\n  min-width: 0;\n  width: auto;\n}\n.beecast-player.sp-chapters-dock .sp-chapters {\n  position: static;\n  flex: 0 0 min(280px, 32%);\n  width: min(280px, 32%);\n  max-width: 320px;\n  align-self: stretch;\n  z-index: 1;\n}\n/* Chapter rows mirror scsh job-graph cards: left accent, state / title / meta. */\n.sp-chap {\n  display: flex; flex-direction: column; justify-content: center;\n  gap: 0.15rem; width: 100%; text-align: left;\n  font: inherit; color: var(--sp-fg);\n  background: #0d1117; border: 1px solid #2a3140;\n  border-left: 3px solid #2a3140; border-radius: 6px;\n  cursor: pointer; padding: 0.45rem 0.65rem;\n  box-sizing: border-box;\n  pointer-events: auto;\n}\n.sp-chap:hover { border-color: #3a4558; background: #161b22; }\n.sp-chap:focus-visible {\n  outline: 2px solid var(--beecast-color-accent);\n  outline-offset: 1px;\n}\n.sp-chap-state {\n  display: flex; align-items: center; gap: 0.35rem;\n  font-size: 0.72rem; font-weight: 600;\n  text-transform: uppercase; letter-spacing: 0.04em;\n  color: var(--beecast-color-text-muted);\n}\n.sp-chap-id {\n  font-weight: 600; font-size: 0.95rem;\n  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n}\n.sp-chap-meta {\n  font-size: 0.75rem; color: var(--beecast-color-text-muted);\n  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n  font-variant-numeric: tabular-nums;\n}\n.sp-chap-on {\n  border-left-color: #3fb950;\n  background: #161b22;\n}\n.sp-chap-on .sp-chap-state,\n.sp-chap-on .sp-chap-id { color: #3fb950; }\n.sp-chap-ann .sp-chap-id { font-style: italic; opacity: 0.95; }\n\n/* Bottom-center disappearing toast: scsh job-graph card silhouette (left accent,\n   state / title / meta), above the control bar. */\n.sp-toast {\n  position: absolute; left: 50%; bottom: 52px; z-index: 6;\n  transform: translateX(-50%) translateY(0.6rem);\n  display: flex; flex-direction: column; justify-content: center;\n  gap: 0.15rem;\n  max-width: min(22rem, calc(100% - 24px));\n  min-width: min(12rem, calc(100% - 24px));\n  padding: 0.45rem 0.75rem;\n  border-radius: 6px;\n  background: #0d1117;\n  border: 1px solid #2a3140;\n  border-left: 3px solid #3fb950;\n  color: var(--sp-fg);\n  font: 0.85rem/1.25 ui-sans-serif, system-ui, sans-serif;\n  text-align: left;\n  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.4);\n  opacity: 0; pointer-events: none;\n  transition: opacity 0.22s ease, transform 0.22s ease;\n  box-sizing: border-box;\n}\n.sp-toast-show { opacity: 1; transform: translateX(-50%) translateY(0); }\n.sp-toast-state {\n  display: flex; align-items: center; gap: 0.35rem;\n  font-size: 0.72rem; font-weight: 600;\n  text-transform: uppercase; letter-spacing: 0.04em;\n  color: #3fb950;\n}\n.sp-toast-id {\n  font-weight: 600; font-size: 0.95rem; color: #3fb950;\n  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n}\n.sp-toast-meta {\n  font-size: 0.75rem; color: var(--beecast-color-text-muted);\n  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;\n  font-variant-numeric: tabular-nums;\n}\n\n.sp-screen {\n  margin: 0;\n  padding: 4px 6px;\n  font: var(--beecast-font-terminal);\n  white-space: pre;\n  transform-origin: top left;\n  width: max-content;\n}\n/* Styled runs fill one complete terminal row. Top alignment removes the baseline\n   leading that otherwise becomes a dark horizontal seam at fractional fit scales. */\n.sp-screen span { display: inline-block; vertical-align: top; }\n.sp-probe { visibility: hidden; position: absolute; }\n.sp-b { font-weight: 700; }\n.sp-d { opacity: 0.6; }\n.sp-i { font-style: italic; }\n.sp-u { text-decoration: underline; }\n.sp-s { text-decoration: line-through; }\n.sp-u.sp-s { text-decoration: underline line-through; }\n.sp-cur { outline: 1px solid var(--sp-fg); outline-offset: -1px; }\n\n.sp-bar {\n  display: flex;\n  align-items: center;\n  flex: 0 0 auto;\n  flex-wrap: nowrap;\n  gap: 10px;\n  width: 100%;\n  min-height: var(--beecast-control-height);\n  padding: 10px 12px;\n  background: var(--beecast-color-surface-raised);\n  border-top: 1px solid rgba(255, 255, 255, 0.08);\n  font: var(--beecast-font-ui);\n  user-select: none;\n  box-sizing: border-box;\n  /* Menus grow upward out of the bar; keep them paintable over the terminal. */\n  position: relative;\n  z-index: 6;\n  overflow: visible;\n}\n.sp-bar button {\n  font: inherit;\n  color: var(--sp-fg);\n  background: transparent;\n  border: none;\n  cursor: pointer;\n  padding: 8px 12px;\n  border-radius: 4px;\n  min-height: 36px;\n  min-width: 36px;\n  line-height: 1.2;\n  flex: 0 0 auto;\n}\n.sp-bar button:hover { color: #fff; background: rgba(255, 255, 255, 0.06); }\n.sp-bar button:focus-visible {\n  outline: 2px solid var(--beecast-color-accent);\n  outline-offset: 1px;\n}\n.sp-play { font-size: 18px; padding: 8px 14px; min-width: 40px; }\n.sp-live {\n  font-weight: 600;\n  letter-spacing: 0.02em;\n  color: var(--beecast-color-text-muted);\n}\n.sp-live.on {\n  color: var(--beecast-color-live);\n  background: rgba(120, 189, 101, 0.12);\n}\n.sp-live.on:hover { color: var(--beecast-color-live); background: rgba(120, 189, 101, 0.18); }\n\n.sp-speedwrap {\n  position: relative;\n  display: inline-flex;\n  flex: 0 0 auto;\n  align-items: center;\n}\n.sp-speed {\n  min-width: 3.25em;\n  font-variant-numeric: tabular-nums;\n  font-weight: 600;\n}\n.sp-speedmenu {\n  position: absolute; bottom: calc(100% + 8px); right: 0; z-index: 30;\n  display: flex; flex-direction: column;\n  min-width: 4.5em; padding: 4px;\n  background: #161a20;\n  border: 1px solid rgba(255, 255, 255, 0.16);\n  border-radius: var(--beecast-radius);\n  box-shadow: 0 6px 18px rgba(0, 0, 0, 0.5);\n}\n.sp-speedopt {\n  text-align: center;\n  border-radius: 3px;\n  min-height: 32px;\n  padding: 6px 10px;\n}\n.sp-speedopt.sp-on {\n  color: var(--sp-c12);\n  font-weight: 700;\n  box-shadow: inset 0 0 0 1px var(--beecast-color-accent);\n}\n.sp-speedopt:hover { background: rgba(106, 157, 237, 0.18); }\n.sp-speedopt:focus-visible {\n  outline: 2px solid var(--beecast-color-accent);\n  outline-offset: 0;\n}\n\n.sp-time, .sp-dur {\n  color: var(--beecast-color-text-muted);\n  min-width: 3.6em;\n  text-align: center;\n  font-variant-numeric: tabular-nums;\n  flex: 0 0 auto;\n  font-size: 13px;\n}\n.sp-seek {\n  position: relative;\n  flex: 1 1 auto;\n  min-width: 64px;\n  height: 10px;\n  border-radius: 5px;\n  background: rgba(255, 255, 255, 0.12);\n  cursor: pointer;\n  touch-action: none;\n}\n.sp-seek:focus-visible {\n  outline: 2px solid var(--beecast-color-accent);\n  outline-offset: 3px;\n}\n.sp-fill {\n  position: absolute; left: 0; top: 0; bottom: 0;\n  width: 0;\n  border-radius: 3px;\n  background: var(--beecast-color-accent);\n  pointer-events: none;\n}\n/* Declared-live (setLive): the bar reads \"now\" \u{2014} pinned full-width, live green \u{2014} not a\n   position that jitters as the growing recording keeps re-proportioning it. */\n.beecast-player.sp-islive .sp-fill { width: 100% !important; background: var(--beecast-color-live); }\n.sp-markers { position: absolute; inset: 0; pointer-events: none; }\n.sp-marker {\n  position: absolute; top: -2px; bottom: -2px; width: 2px;\n  background: var(--beecast-color-marker);\n  pointer-events: auto;\n}\n.sp-marker-ann {\n  width: 0;\n  border-left: 2px dashed var(--beecast-color-marker);\n  background: transparent;\n}\n\n/* Custom element host fills its mount when used directly. */\nbeecast-player {\n  display: block;\n  width: 100%;\n  height: 100%;\n}\n\n/* Keep every primary action reachable on narrow phones. Time remains available to\n   assistive technology through the seek slider\'s aria-valuetext. */\n@media (max-width: 430px) {\n  .sp-bar { gap: 4px; padding: 6px; }\n  .sp-bar button { padding-left: 8px; padding-right: 8px; }\n  .sp-time, .sp-dur { display: none; }\n  .sp-seek { min-width: 40px; }\n}\n";
Expand description

The player chrome and terminal palette. Semantic --beecast-* tokens are the stable theming surface; --sp-* is the terminal palette. Nothing is fetched (no fonts, no images).