/* ============================================
   WilcoChess Design System
   The editorial skin's default tokens; every club overrides them with its own.
   ============================================ */

:root {
    /* Primary Colors - WilcoChess Brand Palette */
    --cedar-green: #2D5016;
    --limestone-cream: #E8DCC4;
    --wilson-blue: #4A6FA5;

    /* The brand's own darker, lighter and palest steps. Until #7561 round 2 these lived as
       hex LITERALS in 64 places across 30 page stylesheets - which is how a hover state kept
       turning one club's navy button another club's green (owner, 2026-09-10). A club sets
       these the same way it sets the base color.
         -dark   a pressed/hover step under WHITE text (so it must stay dark)
         -light  a lifted hover step, also under WHITE text
         -tint   the palest wash, a row or chip background under DARK text */
    --cedar-green-dark: #1a4010;
    --cedar-green-light: #3a6b1e;
    --cedar-green-tint: #f0f5ec;
    --wilson-blue-dark: #3A5F95;

    /* The same three brand colours as RGB channels, for the rgba() tints and shadows the
       components paint with. A club that overrides --cedar-green must override this too or
       its shadows keep the default green - that is why they are club-settable tokens and not
       literals inside 60 stylesheets (#7561). */
    --cedar-green-rgb: 45, 80, 22;
    --wilson-blue-rgb: 74, 111, 165;
    --wheat-gold-rgb: 212, 175, 55;
    --tobacco-barn-red-rgb: 139, 69, 19;
    --limestone-cream-rgb: 232, 220, 196;

    /* Secondary Colors */
    --wheat-gold: #D4AF37;
    --river-pearl: #F5F5F0;
    --tobacco-barn-red: #8B4513;

    /* The colour an ACCENTED WORD takes - the gold half of a two-tone headline, an eyebrow,
       a section rule. Two tokens because the answer can differ by ground: one club answers
       gold to both, another answers its blue on light grounds and white on its navy heroes
       (owner ruling, 2026-09-10). */
    --accent-text: var(--wheat-gold);
    --accent-text-on-dark: var(--wheat-gold);
    --accent-rule: var(--wheat-gold);

    /* The same accent at SMALL running-text size on a light ground - an eyebrow, a caption.
       It exists because a display accent and a 12px accent have different contrast floors:
       WCAG wants 3:1 for large text and 4.5:1 for small, so a club whose display accent is a
       bright hue needs a darker step here, and it is also the focus ring on the admin forms.
       The default is the wheat gold's own hue taken dark enough for small text on this skin's
       light grounds (white, river pearl, limestone cream). It used to answer the display gold
       itself, which axe measured at 2.1:1 on white (#8156). It is a flat color, never a var()
       of the display accent: a club that sets its own accent-text sets this token too, on the
       branding page, in a step of its own that meets 4.5:1. */
    --accent-text-small: #715c18;

    /* Accent Colors */
    --color-gold: var(--wheat-gold);
    --color-green: var(--cedar-green);
    --color-purple: #91268f;
    --color-pink: #d0146f;

    /* Semantic Colors */
    --color-success: var(--cedar-green);
    --color-error: #dc2626;
    --color-warning: var(--wheat-gold);

    /* Status colors (#8150): the ground of a status badge or label whose text is WHITE ("Active",
       "Completed", "Recommended"), and the ink of status text on a light ground. They are not
       brand colors, so every skin answers the same; each carries white text at 4.5:1 or better,
       measured with axe-core (success 5.01, danger 6.47, warning 5.02, neutral 7.55), and the
       danger ink reads 5.91:1 on its pale wash #fef2f2. The bright literals they replace failed
       under white text: #22c55e measured 2.27:1 and #10b981 2.53:1 in the 3.0.1 walk. */
    --status-success: #15803d;
    --status-danger: #b91c1c;
    --status-warning: #b45309;
    --status-neutral: #4b5563;
    --status-ink: #ffffff;

    /* Text on a gold (--wheat-gold) ground, such as a gold button (#8150): the brand's dark
       step. On this skin's gold the base brand color measured 4.39:1 and the dark step 5.59:1
       (4.67:1 on the darker hover gold). It follows a club's own dark step, which is dark by
       definition. */
    --on-gold: var(--cedar-green-dark);

    /* Light Mode Colors */
    --color-dark: var(--cedar-green);
    --color-gray-dark: #374151;
    --color-gray: #6b7280;
    --color-gray-light: #d1d5db;
    --color-gray-lighter: #e5e7eb;
    --color-gray-lightest: var(--river-pearl);
    --color-white: #ffffff;
    --color-background: var(--limestone-cream);
    --color-surface: #ffffff;
    --color-text: var(--cedar-green);
    /* Muted running text: a date, a count, an "optional" hint, a secondary line (#8258). One
       token, and it must read at 4.5:1 on every light ground this skin paints: white, the river
       pearl and the limestone-cream parchment. The old #6b7280 measured 3.56:1 on the parchment
       and the #9ca3af literals it replaces 2.53:1 on white (axe-core, 3.0.5 walk). #4b5563 is
       the same step --status-neutral uses. A skin sets its own (the photo skin's is #475569). */
    --color-text-secondary: #4b5563;
    --color-border: #e5e7eb;

    /* The phone header (#8123): its ground, and the ink its club name and menu button are
       drawn in. They are a PAIR, and a skin that repaints the ground names the ink in the same
       rule. The default ink is the brand color, which is right on this white ground and exactly
       wrong on a dark one: the photo skin painted the ground its dark brand color, kept this ink,
       and drew the menu button navy on navy, so a phone visitor had no visible way to open the
       navigation. */
    --mobile-header-ground: #ffffff;
    --mobile-header-ink: var(--cedar-green);

    /* The stacking ladder for the fixed chrome and the dialogs (#8193). A dialog is modal: its
       overlay covers EVERYTHING, the site header, the phone header and its menu included. The
       event dialog's overlay used to sit at 1000 under the phone header's 1002, so its close (X)
       was under the header and a tap on it opened the menu. Every dialog overlay takes
       --z-dialog; every header, menu or drawer stays below it (pinned by
       DialogsSitAboveTheHeaderTests). */
    --z-dialog: 2000;

    /* Blazor's "An error has occurred. Reload" bar (#blazor-error-ui) sits above EVERY overlay,
       the dialogs and the checkout's full-screen processing overlays included (3.0.7 review of
       #8193): when the circuit dies behind an open dialog, the dialog's own close handler is dead
       with it, and the Reload link is the only way out, so no overlay may cover or dim it (pinned
       by DialogsSitAboveTheHeaderTests). */
    --z-app-error: 10000;

    /* The band the fixed Join / Upgrade pill covers at the bottom of the screen (#8042). Zero
       until the pill is on the page; see "Room for the fixed Join / Upgrade pill" below. */
    --join-cta-clearance: 0px;

    /* Typography */
    --font-sans: 'source-sans-pro', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Helvetica Neue', Arial, sans-serif;
    --font-display: 'proxima-nova', 'Bebas Neue', sans-serif;
    --font-serif: 'freight-display-pro', 'Kepler', Georgia, serif;
    --font-size-xs: 0.75rem;    /* 12px */
    --font-size-sm: 0.875rem;   /* 14px */
    --font-size-base: 1rem;     /* 16px */
    --font-size-lg: 1.125rem;   /* 18px */
    --font-size-xl: 1.25rem;    /* 20px */
    --font-size-2xl: 1.5rem;    /* 24px */
    --font-size-3xl: 1.875rem;  /* 30px */
    --font-size-4xl: 2.25rem;   /* 36px */
    --font-size-5xl: 3rem;      /* 48px */
    --font-size-6xl: 3.75rem;   /* 60px */
    --font-size-7xl: 4.5rem;    /* 72px */

    /* Spacing */
    --spacing-xs: 0.25rem;
    --spacing-sm: 0.5rem;
    --spacing-md: 1rem;
    --spacing-lg: 1.5rem;
    --spacing-xl: 2rem;
    --spacing-2xl: 3rem;
    --spacing-3xl: 4rem;

    /* Border Radius - Modern, more rounded */
    --radius-sm: 0.375rem;   /* 6px */
    --radius-md: 0.5rem;     /* 8px */
    --radius-lg: 0.75rem;    /* 12px */
    --radius-xl: 1rem;       /* 16px */
    --radius-2xl: 1.5rem;    /* 24px */
    --radius-full: 9999px;

    /* Shadows - Enhanced depth */
    --shadow-sm: 0 1px 2px 0 rgba(var(--cedar-green-rgb), 0.05);
    --shadow: 0 1px 3px 0 rgba(var(--cedar-green-rgb), 0.1), 0 1px 2px 0 rgba(var(--cedar-green-rgb), 0.06);
    --shadow-md: 0 4px 6px -1px rgba(var(--cedar-green-rgb), 0.1), 0 2px 4px -1px rgba(var(--cedar-green-rgb), 0.06);
    --shadow-lg: 0 10px 15px -3px rgba(var(--cedar-green-rgb), 0.15), 0 4px 6px -2px rgba(var(--cedar-green-rgb), 0.08);
    --shadow-xl: 0 20px 25px -5px rgba(var(--cedar-green-rgb), 0.2), 0 10px 10px -5px rgba(var(--cedar-green-rgb), 0.1);
    --shadow-2xl: 0 25px 50px -12px rgba(var(--cedar-green-rgb), 0.25);

    /* Transitions */
    --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
    --transition-base: 250ms cubic-bezier(0.4, 0, 0.2, 1);
    --transition-slow: 350ms cubic-bezier(0.4, 0, 0.2, 1);

    /* Gradients */
    --gradient-primary: linear-gradient(135deg, var(--cedar-green) 0%, var(--wilson-blue) 100%);
    --gradient-secondary: linear-gradient(135deg, var(--wilson-blue) 0%, var(--wheat-gold) 100%);
    --gradient-accent: linear-gradient(135deg, var(--wheat-gold) 0%, var(--cedar-green) 100%);
    --gradient-hero: linear-gradient(135deg, rgba(var(--cedar-green-rgb), 0.95) 0%, rgba(var(--wilson-blue-rgb), 0.9) 100%);
    /* The club's mark. A club whose logo is a gradient overrides this token instead of
       hardcoding stops in a component. */
    --gradient-brand: var(--gradient-primary);
}

/* Dark mode removed - light mode only */

/* ============================================
   Global Reset & Base Styles
   ============================================ */

* {
    box-sizing: border-box;
}

html {
    scroll-behavior: smooth;
}

body {
    margin: 0;
    padding: 0;
    font-family: var(--font-sans);
    font-size: var(--font-size-base);
    line-height: 1.7;
    color: #000000;
    background: #ffffff;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    transition: background-color var(--transition-base), color var(--transition-base);
    overflow-x: hidden;
    width: 100%;
}

/* An image never sets the width of the page. This is the site-wide floor for the rule three
   shell stylesheets already carried locally: /ratings shipped an 802px affiliate PNG with no
   cap, which held a grid track open and measured innerWidth 1560 / scrollWidth 2126 on a
   390px phone (#7561 round 2). A cap can only ever SHRINK an oversized image, so it is inert
   for every image that already fits. */
img,
video {
    max-width: 100%;
    height: auto;
}

h1, h2, h3, h4, h5, h6 {
    margin: 0;
    font-family: var(--font-display);
    font-weight: 700;
    line-height: 1.2;
    color: var(--color-dark);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

h1 {
    font-size: var(--font-size-6xl);
    font-weight: 900;
    letter-spacing: -0.02em;
}
h2 {
    font-size: var(--font-size-4xl);
    font-weight: 800;
}
h3 {
    font-size: var(--font-size-3xl);
    font-weight: 700;
}
h4 { font-size: var(--font-size-2xl); }
h5 { font-size: var(--font-size-xl); }
h6 { font-size: var(--font-size-lg); }

/* Suppress focus outline only when focus was set programmatically (e.g.,
   FocusOnNavigate landing on the heading after route change). Keyboard
   :focus-visible still wins. */
h1:focus:not(:focus-visible) {
    outline: none;
}

p {
    margin: 0 0 var(--spacing-md) 0;
}

a {
    color: var(--wilson-blue);
    text-decoration: none;
    transition: color var(--transition-fast);
}

a:hover {
    color: var(--cedar-green);
}

/* ============================================
   Form Validation Styles
   ============================================ */

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--color-success);
}

.invalid {
    outline: 1px solid var(--color-error);
}

.validation-message {
    color: var(--color-error);
    font-size: var(--font-size-sm);
    margin-top: var(--spacing-xs);
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, var(--color-error);
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

.blazor-error-boundary::after {
    content: "An error has occurred."
}

.darker-border-checkbox.form-check-input {
    border-color: var(--color-gray);
}

.form-floating > .form-control-plaintext::placeholder,
.form-floating > .form-control::placeholder {
    color: var(--color-gray);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder,
.form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* ============================================
   Utility Classes
   ============================================ */

.container {
    width: 100%;
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 var(--spacing-md);
}

.container-wide {
    width: 100%;
    max-width: 1400px;
    margin: 0 auto;
    padding: 0 var(--spacing-md);
}

.text-center {
    text-align: center;
}

.text-mtsu-blue {
    color: var(--wilson-blue);
}

.text-wilson-blue {
    color: var(--wilson-blue);
}

.text-cedar-green {
    color: var(--cedar-green);
}

.bg-mtsu-blue {
    background-color: var(--wilson-blue);
}

.bg-mtsu-navy {
    background-color: var(--cedar-green);
}

.bg-wilson-blue {
    background-color: var(--wilson-blue);
}

.bg-cedar-green {
    background-color: var(--cedar-green);
}

.bg-limestone-cream {
    background-color: var(--limestone-cream);
}

/* ============================================
   Accessibility Utilities
   ============================================ */

/* Visually hidden - for screen readers only */
.visually-hidden,
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ============================================
   Skip-to-content link (WCAG 2.4.1 Bypass Blocks)
   ============================================
   Lives at the very top of the DOM (rendered in MainLayout). Hidden
   off-screen via transform (not `top: -40px`) so it never participates
   in layout flow even if a scoped-CSS attribute fails to attach. Slides
   into view only on :focus — first Tab press surfaces it. */
.skip-to-content {
    position: fixed;
    top: 0;
    left: 0;
    background: var(--cedar-green, #2D5016);
    color: #ffffff;
    padding: 0.75rem 1.5rem;
    z-index: 2147483647; /* max 32-bit signed int — wins all stacking battles */
    text-decoration: none;
    font-weight: 600;
    font-family: var(--font-display, sans-serif);
    transform: translateY(-150%);
    transition: transform 0.18s ease;
}

.skip-to-content:focus,
.skip-to-content:focus-visible {
    transform: translateY(0);
    outline: 2px solid var(--wheat-gold, #D4AF37) !important;
    outline-offset: 2px !important;
}

/* ============================================
   Focus Visible — global a11y baseline (WCAG 2.4.13)
   ============================================
   Every interactive element gets a visible focus ring when reached via
   keyboard. Wilson Blue on white = 4.5:1 contrast (passes AA). Light
   backgrounds inherit this. Dark backgrounds (sidebar nav, dark footers,
   hero CTAs on black) override with a high-contrast white/gold ring in
   their own component CSS. */
:focus-visible {
    outline: 2px solid var(--wilson-blue);
    outline-offset: 2px;
}

/* !important is load-bearing here: many scoped `.razor.css` files use
   `:focus { outline: none }` patterns with higher specificity than this
   global rule. Without !important, the focus ring disappears for keyboard
   users in dozens of places. Treating accessibility focus indicators as a
   non-negotiable global is the right call. */
button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[role="button"]:focus-visible,
summary:focus-visible {
    outline: 2px solid var(--wilson-blue) !important;
    outline-offset: 2px !important;
}

/* Dark surface focus override — used inside .sidebar-nav and any dark
   section. Wilson blue on near-black is ~1.2:1; switch to gold (~10:1). */
.sidebar-nav :focus-visible,
.footer-main :focus-visible,
.page-hero :focus-visible,
[data-dark-surface] :focus-visible {
    outline: 2px solid var(--wheat-gold) !important;
    outline-offset: 2px !important;
}

/* Reduced motion for users who prefer it */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ============================================
   Focus and Scroll Management
   ============================================ */

/* Remove focus outline from programmatic focus (FocusOnNavigate) */
#main-content:focus {
    outline: none;
}

/* Ensure smooth scroll behavior, plus scroll-padding so the sticky
   banner-stack in MainLayout doesn't obscure anchor targets or focused
   elements (WCAG 2.4.11 Focus Not Obscured). The bottom edge does the same
   for the fixed Join / Upgrade pill (#8042, below). */
html {
    scroll-behavior: smooth;
    scroll-padding-top: 80px;
    scroll-padding-bottom: var(--join-cta-clearance);
}

/* ============================================
   Room for the fixed Join / Upgrade pill (#8042)
   ============================================
   JoinCTA pins a pill to the bottom of the screen for a visitor, and for a member who has not
   paid. Nothing a member needs to tap may stay under it, so while it is on the page the
   document reserves the band it covers, in two places:
     - scroll-padding-bottom (above), so the browser never parks a focused control, an anchor
       target or a scrollIntoView() under it; and
     - both layouts' footers pad their foot by the same amount (MainLayout's .footer-main,
       PhotoLayout's .photo-footer), so the page's LAST control, the footer's Terms of Service
       link, can scroll clear of it as well. Before this it could not wherever the pill lay
       over the footer's end: at 768px and below, where the pill spans the screen, on both
       skins; and at desktop width on the photo skin, whose footer runs under the pill's
       corner. On the editorial skin at desktop width the footer's links end left of the pill
       (measured at 1440px), so there the band only keeps the page's end clear and one rule for
       both layouts; that footer is 9rem taller while the pill shows.
   Each value is the band the pill covers at that JoinCTA.razor.css breakpoint - its inset from
   the bottom plus its own height - with a gap to spare. Measured in a browser on both skins
   (#8042): 87-88px up to 480px wide, 91-102px up to 768px, 126px wider than that.
   A paying member never gets the pill, so :has() keeps the clearance at zero for them. */
html:has(.join-cta-sticky) {
    --join-cta-clearance: 9rem;
}

@media (max-width: 768px) {
    html:has(.join-cta-sticky) {
        --join-cta-clearance: 7.5rem;
    }
}

@media (max-width: 480px) {
    html:has(.join-cta-sticky) {
        --join-cta-clearance: 6.5rem;
    }
}

/* ============================================
   Blazor error banner - GLOBAL on purpose. This used to live in MainLayout.razor.css (scoped),
   so any other layout (the photo skin's PhotoLayout) rendered its own #blazor-error-ui with
   no rule hiding it and the banner sat on every page ("That error survives every page refresh").
   ============================================ */
#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: var(--z-app-error);
}

#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.75rem;
    top: 0.5rem;
}
