Files
ProdDash/band-lineup-display/styles.css
christianandClaude Opus 5 882a418a0f Band Lineup Display snapshot catches up: 1.3.6 → 1.3.10
The reference fork had drifted four builds behind the app actually running
backstage. What it was missing is Birthday Mode, the feature the ProdDash
module was ported with and this snapshot never had:

- main.js grows the Planning Center birthday fetch (`pcoFetchBirthday`),
  mm-dd normalising, and a `pco-test-birthdays` IPC handler behind the
  settings pane's Test Birthdays button.
- renderer.js gains the whole celebration: the Wednesday→Tuesday birthday
  week, the canvas confetti loop, the gold glow, and the controls that switch
  it on and set its intensity.
- index.html and styles.css carry the Birthday Mode block in settings.

Purely additive — 597 lines in, four out, and those four are the version and
build number. Source only, as the fork has always been: `.claude/` settings
stay as they are (the local copy's are one machine's accumulated permissions,
and it has no launch.json to give), and the stray test file beside them is not
part of the app.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 16:37:54 -04:00

1333 lines
23 KiB
CSS

* {
box-sizing: border-box;
}
html,
body {
margin: 0;
height: 100%;
font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
background: #0f0f12;
color: #e8e8ec;
user-select: none;
}
body {
display: flex;
flex-direction: column;
overflow: hidden;
}
.top-edge-hit {
display: none;
}
.toolbar {
display: flex;
align-items: center;
gap: 12px;
padding: 10px 14px;
background: #1a1a20;
border-bottom: 1px solid #2a2a32;
flex-shrink: 0;
overflow: hidden;
max-height: 72px;
opacity: 1;
transition: max-height 0.22s ease, padding 0.22s ease, opacity 0.22s ease, transform 0.22s ease, border-color 0.22s ease;
}
.toolbar-spacer {
flex: 1;
}
.app-version {
flex-shrink: 0;
font-size: 11px;
font-weight: 600;
letter-spacing: 0.04em;
color: #6f6f7d;
white-space: nowrap;
user-select: text;
}
.layout-controls {
display: flex;
align-items: center;
gap: 10px;
}
.layout-field {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: #a0a0ae;
}
.layout-field input {
width: 64px;
padding: 7px 8px;
border-radius: 8px;
border: 1px solid #3a3a44;
background: #25252e;
color: #e8e8ec;
font-size: 14px;
}
.layout-field input:focus {
outline: none;
border-color: #4a6fa5;
}
.btn {
padding: 8px 14px;
border-radius: 8px;
border: 1px solid #3a3a44;
background: #25252e;
color: #e8e8ec;
font-size: 14px;
cursor: pointer;
touch-action: manipulation;
}
.btn:hover {
background: #32323c;
}
.btn.primary {
background: #3d5a80;
border-color: #4a6fa5;
}
.btn.primary:hover {
background: #4a6fa5;
}
.btn.btn-small {
padding: 6px 10px;
font-size: 12px;
}
.app-main {
flex: 1;
min-height: 0;
display: flex;
align-items: stretch;
}
.stage {
flex: 1;
min-width: 0;
position: relative;
display: flex;
align-items: stretch;
justify-content: stretch;
padding: 12px 14px 12px 16px;
overflow: hidden;
}
.stage.drag-over {
outline: 2px dashed #4a6fa5;
outline-offset: -6px;
background: #15151a;
}
.row {
width: 100%;
height: 100%;
display: grid;
grid-template-columns: repeat(7, minmax(0, 1fr));
grid-template-rows: repeat(2, minmax(0, 1fr));
gap: 10px;
}
.stage-slot {
min-width: 0;
min-height: 0;
position: relative;
border-radius: 12px;
overflow: hidden;
background: #15151b;
border: 2px solid #282832;
}
.stage-slot.empty-slot {
border-style: dashed;
border-color: #343442;
background: rgba(30, 30, 38, 0.65);
}
.stage-slot.empty-slot::before {
content: attr(data-slot-label);
position: absolute;
top: 8px;
left: 10px;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: #646474;
}
.slot-placeholder {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
padding: 12px;
color: #555563;
font-size: 14px;
}
.slot-visual {
position: relative;
flex: 1;
min-height: 0;
overflow: hidden;
}
.library-panel {
width: clamp(320px, 30vw, 420px);
min-width: 320px;
flex-shrink: 0;
display: flex;
flex-direction: column;
/* Show mode collapses this panel to width 0 rather than hiding it; without clipping, the
tab strip and pane contents spill across the stage. */
overflow: hidden;
background: #141418;
border-left: 1px solid #2a2a32;
transition: width 0.22s ease, min-width 0.22s ease, border-color 0.22s ease;
}
/* ---------- panel tabs ---------- */
.library-tabs {
display: flex;
flex-shrink: 0;
gap: 4px;
padding: 8px 8px 0;
border-bottom: 1px solid #2a2a32;
transition: opacity 0.18s ease;
}
.lib-tab {
flex: 1;
min-width: 0;
padding: 9px 6px;
font-family: inherit;
font-size: 12px;
font-weight: 700;
letter-spacing: 0.04em;
text-transform: uppercase;
color: #8a8a99;
background: none;
border: none;
border-bottom: 2px solid transparent;
border-radius: 6px 6px 0 0;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.lib-tab:hover {
color: #c6cada;
background: rgba(255, 255, 255, 0.03);
}
.lib-tab.is-active {
color: #cfe0f7;
border-bottom-color: #4a6fa5;
background: rgba(74, 111, 165, 0.12);
}
/* One pane at a time. display:none rather than opacity, so a hidden pane cannot be
clicked, tabbed into, or measured. */
.library-pane {
display: none;
min-height: 0;
transition: opacity 0.18s ease;
}
.library-pane.is-active {
/* This chain is load-bearing: .library-scroll's flex:1 only expands because every
ancestor up to .library-panel is a column flex box with min-height:0. */
display: flex;
flex: 1;
flex-direction: column;
min-height: 0;
}
.pane-scroll {
flex: 1;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
padding: 10px;
touch-action: pan-y;
}
.pane-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.pane-head-spaced {
margin-top: 16px;
padding-top: 12px;
border-top: 1px solid #2a2a32;
}
.pane-title {
font-size: 13px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #9a9aa8;
}
.pane-foot {
flex-shrink: 0;
padding: 6px 10px 8px;
border-top: 1px solid #2a2a32;
}
.slot-size-readout {
font-size: 11px;
line-height: 1.4;
color: #7d8492;
user-select: text;
}
.pco-controls {
display: grid;
grid-template-columns: minmax(0, 1fr) auto auto;
gap: 8px;
margin-top: 8px;
}
.pco-select {
min-width: 0;
width: 100%;
padding: 7px 10px;
border-radius: 8px;
border: 1px solid #3a3a44;
background: #25252e;
color: #e8e8ec;
font-size: 13px;
}
.pco-status {
margin-top: 8px;
min-height: 18px;
font-size: 12px;
color: #9ea7bc;
}
.pco-birthday-result {
min-height: 0;
line-height: 1.45;
}
.pco-birthday-result:empty {
display: none;
}
/* ---- Birthday Mode settings ---- */
.bday-block {
margin-top: 14px;
border-top: 1px solid #23232c;
padding-top: 12px;
}
.bday-head {
display: flex;
align-items: center;
justify-content: space-between;
}
.bday-title {
font-size: 13px;
font-weight: 700;
color: #e7e7ef;
}
.bday-switch {
display: inline-flex;
align-items: center;
gap: 6px;
cursor: pointer;
font-size: 12px;
color: #9ea7bc;
}
.bday-controls {
margin-top: 10px;
display: flex;
flex-direction: column;
gap: 10px;
}
.bday-line {
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.bday-line-label {
font-size: 11px;
letter-spacing: 0.06em;
text-transform: uppercase;
color: #8a8a99;
min-width: 74px;
}
.bday-line-label em {
font-style: normal;
text-transform: none;
letter-spacing: 0;
color: #6d6d7a;
}
.seg-inline {
display: inline-flex;
gap: 4px;
background: #0e0e14;
border: 1px solid #23232c;
border-radius: 9px;
padding: 3px;
}
.seg-inline button {
appearance: none;
border: 0;
background: transparent;
color: #9ea7bc;
font: inherit;
font-size: 12px;
font-weight: 600;
padding: 5px 12px;
border-radius: 6px;
cursor: pointer;
}
.seg-inline button[aria-pressed="true"] {
background: #f5c451;
color: #241a02;
}
.bday-check {
display: inline-flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: #c6cada;
cursor: pointer;
}
.bday-test-select {
flex: 1;
min-width: 150px;
}
.bday-hint {
font-size: 11px;
color: #6d6d7a;
}
.pco-position-builder {
display: none;
grid-template-columns: minmax(0, 1fr) auto;
gap: 8px;
margin-top: 8px;
}
.pco-position-list {
display: none;
flex-direction: column;
gap: 6px;
margin-top: 8px;
max-height: 170px;
overflow-y: auto;
}
.pco-position-empty {
padding: 8px 10px;
border: 1px dashed #353542;
border-radius: 8px;
color: #808092;
font-size: 12px;
}
.pco-position-item {
display: grid;
grid-template-columns: minmax(0, 1fr) auto auto auto auto auto auto;
gap: 6px;
align-items: center;
padding: 8px;
border: 1px solid #30303a;
border-radius: 8px;
background: #1a1a20;
}
.pco-position-copy {
min-width: 0;
}
.pco-position-name {
font-size: 12px;
font-weight: 600;
color: #ececf1;
}
.pco-position-team {
margin-top: 2px;
font-size: 11px;
color: #9da5b6;
}
.pco-count-chip {
min-width: 34px;
text-align: center;
font-size: 12px;
color: #d8deea;
}
.library-scroll {
flex: 1;
min-height: 0;
overflow-y: auto;
overflow-x: hidden;
padding: 8px;
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 8px;
align-content: start;
touch-action: pan-y;
transition: opacity 0.18s ease;
}
.lib-item {
position: relative;
width: 100%;
aspect-ratio: 3 / 4;
border-radius: 10px;
overflow: hidden;
border: 2px solid #33333e;
background: #0a0a0c;
flex-shrink: 0;
touch-action: pan-y;
cursor: grab;
}
.lib-item:active {
cursor: grabbing;
}
.lib-item.dragging-source {
opacity: 0.35;
}
.lib-item.on-lineup {
border-color: #3d5a80;
box-shadow: 0 0 0 1px rgba(61, 90, 128, 0.5);
}
.lib-item img {
width: 100%;
height: 100%;
aspect-ratio: 3 / 4;
object-fit: cover;
object-position: center top;
display: block;
pointer-events: none;
}
.lib-name-overlay {
position: absolute;
top: 8px;
left: 8px;
right: 8px;
z-index: 1;
padding: 7px 8px;
border-radius: 8px;
background: rgba(8, 8, 12, 0.74);
color: #f4f4f6;
font-size: 11px;
font-weight: 700;
line-height: 1.2;
text-align: center;
word-break: break-word;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.65);
pointer-events: none;
}
.lib-delete {
position: absolute;
top: 4px;
right: 4px;
width: 24px;
height: 24px;
border: none;
border-radius: 8px;
background: rgba(0, 0, 0, 0.6);
color: #fff;
font-size: 14px;
line-height: 1;
cursor: pointer;
z-index: 2;
touch-action: manipulation;
padding: 0;
}
.lib-delete:hover {
background: #8b2942;
}
.tile {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
border-radius: 12px;
overflow: hidden;
background: #1a1a22;
position: relative;
touch-action: none;
cursor: grab;
}
.tile:active {
cursor: grabbing;
}
.tile.dragging-source {
opacity: 0.4;
}
.tile .photo-area {
position: absolute;
inset: 0;
display: flex;
align-items: center;
justify-content: center;
background: #0a0a0c;
}
.tile img {
width: 100%;
height: 100%;
object-fit: contain;
object-position: center center;
pointer-events: none;
display: block;
}
.tile .parallax-viewport {
position: absolute;
inset: 0;
z-index: 1;
overflow: hidden;
pointer-events: none;
}
.tile .moving-stage-image {
position: absolute;
inset: -5%;
width: 110%;
height: 110%;
object-fit: cover;
object-position: center center;
will-change: transform;
backface-visibility: hidden;
transform-origin: center center;
image-rendering: -webkit-optimize-contrast;
transform: translate3d(calc(var(--cam-x, 0px) * -0.3), calc(var(--cam-y, 0px) * -0.3), 0) scale(1.01);
}
.tile .static-stage-image {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center center;
}
.tile .name-badge {
position: absolute;
top: 8px;
left: 8px;
max-width: calc(100% - 52px);
padding: 6px 10px;
border-radius: 8px;
background: rgba(8, 8, 12, 0.84);
color: #f4f4f6;
font-size: clamp(11px, 1vw, 15px);
font-weight: 700;
line-height: 1.2;
z-index: 3;
cursor: pointer;
touch-action: manipulation;
word-break: break-word;
}
.empty-name-hotspot {
position: absolute;
top: 8px;
left: 8px;
right: 40px;
min-height: 28px;
border: 0;
border-radius: 8px;
padding: 6px 10px;
background: transparent;
color: #f4f4f6;
font-size: clamp(11px, 1vw, 15px);
font-weight: 700;
line-height: 1.2;
text-align: left;
z-index: 2;
cursor: pointer;
touch-action: manipulation;
}
.empty-name-hotspot:not(:empty) {
background: rgba(8, 8, 12, 0.68);
}
.empty-name-hotspot:focus-visible {
outline: 2px solid #6b9ee0;
outline-offset: 1px;
}
.tile .name-badge:empty::before {
content: "Tap for name";
color: #b2b2c0;
font-weight: 600;
}
.tile .caption {
position: relative;
padding: 10px 8px;
font-size: clamp(11px, 1vw, 15px);
font-weight: 600;
text-align: center;
background: rgba(12, 12, 16, 0.88);
border-top: 1px solid #2e2e38;
min-height: 42px;
display: flex;
align-items: center;
justify-content: center;
word-break: break-word;
touch-action: manipulation;
cursor: pointer;
}
.stage-slot > .caption:empty::before {
content: "Tap for mic / pack";
color: #6b6b79;
font-weight: 500;
}
/* ---- Birthday Mode tile effects ---- */
.tile.birthday-subtle {
animation: bdayGlowSubtle 3.4s ease-in-out infinite;
}
.tile.birthday-full {
animation: bdayGlowFull 2.2s ease-in-out infinite;
}
@keyframes bdayGlowSubtle {
0%, 100% { box-shadow: inset 0 0 0 2px rgba(245, 196, 81, 0.55), 0 0 14px rgba(245, 196, 81, 0.18); }
50% { box-shadow: inset 0 0 0 2px rgba(245, 196, 81, 0.85), 0 0 20px rgba(245, 196, 81, 0.32); }
}
@keyframes bdayGlowFull {
0%, 100% { box-shadow: inset 0 0 0 3px rgba(245, 196, 81, 0.8), 0 0 20px rgba(245, 196, 81, 0.42); }
50% { box-shadow: inset 0 0 0 3px #ffd873, 0 0 34px rgba(245, 196, 81, 0.66); }
}
/* Birthday Mode intentionally keeps animating even under OS "reduced motion" — it's a celebration
the operator opts into, and freezing it leaves confetti stuck mid-fall. */
.birthday-confetti {
position: absolute;
inset: 0;
z-index: 2;
pointer-events: none;
}
.tile .remove {
position: absolute;
top: 6px;
right: 6px;
width: 30px;
height: 30px;
border: none;
border-radius: 8px;
background: rgba(0, 0, 0, 0.6);
color: #fff;
font-size: 18px;
line-height: 1;
cursor: pointer;
z-index: 4;
touch-action: manipulation;
padding: 0;
opacity: 0;
pointer-events: none;
transition: opacity 0.15s ease;
}
body:not(.chrome-hidden) .tile .remove {
opacity: 1;
pointer-events: auto;
}
.tile .remove:hover {
background: #8b2942;
}
.stage-slot {
display: flex;
flex-direction: column;
}
.stage-slot > .caption {
flex-shrink: 0;
padding: 10px 8px;
font-size: clamp(11px, 1vw, 15px);
font-weight: 600;
text-align: center;
background: rgba(12, 12, 16, 0.88);
border-top: 1px solid #2e2e38;
min-height: 42px;
display: flex;
align-items: center;
justify-content: center;
word-break: break-word;
touch-action: manipulation;
cursor: pointer;
}
.empty {
display: none;
position: absolute;
inset: 0;
align-items: center;
justify-content: center;
text-align: center;
color: #666670;
font-size: 16px;
margin: 0;
pointer-events: none;
}
.empty.visible {
display: flex;
}
body.chrome-hidden .toolbar {
max-height: 0;
padding-top: 0;
padding-bottom: 0;
opacity: 0;
transform: translateY(-10px);
border-bottom-color: transparent;
pointer-events: none;
}
body.chrome-hidden .library-panel {
width: 0;
min-width: 0;
border-left-color: transparent;
}
body.chrome-hidden .library-tabs,
body.chrome-hidden .library-pane {
opacity: 0;
pointer-events: none;
}
body.chrome-hidden .tile .remove {
opacity: 0;
pointer-events: none;
}
body.chrome-hidden .stage-slot.empty-slot::before,
body.chrome-hidden .slot-placeholder,
body.chrome-hidden .stage-slot > .caption:empty::before,
body.chrome-hidden .tile .name-badge:empty::before {
opacity: 0;
}
.drag-ghost {
position: fixed;
width: 88px;
height: 118px;
border-radius: 10px;
overflow: hidden;
border: 2px solid #4a6fa5;
box-shadow: 0 12px 32px rgba(0, 0, 0, 0.55);
pointer-events: none;
z-index: 1000;
opacity: 0.92;
}
.drag-ghost img {
width: 100%;
height: 100%;
object-fit: cover;
object-position: center top;
display: block;
}
.drag-ghost.hidden {
display: none;
}
.modal {
position: fixed;
inset: 0;
z-index: 2000;
display: flex;
align-items: center;
justify-content: center;
padding: 16px;
}
.modal.hidden {
display: none;
}
.modal-backdrop {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.72);
}
.modal-card {
position: relative;
width: min(720px, 100%);
max-height: min(92vh, 900px);
overflow: auto;
background: #1e1e26;
border: 1px solid #3a3a48;
border-radius: 16px;
padding: 20px;
box-shadow: 0 24px 64px rgba(0, 0, 0, 0.5);
}
.modal-card-small {
width: min(420px, 100%);
}
.modal-title {
margin: 0 0 12px;
font-size: 18px;
font-weight: 600;
}
.modal-copy {
margin: 0 0 12px;
color: #aeb6c8;
font-size: 13px;
line-height: 1.4;
}
.modal-field {
display: block;
margin-bottom: 12px;
color: #c6cada;
font-size: 13px;
}
.modal-field span {
display: block;
margin-bottom: 6px;
}
.label-input {
width: 100%;
padding: 14px 12px;
font-size: 22px;
border-radius: 10px;
border: 2px solid #4a6fa5;
background: #121218;
color: #e8e8ec;
margin-bottom: 14px;
}
.label-input:focus {
outline: none;
border-color: #6b9ee0;
}
.modal-input {
margin-bottom: 0;
font-size: 16px;
}
.number-input {
text-align: center;
font-size: 32px;
font-weight: 700;
letter-spacing: 0.04em;
}
.vkeyboard {
display: flex;
flex-direction: column;
gap: 8px;
margin-bottom: 16px;
}
.vk-row {
display: flex;
flex-wrap: wrap;
gap: 6px;
justify-content: center;
}
.vk-key {
min-width: 44px;
height: 48px;
padding: 0 12px;
border-radius: 8px;
border: 1px solid #3a3a48;
background: #2a2a34;
color: #e8e8ec;
font-size: 18px;
font-weight: 600;
cursor: pointer;
touch-action: manipulation;
}
.vk-key:hover {
background: #363642;
}
.vk-key.wide {
min-width: 120px;
}
.vk-key.space {
flex: 1;
min-width: 160px;
max-width: 320px;
}
.modal-actions {
display: flex;
justify-content: flex-end;
gap: 10px;
}
/* ---------- ProPresenter config (in library head) ---------- */
.pp-controls {
margin-top: 10px;
padding-top: 10px;
border-top: 1px solid #2a2a32;
}
.pp-controls-top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.pp-controls-title {
font-size: 13px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.06em;
color: #9a9aa8;
}
.pp-controls-buttons {
display: flex;
gap: 8px;
}
.pp-status {
margin-top: 8px;
min-height: 18px;
font-size: 12px;
color: #9ea7bc;
}
.pp-playlist-select {
margin-top: 8px;
}
/* ---------- Studio displays (hosting the Now/Next page on the LAN) ---------- */
.display-urls {
display: flex;
flex-direction: column;
gap: 6px;
margin-top: 8px;
/* A multi-homed machine can offer five or six addresses; keep the list from taking over
the panel on its own. */
max-height: 168px;
overflow-y: auto;
touch-action: pan-y;
}
.display-urls:empty {
display: none;
}
.display-url-row {
display: flex;
align-items: center;
gap: 8px;
padding: 7px 9px;
border: 1px solid #2a2a34;
border-radius: 8px;
background: rgba(26, 26, 32, 0.7);
}
.display-url-row.is-best {
border-color: #4a6fa5;
background: rgba(74, 111, 165, 0.16);
}
.display-url-main {
flex: 1;
min-width: 0;
}
.display-url-text {
font-size: 13px;
font-weight: 700;
color: #cfe0f7;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
user-select: text;
}
.display-url-note {
margin-top: 2px;
font-size: 11px;
line-height: 1.35;
color: #8a8a99;
}
.display-url-row.is-best .display-url-note {
color: #9fb6d6;
}
.display-port-row {
display: flex;
align-items: center;
gap: 10px;
margin-top: 8px;
}
.display-port-field {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: #a0a0ae;
}
.display-port-field input {
width: 74px;
padding: 6px 8px;
border-radius: 8px;
border: 1px solid #33333d;
background: #0f0f13;
color: #e8e8ec;
font-size: 13px;
}
.display-port-field input:focus {
outline: none;
border-color: #4a6fa5;
}
/* ---------- ProPresenter Now / Next column (show mode) ---------- */
.pp-column {
display: none;
width: clamp(280px, 26vw, 380px);
min-width: 280px;
flex-shrink: 0;
flex-direction: column;
gap: 14px;
padding: 18px 16px;
background: rgba(16, 16, 20, 0.96);
border-left: 1px solid #2a2a32;
overflow: hidden;
}
/* Only present in minimal/show mode, and only when ProPresenter has live data. */
body.chrome-hidden.pp-active .pp-column {
display: flex;
}
.pp-playlist-name {
font-size: 12px;
font-weight: 700;
letter-spacing: 0.08em;
text-transform: uppercase;
color: #8a8a99;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.pp-playlist-name:empty {
display: none;
}
.pp-now {
border: 1px solid #30303c;
border-radius: 14px;
background: linear-gradient(160deg, rgba(61, 90, 128, 0.22), rgba(26, 26, 34, 0.6));
padding: 14px 16px;
}
.pp-now-label {
font-size: 11px;
font-weight: 800;
letter-spacing: 0.14em;
text-transform: uppercase;
color: #7fa8e0;
}
.pp-now-name {
margin-top: 6px;
/* Size is set dynamically by fitNowTitle() in renderer.js to fill the box;
this is just the pre-fit default. Keep line-height in sync with that helper. */
font-size: 36px;
font-weight: 700;
line-height: 1.1;
color: #f4f6fb;
/* Wrapping is controlled by fitNowTitle() in renderer.js — it forbids mid-word breaks
and sizes down until whole words fit, so the base must not force break-word. */
overflow-wrap: normal;
word-break: normal;
}
.pp-now-meta {
margin-top: 10px;
font-size: clamp(13px, 1.2vw, 17px);
font-weight: 600;
color: #c6cada;
font-variant-numeric: tabular-nums;
/* Never wrap — a 2nd line would resize the title box and flap the fitted title size. */
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.pp-progress {
margin-top: 10px;
height: 6px;
border-radius: 999px;
background: rgba(255, 255, 255, 0.1);
overflow: hidden;
}
.pp-progress-fill {
height: 100%;
border-radius: 999px;
background: #4a6fa5;
transition: width 0.25s ease;
}
.pp-next-wrap {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
gap: 8px;
}
.pp-section-label {
font-size: 11px;
font-weight: 800;
letter-spacing: 0.14em;
text-transform: uppercase;
color: #7a7a8a;
}
.pp-next-list {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
gap: 8px;
overflow: hidden;
}
.pp-next-item {
display: flex;
align-items: center;
gap: 10px;
padding: 10px 12px;
border: 1px solid #2a2a34;
border-radius: 10px;
background: rgba(26, 26, 32, 0.7);
}
.pp-next-name {
flex: 1;
min-width: 0;
font-size: clamp(14px, 1.3vw, 19px);
font-weight: 600;
color: #e2e4ec;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.pp-count-chip {
flex-shrink: 0;
min-width: 30px;
padding: 3px 9px;
text-align: center;
border-radius: 999px;
background: rgba(74, 111, 165, 0.28);
color: #cfe0f7;
font-size: 13px;
font-weight: 700;
}
.pp-type-tag {
flex-shrink: 0;
font-size: 11px;
font-weight: 700;
letter-spacing: 0.06em;
text-transform: uppercase;
color: #8a8a99;
}
.pp-next-item.is-header {
background: none;
border: none;
border-bottom: 1px solid #2f2f3a;
border-radius: 0;
padding: 10px 2px 4px;
}
.pp-next-item.is-header .pp-next-name {
font-size: 11px;
font-weight: 800;
letter-spacing: 0.12em;
text-transform: uppercase;
color: #8a8a99;
white-space: normal;
}
.pp-waiting {
font-size: 14px;
color: #7a7a8a;
}
.pp-error {
margin-top: 6px;
font-size: 11px;
color: #d98c8c;
word-break: break-word;
}