Reload the browser on template and static changes in dev
Adds django-browser-reload: runserver already restarts on Python changes, but the browser had to be refreshed by hand for every template or CSS edit. It also watches static/, so a Tailwind rebuild now refreshes the page on its own. Mounted only under DEBUG -- it injects a script into every HTML response and serves an open event stream, neither of which belongs in production; a test holds that line. Its endpoint is exempt from RequireMFAMiddleware, otherwise a not-yet-enrolled staff user has the stream redirected away and live reload dies on the MFA enrolment page, which is exactly a page we are restyling. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
BIN
static/.DS_Store
vendored
Normal file
BIN
static/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -27,6 +27,10 @@
|
||||
--font-weight-medium: 500;
|
||||
--font-weight-semibold: 600;
|
||||
--font-weight-bold: 700;
|
||||
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
||||
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--default-transition-duration: 150ms;
|
||||
--default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--default-font-family: var(--font-sans);
|
||||
--default-mono-font-family: var(--font-mono);
|
||||
}
|
||||
@@ -464,6 +468,26 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.collapse-plus {
|
||||
@layer daisyui.l1.l2 {
|
||||
> .collapse-title:after {
|
||||
position: absolute;
|
||||
display: block;
|
||||
height: 0.5rem;
|
||||
width: 0.5rem;
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
transition-property: all;
|
||||
transition-duration: 300ms;
|
||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
top: 0.9rem;
|
||||
inset-inline-end: 1.4rem;
|
||||
--tw-content: "+";
|
||||
content: var(--tw-content);
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.dropdown {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
position: relative;
|
||||
@@ -917,6 +941,21 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.collapse-open {
|
||||
@layer daisyui.l1.l2 {
|
||||
grid-template-rows: max-content 1fr;
|
||||
> .collapse-content {
|
||||
--overflow-delay: 0.2s;
|
||||
overflow: revert-layer;
|
||||
content-visibility: visible;
|
||||
min-height: fit-content;
|
||||
padding-bottom: 1rem;
|
||||
@supports not (content-visibility: visible) {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.collapse {
|
||||
visibility: collapse;
|
||||
}
|
||||
@@ -982,6 +1021,27 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.toast {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
position: fixed;
|
||||
inset-inline-start: auto;
|
||||
inset-inline-end: calc(0.25rem * 4);
|
||||
top: auto;
|
||||
bottom: calc(0.25rem * 4);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: calc(0.25rem * 2);
|
||||
background-color: transparent;
|
||||
translate: var(--toast-x, 0) var(--toast-y, 0);
|
||||
width: max-content;
|
||||
max-width: calc(100vw - 2rem);
|
||||
& > * {
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
animation: toast 0.25s ease-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.toggle {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
border: var(--border) solid currentColor;
|
||||
@@ -1318,6 +1378,51 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.aura {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
--aura-padding: 0.125rem;
|
||||
padding: var(--aura-padding);
|
||||
border-radius: calc(var(--aura-padding) + var(--aura-radius, var(--radius-box)));
|
||||
animation: aura var(--tw-duration, 6s) linear infinite;
|
||||
background-image: conic-gradient(from var(--aura-angle), transparent 225deg, currentColor);
|
||||
&:has( > .card, > .alert) {
|
||||
--aura-radius: var(--radius-box);
|
||||
}
|
||||
&:has( > .btn, > .input, > .select) {
|
||||
--aura-radius: var(--radius-field);
|
||||
}
|
||||
&:has( > .checkbox, > .toggle, > .badge) {
|
||||
--aura-radius: var(--radius-selector);
|
||||
}
|
||||
&:before, &:after {
|
||||
animation: inherit;
|
||||
background-color: inherit;
|
||||
background-image: inherit;
|
||||
border-radius: inherit;
|
||||
position: absolute;
|
||||
top: calc(1 / 2 * 100%);
|
||||
left: calc(1 / 2 * 100%);
|
||||
z-index: 0;
|
||||
display: block;
|
||||
opacity: 70%;
|
||||
filter: blur(0.25rem);
|
||||
translate: -50% -50%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
content: "";
|
||||
}
|
||||
&:after {
|
||||
opacity: 30%;
|
||||
filter: blur(1rem);
|
||||
}
|
||||
& > * {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
.select {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
position: relative;
|
||||
@@ -1666,6 +1771,48 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
.rating {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
vertical-align: middle;
|
||||
--size: var(--size-selector, 0.25rem) * 6;
|
||||
input {
|
||||
cursor: pointer;
|
||||
appearance: none;
|
||||
}
|
||||
* {
|
||||
border-radius: 0;
|
||||
background-color: var(--color-base-content);
|
||||
opacity: 20%;
|
||||
width: calc(var(--size) * 1);
|
||||
height: calc(var(--size));
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
animation: rating 0.25s ease-out;
|
||||
}
|
||||
}
|
||||
.rating-hidden {
|
||||
width: calc(0.25rem * 2);
|
||||
background-color: transparent;
|
||||
}
|
||||
:checked, [aria-checked="true"], [aria-current="true"], :has( ~ :checked, ~ [aria-checked="true"], ~ [aria-current="true"]) {
|
||||
opacity: 100%;
|
||||
}
|
||||
:focus-visible {
|
||||
scale: 1.1;
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
transition: scale 0.2s ease-out;
|
||||
}
|
||||
}
|
||||
:active:focus {
|
||||
animation: none;
|
||||
scale: 1.1;
|
||||
}
|
||||
}
|
||||
@layer daisyui.l1.l2 {
|
||||
--size: var(--size-selector, 0.25rem) * 6;
|
||||
}
|
||||
}
|
||||
.navbar {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
display: flex;
|
||||
@@ -1734,9 +1881,89 @@
|
||||
border-radius: var(--radius-box);
|
||||
}
|
||||
}
|
||||
.progress {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
position: relative;
|
||||
height: calc(0.25rem * 2);
|
||||
width: 100%;
|
||||
appearance: none;
|
||||
overflow: hidden;
|
||||
border-radius: var(--radius-box);
|
||||
background-color: currentcolor;
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
background-color: color-mix(in oklab, currentcolor 20%, transparent);
|
||||
}
|
||||
color: var(--color-base-content);
|
||||
&:indeterminate {
|
||||
background-image: repeating-linear-gradient( 90deg, currentColor -1%, currentColor 10%, #0000 10%, #0000 90% );
|
||||
background-size: 200%;
|
||||
background-position-x: 15%;
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
animation: progress 5s ease-in-out infinite;
|
||||
}
|
||||
@supports (-moz-appearance: none) {
|
||||
&::-moz-progress-bar {
|
||||
background-color: transparent;
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
animation: progress 5s ease-in-out infinite;
|
||||
background-image: repeating-linear-gradient( 90deg, currentColor -1%, currentColor 10%, #0000 10%, #0000 90% );
|
||||
background-size: 200%;
|
||||
background-position-x: 15%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@supports (-moz-appearance: none) {
|
||||
&::-moz-progress-bar {
|
||||
border-radius: var(--radius-box);
|
||||
background-color: currentcolor;
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
transition: inline-size 0.3s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
@supports (-webkit-appearance: none) {
|
||||
&::-webkit-progress-bar {
|
||||
border-radius: var(--radius-box);
|
||||
background-color: transparent;
|
||||
}
|
||||
&::-webkit-progress-value {
|
||||
border-radius: var(--radius-box);
|
||||
background-color: currentColor;
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
transition: inline-size 0.3s ease;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.static {
|
||||
position: static;
|
||||
}
|
||||
.dropdown-right {
|
||||
@layer daisyui.l1.l2 {
|
||||
--anchor-h: right;
|
||||
--anchor-v: span-bottom;
|
||||
.dropdown-content {
|
||||
inset-inline-start: 100%;
|
||||
top: 0;
|
||||
bottom: auto;
|
||||
transform-origin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
.dropdown-left {
|
||||
@layer daisyui.l1.l2 {
|
||||
--anchor-h: left;
|
||||
--anchor-v: span-bottom;
|
||||
.dropdown-content {
|
||||
inset-inline-end: 100%;
|
||||
top: 0;
|
||||
bottom: auto;
|
||||
transform-origin: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.dropdown-end {
|
||||
@layer daisyui.l1.l2 {
|
||||
--anchor-h: span-left;
|
||||
@@ -1931,6 +2158,26 @@
|
||||
.z-10 {
|
||||
z-index: 10;
|
||||
}
|
||||
.tab-content {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
order: var(--tabcontent-order);
|
||||
display: none;
|
||||
border-color: transparent;
|
||||
--tabcontent-radius-ss: var(--radius-box);
|
||||
--tabcontent-radius-se: var(--radius-box);
|
||||
--tabcontent-radius-es: var(--radius-box);
|
||||
--tabcontent-radius-ee: var(--radius-box);
|
||||
--tabcontent-order: 1;
|
||||
width: 100%;
|
||||
height: calc(100% - var(--tab-height) + var(--border));
|
||||
margin: var(--tabcontent-margin);
|
||||
border-width: var(--border);
|
||||
border-start-start-radius: var(--tabcontent-radius-ss);
|
||||
border-start-end-radius: var(--tabcontent-radius-se);
|
||||
border-end-start-radius: var(--tabcontent-radius-es);
|
||||
border-end-end-radius: var(--tabcontent-radius-ee);
|
||||
}
|
||||
}
|
||||
.hero {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
display: grid;
|
||||
@@ -2328,6 +2575,46 @@
|
||||
.flex-none {
|
||||
flex: none;
|
||||
}
|
||||
.flex-shrink {
|
||||
flex-shrink: 1;
|
||||
}
|
||||
.flex-grow {
|
||||
flex-grow: 1;
|
||||
}
|
||||
.border-collapse {
|
||||
border-collapse: collapse;
|
||||
}
|
||||
.transform {
|
||||
transform: var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,);
|
||||
}
|
||||
.skeleton {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
border-radius: var(--radius-box);
|
||||
background-color: var(--color-base-300);
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
transition-duration: 15s;
|
||||
}
|
||||
will-change: background-position;
|
||||
background-image: linear-gradient( 105deg, #0000 0% 40%, var(--color-base-100) 50%, #0000 60% 100% );
|
||||
background-size: 200% auto;
|
||||
background-position-x: -50%;
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
animation: skeleton 1.8s ease-in-out infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
.aura-glow {
|
||||
@layer daisyui.l1.l2 {
|
||||
animation: none;
|
||||
background-image: radial-gradient(closest-corner at center, currentColor 0%, transparent 90%);
|
||||
&:before {
|
||||
animation: aura-glow var(--tw-duration, 6s) ease-out infinite;
|
||||
}
|
||||
&:after {
|
||||
animation: aura-glow-after var(--tw-duration, 6s) ease-out infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
.link {
|
||||
@layer daisyui.l1.l2.l3 {
|
||||
cursor: pointer;
|
||||
@@ -2349,6 +2636,9 @@
|
||||
.cursor-pointer {
|
||||
cursor: pointer;
|
||||
}
|
||||
.resize {
|
||||
resize: both;
|
||||
}
|
||||
.flex-wrap {
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
@@ -2435,6 +2725,9 @@
|
||||
.bg-base-200 {
|
||||
background-color: var(--color-base-200);
|
||||
}
|
||||
.bg-base-300 {
|
||||
background-color: var(--color-base-300);
|
||||
}
|
||||
.btn-link {
|
||||
@layer daisyui {
|
||||
text-decoration-line: underline;
|
||||
@@ -2553,6 +2846,9 @@
|
||||
--alert-color: var(--color-warning);
|
||||
}
|
||||
}
|
||||
.text-base-content {
|
||||
color: var(--color-base-content);
|
||||
}
|
||||
.text-base-content\/70 {
|
||||
color: var(--color-base-content);
|
||||
@supports (color: color-mix(in lab, red, red)) {
|
||||
@@ -2587,6 +2883,9 @@
|
||||
text-decoration-line: none;
|
||||
}
|
||||
}
|
||||
.underline {
|
||||
text-decoration-line: underline;
|
||||
}
|
||||
.opacity-60 {
|
||||
opacity: 60%;
|
||||
}
|
||||
@@ -2601,9 +2900,26 @@
|
||||
--tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));
|
||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||
}
|
||||
.outline {
|
||||
outline-style: var(--tw-outline-style);
|
||||
outline-width: 1px;
|
||||
}
|
||||
.filter {
|
||||
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
||||
}
|
||||
.transition {
|
||||
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter, display, content-visibility, overlay, pointer-events;
|
||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
||||
}
|
||||
.ease-in-out {
|
||||
--tw-ease: var(--ease-in-out);
|
||||
transition-timing-function: var(--ease-in-out);
|
||||
}
|
||||
.ease-out {
|
||||
--tw-ease: var(--ease-out);
|
||||
transition-timing-function: var(--ease-out);
|
||||
}
|
||||
.btn-error {
|
||||
@layer daisyui.l1.l2 {
|
||||
--btn-color: var(--color-error);
|
||||
@@ -2683,6 +2999,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
[data-theme="light"] .logo {
|
||||
content: var(--logo-dark);
|
||||
}
|
||||
[data-theme="dark"] .logo {
|
||||
content: var(--logo-light);
|
||||
}
|
||||
@layer base {
|
||||
:where(:root),:root:has(input.theme-controller[value=light]:checked),[data-theme=light] {
|
||||
color-scheme: light;
|
||||
@@ -2969,6 +3291,26 @@
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@property --tw-rotate-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-rotate-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-rotate-z {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-skew-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-skew-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-space-y-reverse {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
@@ -3073,6 +3415,11 @@
|
||||
inherits: false;
|
||||
initial-value: 0 0 #0000;
|
||||
}
|
||||
@property --tw-outline-style {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: solid;
|
||||
}
|
||||
@property --tw-blur {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
@@ -3126,9 +3473,18 @@
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@property --tw-ease {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
}
|
||||
@layer properties {
|
||||
@supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {
|
||||
*, ::before, ::after, ::backdrop {
|
||||
--tw-rotate-x: initial;
|
||||
--tw-rotate-y: initial;
|
||||
--tw-rotate-z: initial;
|
||||
--tw-skew-x: initial;
|
||||
--tw-skew-y: initial;
|
||||
--tw-space-y-reverse: 0;
|
||||
--tw-divide-y-reverse: 0;
|
||||
--tw-border-style: solid;
|
||||
@@ -3152,6 +3508,7 @@
|
||||
--tw-ring-offset-width: 0px;
|
||||
--tw-ring-offset-color: #fff;
|
||||
--tw-ring-offset-shadow: 0 0 #0000;
|
||||
--tw-outline-style: solid;
|
||||
--tw-blur: initial;
|
||||
--tw-brightness: initial;
|
||||
--tw-contrast: initial;
|
||||
@@ -3165,6 +3522,7 @@
|
||||
--tw-drop-shadow-color: initial;
|
||||
--tw-drop-shadow-alpha: 100%;
|
||||
--tw-drop-shadow-size: initial;
|
||||
--tw-ease: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
6
static/images/rosterchief-dark.svg
Normal file
6
static/images/rosterchief-dark.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="200" height="200">
|
||||
<path d="M50 4 L90 18 V50 C90 76 72 92 50 98 C28 92 10 76 10 50 V18 Z" fill="#0F1A2E"></path>
|
||||
<rect x="27" y="30" width="46" height="8" rx="4" fill="#FFFFFF"></rect>
|
||||
<rect x="27" y="44" width="34" height="8" rx="4" fill="#FFFFFF"></rect>
|
||||
<path d="M27 80 L50 62 L73 80 L66 85 L50 72 L34 85 Z" fill="#FFFFFF"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 417 B |
6
static/images/rosterchief-white.svg
Normal file
6
static/images/rosterchief-white.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="200" height="200">
|
||||
<path d="M50 4 L90 18 V50 C90 76 72 92 50 98 C28 92 10 76 10 50 V18 Z" fill="#FFFFFF"></path>
|
||||
<rect x="27" y="30" width="46" height="8" rx="4" fill="#0F1A2E"></rect>
|
||||
<rect x="27" y="44" width="34" height="8" rx="4" fill="#0F1A2E"></rect>
|
||||
<path d="M27 80 L50 62 L73 80 L66 85 L50 72 L34 85 Z" fill="#0F1A2E"></path>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 417 B |
@@ -8,5 +8,13 @@
|
||||
/* daisyUI: light is the default, dark applies automatically when the OS asks
|
||||
for it. An explicit data-theme on <html> (set by the toggle) overrides both. */
|
||||
@plugin "daisyui" {
|
||||
themes: light --default, dark --prefersdark;
|
||||
themes: light --default, dark --prefersdark;
|
||||
}
|
||||
|
||||
[data-theme="light"] .logo {
|
||||
content: var(--logo-dark);
|
||||
}
|
||||
|
||||
[data-theme="dark"] .logo {
|
||||
content: var(--logo-light);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user