.select's content box (2.125rem height minus padding and border) left only ~16px for a 14px line -- descenders (g/y/p/q) rendered clipped in some browsers, most visibly on the Competition edit modal's Sport dropdown. Bumped .input/.select to 2.25rem for headroom, and .btn/ .btn-square the same amount so a button next to a field in the same row still lines up -- .btn itself never had the clipping problem (flex centring), this is purely for row alignment. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ECGMEwrc2k4D8VQuwjstj9
1074 lines
35 KiB
CSS
1074 lines
35 KiB
CSS
/* RosterChief control panel — a deliberately separate stylesheet.
|
|
*
|
|
* The control panel is a distinct surface (see design_handoff_rosterchief_platform/README.md):
|
|
* industrial, dark command bar over a light workspace, its own type system (Barlow /
|
|
* Barlow Condensed / IBM Plex Mono) and colour tokens, and — per that handoff — "never
|
|
* club-branded". It does not import assets/app.css and does not load daisyUI: sharing either
|
|
* would mean the panel inherits the club-facing app's theme variables and component shapes,
|
|
* which is exactly what "standalone" rules out.
|
|
*
|
|
* One wrinkle: a handful of templates the control panel renders — `controlpanel/_form_fields.html`,
|
|
* `templatetags/field.html`, and the `daisy`/`form_field` template tags in
|
|
* `controlpanel/templatetags/ui.py` — are also used by the sitewide login/MFA templates
|
|
* (templates/account/, templates/allauth/), so their *markup* is off limits here (changing it
|
|
* would reskin the login page too). Those templates emit daisyUI-shaped class names
|
|
* (`input`, `select`, `textarea`, `checkbox`, `toggle`, `file-input`, `btn`, `badge`, `card`,
|
|
* `table`, `modal`, `alert`, `avatar`, `progress`, `form-control`, `label`, `divide-y`, `link`)
|
|
* without daisyUI itself supplying their CSS (it isn't loaded here). So this file hand-rolls
|
|
* industrial-styled definitions for exactly that class vocabulary — same names, new look —
|
|
* scoped to controlpanel templates only via @source below, so nothing here reaches the
|
|
* pages built on assets/app.css.
|
|
*/
|
|
@import "tailwindcss";
|
|
|
|
@source "../controlpanel";
|
|
|
|
@theme {
|
|
--font-display: "Barlow Condensed", ui-sans-serif, system-ui, sans-serif;
|
|
--font-sans: "Barlow", ui-sans-serif, system-ui, sans-serif;
|
|
--font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, monospace;
|
|
|
|
--color-ink: #0b1220; /* darkest -- command bar, sidebars, dark cards */
|
|
--color-navy: #101e36;
|
|
--color-steel: #1b2b47; /* inset controls on dark */
|
|
--color-hairline: #1e2b42; /* rules on dark surfaces */
|
|
--color-paper: #f4f5f7; /* app/page background */
|
|
--color-line: #e3e6eb; /* 1px borders on light */
|
|
--color-rule: #eef0f3; /* table row dividers */
|
|
--color-edge: #d6dae1; /* stronger light border -- control panel, inputs */
|
|
--color-stroke: #c9cfd8; /* secondary-button border */
|
|
--color-muted: #6c7787; /* secondary text */
|
|
--color-dim: #8b95a4; /* tertiary text, inactive icons */
|
|
--color-slate: #3a4658; /* body copy on light */
|
|
--color-on-dark: #93a0b4;
|
|
--color-on-dark-dim: #7c8aa0;
|
|
--color-on-dark-faint: #5c6b85;
|
|
|
|
/* Fixed platform brand red -- the control panel is never club-branded (per the design
|
|
handoff), so this is NOT the club.secondary_color CSS variable used elsewhere. */
|
|
--color-club: #e4002b;
|
|
--color-club-dark: #b00021;
|
|
|
|
--color-ice: #14b8e8;
|
|
--color-ice-ink: #04212c;
|
|
|
|
--color-ok: #14a05a;
|
|
--color-ok-bg: #e6f6ee;
|
|
--color-ok-border: #bfe7d3;
|
|
--color-ok-text: #0c7a43;
|
|
|
|
--color-warn: #f0a22e;
|
|
--color-warn-bg: #fff5e4;
|
|
--color-warn-border: #f6e0b8;
|
|
--color-warn-text: #9a6410;
|
|
--color-warn-deep: #7a4e08;
|
|
|
|
--color-danger-bg: #fdecec;
|
|
--color-danger-border: #f5c9ce;
|
|
|
|
--color-info-bg: #eaf7fc;
|
|
--color-info-border: #c3e7f4;
|
|
--color-info-text: #0a6f91;
|
|
|
|
--color-row-sel: #fff7f8; /* selected table row */
|
|
--color-row-focus: #f4f9ff; /* focused/active row */
|
|
--color-row-warn: #fffdf6; /* row needing attention */
|
|
--color-subhead: #f8f9fa; /* table header fill */
|
|
|
|
--radius-box: 0.25rem; /* control panel is square by intent -- 4px, not the usual rounded-xl */
|
|
}
|
|
|
|
/* --- fonts: self-hosted, same latin/latin-ext split as assets/app.css and the same
|
|
reasoning -- no request to Google's CDN on an EU club platform's admin surface. --- */
|
|
|
|
@font-face {
|
|
font-family: "Barlow";
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-latin-400-normal.woff2") format("woff2");
|
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow";
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-latin-ext-400-normal.woff2") format("woff2");
|
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow";
|
|
font-style: normal;
|
|
font-weight: 500;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-latin-500-normal.woff2") format("woff2");
|
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow";
|
|
font-style: normal;
|
|
font-weight: 500;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-latin-ext-500-normal.woff2") format("woff2");
|
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow";
|
|
font-style: normal;
|
|
font-weight: 600;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-latin-600-normal.woff2") format("woff2");
|
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow";
|
|
font-style: normal;
|
|
font-weight: 600;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-latin-ext-600-normal.woff2") format("woff2");
|
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow";
|
|
font-style: normal;
|
|
font-weight: 700;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-latin-700-normal.woff2") format("woff2");
|
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow";
|
|
font-style: normal;
|
|
font-weight: 700;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-latin-ext-700-normal.woff2") format("woff2");
|
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow Condensed";
|
|
font-style: normal;
|
|
font-weight: 600;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-condensed-latin-600-normal.woff2") format("woff2");
|
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow Condensed";
|
|
font-style: normal;
|
|
font-weight: 600;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-condensed-latin-ext-600-normal.woff2") format("woff2");
|
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow Condensed";
|
|
font-style: normal;
|
|
font-weight: 700;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-condensed-latin-700-normal.woff2") format("woff2");
|
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow Condensed";
|
|
font-style: normal;
|
|
font-weight: 700;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-condensed-latin-ext-700-normal.woff2") format("woff2");
|
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow Condensed";
|
|
font-style: normal;
|
|
font-weight: 800;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-condensed-latin-800-normal.woff2") format("woff2");
|
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "Barlow Condensed";
|
|
font-style: normal;
|
|
font-weight: 800;
|
|
font-display: swap;
|
|
src: url("../fonts/barlow-condensed-latin-ext-800-normal.woff2") format("woff2");
|
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "IBM Plex Mono";
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
font-display: swap;
|
|
src: url("../fonts/ibm-plex-mono-latin-400-normal.woff2") format("woff2");
|
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "IBM Plex Mono";
|
|
font-style: normal;
|
|
font-weight: 400;
|
|
font-display: swap;
|
|
src: url("../fonts/ibm-plex-mono-latin-ext-400-normal.woff2") format("woff2");
|
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "IBM Plex Mono";
|
|
font-style: normal;
|
|
font-weight: 500;
|
|
font-display: swap;
|
|
src: url("../fonts/ibm-plex-mono-latin-500-normal.woff2") format("woff2");
|
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "IBM Plex Mono";
|
|
font-style: normal;
|
|
font-weight: 500;
|
|
font-display: swap;
|
|
src: url("../fonts/ibm-plex-mono-latin-ext-500-normal.woff2") format("woff2");
|
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "IBM Plex Mono";
|
|
font-style: normal;
|
|
font-weight: 600;
|
|
font-display: swap;
|
|
src: url("../fonts/ibm-plex-mono-latin-600-normal.woff2") format("woff2");
|
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
|
}
|
|
|
|
@font-face {
|
|
font-family: "IBM Plex Mono";
|
|
font-style: normal;
|
|
font-weight: 600;
|
|
font-display: swap;
|
|
src: url("../fonts/ibm-plex-mono-latin-ext-600-normal.woff2") format("woff2");
|
|
unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
|
}
|
|
|
|
/* @layer base, not a bare rule: a bare `body { background: ... }` is unlayered CSS, which
|
|
* beats every Tailwind utility class regardless of specificity -- including a `bg-ink` on
|
|
* <body> itself (see controlpanel/templates/controlpanel/_auth_base.html), which would
|
|
* silently lose to this and always render var(--color-paper) instead. Layering it puts it
|
|
* where Tailwind's own base styles live, so a `bg-*`/`text-*` utility on <body> wins as
|
|
* expected; this only supplies the default for whichever page doesn't set one. */
|
|
@layer base {
|
|
body {
|
|
background: var(--color-paper);
|
|
color: var(--color-slate);
|
|
font-family: var(--font-sans);
|
|
}
|
|
}
|
|
|
|
/* --- component layer: the daisyUI-shaped class vocabulary the shared form/message
|
|
templates render (controlpanel/templates/controlpanel/_form_fields.html,
|
|
controlpanel/templates/templatetags/field.html, controlpanel/templatetags/ui.py), plus
|
|
the same names used directly in controlpanel's own page templates. Hand-rolled rather
|
|
than @plugin "daisyui" -- see the file banner. --- */
|
|
|
|
@layer components {
|
|
/* Buttons -- 34-36px desktop per the handoff; controlpanel is desktop-only. */
|
|
.btn {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 0.5rem;
|
|
/* Matches .input/.select's own 2.25rem -- see that rule's comment; .btn itself
|
|
never had the clipping problem (flex centring), this is purely so a button
|
|
sitting next to a field in the same row lines up. */
|
|
height: 2.25rem;
|
|
padding-inline: 0.875rem;
|
|
border-radius: var(--radius-box);
|
|
font-family: var(--font-display);
|
|
font-weight: 800;
|
|
font-size: 0.8125rem;
|
|
letter-spacing: 0.1em;
|
|
text-transform: uppercase;
|
|
background: var(--color-ink);
|
|
color: #fff;
|
|
border: 1px solid transparent;
|
|
cursor: pointer;
|
|
transition: opacity 0.15s ease;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.btn:hover {
|
|
opacity: 0.85;
|
|
}
|
|
|
|
.btn:disabled {
|
|
opacity: 0.45;
|
|
cursor: not-allowed;
|
|
}
|
|
|
|
.btn-primary {
|
|
background: var(--color-club);
|
|
color: #fff;
|
|
}
|
|
|
|
.btn-success {
|
|
background: var(--color-ok);
|
|
color: #fff;
|
|
}
|
|
|
|
.btn-warning {
|
|
background: var(--color-warn);
|
|
color: var(--color-ink);
|
|
}
|
|
|
|
.btn-error {
|
|
background: var(--color-club-dark);
|
|
color: #fff;
|
|
}
|
|
|
|
.btn-ghost {
|
|
background: transparent;
|
|
color: var(--color-ink);
|
|
}
|
|
|
|
.btn-ghost:hover {
|
|
background: var(--color-rule);
|
|
opacity: 1;
|
|
}
|
|
|
|
.btn-outline {
|
|
background: #fff;
|
|
color: var(--color-ink);
|
|
border-color: var(--color-stroke);
|
|
}
|
|
|
|
.btn-outline:hover {
|
|
background: var(--color-subhead);
|
|
opacity: 1;
|
|
}
|
|
|
|
.btn-outline.btn-primary {
|
|
background: #fff;
|
|
color: var(--color-club-dark);
|
|
border-color: var(--color-danger-border);
|
|
}
|
|
|
|
.btn-outline.btn-error {
|
|
background: #fff;
|
|
color: var(--color-club-dark);
|
|
border-color: var(--color-danger-border);
|
|
}
|
|
|
|
.btn-outline.btn-success {
|
|
background: #fff;
|
|
color: var(--color-ok-text);
|
|
border-color: var(--color-ok-border);
|
|
}
|
|
|
|
/* accent -- allauth tags the passkey/security-key buttons "accent" (see
|
|
templates/allauth/elements/button.html and the manual btn-accent usages in
|
|
templates/account/login.html, password_change.html, mfa/authenticate.html).
|
|
Not one of the daisyUI semantic colours the rest of the app uses, so it gets
|
|
its own token: the ice cyan, which otherwise only appears on focus rings. */
|
|
.btn-accent {
|
|
background: var(--color-ice);
|
|
color: var(--color-ice-ink);
|
|
}
|
|
|
|
.btn-outline.btn-accent {
|
|
background: #fff;
|
|
color: var(--color-ice-ink);
|
|
border-color: var(--color-ice);
|
|
}
|
|
|
|
/* A bare text link shaped like a button-slot -- allauth's button element renders
|
|
this for anything tagged "link" (a lower-emphasis alternative action). */
|
|
.btn-link {
|
|
height: auto;
|
|
padding-inline: 0;
|
|
background: transparent;
|
|
color: var(--color-club-dark);
|
|
border-color: transparent;
|
|
text-transform: none;
|
|
letter-spacing: normal;
|
|
font-family: var(--font-sans);
|
|
font-weight: 600;
|
|
text-decoration: underline;
|
|
}
|
|
|
|
.btn-link:hover {
|
|
opacity: 1;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-soft {
|
|
background: color-mix(in oklab, currentColor 12%, transparent);
|
|
}
|
|
|
|
.btn-square {
|
|
padding-inline: 0;
|
|
width: 2.25rem;
|
|
}
|
|
|
|
.btn-sm {
|
|
height: 1.75rem;
|
|
padding-inline: 0.625rem;
|
|
font-size: 0.75rem;
|
|
}
|
|
|
|
.btn-xs {
|
|
height: 1.5rem;
|
|
padding-inline: 0.5rem;
|
|
font-size: 0.6875rem;
|
|
gap: 0.25rem;
|
|
}
|
|
|
|
/* Badges / status pills -- rounded-full per the handoff's "status pills" spec. */
|
|
.badge {
|
|
display: inline-flex;
|
|
align-items: center;
|
|
gap: 0.25rem;
|
|
padding: 0.15rem 0.6rem;
|
|
border-radius: 999px;
|
|
font-family: var(--font-display);
|
|
font-weight: 700;
|
|
font-size: 0.6875rem;
|
|
letter-spacing: 0.08em;
|
|
text-transform: uppercase;
|
|
background: var(--color-rule);
|
|
color: var(--color-slate);
|
|
border: 1px solid var(--color-line);
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.badge-sm {
|
|
font-size: 0.625rem;
|
|
padding: 0.1rem 0.45rem;
|
|
}
|
|
|
|
.badge-xs {
|
|
font-size: 0.5625rem;
|
|
padding: 0.05rem 0.35rem;
|
|
}
|
|
|
|
.badge-success {
|
|
background: var(--color-ok-bg);
|
|
color: var(--color-ok-text);
|
|
border-color: var(--color-ok-border);
|
|
}
|
|
|
|
.badge-error {
|
|
background: var(--color-danger-bg);
|
|
color: var(--color-club-dark);
|
|
border-color: var(--color-danger-border);
|
|
}
|
|
|
|
.badge-warning {
|
|
background: var(--color-warn-bg);
|
|
color: var(--color-warn-text);
|
|
border-color: var(--color-warn-border);
|
|
}
|
|
|
|
.badge-info {
|
|
background: var(--color-info-bg);
|
|
color: var(--color-info-text);
|
|
border-color: var(--color-info-border);
|
|
}
|
|
|
|
.badge-ghost,
|
|
.badge-outline {
|
|
background: #fff;
|
|
color: var(--color-muted);
|
|
border-color: var(--color-edge);
|
|
}
|
|
|
|
.badge-neutral {
|
|
background: var(--color-ink);
|
|
color: #fff;
|
|
border-color: var(--color-ink);
|
|
}
|
|
|
|
/* Cards -- square by intent (4px radius), hairline border, no shadow. */
|
|
.card {
|
|
background: #fff;
|
|
border: 1px solid var(--color-edge);
|
|
border-radius: var(--radius-box);
|
|
}
|
|
|
|
.card-body {
|
|
padding: 1.125rem;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.card-title {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
font-family: var(--font-display);
|
|
font-weight: 800;
|
|
font-size: 0.9375rem;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--color-ink);
|
|
}
|
|
|
|
/* The action row a card/form/panel puts its buttons in -- allauth's own form and
|
|
panel elements (templates/allauth/elements/form.html, panel.html) render this
|
|
unconditionally, pairing it with justify-end plus a margin/padding utility that
|
|
varies per call site. */
|
|
.card-actions {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
/* Tables -- CSS-grid-flavoured look via plain <table>: subhead fill, mono headings,
|
|
hairline row dividers. */
|
|
.table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
font-size: 0.8125rem;
|
|
}
|
|
|
|
.table thead tr {
|
|
background: var(--color-subhead);
|
|
border-bottom: 1px solid var(--color-line);
|
|
}
|
|
|
|
.table thead th {
|
|
padding: 0.5rem 0.875rem;
|
|
text-align: left;
|
|
font-family: var(--font-mono);
|
|
font-size: 0.6875rem;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--color-muted);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.table tbody tr {
|
|
border-bottom: 1px solid var(--color-rule);
|
|
}
|
|
|
|
.table tbody tr:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.table tbody td {
|
|
padding: 0.625rem 0.875rem;
|
|
color: var(--color-ink);
|
|
vertical-align: middle;
|
|
}
|
|
|
|
/* Alerts -- left-accented banner, per the handoff's severity-bar language. */
|
|
.alert {
|
|
display: flex;
|
|
align-items: flex-start;
|
|
gap: 0.75rem;
|
|
padding: 0.875rem 1rem;
|
|
border-radius: var(--radius-box);
|
|
border: 1px solid var(--color-line);
|
|
background: #fff;
|
|
font-size: 0.875rem;
|
|
}
|
|
|
|
.alert-soft {
|
|
background: var(--color-warn-bg);
|
|
}
|
|
|
|
.alert-error {
|
|
background: var(--color-danger-bg);
|
|
border-color: var(--color-danger-border);
|
|
color: var(--color-club-dark);
|
|
}
|
|
|
|
.alert-warning {
|
|
background: var(--color-warn-bg);
|
|
border-color: var(--color-warn-border);
|
|
color: var(--color-warn-deep);
|
|
}
|
|
|
|
.alert-success {
|
|
background: var(--color-ok-bg);
|
|
border-color: var(--color-ok-border);
|
|
color: var(--color-ok-text);
|
|
}
|
|
|
|
.alert-info {
|
|
background: var(--color-info-bg);
|
|
border-color: var(--color-info-border);
|
|
color: var(--color-info-text);
|
|
}
|
|
|
|
/* Avatars -- fallback initials block; a real club.logo uses the <img> branch. */
|
|
.avatar > div {
|
|
border-radius: 999px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.avatar-placeholder > div {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: var(--color-ink);
|
|
color: #fff;
|
|
font-family: var(--font-display);
|
|
font-weight: 800;
|
|
}
|
|
|
|
/* Progress bars. */
|
|
progress.progress {
|
|
appearance: none;
|
|
width: 100%;
|
|
height: 0.375rem;
|
|
border-radius: 999px;
|
|
overflow: hidden;
|
|
background: var(--color-rule);
|
|
border: none;
|
|
}
|
|
|
|
progress.progress::-webkit-progress-bar {
|
|
background: var(--color-rule);
|
|
}
|
|
|
|
progress.progress::-webkit-progress-value {
|
|
background: var(--color-ink);
|
|
}
|
|
|
|
progress.progress::-moz-progress-bar {
|
|
background: var(--color-ink);
|
|
}
|
|
|
|
progress.progress-success::-webkit-progress-value {
|
|
background: var(--color-ok);
|
|
}
|
|
|
|
progress.progress-success::-moz-progress-bar {
|
|
background: var(--color-ok);
|
|
}
|
|
|
|
progress.progress-warning::-webkit-progress-value {
|
|
background: var(--color-warn);
|
|
}
|
|
|
|
progress.progress-warning::-moz-progress-bar {
|
|
background: var(--color-warn);
|
|
}
|
|
|
|
progress.progress-error::-webkit-progress-value {
|
|
background: var(--color-club);
|
|
}
|
|
|
|
progress.progress-error::-moz-progress-bar {
|
|
background: var(--color-club);
|
|
}
|
|
|
|
/* Form controls -- rounded-lg per the handoff's field spec (a touch softer than the
|
|
square 4px chrome, matching "buttons and inputs rounded-lg"). */
|
|
.input,
|
|
.select,
|
|
.textarea,
|
|
.file-input {
|
|
width: 100%;
|
|
border: 1px solid var(--color-edge);
|
|
border-radius: 0.5rem;
|
|
background: #fff;
|
|
color: var(--color-ink);
|
|
font-family: var(--font-sans);
|
|
font-size: 0.875rem;
|
|
padding: 0.5rem 0.75rem;
|
|
}
|
|
|
|
/* .input and .select get an explicit, identical height rather than relying on padding
|
|
plus the browser's own line-height to land on the same box: a <select> reserves extra
|
|
space for its native dropdown arrow and several browsers give it a different default
|
|
line-height than a text <input>, so the same padding alone does not guarantee the
|
|
same rendered height. appearance: none plus a hand-drawn arrow replaces the native
|
|
one, since that reserved space was part of what caused the mismatch.
|
|
|
|
2.25rem, not 2.125rem: at the tighter height, a <select>'s own vertical text
|
|
centring (unlike .btn's flex centring below, a <select> isn't a flex container)
|
|
left only ~16px of content box for a 14px line -- descenders (g/y/p/q) rendered
|
|
clipped at the bottom in some browsers. .btn is bumped the same amount purely
|
|
for row alignment (a filter bar mixing buttons and inputs) -- flex centring
|
|
itself was never the problem. */
|
|
.input,
|
|
.select {
|
|
height: 2.25rem;
|
|
}
|
|
|
|
.select {
|
|
padding-right: 2rem;
|
|
appearance: none;
|
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 20' fill='none' stroke='%236c7787' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 7.5L10 12.5L15 7.5'/%3E%3C/svg%3E");
|
|
background-repeat: no-repeat;
|
|
background-position: right 0.6rem center;
|
|
background-size: 1rem;
|
|
}
|
|
|
|
.input:focus,
|
|
.select:focus,
|
|
.textarea:focus {
|
|
outline: 2px solid var(--color-ice);
|
|
outline-offset: -1px;
|
|
border-color: var(--color-ice);
|
|
}
|
|
|
|
.textarea {
|
|
height: auto;
|
|
min-height: 6rem;
|
|
}
|
|
|
|
.input-error,
|
|
.select-error,
|
|
.textarea-error {
|
|
border-color: var(--color-club);
|
|
color: var(--color-club-dark);
|
|
}
|
|
|
|
/* Taller variant for a code-entry input that has fallen back out of the boxed
|
|
.otp layout below (a recovery code is longer than the boxes fit). */
|
|
.input-lg {
|
|
height: 3rem;
|
|
font-family: var(--font-mono);
|
|
font-size: 1.125rem;
|
|
letter-spacing: 0.2em;
|
|
text-align: center;
|
|
}
|
|
|
|
/* Boxed one-time-code input -- recreates daisyUI's `otp`/`otp-lg` layout (a row of
|
|
character boxes with the real, accessible <input> sitting on top, invisible but still
|
|
focusable/typeable, so a tap or click still lands on it) without daisyUI. The boxes are
|
|
drawn as plain sibling <span>s -- see templates/allauth/elements/fields.html, which
|
|
keeps the exact daisyUI-shaped markup/class names because the same template also
|
|
renders on a club subdomain, where daisyUI itself (assets/app.css) still styles them.
|
|
A letter-spacing/text-indent overlay (faking alignment by spacing the real input's own
|
|
glyphs to match the box pitch) turned out too font-metric-fragile to land reliably --
|
|
drifted more with every character typed, in a way that resisted two rounds of tuning.
|
|
Instead the real input's text is made invisible (`color: transparent`, only the caret
|
|
shows) and controlpanel/templates/controlpanel/_auth_base.html's `data-otp` script
|
|
writes each typed character into its own <span>'s textContent -- exact by construction,
|
|
no font metrics involved. */
|
|
.otp {
|
|
position: relative;
|
|
display: inline-flex;
|
|
gap: 0.5rem;
|
|
}
|
|
|
|
.otp span {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
width: 2.75rem;
|
|
height: 3rem;
|
|
border: 1px solid var(--color-edge);
|
|
border-radius: 0.5rem;
|
|
background: #fff;
|
|
font-family: var(--font-mono);
|
|
font-size: 1.25rem;
|
|
color: var(--color-ink);
|
|
}
|
|
|
|
.otp:focus-within span {
|
|
border-color: var(--color-ice);
|
|
}
|
|
|
|
.otp input {
|
|
position: absolute;
|
|
inset: 0;
|
|
width: 100%;
|
|
height: 100%;
|
|
padding: 0;
|
|
border: none;
|
|
outline: none;
|
|
background: transparent;
|
|
color: transparent;
|
|
caret-color: var(--color-ink);
|
|
}
|
|
|
|
.otp-lg span {
|
|
width: 3.25rem;
|
|
height: 3.5rem;
|
|
font-size: 1.375rem;
|
|
}
|
|
|
|
.checkbox {
|
|
width: 1.125rem;
|
|
height: 1.125rem;
|
|
border-radius: 0.25rem;
|
|
border: 1.5px solid var(--color-stroke);
|
|
accent-color: var(--color-club);
|
|
}
|
|
|
|
.toggle {
|
|
width: 2.5rem;
|
|
height: 1.375rem;
|
|
border-radius: 999px;
|
|
accent-color: var(--color-ok);
|
|
}
|
|
|
|
.form-control {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
/* Wraps a .label-text (+ an optional trailing badge/alt), a row by default -- see
|
|
templates/allauth/elements/field.html and fields.html, whose checkbox layout
|
|
pairs it with justify-start/gap-3 utilities for the checkbox-then-text order. */
|
|
.label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.5rem;
|
|
padding-bottom: 0.375rem;
|
|
}
|
|
|
|
.label-text {
|
|
font-size: 0.8125rem;
|
|
font-weight: 600;
|
|
color: var(--color-slate);
|
|
}
|
|
|
|
.label-text-alt {
|
|
font-size: 0.75rem;
|
|
color: var(--color-muted);
|
|
}
|
|
|
|
/* Links inside table rows / prose. */
|
|
.link {
|
|
color: var(--color-club-dark);
|
|
text-decoration: none;
|
|
}
|
|
|
|
.link-hover:hover {
|
|
text-decoration: underline;
|
|
}
|
|
|
|
/* A plain horizontal rule between sections -- allauth's `hr` element
|
|
(templates/allauth/elements/hr.html) renders a bare `<div class="divider">`. */
|
|
.divider {
|
|
margin: 1.5rem 0;
|
|
border-top: 1px solid var(--color-line);
|
|
}
|
|
|
|
/* A native <details>/<summary> disclosure -- allauth's `details` element
|
|
(templates/allauth/elements/details.html), not currently exercised by any of
|
|
the pages this redesign covers, restyled defensively since it is shared
|
|
low-level allauth plumbing like the rest of templates/allauth/elements/. The
|
|
browser's own default marker on <summary> is left alone rather than replaced. */
|
|
.collapse {
|
|
border: 1px solid var(--color-line);
|
|
border-radius: var(--radius-box);
|
|
overflow: hidden;
|
|
}
|
|
|
|
.collapse-title {
|
|
padding: 0.75rem 1rem;
|
|
cursor: pointer;
|
|
font-weight: 600;
|
|
color: var(--color-ink);
|
|
}
|
|
|
|
.collapse-content {
|
|
padding: 0 1rem 1rem;
|
|
color: var(--color-slate);
|
|
}
|
|
|
|
.border-base-300 {
|
|
border-color: var(--color-line);
|
|
}
|
|
|
|
/* The command bar's account menu (controlpanel/base.html) -- a native
|
|
<details>/<summary> disclosure, so the only CSS it actually needs is hiding the
|
|
browser's own marker triangle; position/spacing are plain utilities at the call
|
|
site. */
|
|
.account-menu > summary {
|
|
list-style: none;
|
|
}
|
|
|
|
.account-menu > summary::-webkit-details-marker {
|
|
display: none;
|
|
}
|
|
|
|
/* --- daisyUI's semantic "base"/"content" vocabulary, aliased rather than renamed.
|
|
templates/allauth/elements/*.html, templates/allauth/layouts/base.html and
|
|
templates/403.html/maintenance.html are shared with the club-branded skin
|
|
(assets/app.css + real daisyUI, untouched, still in charge there), so they keep
|
|
daisyUI's own class names rather than controlpanel-specific ones. These give
|
|
those exact names an industrial-appropriate meaning for pages rendered through
|
|
this stylesheet; shadow-xl/shadow and .prose are deliberately left undefined --
|
|
no shadow and no auto-prose-spacing is the point of the square, hairline-bordered
|
|
look here, not a gap. --- */
|
|
.bg-base-100 {
|
|
background: #fff;
|
|
}
|
|
|
|
.border-base-content {
|
|
border-color: var(--color-line);
|
|
}
|
|
|
|
.border-base-content\/20 {
|
|
border-color: var(--color-line);
|
|
}
|
|
|
|
.text-base-content {
|
|
color: var(--color-slate);
|
|
}
|
|
|
|
.text-base-content\/70 {
|
|
color: var(--color-muted);
|
|
}
|
|
|
|
.text-base-content\/80 {
|
|
color: var(--color-slate);
|
|
}
|
|
|
|
.text-error,
|
|
.text-error-content {
|
|
color: var(--color-club-dark);
|
|
}
|
|
|
|
.text-warning {
|
|
color: var(--color-warn-deep);
|
|
}
|
|
|
|
.text-neutral-content {
|
|
color: #fff;
|
|
}
|
|
|
|
/* Divide-y utility (used by label/value stat lists). */
|
|
.divide-y > * + * {
|
|
border-top: 1px solid var(--color-rule);
|
|
}
|
|
|
|
/* Native <dialog>-based modals -- see controlpanel/templates/controlpanel/_modal_form.html
|
|
and _confirm_modal.html. No JS beyond the inline .showModal()/method=dialog already in
|
|
those templates; this only supplies the visual treatment daisyUI would otherwise. */
|
|
dialog.modal {
|
|
margin: auto;
|
|
padding: 0;
|
|
border: none;
|
|
border-radius: var(--radius-box);
|
|
background: transparent;
|
|
max-width: none;
|
|
max-height: none;
|
|
}
|
|
|
|
dialog.modal::backdrop {
|
|
background: rgba(11, 18, 32, 0.55);
|
|
}
|
|
|
|
dialog.modal .modal-box {
|
|
background: #fff;
|
|
border: 1px solid var(--color-edge);
|
|
border-radius: var(--radius-box);
|
|
padding: 1.5rem;
|
|
width: 32rem;
|
|
max-width: 91vw;
|
|
max-height: 85vh;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
dialog.modal.modal-start {
|
|
margin: 0 0 0 auto;
|
|
height: 100vh;
|
|
max-height: none;
|
|
}
|
|
|
|
dialog.modal.modal-start .modal-box {
|
|
height: 100%;
|
|
max-height: none;
|
|
border-radius: 0;
|
|
border-left: 1px solid var(--color-edge);
|
|
}
|
|
|
|
.modal-action {
|
|
display: flex;
|
|
justify-content: flex-end;
|
|
gap: 0.5rem;
|
|
margin-top: 1.5rem;
|
|
}
|
|
|
|
.modal-backdrop {
|
|
display: none;
|
|
}
|
|
|
|
/* The club crest mark -- fallback for every club until a real Club.logo is uploaded.
|
|
A plain circle, same convention as .avatar-placeholder elsewhere in this file. Size
|
|
and colour are set per usage site (bg-* + explicit width/height utilities); this only
|
|
supplies the shape. */
|
|
.crest {
|
|
border-radius: 999px;
|
|
}
|
|
|
|
/* A club's own primary_color, applied as a ring around its uploaded logo -- scoped to a
|
|
locally-set --color-primary custom property (see club_detail.html) rather than a
|
|
page-wide override, because the control panel itself is never club-branded. */
|
|
.ring-primary {
|
|
box-shadow:
|
|
0 0 0 2px #fff,
|
|
0 0 0 4px var(--color-primary, var(--color-edge));
|
|
}
|
|
|
|
/* Sidebar menu (mobile nav drawer only -- see base.html). */
|
|
.menu li a {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 0.625rem;
|
|
padding: 0.5rem 0.75rem;
|
|
border-radius: 0.375rem;
|
|
font-family: var(--font-display);
|
|
font-weight: 700;
|
|
font-size: 0.875rem;
|
|
letter-spacing: 0.04em;
|
|
text-transform: uppercase;
|
|
color: var(--color-slate);
|
|
}
|
|
|
|
.menu li a:hover {
|
|
background: var(--color-rule);
|
|
}
|
|
|
|
.menu li a.menu-active {
|
|
background: var(--color-club);
|
|
color: #fff;
|
|
}
|
|
|
|
.menu-title {
|
|
padding: 0.5rem 0.75rem 0.25rem;
|
|
font-family: var(--font-mono);
|
|
font-size: 0.6875rem;
|
|
letter-spacing: 0.06em;
|
|
text-transform: uppercase;
|
|
color: var(--color-dim);
|
|
}
|
|
}
|
|
|
|
/* SubscriptionForm.notes (Change plan / Start billing modal), PlanForm.description (New/Edit
|
|
* plan modal) and FlagForm.note (Edit feature modal): templatetags/field.html's textarea
|
|
* branch hard-codes an `h-72` (18rem) utility class on every textarea with no per-field way
|
|
* to pass rows/height, so the only remaining hook is the rendered `name` attribute -- unique
|
|
* to these fields within the control panel (no other controlpanel form uses "notes",
|
|
* "description" or "note"). Kept unlayered, rather than inside `@layer components` above, so
|
|
* it beats the `.h-72` utility class regardless of selector specificity: Tailwind's utilities
|
|
* layer is declared after components and always wins at equal or lower specificity, and only
|
|
* an unlayered rule is guaranteed to outrank it. Every other textarea in the panel
|
|
* (maintenance message, etc.) is untouched, so this does not shrink anything else. */
|
|
textarea[name="notes"],
|
|
textarea[name="description"],
|
|
textarea[name="note"] {
|
|
height: 5rem;
|
|
}
|