/*
 * ============================================================
 *  UNISPECT DESIGN SYSTEM — Design Tokens (Single Source of Truth)
 *  All brand colors, typography, spacing, and elevation are
 *  defined here. Import this file first in every CSS entry point.
 *
 *  Palette: Gray / Blueish — modern, professional, calm
 * ============================================================
 */

/*
 * ── Webfonts ─────────────────────────────────────────────────
 *  Inter is the face --font-family-base names first. It is self-hosted from wwwroot/fonts
 *  rather than linked from Google Fonts, so rendering a page never sends a visitor's IP address
 *  to a third party - a GDPR point for a service whose privacy notice names its processors.
 *  The files are the latin and latin-ext subsets of Inter v20 (SIL Open Font License 1.1) as a
 *  variable font; one file covers every weight, and the pages use 400-700.
 */
@font-face {
    font-family: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../fonts/inter-latin.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: 'Inter';
    font-style: normal;
    font-weight: 100 900;
    font-display: swap;
    src: url('../fonts/inter-latin-ext.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;
}

:root {
    /* ── Brand Palette ────────────────────────────────────── */
    --color-brand-50:  #eef3f9;   /* lightest tint */
    --color-brand-100: #d5e3f0;
    --color-brand-200: #a8c4e0;
    --color-brand-300: #6e9dc8;
    --color-brand-400: #3d7ab0;
    --color-brand-500: #2f6699;   /* primary brand */
    --color-brand-600: #1f4f7a;   /* hover / active */
    --color-brand-700: #163a5c;
    --color-brand-800: #0e2640;
    --color-brand-900: #071525;   /* darkest shade */

    /* ── Neutral / Gray ───────────────────────────────────── */
    --color-gray-50:  #f7f8fa;
    --color-gray-100: #eef0f3;
    --color-gray-200: #dde1e7;
    --color-gray-300: #c4c9d4;
    --color-gray-400: #9da5b4;
    --color-gray-500: #6b7585;
    --color-gray-600: #4e5869;
    --color-gray-700: #363e4d;
    --color-gray-800: #22283a;
    --color-gray-900: #131820;

    /* ── Semantic Colors ──────────────────────────────────── */
    --color-surface:        #ffffff;
    --color-surface-raised: var(--color-gray-50);
    --color-surface-overlay: var(--color-gray-100);

    --color-background:     var(--color-gray-50);
    --color-background-alt: var(--color-brand-50);

    --color-text-primary:   var(--color-gray-900);
    --color-text-secondary: var(--color-gray-600);
    --color-text-disabled:  var(--color-gray-400);
    --color-text-inverse:   #ffffff;

    --color-primary:        var(--color-brand-500);
    --color-primary-hover:  var(--color-brand-600);
    --color-primary-active: var(--color-brand-700);
    --color-primary-subtle: var(--color-brand-50);

    --color-border:         var(--color-gray-200);
    --color-border-focus:   var(--color-brand-400);

    /* ── Feedback Colors ──────────────────────────────────── */
    --color-success:  #2e7d56;
    --color-warning:  #b06c1a;
    --color-error:    #b32121;
    --color-error-hover: #8f1a1a;
    --color-info:     var(--color-brand-500);

    /* Each feedback role also has a wash to sit on and an ink to read on that wash. The pairs were
       hardcoded inside .us-badge-* and .text-bg-* before they were named here, which is how a
       status pill and the note beside it could disagree about the same green. -ink is darker than
       the base colour on purpose: it carries text on the tint, where the base passes on white but
       not on its own wash. */
    --color-success-subtle: #e6f4ea;
    --color-success-ink:    #1c6b45;
    --color-warning-subtle: #fdf3e3;
    --color-warning-ink:    #8a5410;
    --color-error-subtle:   #fdecec;
    --color-error-ink:      #97282c;
    --color-info-subtle:    var(--color-brand-50);
    --color-info-ink:       var(--color-brand-600);

    /* A separator between two facts on one line, where the hairline would disappear. */
    --color-border-strong:  var(--color-gray-300);

    /* ── Sidebar / Nav ────────────────────────────────────── */
    --color-nav-bg:           var(--color-gray-800);
    --color-nav-bg-hover:     var(--color-gray-700);
    --color-nav-bg-active:    var(--color-brand-600);
    --color-nav-text:         var(--color-gray-200);
    --color-nav-text-active:  #ffffff;
    --color-nav-border:       var(--color-gray-700);
    --color-nav-logo-bg:      var(--color-gray-900);

    /* ── Topbar ───────────────────────────────────────────── */
    --color-topbar-bg:    var(--color-surface);
    --color-topbar-border: var(--color-border);

    /* ── Typography ───────────────────────────────────────── */
    --font-family-base: 'Inter', 'Segoe UI', system-ui, -apple-system, sans-serif;
    --font-family-mono: 'JetBrains Mono', 'Cascadia Code', 'Fira Code', monospace;

    --font-size-xs:   0.75rem;   /*  12px */
    --font-size-sm:   0.875rem;  /*  14px */
    --font-size-base: 1rem;      /*  16px */
    --font-size-md:   1.125rem;  /*  18px */
    --font-size-lg:   1.25rem;   /*  20px */
    --font-size-xl:   1.5rem;    /*  24px */
    --font-size-2xl:  1.875rem;  /*  30px */
    --font-size-3xl:  2.25rem;   /*  36px */

    --font-weight-normal:   400;
    --font-weight-medium:   500;
    --font-weight-semibold: 600;
    --font-weight-bold:     700;

    --line-height-tight:  1.25;
    --line-height-base:   1.5;
    --line-height-loose:  1.75;

    /* ── Spacing (4px base grid) ──────────────────────────── */
    --space-1:  0.25rem;   /*  4px */
    --space-2:  0.5rem;    /*  8px */
    --space-3:  0.75rem;   /* 12px */
    --space-4:  1rem;      /* 16px */
    --space-5:  1.25rem;   /* 20px */
    --space-6:  1.5rem;    /* 24px */
    --space-8:  2rem;      /* 32px */
    --space-10: 2.5rem;    /* 40px */
    --space-12: 3rem;      /* 48px */
    --space-16: 4rem;      /* 64px */

    /* ── Border Radius ────────────────────────────────────── */
    --radius-sm:   0.25rem;   /*  4px */
    --radius-md:   0.5rem;    /*  8px */
    --radius-lg:   0.75rem;   /* 12px */
    --radius-xl:   1rem;      /* 16px */
    --radius-full: 9999px;    /* pill */

    /* ── Shadows / Elevation ──────────────────────────────── */
    --shadow-xs: 0 1px 2px rgba(0,0,0,.06);
    --shadow-sm: 0 1px 4px rgba(0,0,0,.08);
    --shadow-md: 0 4px 12px rgba(0,0,0,.10);
    --shadow-lg: 0 8px 24px rgba(0,0,0,.12);
    --shadow-xl: 0 16px 40px rgba(0,0,0,.14);

    /* The one focus halo, on buttons and fields alike; .us-event-theme re-points it. */
    --focus-ring: 0 0 0 3px var(--color-brand-100);

    /* ── Layout ───────────────────────────────────────────── */
    --sidebar-width:      260px;
    --sidebar-width-icon: 60px;
    --topbar-height:      72px;
    --content-max-width:  1280px;

    /* ── Transitions ──────────────────────────────────────── */
    --transition-fast:   100ms ease;
    --transition-base:   200ms ease;
    --transition-slow:   350ms ease;

    /* ── Z-index scale ────────────────────────────────────── */
    --z-base:    1;
    --z-dropdown: 100;
    --z-sticky:   200;
    --z-overlay:  300;
    --z-modal:    400;
    --z-toast:    500;
}

/*
 * ── Global Reset & Base Styles ──────────────────────────────
 */
*, *::before, *::after {
    box-sizing: border-box;
}

html {
    font-size: 16px;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    scroll-behavior: smooth;
}

body {
    font-family: var(--font-family-base);
    font-size: var(--font-size-base);
    font-weight: var(--font-weight-normal);
    line-height: var(--line-height-base);
    color: var(--color-text-primary);
    background-color: var(--color-background);
    margin: 0;
}

/* ── Headings ───────────────────────────────────────────────── */
h1, h2, h3, h4, h5, h6 {
    font-weight: var(--font-weight-semibold);
    line-height: var(--line-height-tight);
    color: var(--color-text-primary);
    margin-top: 0;
    margin-bottom: var(--space-4);
}

h1 { font-size: var(--font-size-3xl); }
h2 { font-size: var(--font-size-2xl); }
h3 { font-size: var(--font-size-xl); }
h4 { font-size: var(--font-size-lg); }
h5 { font-size: var(--font-size-md); }
h6 { font-size: var(--font-size-base); }

/* ── Links ──────────────────────────────────────────────────── */
a {
    color: var(--color-primary);
    text-decoration: none;
    transition: color var(--transition-fast);
}

a:hover {
    color: var(--color-primary-hover);
    text-decoration: underline;
}

/* ── Focus rings ────────────────────────────────────────────── */
:focus-visible {
    outline: 2px solid var(--color-border-focus);
    outline-offset: 2px;
}

/* ── Utility: card ──────────────────────────────────────────── */
.us-card {
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--space-6);
    box-shadow: var(--shadow-sm);
}

/* ── Utility: badge ─────────────────────────────────────────── */
.us-badge {
    display: inline-flex;
    align-items: center;
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-full);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-medium);
    background: var(--color-primary-subtle);
    color: var(--color-primary);
}

/* ── Utility: status pill ───────────────────────────────────────
   A state, not a count: "Open · closes 2026-01-20", "Closed", "Requested". Each variant is a
   feedback wash with its own ink, so the pill reads on the tint rather than relying on the base
   colour that only passes on white. Muted is the absence of a state and carries no colour at all -
   a closed competition is not a warning. */
.us-pill {
    display: inline-flex;
    align-items: center;
    gap: var(--space-1);
    padding: var(--space-1) var(--space-3);
    border-radius: var(--radius-full);
    font-size: var(--font-size-xs);
    font-weight: var(--font-weight-semibold);
    line-height: 1.4;
    white-space: nowrap;
}

.us-pill-success { background: var(--color-success-subtle); color: var(--color-success-ink); }
.us-pill-warning { background: var(--color-warning-subtle); color: var(--color-warning-ink); }
.us-pill-error   { background: var(--color-error-subtle);   color: var(--color-error-ink); }
.us-pill-info    { background: var(--color-info-subtle);    color: var(--color-info-ink); }
.us-pill-muted   { background: var(--color-surface-overlay); color: var(--color-text-secondary); }

/* ── Utility: divider ───────────────────────────────────────── */
.us-divider {
    border: none;
    border-top: 1px solid var(--color-border);
    margin: var(--space-6) 0;
}

/* ── Buttons ────────────────────────────────────────────────────
   The pages use Bootstrap's button classes, so each variant is re-pointed here at the one token
   that owns its role: primary and outline-primary at --color-primary, danger at --color-error,
   success at --color-success, secondary and outline-secondary at the hairline outline. Every
   Bootstrap state selector (:hover, :focus, :active, :disabled) is restated on purpose: Bootstrap
   paints its own #0d6efd on those with higher specificity than the base class, which is how a
   disabled "Tilldela" was Bootstrap blue while the enabled one was brand blue. */
.btn {
    border-radius: var(--radius-md);
    font-weight: var(--font-weight-medium);
    transition: background-color var(--transition-fast), border-color var(--transition-fast),
                color var(--transition-fast), box-shadow var(--transition-fast);
}

/* Radii climb with the element - 8px on every button, small ones included. */
.btn-sm, .btn-group-sm > .btn {
    border-radius: var(--radius-md);
}

/* Disabled stays visible - dimmed, never hidden - and says so with the cursor. */
.btn:disabled, .btn.disabled {
    opacity: 0.55;
}

.btn:disabled {
    pointer-events: auto;
    cursor: not-allowed;
}

/* Primary: the brand blue, in every state. */
.btn-primary,
.btn-primary:focus {
    background-color: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-text-inverse);
}

.btn-primary:hover {
    background-color: var(--color-primary-hover);
    border-color: var(--color-primary-hover);
    color: var(--color-text-inverse);
    box-shadow: var(--shadow-sm);
}

.btn-primary:active, .btn-primary.active, .btn-primary:active:focus {
    background-color: var(--color-primary-active);
    border-color: var(--color-primary-active);
    color: var(--color-text-inverse);
}

.btn-primary:disabled, .btn-primary.disabled {
    background-color: var(--color-primary);
    border-color: var(--color-primary);
    color: var(--color-text-inverse);
    box-shadow: none;
}

.btn-outline-primary,
.btn-outline-primary:focus {
    color: var(--color-primary);
    border-color: var(--color-primary);
    background-color: transparent;
}

.btn-outline-primary:hover,
.btn-outline-primary:active, .btn-outline-primary.active, .btn-outline-primary:active:focus {
    color: var(--color-text-inverse);
    background-color: var(--color-primary);
    border-color: var(--color-primary);
}

.btn-outline-primary:disabled, .btn-outline-primary.disabled {
    color: var(--color-primary);
    border-color: var(--color-primary);
    background-color: transparent;
}

/* Secondary: a hairline outline on the surface. Bootstrap's grey fill (#6c757d) is not a colour
   in this system, so .btn-secondary and .btn-outline-secondary are the same control. */
.btn-secondary, .btn-outline-secondary,
.btn-secondary:focus, .btn-outline-secondary:focus {
    color: var(--color-text-primary);
    background-color: transparent;
    border-color: var(--color-border);
}

.btn-secondary:hover, .btn-outline-secondary:hover,
.btn-secondary:active, .btn-secondary.active, .btn-secondary:active:focus,
.btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary:active:focus {
    color: var(--color-text-primary);
    background-color: var(--color-surface-overlay);
    border-color: var(--color-gray-300);
}

.btn-secondary:disabled, .btn-secondary.disabled,
.btn-outline-secondary:disabled, .btn-outline-secondary.disabled {
    color: var(--color-text-primary);
    background-color: transparent;
    border-color: var(--color-border);
}

/* Destructive: --color-error, not Bootstrap's #dc3545. A red fill always carries white text -
   --color-text-inverse is not used here because an organizer theme may re-point it to black for
   a light club colour, and that is a decision about the club's blue, not about red. */
.btn-danger,
.btn-danger:focus {
    color: #ffffff;
    background-color: var(--color-error);
    border-color: var(--color-error);
}

.btn-danger:hover,
.btn-danger:active, .btn-danger.active, .btn-danger:active:focus {
    color: #ffffff;
    background-color: var(--color-error-hover);
    border-color: var(--color-error-hover);
}

.btn-danger:disabled, .btn-danger.disabled {
    color: #ffffff;
    background-color: var(--color-error);
    border-color: var(--color-error);
}

.btn-outline-danger,
.btn-outline-danger:focus {
    color: var(--color-error);
    border-color: var(--color-error);
    background-color: transparent;
}

.btn-outline-danger:hover,
.btn-outline-danger:active, .btn-outline-danger.active, .btn-outline-danger:active:focus {
    color: #ffffff;
    background-color: var(--color-error);
    border-color: var(--color-error);
}

.btn-outline-danger:disabled, .btn-outline-danger.disabled {
    color: var(--color-error);
    border-color: var(--color-error);
    background-color: transparent;
}

/* Success and warning follow the feedback tokens the badges already use. */
.btn-success, .btn-success:focus, .btn-success:disabled, .btn-success.disabled {
    color: #ffffff;
    background-color: var(--color-success);
    border-color: var(--color-success);
}

.btn-success:hover, .btn-success:active, .btn-success.active, .btn-success:active:focus {
    color: #ffffff;
    background-color: color-mix(in srgb, var(--color-success) 85%, black);
    border-color: color-mix(in srgb, var(--color-success) 85%, black);
}

.btn-outline-success, .btn-outline-success:focus,
.btn-outline-success:disabled, .btn-outline-success.disabled {
    color: var(--color-success);
    border-color: var(--color-success);
    background-color: transparent;
}

.btn-outline-success:hover,
.btn-outline-success:active, .btn-outline-success.active, .btn-outline-success:active:focus {
    color: #ffffff;
    background-color: var(--color-success);
    border-color: var(--color-success);
}

.btn-outline-warning, .btn-outline-warning:focus,
.btn-outline-warning:disabled, .btn-outline-warning.disabled {
    color: var(--color-warning);
    border-color: var(--color-warning);
    background-color: transparent;
}

.btn-outline-warning:hover,
.btn-outline-warning:active, .btn-outline-warning.active, .btn-outline-warning:active:focus {
    color: #ffffff;
    background-color: var(--color-warning);
    border-color: var(--color-warning);
}

.btn-link, .btn-link:focus {
    color: var(--color-primary);
}

.btn-link:hover, .btn-link:active {
    color: var(--color-primary-hover);
}

/* Focus: Bootstrap draws a #0d6efd-tinted ring on every focused button, mouse clicks included.
   Here a mouse click shows nothing and keyboard focus shows the system's outline plus halo. */
.btn:focus, .btn:active:focus {
    box-shadow: none;
}

.btn:focus-visible {
    outline: 2px solid var(--color-border-focus);
    outline-offset: 2px;
    box-shadow: var(--focus-ring);
}

/* ── Form controls ──────────────────────────────────────────────
   Bootstrap's controls, restyled. The right padding on a select is the room its caret is drawn
   in - shortening it is what put the arrow on top of "GlobalAdmin". The -sm variants are stated
   here too, after the base rule, or the base rule (equal specificity, later file) beats
   Bootstrap's and "small" is not small. */
.form-control,
.form-select {
    border: 1px solid var(--color-border);
    border-radius: var(--radius-md);
    padding: var(--space-2) var(--space-3);
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
    background-color: var(--color-surface);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
}

/* A select has to keep the room its caret is drawn in. The caret itself is the system's
   secondary grey, not Bootstrap's #343a40. */
.form-select {
    padding-right: 2.25rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='none' stroke='%234e5869' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M2 5l6 6 6-6'/%3E%3C/svg%3E");
    background-position: right var(--space-3) center;
    background-size: 14px 10px;
}

/* Small really is small - and keeps a proportional caret gutter. */
.form-control-sm {
    padding: var(--space-1) var(--space-2);
    font-size: var(--font-size-sm);
}

.form-select-sm {
    padding: var(--space-1) 1.75rem var(--space-1) var(--space-2);
    font-size: var(--font-size-sm);
    background-position: right var(--space-2) center;
}

.form-control:focus,
.form-select:focus {
    border-color: var(--color-border-focus);
    box-shadow: var(--focus-ring);
    outline: none;
}

.form-control::placeholder {
    color: var(--color-text-disabled);
}

/* Checkboxes and radios: Bootstrap fills a checked box with #0d6efd and rings it in #86b7fe. */
.form-check-input:checked {
    background-color: var(--color-primary);
    border-color: var(--color-primary);
}

.form-check-input:focus {
    border-color: var(--color-border-focus);
    box-shadow: var(--focus-ring);
}

/* ── Validation ─────────────────────────────────────────────── */
.valid.modified:not([type=checkbox]) {
    border-color: var(--color-success);
    box-shadow: 0 0 0 2px rgba(46, 125, 86, .15);
}

.invalid {
    border-color: var(--color-error);
    box-shadow: 0 0 0 2px rgba(179, 33, 33, .15);
}

.validation-message {
    color: var(--color-error);
    font-size: var(--font-size-sm);
    margin-top: var(--space-1);
}

/* ── Sidebar / Nav ──────────────────────────────────────────── */
.sidebar {
    width: var(--sidebar-width);
    background-color: var(--color-nav-bg);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    transition: width var(--transition-base);
    overflow: hidden;
    box-shadow: var(--shadow-md);
    flex-shrink: 0;
}

.sidebar .navbar {
    background-color: var(--color-nav-logo-bg) !important;
    border-bottom: 1px solid var(--color-nav-border);
    padding: var(--space-3) var(--space-4);
}

.sidebar .nav-link {
    color: var(--color-nav-text);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
    display: flex;
    align-items: center;
    gap: var(--space-3);
    padding: var(--space-2) var(--space-4);
    border-radius: var(--radius-md);
    margin: var(--space-1) var(--space-2);
    transition: background-color var(--transition-fast), color var(--transition-fast);
    white-space: nowrap;
    overflow: hidden;
}

.sidebar .nav-link:hover {
    background-color: var(--color-nav-bg-hover);
    color: var(--color-nav-text-active);
    text-decoration: none;
}

.sidebar .nav-link.active {
    background-color: var(--color-nav-bg-active);
    color: var(--color-nav-text-active);
    box-shadow: var(--shadow-xs);
}

.sidebar .nav-link label {
    cursor: pointer;
    font-size: var(--font-size-sm);
}

/* ── Topbar ─────────────────────────────────────────────────── */
.top-row {
    height: var(--topbar-height);
    background-color: var(--color-topbar-bg);
    border-bottom: 1px solid var(--color-topbar-border);
    display: flex;
    align-items: center;
    padding: 0 var(--space-6);
    box-shadow: var(--shadow-xs);
    position: sticky;
    top: 0;
    z-index: var(--z-sticky);
}

/* ── Page layout ────────────────────────────────────────────── */
.page {
    display: flex;
    min-height: 100vh;
}

main {
    flex: 1;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    background-color: var(--color-background);
}

.content {
    padding: var(--space-8) var(--space-6);
    max-width: var(--content-max-width);
    width: 100%;
}

/* ── Blazor error UI ────────────────────────────────────────── */
#blazor-error-ui {
    background: #fff3cd;
    border-top: 2px solid var(--color-warning);
    bottom: 0;
    box-shadow: var(--shadow-lg);
    display: none;
    left: 0;
    padding: var(--space-3) var(--space-6);
    position: fixed;
    width: 100%;
    z-index: var(--z-toast);
    font-size: var(--font-size-sm);
    color: var(--color-gray-800);
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: var(--space-4);
    top: 50%;
    transform: translateY(-50%);
}

.blazor-error-boundary {
    background: var(--color-error);
    padding: var(--space-4) var(--space-4) var(--space-4) 3.7rem;
    color: white;
    border-radius: var(--radius-md);
}

.blazor-error-boundary::after {
    content: "An error has occurred.";
}

/* ── Loading progress ───────────────────────────────────────── */
.loading-progress {
    position: relative;
    display: block;
    width: 8rem;
    height: 8rem;
    margin: 20vh auto var(--space-4) auto;
}

.loading-progress circle {
    fill: none;
    stroke: var(--color-gray-200);
}

.loading-progress circle:last-child {
    stroke: var(--color-primary);
}

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: var(--font-weight-medium);
    inset: calc(20vh + 3.25rem) 0 auto;
    color: var(--color-text-secondary);
}

/* ── Tables ─────────────────────────────────────────────────── */
.table {
    border-collapse: separate;
    border-spacing: 0;
    width: 100%;
    font-size: var(--font-size-sm);
    color: var(--color-text-primary);
}

.table th {
    background-color: var(--color-surface-raised);
    color: var(--color-text-secondary);
    font-weight: var(--font-weight-semibold);
    font-size: var(--font-size-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--color-border);
}

.table td {
    padding: var(--space-3) var(--space-4);
    border-bottom: 1px solid var(--color-border);
    vertical-align: middle;
}

/* The hover is the row affordance: it says "this row's dropdown and delete button belong
   together". There is no zebra striping - Bootstrap's .table-striped paints an inset shadow on
   the cells of every other row, which sat on top of this hover and hid it on half the rows. */
.table tbody tr {
    transition: background-color var(--transition-fast);
}

.table tbody tr:hover {
    background-color: var(--color-surface-raised);
}

/* Should the class come back on a table, it does nothing - the hover must stay visible. */
.table-striped > tbody > tr:nth-of-type(odd) {
    --bs-table-accent-bg: transparent;
    color: inherit;
}

/* ── Bootstrap colour utilities → tokens ─────────────────────────
   The markup uses Bootstrap's text-* classes; Bootstrap's values (#6c757d grey, #dc3545 red,
   #0d6efd blue) are not colours in this system. The !important matches Bootstrap's own, so the
   later declaration here is the one that applies. */
.text-secondary { color: var(--color-text-secondary) !important; }
.text-primary   { color: var(--color-primary) !important; }
.text-danger    { color: var(--color-error) !important; }
.text-success   { color: var(--color-success) !important; }
.text-warning   { color: var(--color-warning) !important; }

/* ── Responsive: collapse sidebar on small screens ───────────── */
@media (max-width: 768px) {
    .sidebar {
        position: fixed;
        z-index: var(--z-overlay);
        transform: translateX(-100%);
        transition: transform var(--transition-base);
    }

    .sidebar.open {
        transform: translateX(0);
    }
}

/* ── Marketing / Page utilities ──────────────────────────────── */
.us-hero {
    background: linear-gradient(135deg, var(--color-brand-50), var(--color-surface));
    border-radius: var(--radius-xl);
    padding: var(--space-12) var(--space-8);
    margin-bottom: var(--space-12);
    border: 1px solid var(--color-border);
}

.us-hero-inner {
    max-width: 720px;
}

.us-hero h1 {
    font-size: var(--font-size-3xl);
    margin-top: var(--space-4);
}

.us-lead {
    font-size: var(--font-size-md);
    color: var(--color-text-secondary);
    line-height: var(--line-height-loose);
}

.us-hero-actions {
    display: flex;
    gap: var(--space-3);
    margin-top: var(--space-6);
    flex-wrap: wrap;
}

.us-section {
    margin-bottom: var(--space-12);
}

.us-page-header {
    margin-bottom: var(--space-8);
}

.us-grid {
    display: grid;
    gap: var(--space-6);
}

.us-grid-2 {
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}

.us-grid-3 {
    grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}

.us-card-link {
    display: block;
    text-decoration: none;
    color: inherit;
    transition: transform var(--transition-fast), box-shadow var(--transition-fast), border-color var(--transition-fast);
}

.us-card-link:hover {
    text-decoration: none;
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: var(--color-primary);
}

.us-card-cta {
    display: inline-block;
    margin-top: var(--space-3);
    color: var(--color-primary);
    font-weight: var(--font-weight-medium);
}


/* ===== Event Logo / Banner =====
   What organizers upload here is a club logo at least as often as it is a wide photograph, and a
   logo cannot be cropped: "cover" filled the band by cutting the ends off the club's name. So the
   whole image is fitted inside the band instead, at its own proportions, whatever its dimensions -
   a tall logo shrinks to the height and centres, a wide banner spans the width. The cost is that
   an image whose shape does not match the band is padded at the sides rather than trimmed, which
   is the right way round: a letterboxed logo still reads, a cropped one does not.

   Same arrangement as .us-org-banner below, which already had to solve this for club logos. */
.us-event-banner {
    width: 100%;
    max-height: 280px;
    min-height: 160px;
    object-fit: contain;
    object-position: center;
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-sm);
    display: block;
    /* The padding keeps the artwork off its own rounded corners; the surface behind it is white
       rather than grey because a logo is nearly always drawn to sit on white. */
    padding: var(--space-3);
    background: var(--color-surface);
}

.us-org-banner {
    width: 100%;
    max-height: 200px;
    min-height: 120px;
    object-fit: contain;
    background: var(--color-surface);
    border: 1px solid var(--color-border);
    border-radius: var(--radius-lg);
    padding: var(--space-3);
}

.us-logo-thumb {
    width: 40px;
    height: 40px;
    object-fit: cover;
    border-radius: var(--radius-sm);
    background: var(--color-gray-100);
    border: 1px solid var(--color-border);
}

.us-logo-thumb-sm {
    width: 24px;
    height: 24px;
    object-fit: cover;
    border-radius: var(--radius-sm);
}

.us-item-thumb {
    width: 100%;
    height: 180px;
    object-fit: cover;
    border-radius: var(--radius-md);
    background: var(--color-gray-100);
    border: 1px solid var(--color-border);
    display: block;
}

.us-item-thumb-placeholder {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 3rem;
    font-weight: var(--font-weight-medium);
    color: var(--color-text-secondary);
    text-transform: uppercase;
}

.us-upload-warning {
    margin-top: var(--space-2);
    color: var(--color-warning);
    font-size: var(--font-size-sm);
    font-weight: var(--font-weight-medium);
}


/* ===== Organization branding (public competition registration) =====
   Public pages wrap their content in .us-event-theme and set --us-brand / --us-accent inline from
   the organizing club's colours. Everything here re-points the design tokens at those two, so a
   themed page restyles by cascade instead of by sprinkling inline colours over each element.
   With no inline values the fallbacks below keep the standard Unispect palette. */
.us-event-theme {
    --us-brand: var(--color-brand-500);
    --us-brand-rgb: 47, 102, 153;
    --us-brand-contrast: #ffffff;
    --us-accent: var(--us-brand);
    --us-accent-contrast: var(--us-brand-contrast);

    --color-primary: var(--us-brand);
    --color-primary-hover: color-mix(in srgb, var(--us-brand) 85%, black);
    --color-primary-active: color-mix(in srgb, var(--us-brand) 72%, black);
    --color-primary-subtle: color-mix(in srgb, var(--us-brand) 12%, white);
    --color-border-focus: var(--us-brand);
    --color-info: var(--us-brand);
    /* The wash and the ink move with it, or an info note on a themed page is a club-coloured
       border around an unthemed blue tint. */
    --color-info-subtle: color-mix(in srgb, var(--us-brand) 10%, white);
    --color-info-ink: color-mix(in srgb, var(--us-brand) 80%, black);
    --color-text-inverse: var(--us-brand-contrast);
    --focus-ring: 0 0 0 3px color-mix(in srgb, var(--us-brand) 35%, white);

    /* Bootstrap utilities in use on these pages (badges, links) read their own variables. */
    --bs-primary: var(--us-brand);
    --bs-primary-rgb: var(--us-brand-rgb);
    --bs-link-color: var(--us-brand);
    --bs-link-hover-color: var(--color-primary-hover);
}

.us-event-theme .badge.bg-primary {
    background-color: var(--us-brand) !important;
    color: var(--us-brand-contrast) !important;
}

/* Banner sized down for the wizard steps, where it is a reminder rather than a headline. */
/* The wizard's version, sitting above a form rather than heading a page. The padding shrinks with
   the band - 12px out of 120 would spend a fifth of the height on empty space. */
.us-event-banner-compact {
    max-height: 120px;
    min-height: 64px;
    padding: var(--space-2);
}

/* The organizer's own words about the competition. Written in a textarea, so the line breaks the
   author typed are the ones that show - but runs of blank lines are not multiplied out. */
.us-event-description {
    white-space: pre-line;
    margin-bottom: var(--space-4);
}

/* Shown when the competition has no banner of its own: the club's name on its colours, so even an
   event without artwork is recognisably the organizer's. */
/* Solid brand behind the text, never the gradient. --us-brand-contrast is picked by WCAG contrast
   against --us-brand alone, so it can only be trusted where --us-brand alone is what sits behind
   the text; with a light accent the right-hand end of a gradient falls to about 3:1 and the name
   becomes unreadable. The two-colour profile is shown by the accent rule underneath instead. */
.us-event-brandbar {
    display: flex;
    align-items: center;
    gap: var(--space-3);
    flex-wrap: wrap;
    padding: var(--space-3) var(--space-4);
    border-radius: var(--radius-lg);
    background: var(--us-brand);
    color: var(--us-brand-contrast);
}

.us-event-brandbar-name {
    font-weight: var(--font-weight-semibold);
}

/* The competition and its dates, beside the club that runs it. */
.us-event-brandbar-meta {
    font-size: var(--font-size-sm);
}

/* Two-colour profiles show both: the rule under the banner runs brand into accent. It is the one
   place the gradient is safe, because nothing is read on top of it. */
.us-event-accentbar {
    height: 4px;
    margin: var(--space-2) 0 var(--space-5);
    border-radius: var(--radius-full);
    background: linear-gradient(90deg, var(--us-brand), var(--us-accent));
}


/* ===== Public registration: polish ========================================
   The pages a competing team sees keep their Bootstrap layout; the rules here only fix what did
   not render and tidy what sits around the form. All scoped to .us-event-theme or to the
   registration components, so the organizer-facing app is untouched. */

/* Bootstrap 5.1 has no .text-bg-* (it arrived in 5.2), so the "Closed", "Not open yet",
   "Fully booked" and "To be confirmed" badges were white text on nothing. */
.text-bg-secondary {
    background-color: var(--color-surface-overlay);
    color: var(--color-text-secondary);
    border: 1px solid var(--color-border);
}

.text-bg-info {
    background-color: var(--color-primary-subtle);
    color: var(--color-primary-hover);
    border: 1px solid color-mix(in srgb, var(--color-primary) 25%, transparent);
}

.text-bg-success {
    background-color: #e6f4ea;
    color: #1c6b45;
    border: 1px solid #c3e3d0;
}

.text-bg-warning {
    background-color: #fdf3e3;
    color: #8a5410;
    border: 1px solid #f0dcc0;
}

.text-bg-danger {
    background-color: #fdecec;
    color: #97282c;
    border: 1px solid #f2cfd0;
}

/* The buttons need no themed rules of their own: every state in the Buttons section reads
   --color-primary and --focus-ring, and the block above re-points both at the club's colour. */

/* Step pills sized as a control rather than a tag. */
.us-wizard-steps .badge {
    font-size: 0.8125rem;
    font-weight: var(--font-weight-medium);
    padding: 0.45em 0.9em;
    letter-spacing: 0.01em;
}

/* A label sits with its field, not floating between two. */
.us-event-theme .form-label {
    font-weight: var(--font-weight-medium);
    margin-bottom: 0.35rem;
}

.us-event-theme .form-text {
    color: var(--color-text-secondary);
}

/* The competition name under a step heading, tight to it. */
.us-event-theme h1 + .text-secondary {
    margin-top: calc(-1 * var(--space-2));
}

/* The Back / Continue bar's rule uses the same grey as everything else on the page. */
.us-event-theme .border-top {
    border-top-color: var(--color-border) !important;
}
