bowler/src/resources/css/app.css

178 lines
4.7 KiB
CSS

@import "tailwindcss";
/* Scan Blade templates for utility classes */
@source "../views";
/* --- Theme tokens ------------------------------------------------------ */
/* Semantic brand colors. Defaults are the stock blues; a customized theme
overrides these :root variables via an inline <style> in the layout head
(values come from the site_themes table), so no CSS rebuild is needed.
Must stay in sync with Theme::DEFAULTS. */
@theme {
--color-primary: #2563eb; /* blue-600 */
--color-primary-hover: #1d4ed8; /* blue-700 */
--color-secondary: #3b82f6; /* blue-500 */
--color-tertiary: #1d4ed8; /* blue-700 */
--color-nav-link: #2563eb;
--color-nav-text: #111827; /* gray-900 */
--color-nav-muted: #6b7280; /* gray-500 */
}
:root {
--theme-nav-bg: #ffffff;
--theme-chart-line: #2a78d6;
}
.site-nav {
background: var(--theme-nav-bg);
}
/* --- Destructive-action confirm modal ---------------------------------- */
#confirm-delete-modal::backdrop {
background: rgba(17, 24, 39, 0.5);
}
/* --- Bowler chart expand/collapse ------------------------------------- */
/* The detail <tr> itself can't animate height; the inner grid wrapper
animates 0fr -> 1fr (no magic max-heights). Entrances are gentle,
exits are quicker, and the KPI line "draws" itself as the hero moment. */
.detail-outer {
display: grid;
grid-template-rows: 0fr;
transition: grid-template-rows 180ms cubic-bezier(0.4, 0, 0.2, 1);
}
.detail-inner {
overflow: hidden;
min-height: 0;
opacity: 0;
transform: translateY(-4px);
transition: opacity 120ms ease-in, transform 120ms ease-in;
}
.js-detail-row.is-open .detail-outer {
grid-template-rows: 1fr;
transition-duration: 250ms;
}
.js-detail-row.is-open .detail-inner {
opacity: 1;
transform: translateY(0);
transition: opacity 200ms ease-out 80ms, transform 200ms ease-out 80ms;
}
/* KPI chart: the value line draws in; points/markers pop with a stagger. */
@keyframes kpi-draw {
from { stroke-dashoffset: 1; }
to { stroke-dashoffset: 0; }
}
@keyframes kpi-pop {
from { opacity: 0; transform: scale(0.4); }
to { opacity: 1; transform: scale(1); }
}
.is-open .kpi-line {
stroke-dasharray: 1;
animation: kpi-draw 600ms cubic-bezier(0.25, 0.1, 0.25, 1) 150ms backwards;
}
.is-open .kpi-pop {
transform-box: fill-box;
transform-origin: center;
animation: kpi-pop 220ms cubic-bezier(0.34, 1.4, 0.64, 1) backwards;
animation-delay: calc(250ms + var(--i, 0) * 40ms);
}
/* --- Noted chart points + floating note tooltip ------------------------ */
/* Points whose entry carries a note get a theme-colored halo that gently
pulses (identity marker, not state — RAG fills stay untouched). Hovering
with intent draws a leader line to a fixed-position floating panel. */
.kpi-note-ring {
fill: none;
stroke: var(--color-primary);
stroke-width: 1.5;
transform-box: fill-box;
transform-origin: center;
}
@keyframes kpi-note-pulse {
0%, 100% { stroke-opacity: 0.85; transform: scale(1); }
50% { stroke-opacity: 0.35; transform: scale(1.35); }
}
.is-open .kpi-note-ring {
/* Starts after the pop-in stagger settles. */
animation: kpi-note-pulse 2.2s ease-in-out 900ms infinite;
}
.js-note-point { cursor: pointer; }
/* Fixed positioning escapes .detail-inner's overflow: hidden and the
table's overflow-x-auto wrapper. */
.kpi-note-tooltip {
position: fixed;
z-index: 50;
max-width: 400px;
opacity: 0;
transform: scale(0.96);
pointer-events: none;
transition: opacity 160ms ease-out, transform 160ms cubic-bezier(0.34, 1.4, 0.64, 1);
}
.kpi-note-tooltip.is-visible {
opacity: 1;
transform: scale(1);
pointer-events: auto; /* lets users move in and scroll long notes */
}
/* Full-viewport overlay carrying the point-to-panel leader line. */
.kpi-note-leader {
position: fixed;
inset: 0;
width: 100%;
height: 100%;
z-index: 49;
pointer-events: none;
}
.kpi-note-leader line {
stroke: var(--color-primary);
stroke-width: 1.5;
stroke-dasharray: 1; /* pathLength="1" in markup */
stroke-dashoffset: 1;
}
.kpi-note-leader.is-visible line {
animation: kpi-draw 220ms ease-out forwards;
}
@media (prefers-reduced-motion: reduce) {
.detail-outer,
.detail-inner,
.js-detail-row.is-open .detail-outer,
.js-detail-row.is-open .detail-inner {
transition: none;
}
.is-open .kpi-line,
.is-open .kpi-pop {
animation: none;
}
.is-open .kpi-note-ring {
animation: none; /* halo stays as a static marker */
}
.kpi-note-tooltip {
transition: none;
}
.kpi-note-leader.is-visible line {
animation: none;
stroke-dashoffset: 0;
}
}