/* ============================================================
   NHL Design Language — Hockey Stats Viewer
   Tokens extracted from nhl.com/stats via designlang
   ============================================================ */

:root {
  --nhl-bg-dark:       #000000;
  --nhl-bg-dark-2:     #1a1a1a;
  --nhl-bg-light:      #ffffff;
  --nhl-bg-light-2:    #f8f8f8;
  --nhl-primary:       #0042bb;
  --nhl-primary-hover: #001e8c;
  --nhl-text-primary:  #121212;
  --nhl-text-secondary:#6f6f6f;
  --nhl-text-muted:    #98989e;
  --nhl-border:        #e0e0e0;
  --nhl-border-light:  #f2f2f2;
  --nhl-accent:        #eca200;
  --nhl-positive:      #00843d;
  --nhl-negative:      #c8102e;
  --nhl-shadow-card:   rgba(0,0,0,.08) 0px 16px 32px 0px,
                       rgba(0,0,0,.16) 0px 8px 16px 0px,
                       rgba(0,0,0,.24) 0px 4px 8px 0px;
}

/* Global */
body {
  font-family: 'Inter', sans-serif;
  background-color: var(--nhl-bg-light);
  color: var(--nhl-text-primary);
  margin: 0;
  font-size: 14px;
  line-height: 21px;
}

/* Bootstrap primary color overrides */
.btn-primary {
  background-color: var(--nhl-primary) !important;
  border-color: var(--nhl-primary) !important;
  font-family: 'Inter', sans-serif;
  font-weight: 700;
  border-radius: 0;
  padding: 10px 32px;
}

.btn-primary:hover {
  background-color: var(--nhl-primary-hover) !important;
  border-color: var(--nhl-primary-hover) !important;
}

.btn-outline-primary {
  color: var(--nhl-primary) !important;
  border-color: var(--nhl-primary) !important;
  font-family: 'Inter', sans-serif;
  font-weight: 700;
  border-radius: 0;
}

.btn-outline-primary:hover,
.btn-outline-primary.active {
  background-color: var(--nhl-primary) !important;
  color: white !important;
}

.card-header {
  background-color: var(--nhl-bg-light-2);
  border-bottom: 2px solid var(--nhl-primary);
}

/* ============================================================
   Navigation
   ============================================================ */
.nhl-navbar {
  background-color: var(--nhl-bg-dark) !important;
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
  padding: 0 24px;
  min-height: 52px;
}

.nhl-navbar-brand {
  color: #ffffff !important;
  font-weight: 900;
  font-size: 15px;
  letter-spacing: 0.5px;
  margin-right: 24px;
}

.nhl-navbar .nav-link {
  color: var(--nhl-text-muted) !important;
  font-size: 13px;
  font-weight: 500;
  padding: 0 14px !important;
  height: 52px;
  display: flex;
  align-items: center;
  border-bottom: 2px solid transparent;
  transition: color 0.2s, border-color 0.2s;
}

.nhl-navbar .nav-link:hover {
  color: #ffffff !important;
}

.nhl-navbar .nav-link.active {
  color: #ffffff !important;
  border-bottom: 2px solid var(--nhl-primary);
}

.nhl-navbar-logout {
  background: transparent !important;
  border: 1px solid rgba(255, 255, 255, 0.2) !important;
  color: var(--nhl-text-muted) !important;
  font-size: 12px !important;
  padding: 4px 12px !important;
  border-radius: 4px !important;
}

.nhl-navbar-logout:hover {
  color: #ffffff !important;
  border-color: rgba(255, 255, 255, 0.5) !important;
}

/* Mobile navbar toggler */
.nhl-navbar .navbar-toggler {
  border-color: rgba(255, 255, 255, 0.2);
}

@media (max-width: 768px) {
  .nhl-navbar .nav-link {
    height: auto;
    padding: 12px 14px !important;
    border-bottom: none;
    border-left: 2px solid transparent;
  }
  .nhl-navbar .nav-link.active {
    border-bottom: none;
    border-left: 2px solid var(--nhl-primary);
  }
}

/* Table Styles */
.table {
    width: 100%;
    margin-bottom: 1rem;
    color: #212529;
    border-collapse: collapse;
}

.table th {
    vertical-align: bottom;
    border-bottom: 2px solid #dee2e6;
    padding: 0.75rem;
    text-align: center;
}

.table td {
    padding: 0.75rem;
    vertical-align: middle;
    border-top: 1px solid #dee2e6;
}

.table-striped tbody tr:nth-of-type(odd) {
    background-color: rgba(0, 0, 0, 0.05);
}

.table-hover tbody tr:hover {
    background-color: rgba(0, 66, 187, 0.08);
}

/* Result Colors */
.text-success {
    color: #28a745 !important;
}

.text-danger {
    color: #dc3545 !important;
}

.text-warning {
    color: #ffc107 !important;
}

/* Card Styles */
.card {
    border: none;
    border-radius: 24px;
    overflow: hidden;
    box-shadow: var(--nhl-shadow-card) !important;
}

.card-body {
    padding: 1.5rem;
}

.shadow-sm {
    box-shadow: var(--nhl-shadow-card) !important;
}

/* ============================================================
   KPI Tiles
   ============================================================ */
.kpi-tile  { text-align: center; padding: 16px 8px; }
.kpi-value { font-size: 36px; font-weight: 700; color: var(--nhl-primary); line-height: 1; }
.kpi-label { font-size: 11px; font-weight: 400; text-transform: uppercase;
             letter-spacing: 0.06em; color: var(--nhl-text-secondary); margin-top: 6px; }

/* ============================================================
   Player Roster Cards
   ============================================================ */
.player-card          { cursor: pointer; transition: transform .15s, box-shadow .15s;
                        border: 2px solid transparent !important; }
.player-card:hover    { transform: translateY(-3px); }
.player-card.selected { border-color: var(--nhl-primary) !important; }
.player-card-body     { padding: 10px 6px !important; }
.player-initials      { width: 52px; height: 52px; border-radius: 50%;
                        background: var(--nhl-primary); color: #fff;
                        font-size: 18px; font-weight: 700;
                        display: flex; align-items: center; justify-content: center;
                        margin: 0 auto 8px; }
.player-initials.goalie  { background: var(--nhl-accent); color: #000; }
.player-initials.defense { background: var(--nhl-bg-dark-2); color: #fff; }

/* Compact roster tiles on mobile — more cards per row, less scroll before
   reaching a selected player's stats. */
@media (max-width: 768px) {
    .player-initials { width: 38px; height: 38px; font-size: 14px; margin-bottom: 6px; }
    .player-card-body { padding: 8px 4px !important; }
    .player-card-body p.small { font-size: 11px; }
}

/* ============================================================
   Game Scorecards
   ============================================================ */
.game-scorecard          { cursor: pointer; transition: transform .15s; }
.game-scorecard:hover    { transform: translateY(-2px); }
.game-scorecard.selected { border-left: 4px solid var(--nhl-primary) !important; }
.game-score              { font-size: 32px; font-weight: 700; line-height: 1; }

/* ============================================================
   Recent Form Dots
   ============================================================ */
.form-dot   { display: inline-flex; align-items: center; justify-content: center;
              width: 28px; height: 28px; border-radius: 50%;
              font-size: 11px; font-weight: 700; color: #fff; margin: 0 3px; }
.form-dot-W { background: var(--nhl-positive); }
.form-dot-L { background: var(--nhl-negative); }
.form-dot-T { background: var(--nhl-accent); color: #000; }

/* ============================================================
   Dark Footer
   ============================================================ */
.nhl-footer { background-color: var(--nhl-bg-dark-2); color: #fff;
              font-size: 14px; padding: 24px 0; margin-top: 3rem; text-align: center; }

/* Position tab active indicator */
.nav-tabs .nav-link.active {
  border-bottom: 3px solid var(--nhl-primary) !important;
  border-top: none !important;
  border-left: none !important;
  border-right: none !important;
  background: transparent !important;
}
.nav-tabs .nav-link {
  border: none !important;
  border-bottom: 3px solid transparent !important;
  color: var(--nhl-text-secondary);
  padding: 10px 20px;
  transition: color .15s;
}
.nav-tabs .nav-link:hover {
  color: var(--nhl-primary);
  border-bottom-color: rgba(0,66,187,.3) !important;
}

/* Dropdown Styles */
.Select-control, .dash-dropdown .Select-control {
    border-radius: 0.25rem;
    border: 2px solid var(--nhl-primary);
    height: 44px;
    font-size: 1.1rem;
    background-color: #f8f9fa;
}

.Select-menu-outer, .dash-dropdown .Select-menu-outer {
    border-bottom-right-radius: 0.25rem;
    border-bottom-left-radius: 0.25rem;
    border: 2px solid var(--nhl-primary);
    border-top: none;
    font-size: 1.1rem;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    z-index: 1000;
}

.Select-value, .dash-dropdown .Select-value {
    line-height: 44px !important;
    padding-left: 10px;
}

.Select-placeholder, .dash-dropdown .Select-placeholder {
    line-height: 44px !important;
    padding-left: 10px;
    color: #6c757d;
}

.Select-input, .dash-dropdown .Select-input {
    height: 44px;
    padding-left: 10px;
}

.Select-option, .dash-dropdown .Select-option {
    padding: 12px 10px;
    border-bottom: 1px solid #e9ecef;
}

.Select-option:hover, .dash-dropdown .Select-option:hover {
    background-color: rgba(0, 66, 187, 0.1);
}

.Select-option.is-selected, .dash-dropdown .Select-option.is-selected {
    background-color: rgba(0, 66, 187, 0.2);
}

/* Mobile Optimizations */
@media (max-width: 768px) {
    /* Adjust card padding for smaller screens */
    .card-body {
        padding: 1rem;
    }
    
    /* Make tables scrollable horizontally */
    .table-responsive {
        display: block;
        width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
    
    /* Adjust font sizes */
    h1 {
        font-size: 1.8rem;
    }
    
    h4 {
        font-size: 1.3rem;
    }
    
    /* Stack columns on small screens */
    .row [class*="col-"] {
        margin-bottom: 1rem;
    }
    
    /* Adjust button group for mobile */
    .btn-group {
        display: flex;
        flex-wrap: wrap;
    }
    
    .btn-group .btn {
        flex: 1 0 auto;
        margin-bottom: 0.5rem;
    }
}

/* Collapsible Sections for Mobile */
.collapsible-section {
    margin-bottom: 1rem;
}

.collapsible-header {
    background-color: #f1f1f1;
    padding: 0.75rem;
    cursor: pointer;
    border-radius: 0.25rem;
    border: 1px solid #dee2e6;
}

.collapsible-content {
    padding: 1rem;
    border: 1px solid #dee2e6;
    border-top: none;
    border-bottom-left-radius: 0.25rem;
    border-bottom-right-radius: 0.25rem;
}

/* Touch-friendly Controls */
@media (max-width: 768px) {
    /* Larger touch targets */
    .btn, .nav-link, .dropdown-item {
        padding: 0.5rem 1rem;
        min-height: 44px; /* Minimum touch target size */
    }
    
    /* More space between items */
    .nav-item, .dropdown-item {
        margin-bottom: 0.25rem;
    }
    
    /* Larger form controls */
    input, select, .Select-control {
        height: 44px;
    }
}

/* DataTable Styles */
.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner th {
    background-color: #f1f3f5;
    font-weight: bold;
    text-align: center;
}

.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner td {
    text-align: center;
}

/* Touch-Friendly Table Header & Sort Controls */
.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner th.dash-header {
    cursor: pointer !important;
    user-select: none !important;
    -webkit-user-select: none !important;
    touch-action: manipulation !important;
    padding: 12px 6px !important;
    min-height: 48px !important;
    position: relative;
    transition: background-color 0.15s ease-in-out;
}

.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner th.dash-header:hover,
.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner th.dash-header:active {
    background-color: #e2e8f0 !important;
}

/* Prominent & Easy-to-Tap Sort Indicators */
.dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner th .column-header--sort {
    font-size: 16px !important;
    font-weight: 800 !important;
    color: #0042bb !important;
    margin-left: 4px !important;
    padding: 2px 4px !important;
    display: inline-block !important;
    vertical-align: middle !important;
}

@media (max-width: 768px) {
    .dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner th.dash-header {
        padding: 14px 6px !important;
        font-size: 14px !important;
    }

    .dash-table-container .dash-spreadsheet-container .dash-spreadsheet-inner th .column-header--sort {
        font-size: 18px !important;
        margin-left: 6px !important;
    }
}

/* Login Page Styles */
.login-container {
    max-width: 400px;
    margin: 0 auto;
    padding: 2rem;
}

/* Footer Styles */
footer {
    margin-top: 3rem;
    padding-top: 1rem;
    border-top: 1px solid #dee2e6;
}

/* Hockey-Themed Login Styles */
.hockey-login-page {
    background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
    min-height: 100vh;
    position: relative;
}

.hockey-login-page::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-image: 
        radial-gradient(circle at 20% 80%, rgba(0, 32, 91, 0.03) 0%, transparent 50%),
        radial-gradient(circle at 80% 20%, rgba(0, 32, 91, 0.03) 0%, transparent 50%);
    pointer-events: none;
}

.hockey-header {
    font-weight: bold;
    text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
    margin-bottom: 0.5rem;
}

.hockey-card {
    background: rgba(255, 255, 255, 0.95);
    border: 2px solid #00205b;
    border-radius: 15px;
    max-width: 400px;
    width: 100%;
    backdrop-filter: blur(10px);
    position: relative;
    overflow: hidden;
}

.hockey-card::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: linear-gradient(90deg, #00205b 0%, #ffffff 50%, #00205b 100%);
}

.hockey-card .card-header {
    background: linear-gradient(135deg, #00205b 0%, #001a4d 100%);
    color: white;
    border-bottom: none;
    padding: 1.25rem;
}

.hockey-card .card-header h4 {
    margin: 0;
    font-weight: 600;
}

.hockey-input {
    border: 2px solid #dee2e6;
    border-radius: 0;
    font-size: 1rem;
    padding: 0.75rem;
    transition: all 0.2s ease;
}

.hockey-input:focus {
    border-color: #00205b;
    box-shadow: 0 0 0 0.2rem rgba(0, 32, 91, 0.25);
}

.password-toggle-btn {
    border: 2px solid #dee2e6;
    border-left: none;
    border-radius: 0;
    padding: 0.75rem 1rem;
    transition: all 0.2s ease;
    background-color: #f8f9fa;
}

.password-toggle-btn:hover {
    background-color: #e9ecef;
    border-color: #00205b;
    color: #00205b;
}

.password-toggle-btn:focus {
    box-shadow: 0 0 0 0.2rem rgba(0, 32, 91, 0.25);
}

.hockey-login-btn {
    background: linear-gradient(135deg, #00205b 0%, #001a4d 100%);
    border: none;
    border-radius: 8px;
    padding: 0.875rem;
    font-weight: 600;
    font-size: 1.1rem;
    transition: all 0.3s ease;
    text-transform: uppercase;
    letter-spacing: 0.5px;
}

.hockey-login-btn:hover {
    background: linear-gradient(135deg, #001a4d 0%, #001540 100%);
    transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(0, 32, 91, 0.3);
}

.hockey-login-btn:active {
    transform: translateY(0);
}

.login-container {
    padding: 2rem 1rem;
}

/* Input Group Styling */
.input-group .input-group-text {
    background-color: #00205b;
    color: white;
    border: 2px solid #00205b;
    border-right: none;
    border-radius: 0;
}

.input-group .form-control {
    border-left: none;
}

.input-group .btn-outline-secondary {
    border-left: none;
}

/* Hockey Puck Animation */
.hockey-header i.fa-hockey-puck {
    animation: puckSpin 3s linear infinite;
}

@keyframes puckSpin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* Mobile Optimizations for Hockey Login */
@media (max-width: 768px) {
    .hockey-card {
        margin: 1rem;
        max-width: none;
    }
    
    .login-container {
        padding: 1rem;
        min-height: 70vh;
    }
    
    .hockey-header {
        font-size: 1.5rem;
    }
    
    .hockey-login-btn {
        font-size: 1rem;
        padding: 0.75rem;
    }
    
    .password-toggle-btn {
        padding: 0.75rem 0.875rem;
    }
}

/* Accessibility Improvements */
.password-toggle-btn:focus-visible {
    outline: 2px solid #00205b;
    outline-offset: 2px;
}

.hockey-input:focus-visible {
    outline: 2px solid #00205b;
    outline-offset: 2px;
}

/* Error Message Styling */
.login-error {
    background-color: rgba(220, 53, 69, 0.1);
    border-left: 4px solid #dc3545;
    padding: 0.5rem 0.75rem;
    border-radius: 0 4px 4px 0;
    font-weight: 500;
}

/* Loading Indicators - Zamboni Theme */
/* A single ice resurfacer drives across a rink strip while Dash loads:
   cartoon resurfacer in the classic comic style - big-wheeled tank
   up front, Luffy (straw hat and all) driving from the rear seat,
   conditioner hanging at the back. The spinner element itself
   carries the animation (background-position), since Dash fixes the
   spinner's DOM structure; its child divs (the default bars/dots) stay
   hidden. Applies to the shell loader, the only loading component in
   the app. The percentage readout under the caption is rendered by
   assets/js/zamboni-loader.js (an eased estimate - Dash exposes no real
   load progress). The caption (::after) and the percentage element are
   both anchored to the spinner element itself, so they ride with the
   machine wherever Dash centers it - even on tall pages. */
.dash-default-spinner,
.dash-sk-circle,
.dash-dot-spinner {
    display: block !important;
    /* Pinned to the viewport, just under the navbar - not left to
       Dash's own centering. Dash 2.13's dcc.Loading renders the
       spinner inside an absolutely-positioned overlay that spans
       the FULL height of the wrapped content and flex-centers the
       spinner in it. The shell Loading wraps the entire page, so
       on any page taller than the screen the spinner (machine,
       caption, percentage and bar) lands in the middle of the
       full page height - measured 1,980px down a 3,414px-tall
       page on a phone, i.e. below the fold for the whole wait,
       while the hidden content left a blank screen up top. That
       is why the loader seemed to show on initial load (content
       still short, centred spinner near the top) but not when
       switching the Games window on a built page. position:fixed
       keeps the whole experience where the user is looking, on
       every load, at any scroll position. The caption (::after)
       and the percentage readout (.zamboni-pct) are positioned
       against the spinner itself, so they stay glued to it
       exactly as before.
       2026-11-05 scale-up: the machine itself doubled (background
       90px -> 180px wide, box 180x64 -> 340x116, strip and drive
       geometry scaled to match) after live checks showed the
       90px Zamboni too small to recognise on a phone - Luffy was
       only a few dozen pixels. Keep the vehicle's rendered width
       at 180px (see tests/test_loader_visibility.py). */
    position: fixed !important;
    top: 84px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 2000;
    width: 340px !important;
    height: 116px !important;
    margin: 0 auto;
    overflow: visible;
    background-image: url("data:image/svg+xml,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%20140%2060%27%3E%3Cdefs%3E%3ClinearGradient%20id%3D%27sheen%27%20x1%3D%270%27%20y1%3D%270%27%20x2%3D%271%27%20y2%3D%270%27%3E%3Cstop%20offset%3D%270%27%20stop-color%3D%27%23ffffff%27%20stop-opacity%3D%270%27%2F%3E%3Cstop%20offset%3D%270.5%27%20stop-color%3D%27%23ffffff%27%20stop-opacity%3D%270.5%27%2F%3E%3Cstop%20offset%3D%271%27%20stop-color%3D%27%23ffffff%27%20stop-opacity%3D%270%27%2F%3E%3C%2FlinearGradient%3E%3C%2Fdefs%3E%3Cpolygon%20points%3D%270%2C57%20140%2C57%20140%2C52%200%2C52%27%20fill%3D%27url%28%23sheen%29%27%2F%3E%3Crect%20x%3D%270%27%20y%3D%2755%27%20width%3D%27140%27%20height%3D%275%27%20fill%3D%27%23d7edfd%27%2F%3E%3Crect%20x%3D%270%27%20y%3D%2755%27%20width%3D%27140%27%20height%3D%271.6%27%20fill%3D%27%23bfe3fb%27%2F%3E%3Cpolygon%20points%3D%2713%2C41%2025%2C35%2028%2C39%2016%2C46%27%20fill%3D%27%238fa9bc%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%271.8%27%20stroke-linejoin%3D%27round%27%2F%3E%3Crect%20x%3D%271%27%20y%3D%2739%27%20width%3D%2713%27%20height%3D%2715%27%20rx%3D%272%27%20fill%3D%27%231c1f24%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272.2%27%2F%3E%3Crect%20x%3D%270%27%20y%3D%2753%27%20width%3D%2717%27%20height%3D%272.6%27%20rx%3D%271%27%20fill%3D%27%235d6d7a%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%271.2%27%2F%3E%3Crect%20x%3D%2750%27%20y%3D%2725%27%20width%3D%2786%27%20height%3D%2721%27%20fill%3D%27%23b9cfdd%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272.4%27%2F%3E%3Cpolygon%20points%3D%2757%2C25%2066%2C12%20128%2C12%20136%2C25%27%20fill%3D%27%233574b8%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272.4%27%20stroke-linejoin%3D%27round%27%2F%3E%3Ctext%20x%3D%2794%27%20y%3D%2736%27%20text-anchor%3D%27middle%27%20font-family%3D%27Arial%2C%20Helvetica%2C%20sans-serif%27%20font-size%3D%279%27%20font-weight%3D%27800%27%20letter-spacing%3D%271%27%20fill%3D%27%23223140%27%3EZAMBONI%3C%2Ftext%3E%3Crect%20x%3D%2751.5%27%20y%3D%2742.5%27%20width%3D%2783%27%20height%3D%273%27%20fill%3D%27%23eca200%27%2F%3E%3Ccircle%20cx%3D%2766%27%20cy%3D%2746%27%20r%3D%279%27%20fill%3D%27%2314161a%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272%27%2F%3E%3Ccircle%20cx%3D%2766%27%20cy%3D%2746%27%20r%3D%273.4%27%20fill%3D%27%23d6dee5%27%2F%3E%3Ccircle%20cx%3D%27114%27%20cy%3D%2746%27%20r%3D%279%27%20fill%3D%27%2314161a%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272%27%2F%3E%3Ccircle%20cx%3D%27114%27%20cy%3D%2746%27%20r%3D%273.4%27%20fill%3D%27%23d6dee5%27%2F%3E%3Crect%20x%3D%2726%27%20y%3D%2721%27%20width%3D%275%27%20height%3D%2714%27%20rx%3D%272.2%27%20fill%3D%27%232f3339%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272%27%2F%3E%3Crect%20x%3D%2727%27%20y%3D%2733.5%27%20width%3D%2721%27%20height%3D%274.5%27%20rx%3D%272%27%20fill%3D%27%232f3339%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272%27%2F%3E%3Cpolygon%20points%3D%2731%2C30%2047%2C30.5%2049%2C36%2033%2C36.5%27%20fill%3D%27%232b5aa6%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272%27%20stroke-linejoin%3D%27round%27%2F%3E%3Crect%20x%3D%2744.5%27%20y%3D%2736%27%20width%3D%274.6%27%20height%3D%278.5%27%20fill%3D%27%23f6cf9d%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%271.8%27%2F%3E%3Cellipse%20cx%3D%2747%27%20cy%3D%2745.5%27%20rx%3D%274%27%20ry%3D%271.8%27%20fill%3D%27%238a5a33%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%271.4%27%2F%3E%3Cpolygon%20points%3D%2728.5%2C33.5%2031.5%2C19.5%2043%2C20.5%2045.5%2C33%27%20fill%3D%27%23d43a2f%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272.2%27%20stroke-linejoin%3D%27round%27%2F%3E%3Cpolygon%20points%3D%2737.5%2C20.8%2042.5%2C21.2%2040%2C29%27%20fill%3D%27%23f6cf9d%27%2F%3E%3Cline%20x1%3D%2743%27%20y1%3D%2723.5%27%20x2%3D%2755%27%20y2%3D%2729.5%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%276.4%27%20stroke-linecap%3D%27round%27%2F%3E%3Cline%20x1%3D%2743%27%20y1%3D%2723.5%27%20x2%3D%2755%27%20y2%3D%2729.5%27%20stroke%3D%27%23f6cf9d%27%20stroke-width%3D%274.2%27%20stroke-linecap%3D%27round%27%2F%3E%3Ccircle%20cx%3D%2735.5%27%20cy%3D%2714.5%27%20r%3D%278.6%27%20fill%3D%27%23f6cf9d%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272.2%27%2F%3E%3Ccircle%20cx%3D%2733%27%20cy%3D%2713.5%27%20r%3D%271.25%27%20fill%3D%27%23191b1f%27%2F%3E%3Ccircle%20cx%3D%2741%27%20cy%3D%2713.5%27%20r%3D%271.25%27%20fill%3D%27%23191b1f%27%2F%3E%3Cpath%20d%3D%27M33.5%2C16.8%20Q38.5%2C21.5%2043.8%2C16.2%20Q41%2C21.8%2036.8%2C20.6%20Q34.2%2C19.6%2033.5%2C16.8%20Z%27%20fill%3D%27%238c3524%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%271.4%27%20stroke-linejoin%3D%27round%27%2F%3E%3Cpath%20d%3D%27M38.6%2C15.2%20l2.2%2C2.2%20M40.8%2C15.2%20l-2.2%2C2.2%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%270.9%27%20stroke-linecap%3D%27round%27%2F%3E%3Cpolygon%20points%3D%2728.2%2C10.2%2029.6%2C7.2%2031.4%2C9.8%2033.2%2C7%2035%2C9.8%2036.8%2C7%2038.6%2C9.8%2040.4%2C7.2%2042%2C10%2043%2C8.8%2043.2%2C10.8%2028.2%2C11.2%27%20fill%3D%27%2317181c%27%2F%3E%3Cpath%20d%3D%27M26.5%2C7%20Q26.5%2C0.8%2035.5%2C0.8%20Q44.5%2C0.8%2044.5%2C7%20Z%27%20fill%3D%27%23f2cd6b%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272%27%2F%3E%3Cpath%20d%3D%27M26.8%2C4.9%20Q35.5%2C3.6%2044.2%2C4.9%20L44.4%2C7.1%20Q35.5%2C8.6%2026.6%2C7.1%20Z%27%20fill%3D%27%23d43a2f%27%2F%3E%3Cellipse%20cx%3D%2735.5%27%20cy%3D%277.4%27%20rx%3D%2711.5%27%20ry%3D%272.9%27%20fill%3D%27%23f2cd6b%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272%27%2F%3E%3Cline%20x1%3D%2754.5%27%20y1%3D%2733.5%27%20x2%3D%2756.8%27%20y2%3D%2731%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%272.6%27%20stroke-linecap%3D%27round%27%2F%3E%3Ccircle%20cx%3D%2757.5%27%20cy%3D%2729.5%27%20r%3D%273.6%27%20fill%3D%27none%27%20stroke%3D%27%2326262b%27%20stroke-width%3D%272.2%27%2F%3E%3Ccircle%20cx%3D%2755%27%20cy%3D%2729.8%27%20r%3D%272.5%27%20fill%3D%27%23f6cf9d%27%20stroke%3D%27%23191b1f%27%20stroke-width%3D%271.4%27%2F%3E%3C%2Fsvg%3E"),
        linear-gradient(to bottom, rgba(220, 240, 255, 0) 0%, #e3f2fd 45%, #bfd9ef 100%);
    background-repeat: no-repeat, no-repeat;
    background-size: 180px auto, 100% 28px;
    background-position: -190px 24px, 0 100%;
    animation: zamboni-drive 2.8s linear infinite;
}

.dash-default-spinner > div:not(.zamboni-pct),
.dash-sk-circle > div:not(.zamboni-pct),
.dash-dot-spinner > div:not(.zamboni-pct) {
    display: none !important;
}

/* "Resurfacing the ice..." caption: hangs off the spinner itself, just
   under the strip, so it always travels with the machine. (It used to
   hang off the loading wrapper, anchored to the wrapper's bottom edge -
   on a tall page that is the bottom of the page, far below the spinner.) */
.dash-default-spinner::after,
.dash-sk-circle::after,
.dash-dot-spinner::after {
    content: "Resurfacing the ice…";
    position: absolute;
    top: 100%;
    margin-top: 8px;
    left: 50%;
    transform: translateX(-50%);
    color: #00205b;
    font-size: 0.95rem;
    font-weight: 500;
    white-space: nowrap;
    pointer-events: none;
}

@keyframes zamboni-drive {
    from { background-position: -190px 24px, 0 100%; }
    to { background-position: 360px 24px, 0 100%; }
}

/* Custom loading messages */
.loading-message {
    text-align: center;
    color: #00205b;
    font-weight: 600;
    margin-top: 1rem;
    font-size: 0.9rem;
}

/* Enhanced loading container */
._dash-loading {
    position: relative;
    min-height: 100px;
}

/* Loading percentage + progress bar (elements created inside the
   spinner element by assets/js/zamboni-loader.js; sit under the
   caption, relative to the spinner).
   The readout container is a DIRECT CHILD div of the spinner, and
   Dash's own spinner stylesheet (.dash-default-spinner > div) paints
   every such div as one of its animated equalizer bars (width: 6px,
   height: 100%, background-color: the Loading color, sk-stretchdelay
   animation). Dash injects those rules after this file, with a more
   specific selector, so the resets below are !important: without them
   the readout renders as a thin vertical bar with the text spilling
   out of it (seen on a phone, 2026-10-21). The text and the bar live
   one level deeper, where Dash's child selector cannot reach them. */
.zamboni-pct {
    position: absolute;
    top: calc(100% + 30px);
    left: 50%;
    transform: translateX(-50%);
    display: block !important;
    width: auto !important;
    height: auto !important;
    margin: 0 !important;
    padding: 0;
    border: none;
    background: transparent !important;
    animation: none !important;
    color: #00205b;
    font-size: 0.95rem;
    font-weight: 600;
    font-variant-numeric: tabular-nums;
    text-align: center;
    white-space: nowrap;
    opacity: 0;
    transition: opacity 0.4s ease;
    pointer-events: none;
}

.zamboni-pct-text {
    display: block;
}

.zamboni-pct-track {
    width: 200px;
    height: 7px;
    margin: 4px auto 0;
    border-radius: 4px;
    background: rgba(0, 32, 91, 0.12);
    overflow: hidden;
}

.zamboni-pct-fill {
    height: 100%;
    width: 0;
    border-radius: 4px;
    background: linear-gradient(90deg, #c47f00, #eca200);
    transition: width 0.12s linear;
}

/* Progress Bar Styling */
.progress {
    height: 8px;
    background-color: rgba(0, 32, 91, 0.1);
    border-radius: 4px;
    overflow: hidden;
}

.progress-bar {
    background: linear-gradient(90deg, #00205b 0%, #001a4d 100%);
    transition: width 0.3s ease;
}

.progress-striped .progress-bar {
    background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
    background-size: 1rem 1rem;
}

.progress-animated .progress-bar {
    animation: progress-bar-stripes 1s linear infinite;
}

@keyframes progress-bar-stripes {
    0% {
        background-position: 1rem 0;
    }
    100% {
        background-position: 0 0;
    }
}

/* Loading States for Navigation */
.nav-link.loading {
    opacity: 0.6;
    pointer-events: none;
    position: relative;
}

.nav-link.loading::after {
    content: "";
    position: absolute;
    right: 10px;
    top: 50%;
    transform: translateY(-50%);
    width: 12px;
    height: 12px;
    border: 2px solid transparent;
    border-top: 2px solid #ffffff;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% { transform: translateY(-50%) rotate(0deg); }
    100% { transform: translateY(-50%) rotate(360deg); }
}

/* Hockey Puck Loading Animation */
.hockey-puck-loader {
    width: 40px;
    height: 40px;
    background-color: #000;
    border-radius: 50%;
    position: relative;
    margin: 20px auto;
    animation: puckSlide 2s ease-in-out infinite;
}

.hockey-puck-loader::before {
    content: '';
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 20px;
    height: 2px;
    background-color: #fff;
    border-radius: 1px;
}

@keyframes puckSlide {
    0%, 100% {
        transform: translateX(-20px);
    }
    50% {
        transform: translateX(20px);
    }
}

/* Loading Overlay */
.loading-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(248, 249, 250, 0.9);
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    z-index: 1000;
    border-radius: 0.5rem;
}

.loading-overlay .loading-text {
    margin-top: 1rem;
    color: #00205b;
    font-weight: 600;
    font-size: 0.9rem;
}

/* Skeleton Loading */
.skeleton {
    background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
    background-size: 200% 100%;
    animation: loading 1.5s infinite;
}

.skeleton-text {
    height: 1rem;
    margin-bottom: 0.5rem;
    border-radius: 4px;
}

.skeleton-text:last-child {
    width: 80%;
}

/* Enhanced Skeleton Components */
.skeleton-card {
    background-color: #ffffff;
    border: 1px solid #dee2e6;
    border-radius: 0.5rem;
    overflow: hidden;
    margin-bottom: 1rem;
}

.skeleton-card .card-header {
    background-color: #f8f9fa;
    padding: 1rem;
    border-bottom: 1px solid #dee2e6;
}

.skeleton-card .card-body {
    padding: 1.5rem;
}

.skeleton-line {
    background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
    background-size: 200% 100%;
    animation: loading 1.5s infinite;
    border-radius: 4px;
    display: block;
}

.skeleton-title {
    height: 1.5rem;
    width: 60%;
    margin-bottom: 0.75rem;
}

.skeleton-subtitle {
    height: 1.25rem;
    width: 40%;
    margin-bottom: 0.5rem;
}

.skeleton-text {
    height: 1rem;
    margin-bottom: 0.5rem;
}

.skeleton-text.short {
    width: 80%;
}

.skeleton-text.medium {
    width: 90%;
}

.skeleton-text.long {
    width: 100%;
}

.skeleton-button {
    height: 38px;
    width: 80px;
    border-radius: 0.375rem;
    display: inline-block;
    margin-right: 0.5rem;
}

.skeleton-table {
    width: 100%;
    border-collapse: collapse;
}

.skeleton-table th,
.skeleton-table td {
    padding: 0.75rem;
    border-bottom: 1px solid #dee2e6;
}

.skeleton-table th .skeleton-line {
    height: 1rem;
    width: 80px;
}

.skeleton-table td .skeleton-line {
    height: 0.875rem;
    width: 60px;
}

/* Skeleton Animation Variants */
.skeleton-pulse {
    animation: pulse 1.5s ease-in-out infinite;
}

.skeleton-wave {
    animation: loading 1.5s infinite;
}

.skeleton-fade {
    animation: fade 1.5s ease-in-out infinite;
}

@keyframes loading {
    0% {
        background-position: 200% 0;
    }
    100% {
        background-position: -200% 0;
    }
}

@keyframes pulse {
    0%, 100% {
        opacity: 1;
    }
    50% {
        opacity: 0.5;
    }
}

@keyframes fade {
    0%, 100% {
        opacity: 0.3;
    }
    50% {
        opacity: 0.8;
    }
}

/* Responsive Skeleton Adjustments */
@media (max-width: 768px) {
    .skeleton-card .card-body {
        padding: 1rem;
    }
    
    .skeleton-title {
        height: 1.25rem;
        width: 70%;
    }
    
    .skeleton-subtitle {
        height: 1rem;
        width: 50%;
    }
    
    .skeleton-text {
        height: 0.875rem;
    }
    
    .skeleton-button {
        height: 44px; /* Larger touch targets on mobile */
        width: 100px;
    }
}

/* Enhanced Button States */
.btn.loading {
    position: relative;
    color: transparent !important;
}

.btn.loading::after {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 16px;
    height: 16px;
    border: 2px solid transparent;
    border-top: 2px solid currentColor;
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

/* Disable loading animations for password toggle button */
.password-toggle-btn.loading {
    color: inherit !important;
    position: static;
}

.password-toggle-btn.loading::after {
    display: none !important;
}

.password-toggle-btn {
    pointer-events: auto !important;
}

/* Mobile Loading Optimizations */
@media (max-width: 768px) {
    .dash-default-spinner::after,
    .dash-sk-circle::after,
    .dash-dot-spinner::after {
        font-size: 0.85rem;
    }
    
    .loading-overlay .loading-text {
        font-size: 0.8rem;
    }
    
    .hockey-puck-loader {
        width: 30px;
        height: 30px;
    }
    
    .hockey-puck-loader::before {
        width: 15px;
        height: 1.5px;
    }
}
