/* ── WPC Global Styles ─────────────────────────────────────────────── */
/* Four named themes (Woodland / Woodland Dark / Royal / Royal Dark). All
   colours flow from the CSS custom properties below — never hard-code a hex
   in a rule, reference a token so the theme flips automatically. The same
   hex values are mirrored in Theme/WpcTheme.cs (MudBlazor can't read CSS
   vars, so it keeps its own per-theme palettes). When you change a token
   here, update the matching constant in WpcTheme.cs.

   :root defaults to the Woodland palette so first paint is correct before
   the SSR bootstrap script in App.razor sets [data-theme]. Each theme then
   has its own html[data-theme="..."] block that overrides the tokens. */

:root,
html[data-theme="woodland"] {
    --wpc-surface:         #EEF4EA;
    --wpc-surface-raised:  #FFFFFF;
    --wpc-surface-sunken:  #E2EDDC;
    --wpc-text-primary:    #0D1B2E;
    --wpc-text-secondary:  #46556E;
    --wpc-text-muted:      #5C6B82;
    --wpc-border:          #C7D7C2;
    --wpc-border-strong:   #A6BCA0;
    --wpc-primary:         #246B45;
    --wpc-primary-hover:   #1A5435;
    --wpc-primary-contrast:#FFFFFF;
    --wpc-primary-soft:    rgba(36, 107, 69, 0.10);
    --wpc-nav-accent:      #7FD0A6;
    --wpc-support:         #2F8F57;
    --wpc-support-soft:    #DFEFE2;
    --wpc-danger:          #C0392B;
    --wpc-warning:         #C2410C;
    --wpc-on-dark:         #EAF3EC;
    --wpc-structure:       #1C3A2E;
    --wpc-overlay:         rgba(10, 25, 18, 0.55);
    --wpc-focus-ring:      rgba(36, 107, 69, 0.45);
}

html[data-theme="woodland-dark"] {
    --wpc-surface:         #0F1812;
    --wpc-surface-raised:  #18221B;
    --wpc-surface-sunken:  #131C16;
    --wpc-text-primary:    #E6EFE7;
    --wpc-text-secondary:  #AEC2B4;
    --wpc-text-muted:      #8AA091;
    --wpc-border:          #2C3A30;
    --wpc-border-strong:   #3E5044;
    --wpc-primary:         #5FB98A;
    --wpc-primary-hover:   #7DCBA0;
    --wpc-primary-contrast:#07140D;
    --wpc-primary-soft:    rgba(95, 185, 138, 0.14);
    --wpc-nav-accent:      #7FD0A6;
    --wpc-support:         #5FB98A;
    --wpc-support-soft:    #173026;
    --wpc-danger:          #E57368;
    --wpc-warning:         #F0894B;
    --wpc-on-dark:         #EAF3EC;
    --wpc-structure:       #16281F;
    --wpc-overlay:         rgba(0, 0, 0, 0.65);
    --wpc-focus-ring:      rgba(95, 185, 138, 0.50);
}

html[data-theme="royal"] {
    --wpc-surface:         #EEF2F8;
    --wpc-surface-raised:  #FFFFFF;
    --wpc-surface-sunken:  #E0E8F2;
    --wpc-text-primary:    #0B1B33;
    --wpc-text-secondary:  #3F4E68;
    --wpc-text-muted:      #586A86;
    --wpc-border:          #C2CFE2;
    --wpc-border-strong:   #9DB1CE;
    --wpc-primary:         #1E47A6;
    --wpc-primary-hover:   #152C71;
    --wpc-primary-contrast:#FFFFFF;
    --wpc-primary-soft:    rgba(30, 71, 166, 0.10);
    --wpc-nav-accent:      #7FB0FF;
    --wpc-support:         #2461C4;
    --wpc-support-soft:    #DEE7F5;
    --wpc-danger:          #C0392B;
    --wpc-warning:         #C2410C;
    --wpc-on-dark:         #E8EEF7;
    --wpc-structure:       #1C2A4A;
    --wpc-overlay:         rgba(10, 20, 50, 0.55);
    --wpc-focus-ring:      rgba(30, 71, 166, 0.45);
}

html[data-theme="royal-dark"] {
    --wpc-surface:         #0A0F1B;
    --wpc-surface-raised:  #131A2A;
    --wpc-surface-sunken:  #0E1422;
    --wpc-text-primary:    #E6ECF5;
    --wpc-text-secondary:  #A8B6CC;
    --wpc-text-muted:      #8597B0;
    --wpc-border:          #2A3650;
    --wpc-border-strong:   #3E4C6A;
    --wpc-primary:         #6FA0F0;
    --wpc-primary-hover:   #8BB4F5;
    --wpc-primary-contrast:#0B1320;
    --wpc-primary-soft:    rgba(111, 160, 240, 0.14);
    --wpc-nav-accent:      #7FB0FF;
    --wpc-support:         #6FA0F0;
    --wpc-support-soft:    #172541;
    --wpc-danger:          #E57368;
    --wpc-warning:         #F0894B;
    --wpc-on-dark:         #E8EEF7;
    --wpc-structure:       #142041;
    --wpc-overlay:         rgba(0, 0, 0, 0.65);
    --wpc-focus-ring:      rgba(111, 160, 240, 0.50);
}

/* ── Text-colour utility classes ────────────────────────────────────────
   Replace inline `Style="color: #..."` overrides scattered across Razor
   markup. All resolve to tokens so they flip with the theme. */
.wpc-text-primary   { color: var(--wpc-text-primary); }
.wpc-text-secondary { color: var(--wpc-text-secondary); }
.wpc-text-muted     { color: var(--wpc-text-muted); }
.wpc-text-accent    { color: var(--wpc-primary); }
.wpc-text-on-dark   { color: var(--wpc-on-dark); }
.wpc-text-danger    { color: var(--wpc-danger); }
.wpc-text-warning   { color: var(--wpc-warning); }
.wpc-bg-structure   { background-color: var(--wpc-structure); }
.wpc-bg-surface     { background-color: var(--wpc-surface-raised); }

/* Season selector dropdown: give the outlined input a solid raised
   surface so it doesn't blend into the tinted page background. The
   background sits behind the notched fieldset border, so match its
   radius. !important because app.css loads before MudBlazor.min.css. */
.wpc-season-select .mud-input.mud-input-outlined {
    background-color: var(--wpc-surface-raised) !important;
    border-radius: var(--mud-default-borderradius);
}

html {
    background: var(--wpc-surface);
    min-height: 100vh;
}

body {
    font-family: var(--wpc-font-family), 'Helvetica Neue', Arial, sans-serif;
    background: transparent !important;
}

/* Content cards. Targets MudCard specifically so the hero, chips,
   alerts, and other intentionally-coloured MudPaper elements are
   unaffected. !important is required because app.css loads before
   MudBlazor.min.css. */
.mud-card {
    background-color: var(--wpc-surface-raised) !important;
}

/* Outlined primary/warning buttons: render as solid filled (the
   amber/gold accent was dropped — these now use the one blue). */
.mud-button-outlined-warning,
.mud-button-outlined-primary {
    background-color: var(--wpc-primary) !important;
    border-color: var(--wpc-primary) !important;
}

.mud-button-outlined-warning .mud-button-label,
.mud-button-outlined-primary .mud-button-label {
    color: var(--wpc-primary-contrast) !important;
}

.mud-button-outlined-warning:hover,
.mud-button-outlined-primary:hover {
    background-color: var(--wpc-primary-hover) !important;
    border-color: var(--wpc-primary-hover) !important;
}

/* scrollbar-gutter moved to .wpc-body-content — html no longer scrolls. */

h1, h2, h3, h4, h5, h6,
.mud-typography-h1, .mud-typography-h2, .mud-typography-h3,
.mud-typography-h4, .mud-typography-h5, .mud-typography-h6,
.wpc-section-title, .wpc-card-title {
    font-family: var(--wpc-font-family), 'Helvetica Neue', Arial, sans-serif;
}

/* Splash card — positioned between the navbar and the feature-card strip,
   matching the same max-width as the page container (MudBlazor ExtraLarge).
   The wrap is a flex container that centres the card; only the card itself
   catches pointer events. Fades out via CSS transition (duration injected
   inline from HeroSplashTransitionSeconds). z-index sits above the
   immersive feature-cards row (5) but below MudBlazor popovers/dialogs.

   top offsets account for the page container padding-top plus the rendered
   navbar height at each breakpoint:
     xs  (< 960 px):  1rem  container-pt  + 64px primary row = 80px
     md+ (≥ 960 px):  1.5rem container-pt + 64px primary row
                       + 30px subnav slot + 5px subnav margin = 123px
   bottom clears the feature-card strip (≈ 165px tall).
   overflow: hidden clips any card overflow on very short viewports.
   padding matches the container side padding at each breakpoint so the
   gap between wrap-edge and splash card equals the viewport-to-navbar gap
   (= container padding-top: 1rem xs / 1.5rem md+). */
.wpc-splash-card-wrap {
    position: fixed;
    top: 80px;
    left: 0;
    right: 0;
    bottom: 165px;
    max-width: 1920px;   /* matches MudBlazor ExtraLarge container */
    margin: 0 auto;
    z-index: 50;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    padding: 1rem;   /* = xs container padding; gap matches viewport-to-navbar gap */
    opacity: 1;
    transition-property: opacity;
    transition-timing-function: ease-in-out;
    pointer-events: none;
}
@media (min-width: 960px) {
    .wpc-splash-card-wrap {
        top: 123px;
        padding: 1.5rem;  /* 1.5rem sides = md+ container padding */
    }
}
.wpc-splash-card-wrap--fading {
    opacity: 0;
}
/* Full-window variant: the card fills the entire viewport, covering the navbar.
   z-index 1400 sits above the inline navbar (z-index 10). The wrap uses
   align-items:stretch so the card fills the full height, and the inner
   mud-card-content flexes to centre the logo/text vertically. */
.wpc-splash-card-wrap--full-window {
    top: 0 !important;
    bottom: 0 !important;
    z-index: 1400;
    padding: 0 !important;
    align-items: stretch;
    max-width: 100% !important;
}
.wpc-splash-card-wrap--full-window .wpc-splash-card {
    height: 100%;
    border-radius: 0 !important;
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.wpc-splash-card-wrap--full-window .mud-card-content {
    display: flex !important;
    align-items: center;
    justify-content: center;
    flex: 1;
}
.wpc-splash-card {
    max-width: 100%;   /* fill the same width as the navbar */
    width: 100%;
    background-color: var(--wpc-structure) !important;
    color: var(--wpc-on-dark);
    text-align: center;
    pointer-events: auto;
    border: 1px solid color-mix(in srgb, var(--wpc-on-dark) 18%, transparent);
    border-top: 1px solid color-mix(in srgb, var(--wpc-on-dark) 18%, transparent);
}
.wpc-splash-title    { color: var(--wpc-on-dark); font-weight: 300 !important; }
.wpc-splash-subtitle {
    color: color-mix(in srgb, var(--wpc-on-dark) 80%, transparent);
    font-weight: 100 !important;
    opacity: 0;
    animation: wpc-splash-tagline-fade-in forwards;
    animation-duration: 0.8s;
    animation-delay: 0.3s;
    animation-timing-function: ease-in-out;
}

@keyframes wpc-splash-tagline-fade-in {
    from { opacity: 0; }
    to { opacity: 1; }
}


/* Feature card carousel — mirrors the hero photo-slot layout for text cards.
   Three slots, each containing A/B layers that crossfade via opacity.
   The transition duration is injected by an inline <style> in Home.razor
   using the admin-configured fade speed, so it overrides the default here. */
.wpc-feature-cards {
    display: flex;
    /* 12px gap matches MudGrid Spacing="3" (padding-left: 12px per item). */
    gap: 0.75rem;
    align-items: stretch;
}

.wpc-feature-slot {
    flex: 1 1 0;
    min-width: 0;
    /* Grid stacking: both A/B layers share the same grid cell so slot
       height is driven by the tallest layer (content-driven, like event
       cards) rather than a fixed min-height. */
    display: grid;
}

.wpc-feature-layer {
    /* Both layers occupy the same grid cell and stack on top of each
       other; the invisible layer doesn't collapse the slot. position:
       relative keeps the link overlay bounded to this layer, not the
       parent slot. */
    grid-area: 1 / 1;
    min-width: 0;
    position: relative;
    will-change: opacity;
    /* Default fade — overridden by the inline <style> on Home.razor. */
    transition: opacity 0.8s ease-in-out;
}

/* ── Flip animation ────────────────────────────────────────────────────
   Implemented via CSS transitions (not @keyframes) because WebKit fails to
   restart a keyframe animation when only the class name changes on the same
   element — Safari was leaving the slot blank during fold-in.  Transitions
   smoothly interpolate transform between value changes regardless of class
   history, so the same render-batch sequence works identically in Chromium
   and WebKit.  The half-duration CSS custom property is written by an inline
   <style> in Home.razor so the admin-configured speed applies. */

/* Flip slot: single visible face, so plain block rather than the grid
   stacking used by fade mode.  Default transform is 0° (visible) and we
   transition into and out of the edge-on (±90°) states. */
.wpc-feature-slot--flip {
    display: block;
    /* Large perspective value (~1500px) keeps foreshortening subtle so the
       near edge of the rotating card doesn't bulge outside its slot — the
       page wrapper has overflow-x: hidden and was clipping the outer-most
       card edges at small perspective values. */
    transform: perspective(1500px) rotateY(0deg);
    transition: transform var(--fc-flip-half-dur, 0.4s) ease;
    will-change: transform;
    /* position + z-index let an actively-flipping slot paint above the
       cards to its right (later DOM siblings would otherwise win the
       default paint order and clip the rotated face). */
    position: relative;
    z-index: 0;
}

/* While any flip phase class is active, raise the slot above its
   right-hand neighbours so the rotating face is never obscured. */
.wpc-feature-slot--flip.wpc-fc-fold-out,
.wpc-feature-slot--flip.wpc-fc-flush,
.wpc-feature-slot--flip.wpc-fc-fold-in {
    z-index: 2;
}

/* Phase 1 — fold-out: smoothly rotate to 90° (edge-on, invisible). */
.wpc-fc-fold-out {
    transform: perspective(1500px) rotateY(90deg);
    transition-timing-function: ease-in;
}

/* Phase 3 — flush: instant snap to -90° (still edge-on) with no transition,
   so the content can be swapped while invisible.  Critical that transition
   is none here, otherwise the browser would animate from +90° to -90° via
   0° and the new card would flash visible. */
.wpc-fc-flush {
    transform: perspective(1500px) rotateY(-90deg);
    transition: none;
}

/* Phase 2 — fold-in: smoothly rotate from -90° back to 0° (visible). */
.wpc-fc-fold-in {
    transform: perspective(1500px) rotateY(0deg);
    transition-timing-function: ease-out;
}

/* ── Slide mode carousel ──────────────────────────────────────────────
   A single strip holds 4 cards side-by-side (3 visible + 1 waiting off-
   screen right).  translateX(-25%) = exactly one card width at any
   breakpoint, so all visible cards slide together as a unit.  After the
   animation the strip resets to 0% instantly while new card content is
   loaded — the classic infinite-carousel pattern.

   Strip widths per breakpoint keep each item = 1/3 (desktop), 1/2
   (tablet), or 1/1 (mobile) of the visible area. */
.wpc-fc-carousel {
    overflow: hidden;
    width: 100%;
}

.wpc-fc-strip {
    display: flex;
    /* Mobile default: 4 cards × full-width = 400% */
    width: 400%;
    will-change: transform;
    /* Speed overridden by inline <style> on Home.razor */
    transition: transform 0.8s ease-in-out;
}

.wpc-fc-item {
    flex: 0 0 25%;   /* always 25% of strip = exactly 1 card */
    min-width: 0;
    box-sizing: border-box;
    padding: 0 0.375rem;   /* 12px total gap between adjacent cards, matches fade-mode gap and MudGrid Spacing="3" */
    position: relative;   /* contains the link overlay */
    display: flex;
    flex-direction: column;
}

/* Stretch each card to the height of the tallest card in the strip. */
.wpc-fc-item .wpc-card {
    flex: 1 1 auto;
}

/* Tablet (600–959 px): 2 cards visible */
@media (min-width: 600px) {
    .wpc-fc-strip { width: 200%; }
}

/* Desktop (960 px+): 3 cards visible — matches MudBlazor md breakpoint */
@media (min-width: 960px) {
    .wpc-fc-strip { width: calc(400% / 3); }
}

/* Invisible overlay anchor that makes the whole card surface clickable.
   Sits above the card (z-index:1); the adjacent-sibling rule propagates
   hover so the card's box-shadow effect still fires. */
.wpc-feature-card-link {
    position: absolute;
    inset: 0;
    z-index: 1;
    cursor: pointer;
}

.wpc-feature-card-link:hover + .wpc-card {
    box-shadow: 0 4px 20px rgba(27, 42, 74, 0.18) !important;
}

/* Default (600-959px): two slots visible, hide the third. */
.wpc-feature-slot:nth-child(3) {
    display: none;
}

/* Below 600px: only one slot visible. */
@media (max-width: 599.98px) {
    .wpc-feature-slot:nth-child(n+2) {
        display: none;
    }
}

/* From 960px up: all three slots visible — matches MudBlazor md breakpoint. */
@media (min-width: 960px) {
    .wpc-feature-slot:nth-child(3) {
        display: grid;
    }
    /* Flip slots use block, not grid — override the grid restore above. */
    .wpc-feature-slot--flip:nth-child(3) {
        display: block;
    }
}

/* Cards */
.wpc-card {
    border-top: 3px solid var(--wpc-primary);
    transition: box-shadow 0.2s ease;
}

/* Compact member card — auto height instead of stretching to fill grid row */
.wpc-member-card {
    height: auto !important;
}

/* Social media favicon images in the member detail dialog — fixed 32 × 32 px. */
.wpc-social-icons img {
    width: 32px;
    height: 32px;
    display: block;
}

/* Cover image container at the top of a card — clips to the card's rounded top corners. */
.wpc-card-cover {
    border-radius: var(--mud-default-borderradius) var(--mud-default-borderradius) 0 0;
}

.wpc-card:hover {
    box-shadow: 0 4px 20px rgba(27, 42, 74, 0.18) !important;
}

.wpc-card-title {
    color: var(--wpc-text-primary);
    font-weight: 600;
}

.wpc-title-marquee {
    overflow: hidden;
    white-space: nowrap;
    width: 100%;
}

/* inline-flex shrinks to a single copy when the title fits; when it overflows
   a second copy is added (see PhotoThumbnailCard) and the track is animated. */
.wpc-title-marquee-inner {
    display: inline-flex;
}

.wpc-title-marquee-item {
    flex: 0 0 auto;
}

/* The trailing gap on each copy is the empty space the eye sees before the
   title comes back around. Only applied while scrolling so a static title
   isn't padded. */
.wpc-title-marquee-inner.wpc-marquee-active .wpc-title-marquee-item {
    padding-right: var(--marquee-gap, 48px);
}

/* Two identical copies sit side by side, so the track is exactly twice one
   copy-plus-gap. Translating by -50% advances by one copy-plus-gap, landing
   the second copy where the first began — an identical frame, so the infinite
   loop has no visible snap. Linear keeps the speed constant; duration is set
   per-card from the measured width to hold a steady px/s. */
.wpc-title-marquee-inner.wpc-marquee-active {
    animation: wpc-title-scroll var(--marquee-dur, 12s) linear infinite;
}

@keyframes wpc-title-scroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}

.wpc-card-body {
    color: var(--wpc-text-secondary);
    line-height: 1.5;
}

/* Feature-card carousel only: lock to 3 lines so all cards share the same height. */
.wpc-fc-body {
    color: var(--wpc-text-secondary);
    line-height: 1.5;
    min-height: calc(1.5em * 3);
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Long-form body copy: cap line length around 70ch and open up the leading
   so multi-paragraph pages (About, History, GDPR, Copyright) read more like
   an article than a wall of text. */
.wpc-prose {
    max-width: 70ch;
}

.wpc-prose .mud-typography-body1,
.wpc-prose .wpc-card-body,
.wpc-prose .wpc-fc-body {
    line-height: 1.65;
    font-size: 1.02rem;
}

.wpc-prose .mud-typography-h6 {
    margin-top: 0.25rem;
    letter-spacing: 0.01em;
}

/* Sidebar nav panels */
.wpc-sidebar-card {
    border-left: 3px solid var(--wpc-primary);
    position: sticky;
    top: 1rem;
}

/* Events */
.wpc-event-card {
    min-height: 108px;
    overflow: hidden;
    transition: box-shadow 0.2s ease;
}

.wpc-event-card:hover {
    box-shadow: 0 4px 16px rgba(27, 42, 74, 0.15) !important;
}

.wpc-event-title {
    color: var(--wpc-text-primary);
    font-weight: 500;
}

/* Section headings */
.wpc-section-title {
    color: var(--wpc-text-primary);
    font-weight: 700;
}

.wpc-clickable-card {
    cursor: pointer;
    transition: box-shadow 0.15s ease, transform 0.15s ease;
}

.wpc-clickable-card:hover {
    box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15) !important;
    transform: translateY(-2px);
}

/* "Needs action" highlight — amber accent + subtle tint, used on dashboard
   tiles/cards that have outstanding work the admin should attend to. */
.wpc-action-card {
    border-top-color: #C8852A !important;
    background: color-mix(in srgb, #C8852A 10%, transparent);
}

/* Gallery teaser — sunken panel */
.wpc-gallery-teaser {
    background-color: var(--wpc-surface-sunken);
    border: 1px solid var(--wpc-border);
}

/* Info strip — sunken panel with blue accent edge */
.wpc-info-strip {
    background-color: var(--wpc-surface-sunken);
    border-left: 4px solid var(--wpc-primary);
}

/* Avatar backgrounds */
.wpc-avatar-bg {
    background-color: var(--wpc-surface-sunken);
}

/* ── Nav menu trigger spans (MudMenu ActivatorContent) ─── */

.wpc-nav-menu-trigger {
    color: var(--wpc-on-dark);
    font-size: 0.875rem;
    font-weight: 500;
    padding: 6px 8px;
    cursor: pointer;
    user-select: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    border-radius: 4px;
    transition: background-color 0.15s;
}

.wpc-nav-menu-trigger:hover {
    background-color: rgba(255, 255, 255, 0.08);
}

/* MudMenu popovers must render above the fixed AppBar (z-index 1300) */
.mud-popover-provider .mud-popover {
    z-index: 1310;
}

/* AppBar MudMenu/MudButton labels are mixed case, not uppercase */
.mud-appbar .mud-button-root,
.mud-appbar .mud-menu .mud-button-root,
.mud-appbar .mud-button-label {
    text-transform: none;
}

/* ── File upload label button ───────────────────────────── */

.wpc-file-label {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    min-height: 36px;
    padding: 6px 16px;
    border: 1px solid var(--wpc-border-strong);
    border-radius: 4px;
    color: var(--wpc-primary);
    background: transparent;
    cursor: pointer;
    font-size: 0.875rem;
    font-weight: 500;
    box-sizing: border-box;
    position: relative;
    transition: border-color 0.15s, background-color 0.15s;
    user-select: none;
}

.wpc-file-label:hover {
    border-color: var(--wpc-primary);
    background-color: var(--wpc-primary-soft);
}

.wpc-file-label input[type="file"] {
    width: 0;
    height: 0;
    opacity: 0;
    position: absolute;
    overflow: hidden;
}

/* ── Programme / Events page ────────────────────────────── */


.wpc-prog-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    padding: 0.6rem 1rem;
    gap: 0.3rem 0.75rem;
    transition: background-color 0.1s ease;
    font-size: 0.9rem;
}

.wpc-prog-row:hover {
    background-color: var(--wpc-surface-sunken);
}

/* wpc-prog-detail is the grid item; padding-top creates the gap between
   the parent card and the sub-card — it is clipped when the row is 0fr. */
.wpc-prog-detail {
    padding-top: 6px;
    font-size: 0.875rem;
}

.wpc-prog-detail-body {
    background-color: var(--wpc-surface-sunken);
    border-left: 3px solid var(--wpc-primary);
    border-radius: 6px;
    padding: 0.65rem 1rem 0.75rem;
}

.wpc-prog-past {
    opacity: 0.5;
}

.wpc-prog-date {
    min-width: 115px;
    flex-shrink: 0;
    padding-top: 2px;
}

.wpc-prog-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    min-width: 140px;
    flex-shrink: 0;
}

.wpc-prog-title {
    flex: 1;
    min-width: 180px;
    padding-top: 2px;
    color: var(--wpc-text-primary);
}

.wpc-prog-desc-container {
    flex: 1;
    min-width: 200px;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    overflow: hidden;
    color: var(--wpc-text-muted);
    font-size: 0.82rem;
}

.wpc-prog-desc {
    white-space: pre-line;
    display: inline;
}

.wpc-prog-desc-link {
    color: var(--wpc-primary);
    font-size: 0.82rem;
    cursor: pointer;
    text-decoration: none;
    font-weight: 500;
    white-space: nowrap;
}

.wpc-prog-desc-link:hover {
    text-decoration: underline;
}

.wpc-prog-desc-container.truncated .wpc-prog-desc {
    -webkit-line-clamp: 1;
    display: -webkit-box;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Event thumbnail in programme card — flush left, full card height */
.wpc-prog-thumb {
    width: 108px;
    flex-shrink: 0;
    align-self: stretch;
    overflow: hidden;
    background: var(--wpc-surface-sunken);
    display: flex;
    align-items: center;
    justify-content: center;
}

@media (max-width: 600px) {
    .wpc-event-card {
        min-height: 84px;
    }
    .wpc-prog-thumb {
        width: 84px;
    }
}

/* Expand toggle button */
.wpc-expand-btn {
    background: color-mix(in srgb, var(--wpc-primary) 12%, transparent);
    border: none;
    border-radius: 50%;
    width: 44px;
    height: 44px;
    padding: 0;
    cursor: pointer;
    color: var(--wpc-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    margin-left: auto;
    margin-right: 8px;
    transition: background-color 0.15s ease;
}

.wpc-expand-btn:hover {
    background: color-mix(in srgb, var(--wpc-primary) 22%, transparent);
}

.wpc-expand-btn .mud-icon-root {
    transition: transform 0.3s ease;
}

.wpc-expand-btn.expanded .mud-icon-root {
    transform: rotate(180deg);
}

/* Animated detail panel — CSS grid 0fr→1fr avoids max-height guessing.
   overflow:hidden on the panel is required to clip content when collapsed. */
.wpc-prog-detail-panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 0.3s ease;
    overflow: hidden;
    margin-left: 2rem;
}

.wpc-prog-detail-panel.expanded {
    grid-template-rows: 1fr;
}

.wpc-prog-detail-panel > .wpc-prog-detail {
    overflow: hidden;
    min-height: 0;
}

/* ── Competition cards ──────────────────────────────────── */

.wpc-comp-card {
    border-top: 3px solid var(--wpc-primary);
    transition: box-shadow 0.2s ease;
}

.wpc-comp-card:hover {
    box-shadow: 0 4px 20px rgba(27, 42, 74, 0.18) !important;
}

/* ── Settings / content panels (4 px accent, no hover shadow) ── */

.wpc-settings-card {
    border-top: 4px solid var(--wpc-primary);
}

/* ── Accent suppression ─────────────────────────────────── */
/* Applied globally via MudLayout class when CardAccentsEnabled = false */
.wpc-no-accents .wpc-card          { border-top:  none; }
.wpc-no-accents .wpc-comp-card     { border-top:  none; }
.wpc-no-accents .wpc-settings-card { border-top:  none; }
.wpc-no-accents .wpc-event-card    { }
.wpc-no-accents .wpc-sidebar-card  { border-left: none; }
.wpc-no-accents .wpc-info-strip    { border-left: none; }
.wpc-no-accents .wpc-tutorial-body blockquote { border-left: none; }


/* ── Logo ───────────────────────────────────────────────── */

.wpc-logo-hero {
    display: block;
}

/* ── MudBlazor form validation (Identity pages) ─────────── */

.valid.modified:not([type=checkbox]) {
    outline: 1px solid var(--wpc-primary);
}

.invalid {
    outline: 1px solid var(--wpc-danger);
}

.validation-message {
    color: var(--wpc-danger);
}

/* Top nav (now rendered inline instead of as a fixed AppBar). MudMainContent
   reserves padding-top for a fixed AppBar by default; reclaim it so the nav
   sits at the same inset from the top as the container's side padding.
   height: 100vh + overflow: hidden caps the layout to the viewport so the
   document never scrolls — all scrolling happens inside .wpc-body-content. */
.mud-main-content {
    padding-top: 0 !important;
    height: 100vh;
    overflow: hidden;
}

/* MudContainer is made a flex column so the navbar sits above the scroll area. */
.wpc-page-container {
    display: flex !important;
    flex-direction: column;
    height: 100%;
    /* Positioning context for the idle-mode brand ghost (.wpc-brand-ghost),
       which is absolutely positioned to sit over the nav bar's brand. */
    position: relative;
}

/* Scrollable body area below the navbar. Content clips at its own top edge,
   which is 16 px / 24 px below the navbar bottom (the navbar's mb-4/mb-md-6
   margin), so content disappears just before it reaches the navbar.
   scrollbar-gutter: stable replaces the old html rule — both the navbar and
   this wrapper are same-width flex siblings, so the gutter still prevents
   the centred nav from shifting when the scrollbar appears. */
.wpc-body-content {
    flex: 1 1 0;
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-gutter: stable;
    scrollbar-width: thin;
    scrollbar-color: #C8852A transparent;
}
.wpc-body-content::-webkit-scrollbar { width: 6px; }
.wpc-body-content::-webkit-scrollbar-thumb { background: #C8852A; border-radius: 3px; }
.wpc-body-content::-webkit-scrollbar-track { background: transparent; }

/* Keep menu trigger labels in their authored case (Mud's default uppercases). */
.wpc-topnav .mud-menu .mud-button-label,
.wpc-topnav .mud-button-label {
    text-transform: none !important;
}

/* Navbar wrapper. CSS grid lays out four zones so the brand (column 1)
   and account (column 3) span BOTH rows and sit vertically centred
   across the full bar height (primary row + subnav slot); the centre
   nav (column 2 row 1) and subnav (column 2 row 2) own the middle.
   overflow:hidden lets the subnav sit at translateY(-100%) without
   poking above the primary row. container-type lets the @container
   queries below shrink nav items based on the navbar's own width. */
.wpc-topnav {
    position: relative !important;
    z-index: 10;
    overflow: hidden;
    container-type: inline-size;
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-rows: minmax(56px, auto) 38px;
    grid-template-areas:
        "brand primary auth"
        "brand subnav auth";
    /* Animate both ways for idle immersive mode (body.wpc-chrome-hidden):
       the whole bar — shadow included — slides off the top. !important because
       MudBlazor's .mud-paper rule sets its own (equal-specificity, later-loaded)
       transition: box-shadow, which would otherwise win and make the slide
       instant. box-shadow kept so elevation changes still ease. */
    transition: transform 0.6s ease, opacity 0.6s ease, box-shadow 0.3s !important;
}

/* Subnav slot background — a pseudo-element pinned to the subnav grid
   area so the slot's dark bg is ALWAYS visible. The actual .wpc-subnav
   above it carries no background of its own, so when it animates with
   translateY, only the foreground (buttons + indicator) appears to move
   while the bar's bg stays put. */
.wpc-topnav::before {
    content: '';
    grid-area: subnav;
    background-color: var(--wpc-structure);
    transition: background-color 600ms ease-in-out;
    pointer-events: none;
    z-index: 0;
}

/* Brand zone — column 1, both rows. align-self: stretch fills the cell
   so the inner flex centres logo + title across the full bar height. */
.wpc-topnav .wpc-topnav-brand {
    grid-area: brand;
    align-self: stretch;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
    overflow: hidden;
    padding: 0 0.5rem 0 0.75rem;
    color: var(--wpc-on-dark);
    text-decoration: none;
    background-color: var(--wpc-structure);
    transition: background-color 600ms ease-in-out;
}

/* Primary row — column 2 row 1. z-index above the subnav so the subnav
   tucks behind it when slid up. */
.wpc-topnav .wpc-topnav-primary {
    grid-area: primary;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0 0.5rem;
    min-height: 56px;
    position: relative;
    z-index: 2;
    background-color: var(--wpc-structure);
    transition: background-color 600ms ease-in-out;
}

.wpc-topnav .wpc-topnav-hamburger { flex: 0 0 auto; }

.wpc-logo-nav {
    display: block;
    flex-shrink: 0;
    height: var(--wpc-nav-logo-height-px, 48px);
    width: auto;
    /* SVG fallback keeps its 1:1 aspect ratio via viewBox; uploaded
       images preserve their own aspect ratio via width:auto. */
}

/* Brand title: each word on its own line, sized so the three-line stack
   sits roughly the same height as a 48px logo beside it. */
.wpc-topnav .wpc-brand-title,
.wpc-brand-ghost .wpc-brand-title {
    display: flex;
    flex-direction: column;
    justify-content: center;
    color: var(--wpc-on-dark);
    font-family: var(--wpc-font-family), 'Helvetica Neue', Arial, sans-serif;
    font-weight: 700;
    font-size: var(--wpc-nav-brand-font-size, 12px);
    line-height: 1.1;
    letter-spacing: 0.5px;
    text-transform: uppercase;
    white-space: nowrap;
    overflow: hidden;
}

/* Centre nav: takes the remaining space, items centred inside it.
   --wpc-nav-pad-x and --wpc-nav-font let the @container queries below
   shrink items in one place when the navbar is tight. */
.wpc-topnav .wpc-topnav-nav {
    flex: 0 0 auto;
    margin: 0 auto;
    align-items: center;
    justify-content: center;
    column-gap: 0.125rem;
    position: relative;
    --wpc-nav-pad-x: 12px;
    --wpc-nav-font: 0.92rem;
}

.wpc-topnav .wpc-nav-link {
    color: var(--wpc-on-dark) !important;
    font-weight: 500;
    padding: 6px var(--wpc-nav-pad-x) !important;
    min-width: 0 !important;
    font-size: var(--wpc-nav-font) !important;
    white-space: nowrap;
}

.wpc-topnav .wpc-nav-link-active .mud-button-label {
    font-weight: 700;
}

/* Grow-from-center indicator under the active primary item — JS writes left/width
   instantly; CSS animates scaleX to expand/contract from the midpoint. */
.wpc-topnav .wpc-nav-indicator {
    position: absolute;
    bottom: 3px;
    left: 0;
    width: 0;
    height: 3px;
    background: var(--wpc-nav-accent);
    border-radius: 1px;
    pointer-events: none;
    opacity: 0;
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 0.22s cubic-bezier(0.4, 0, 0.2, 1),
                opacity 0.15s ease;
}


/* Subnav row — column 2 row 2. No background of its own; the slot's
   bg comes from .wpc-topnav::before above (pinned to the same grid
   area), so animating this element with translateY moves only the
   buttons + indicator, not the bar's dark backdrop. The primary row
   at z-index 2 still masks the foreground when it slides up past it. */
.wpc-topnav .wpc-subnav {
    grid-area: subnav;
    position: relative;
    z-index: 1;
    align-items: center;
    justify-content: center;
    min-height: 38px;
    padding: 0 0.5rem 13px;
    /* Default = closed; .wpc-subnav--open flips it into view. The
       deferred flip in OnAfterRenderAsync produces the drop-down on load. */
    transform: translateY(-100%);
    transition: transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    overflow: hidden;
}

.wpc-topnav .wpc-subnav.wpc-subnav--open {
    transform: translateY(0);
}

/* Keyed wrapper around the sub-links — Blazor recreates this element
   whenever the active top-nav section changes, which re-fires the
   fade-in animation below. */
.wpc-topnav .wpc-subnav-inner {
    display: flex;
    align-items: center;
    column-gap: 0.25rem;
    animation: wpcSubnavFadeIn 0.25s ease forwards;
}

@keyframes wpcSubnavFadeIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Grow-from-center indicator under the active sub-link — same pattern as the
   primary indicator, just lower in the row. */
.wpc-topnav .wpc-subnav-indicator {
    position: absolute;
    bottom: 12px;
    left: 0;
    width: 0;
    height: 2px;
    background: var(--wpc-nav-accent);
    border-radius: 1px;
    pointer-events: none;
    opacity: 0;
    transform: scaleX(0);
    transform-origin: center;
    transition: transform 0.22s cubic-bezier(0.4, 0, 0.2, 1),
                opacity 0.15s ease;
}

.wpc-topnav .wpc-subnav-link {
    color: rgba(232, 240, 255, 0.72) !important;
    font-weight: 400 !important;
    font-size: 0.78rem !important;
    min-width: 0 !important;
    padding: 2px 8px !important;
}

/* Inline pending-count pill on subnav items. Positioned entirely within the
   button label so it is never clipped by .wpc-subnav's overflow:hidden. */
.wpc-topnav .wpc-subnav-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--mud-palette-error);
    color: var(--mud-palette-error-text);
    border-radius: 10px;
    min-width: 16px;
    height: 16px;
    font-size: 0.6rem;
    font-weight: 700;
    padding: 0 3px;
    margin-left: 4px;
    vertical-align: middle;
    line-height: 1;
}

/* Active sub-link only changes its colour — the accent underline is
   drawn by .wpc-subnav-indicator above, which slides between items
   rather than blinking on the new one and off the old. */
.wpc-topnav .wpc-subnav-link-active .mud-button-label {
    color: var(--wpc-on-dark);
}

/* Authentication area — Login/Register buttons shown for anonymous users.
   Spans both grid rows (94 px total); items are laid out in a single flex
   row centred vertically across the full bar height. */
.wpc-topnav .wpc-topnav-auth {
    grid-area: auth;
    align-self: stretch;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-end;
    gap: 0;
    padding: 0 0.75rem 0 0.5rem;
    background-color: var(--wpc-structure);
    transition: background-color 600ms ease-in-out;
}

/* Icons + Login/Register buttons (anonymous) */
.wpc-topnav .wpc-topnav-auth-row {
    display: flex;
    align-items: center;
    gap: 0.1rem;
}

.wpc-topnav .wpc-topnav-auth-avatar {
    display: flex;
    align-items: center;
}

/* Avatar scaled to fill the full bar height (94 px nominal); 68 px gives
   a small breathing gap above and below. */
.wpc-topnav .wpc-topnav-auth-avatar .wpc-avatar-circle,
.wpc-topnav .wpc-topnav-auth-avatar .wpc-avatar-initials {
    width: 68px;
    height: 68px;
    font-size: 1.5rem;
    border-width: 2px;
}

/* Tight spacing for grouped icons (Tune + Person). */
.wpc-topnav .wpc-topnav-icons {
    display: flex;
    align-items: center;
    gap: 0;
}

.wpc-topnav .wpc-topnav-icons .mud-icon-button:not(:first-child) {
    margin-left: -0.85rem;
}

/* Form-based subnav items (e.g., logout) styled to match link buttons. */
.wpc-topnav .wpc-subnav-form {
    display: flex;
    align-items: center;
}

.wpc-topnav .wpc-subnav-form button {
    color: rgba(232, 240, 255, 0.72) !important;
    font-weight: 400 !important;
    font-size: 0.78rem !important;
    padding: 2px 8px !important;
    background: none;
    border: none;
    cursor: pointer;
    font: inherit;
}

.wpc-topnav .wpc-subnav-form button:hover {
    color: var(--wpc-on-dark) !important;
}

/* Top-nav logout button — styled like the login button */
.wpc-topnav .wpc-topnav-logout-btn {
    display: flex;
    align-items: center;
    color: var(--wpc-on-dark) !important;
    font-weight: 500;
    padding: 6px 12px !important;
    font-size: 0.92rem !important;
    background: none;
    border: none;
    cursor: pointer;
    font: inherit;
}

.wpc-topnav .wpc-topnav-logout-btn:hover {
    opacity: 0.8;
}

/* Container queries shrink the centre nav when the navbar itself gets
   tight, so items collapse padding/font before falling back to the
   hamburger drawer at the 960px media breakpoint below. */
@container (max-width: 1100px) {
    .wpc-topnav .wpc-topnav-nav {
        --wpc-nav-pad-x: 8px;
        --wpc-nav-font: 0.85rem;
    }
}

@container (max-width: 980px) {
    .wpc-topnav .wpc-topnav-nav {
        --wpc-nav-pad-x: 5px;
        --wpc-nav-font: 0.78rem;
        column-gap: 0;
    }
}

/* Mobile: collapse the grid into a simple flex row so the hamburger
   sits to the left of the brand. .wpc-topnav-nav and .wpc-subnav are
   already display:none on mobile (.d-md-flex), so the row reduces to
   hamburger + brand. The `order` overrides put the hamburger first since
   the brand appears earlier in the DOM. */
@media (max-width: 959px) {
    .wpc-topnav {
        display: flex;
        align-items: center;
        gap: 0.5rem;
        /* !important overrides the inline style="background-color:transparent" on MudPaper,
           which exists to suppress MudPaper's default palette background on desktop (where
           children supply their own backgrounds). On mobile the container
           must carry the background itself — CSS class rules lose to inline styles without !important. */
        background-color: var(--wpc-structure) !important;
        transition: background-color 600ms ease-in-out;
    }
    .wpc-topnav .wpc-topnav-primary {
        order: -1;
        flex: 0 0 auto;
        background: transparent;
        min-height: auto;
        padding: 0 0 0 0.25rem;
        z-index: auto;
    }
    .wpc-topnav .wpc-topnav-brand {
        flex: 1 1 auto;
        background: transparent;
        align-self: center;
        padding: 0.5rem 0.75rem 0.5rem 0;
    }
}


/* Icon buttons in the top nav (e.g. mobile hamburger) need light icons against
   the dark navy background. */
.wpc-topnav .mud-icon-button .mud-icon-root {
    color: var(--wpc-on-dark);
    fill: var(--wpc-on-dark);
}

/* Logout entry inside the mobile drawer — render the form button so it
   matches the surrounding MudNavLink rows. */
.wpc-drawer-logout button {
    display: flex;
    align-items: center;
    width: 100%;
    padding: 0.75rem 1rem;
    background: none;
    border: none;
    cursor: pointer;
    font: inherit;
    color: var(--wpc-on-dark);
    text-align: left;
}

.wpc-drawer-logout button:hover {
    background: rgba(232, 240, 255, 0.08);
}

.wpc-drawer-avatar {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 12px 16px 8px;
    color: var(--wpc-on-dark);
    text-decoration: none;
}

.wpc-drawer-avatar:hover {
    opacity: 0.85;
}

.wpc-drawer-avatar-name {
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--wpc-on-dark);
    opacity: 0.9;
}

/* MudBlazor's default active MudNavLink uses --mud-palette-primary (#246B45),
   which is dark green — illegible against the dark green drawer background.
   Override to the teal accent already used for the top-nav indicators. */
.mud-drawer .mud-nav-link.active:not(.mud-nav-link-disabled) {
    color: var(--wpc-nav-accent) !important;
    border-inline-end-color: var(--wpc-nav-accent) !important;
    background-color: color-mix(in srgb, var(--wpc-nav-accent) 12%, transparent) !important;
}
.mud-drawer .mud-nav-link.active:not(.mud-nav-link-disabled) .mud-nav-link-icon {
    color: var(--wpc-nav-accent) !important;
}

/* Club history figures: float beside the body copy on wider screens, stack on mobile. */
.wpc-history-figure {
    margin: 0 0 1rem;
    max-width: 220px;
}

.wpc-history-figure img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 0.5rem;
    box-shadow: 0 2px 12px rgba(13, 27, 46, 0.18);
}

.wpc-history-figure figcaption {
    margin-top: 0.4rem;
    font-size: 0.78rem;
    font-style: italic;
    color: var(--wpc-text-secondary);
    text-align: center;
}

@media (min-width: 720px) {
    .wpc-history-figure-right {
        float: right;
        margin: 0 0 1rem 1.5rem;
    }
    .wpc-history-figure-left {
        float: left;
        margin: 0 1.5rem 1rem 0;
    }
}

/* ── CMS article body (ArticleView / ArticleEditor) ──────────────────
   Raw HTML emitted by the WYSIWYG editor, rendered inside .wpc-prose.
   These rules ARE the "force website style" guarantee on the render side:
   the editor only emits this small set of structural tags and they all map
   onto the site palette/type scale, so authored content can't drift off-brand. */
.wpc-prose h2 {
    color: var(--wpc-text-primary);
    font-weight: 600;
    font-size: 1.35rem;
    margin: 1.75rem 0 0.75rem;
}
.wpc-prose h2:first-child { margin-top: 0.25rem; }
.wpc-prose h3 {
    color: var(--wpc-text-primary);
    font-weight: 600;
    font-size: 1.12rem;
    margin: 1.25rem 0 0.5rem;
}
.wpc-prose p {
    color: var(--wpc-text-secondary);
    line-height: 1.65;
    font-size: 1.02rem;
    margin: 0 0 1rem;
}
.wpc-prose ul,
.wpc-prose ol {
    color: var(--wpc-text-secondary);
    line-height: 1.65;
    font-size: 1.02rem;
    margin: 0 0 1rem;
    padding-left: 1.5rem;
}
.wpc-prose li { margin: 0.25rem 0; }
.wpc-prose a { color: var(--wpc-primary); }
.wpc-prose blockquote {
    border-left: 3px solid var(--wpc-primary);
    margin: 1rem 0;
    padding: 0.25rem 0 0.25rem 1rem;
    color: var(--wpc-text-secondary);
    background: var(--wpc-surface-sunken);
    border-radius: 0 4px 4px 0;
}
.wpc-prose hr {
    border: none;
    border-top: 1px solid var(--wpc-border);
    margin: 1.5rem 0;
    clear: both;
}

/* Inline figures. Width is set inline by the editor's resize handle and is
   clamped to 10–100% server-side by ArticleHtmlSanitizer; alignment is a class. */
.wpc-article-figure {
    margin: 0 0 1rem;
    max-width: 100%;
}
.wpc-article-figure img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 0.5rem;
    box-shadow: 0 2px 12px rgba(13, 27, 46, 0.18);
}
.wpc-article-figure figcaption {
    margin-top: 0.4rem;
    font-size: 0.78rem;
    font-style: italic;
    color: var(--wpc-text-secondary);
    text-align: center;
}
.wpc-article-figure-center {
    margin-left: auto;
    margin-right: auto;
}
.wpc-article-figure-full {
    width: 100% !important;
}
@media (min-width: 720px) {
    .wpc-article-figure-right { float: right; margin: 0 0 1rem 1.5rem; }
    .wpc-article-figure-left  { float: left;  margin: 0 1.5rem 1rem 0; }
}

/* ── Custom-page layout blocks (card grids + inline icons) ───────────
   Author-inserted via the editor toolbar; only the wpc-page-grid /
   wpc-page-card / wpc-icon classes survive the sanitizer. Scoped under
   .wpc-prose so they render the same in the editor surface and on the
   live page, and recolour with the theme via the --wpc-* tokens. */
.wpc-prose .wpc-page-grid {
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
    margin: 0 0 1.5rem;
    clear: both;
}
.wpc-prose .wpc-page-card {
    background: var(--wpc-surface-raised);
    border-radius: 0.5rem;
    padding: 1.25rem 1.5rem;
    border-top: 3px solid var(--wpc-primary);
    box-shadow: 0 1px 4px rgba(13, 27, 46, 0.08);
}
/* Tidy the first/last child margins so card text sits flush inside the padding. */
.wpc-prose .wpc-page-card > :first-child { margin-top: 0; }
.wpc-prose .wpc-page-card > :last-child  { margin-bottom: 0; }
.wpc-no-accents .wpc-prose .wpc-page-card { border-top: none; }

/* ── Grid-layout pages ────────────────────────────────────────────────
   Cards rendered directly on the page background (no outer card wrapper).
   Column count is driven by the --wpc-grid-cols custom property set inline.
   On small screens we collapse to a single column regardless of the setting. */
.wpc-page-grid-layout {
    display: grid;
    gap: 1rem;
    grid-template-columns: repeat(var(--wpc-grid-cols, 3), 1fr);
}
/* Reuse the same card chrome as inline editor cards. */
.wpc-page-grid-layout .wpc-page-card {
    background: var(--wpc-surface-raised);
    border-radius: 0.5rem;
    padding: 1.25rem 1.5rem;
    border-top: 3px solid var(--wpc-primary);
    box-shadow: 0 1px 4px rgba(13, 27, 46, 0.08);
}
.wpc-page-grid-layout .wpc-page-card > :first-child { margin-top: 0; }
.wpc-page-grid-layout .wpc-page-card > :last-child  { margin-bottom: 0; }
.wpc-no-accents .wpc-page-grid-layout .wpc-page-card { border-top: none; }
@media (max-width: 600px) {
    .wpc-page-grid-layout { grid-template-columns: 1fr !important; }
}

/* ── WYSIWYG grid card editor chrome ─────────────────────────────────
   Each card in the admin grid editor. The .editing modifier highlights the
   active card with the primary accent and a stronger shadow. */
.wpc-grid-card-editor {
    border-radius: 0.5rem !important;
    overflow: hidden;
    border-top: 3px solid var(--mud-palette-divider);
    transition: box-shadow 0.15s ease, border-color 0.15s ease;
}
.wpc-grid-card-editor.editing {
    border-top-color: var(--wpc-primary) !important;
    box-shadow: 0 4px 20px rgba(13, 27, 46, 0.18) !important;
}
/* Preview area inside a non-active card — pointer cursor + subtle hover tint. */
.wpc-grid-preview {
    cursor: pointer;
    transition: background 0.1s ease;
}
.wpc-grid-preview:hover {
    background: rgba(0, 0, 0, 0.03);
}

/* Inline icon glyph (Material Symbols ligature). font-size:1.4em tracks the
   surrounding text; vertical-align keeps it on the baseline of headings/rows. */
.wpc-icon {
    font-family: 'Material Symbols Outlined';
    font-weight: normal;
    font-style: normal;
    font-size: 1.4em;
    line-height: 1;
    vertical-align: middle;
    color: var(--wpc-primary);
    display: inline-block;
    white-space: nowrap;
    direction: ltr;
    -webkit-font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
    font-feature-settings: 'liga';
}
.wpc-no-accents .wpc-icon { color: inherit; }

/* Personalisation-token chips in the custom-page editor (mirror the Mailing
   compose chips). Soft-tinted, clickable; insert a {{token}} at the caret. */
.wpc-token-chip {
    font-size: 0.75rem;
    font-weight: 600;
    padding: 2px 9px;
    border-radius: 12px;
    cursor: pointer;
    color: var(--wpc-primary);
    background: var(--wpc-primary-soft);
    border: 1px solid var(--wpc-border);
    transition: background 0.15s ease, border-color 0.15s ease;
}
.wpc-token-chip:hover {
    background: var(--wpc-surface-sunken);
    border-color: var(--wpc-primary);
}

/* ── Article editor (ArticleEditor.razor + article-editor.js) ───────── */
.wpc-ae-editing:empty::before {
    content: "Start writing…";
    color: var(--wpc-text-secondary);
    opacity: 0.6;
}
.wpc-ae-editing:focus { outline: none; }
.wpc-ae-selected {
    outline: 2px solid var(--wpc-primary);
    outline-offset: 2px;
}
.wpc-ae-resize-handle {
    position: absolute;
    width: 16px;
    height: 16px;
    background: var(--wpc-primary);
    border: 2px solid #fff;
    border-radius: 50%;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
    cursor: nwse-resize;
    z-index: 5;
    touch-action: none;
}

/* ── Slideshow overlay ───────────────────────────────────────
   A full-screen "cinema" zone: intentionally dark in BOTH themes —
   photos are viewed against near-black regardless of light/dark mode,
   so these colours are deliberately literal, not tokenised. */
.wpc-slideshow-overlay {
    position: fixed;
    inset: 0;
    background: #000;
    z-index: 2000;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    outline: none;
}

/* Cursor hides after idle timeout — JS adds this class */
.wpc-slideshow-controls-hidden {
    cursor: none;
}

.wpc-slideshow-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 4px 8px;
    background: rgba(0, 0, 0, 0.5);
    flex-shrink: 0;
    transition: opacity 0.4s ease;
}

/* Fade out header and bottom controls on idle; caption stays visible */
.wpc-slideshow-controls-hidden .wpc-slideshow-header,
.wpc-slideshow-controls-hidden .wpc-slideshow-controls {
    opacity: 0;
    pointer-events: none;
}

.wpc-slideshow-counter {
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.875rem;
    padding-left: 8px;
}

.wpc-slideshow-image-area {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    padding: 8px 16px 4px;
    min-height: 0;
}

.wpc-slideshow-img-wrap {
    position: relative;
    width: 100%;
    height: 100%;
    overflow: hidden;
}

.wpc-slideshow-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    transition: opacity 1.2s ease-in-out;
}

.wpc-slideshow-caption {
    text-align: center;
    padding: 4px 16px 0;
    flex-shrink: 0;
    transition: opacity 0.5s ease-in-out;
}

.wpc-slideshow-caption-title {
    color: white;
    font-size: 1rem;
    font-weight: 600;
}

.wpc-slideshow-caption-desc {
    color: rgba(255, 255, 255, 0.65);
    font-size: 0.85rem;
    margin-top: 2px;
}

.wpc-slideshow-caption-author {
    color: #7FC8A0;
    font-size: 0.8rem;
    margin-top: 2px;
}

.wpc-slideshow-controls {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 4px;
    padding: 6px 16px;
    background: rgba(0, 0, 0, 0.5);
    flex-shrink: 0;
    transition: opacity 0.4s ease;
}

.wpc-slideshow-speed {
    display: flex;
    align-items: center;
    gap: 10px;
    margin-left: 12px;
    padding-left: 16px;
    border-left: 1px solid rgba(255, 255, 255, 0.15);
}

.wpc-slideshow-speed-slider {
    -webkit-appearance: none;
    appearance: none;
    width: 260px;
    height: 3px;
    background: rgba(255, 255, 255, 0.25);
    border-radius: 2px;
    outline: none;
    cursor: pointer;
}

.wpc-slideshow-speed-slider::-webkit-slider-thumb {
    -webkit-appearance: none;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: white;
    cursor: pointer;
}

.wpc-slideshow-speed-slider::-moz-range-thumb {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: white;
    cursor: pointer;
    border: none;
}

.wpc-slideshow-speed-label {
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.8rem;
    min-width: 28px; /* prevents layout shift between "1 s" and "60 s" */
}

/* Photo viewer dialog for gallery photos. Uses object-fit: contain
   to display the full image without cropping. */
.wpc-photo-viewer {
    display: flex;
    flex-direction: column;
    align-items: center;
}

.wpc-photo-display-area {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
}

.wpc-photo-display-img {
    max-width: 100%;
    /* Constrain to viewport so tall images never cause dialog scrolling.
       250px covers MudBlazor dialog margins, actions bar, and info panel. */
    max-height: calc(100dvh - 250px);
    width: auto;
    height: auto;
    object-fit: contain;
    display: block;
}


/* Browser-fullscreen target for PhotoViewerDialog. Hidden until it becomes the
   :fullscreen element, so it only covers the screen while in fullscreen. */
.wpc-photo-fullscreen {
    display: none;
}

.wpc-photo-fullscreen:fullscreen {
    display: flex;
    align-items: center;
    justify-content: center;
    background: #000;
}

.wpc-photo-fullscreen:fullscreen .wpc-photo-fullscreen-img {
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
}

.wpc-photo-fullscreen-close {
    position: fixed !important;
    top: 12px !important;
    right: 12px !important;
    z-index: 1;
    color: rgba(255, 255, 255, 0.8) !important;
}

.wpc-photo-info {
    padding: 16px;
    flex-shrink: 0;
}

.wpc-photo-title {
    color: var(--wpc-text-primary);
    font-weight: 600;
    margin-bottom: 0;
}

.wpc-photo-description {
    margin-top: 8px;
    color: var(--wpc-text-secondary);
}

/* Blazor error boundary */
.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

.blazor-error-boundary::after {
    content: "An error has occurred."
}

/* Rendered tutorial body (Markdown / HTML). Keeps long-form prose
   readable without imposing the brand chrome on every element. */
.wpc-tutorial-body {
    color: var(--wpc-text-primary);
    line-height: 1.65;
    font-size: 1rem;
}

.wpc-tutorial-body h1,
.wpc-tutorial-body h2,
.wpc-tutorial-body h3,
.wpc-tutorial-body h4 {
    color: var(--wpc-text-primary);
    margin: 1.25rem 0 0.5rem;
    font-weight: 700;
}

.wpc-tutorial-body p {
    margin: 0.5rem 0 1rem;
}

.wpc-tutorial-body a {
    color: var(--wpc-primary);
}

.wpc-tutorial-body img {
    max-width: 100%;
    height: auto;
    border-radius: 6px;
}

.wpc-tutorial-body pre,
.wpc-tutorial-body code {
    background: var(--wpc-surface-sunken);
    border-radius: 4px;
}

.wpc-tutorial-body pre {
    padding: 0.75rem 1rem;
    overflow-x: auto;
}

.wpc-tutorial-body code {
    padding: 0.1rem 0.3rem;
    font-size: 0.95em;
}

.wpc-tutorial-body blockquote {
    border-left: 3px solid var(--wpc-primary);
    margin: 1rem 0;
    padding: 0.25rem 0 0.25rem 1rem;
    color: var(--wpc-text-secondary);
    background: var(--wpc-surface-sunken);
}

.wpc-tutorial-body table {
    border-collapse: collapse;
    margin: 0.75rem 0;
}

.wpc-tutorial-body th,
.wpc-tutorial-body td {
    border: 1px solid var(--wpc-border);
    padding: 0.4rem 0.7rem;
}

.wpc-tutorial-body th {
    background: var(--wpc-surface-sunken);
}

/* ── Profile avatar display ─────────────────────────────────────────── */

.wpc-avatar-circle {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    object-fit: cover;
    border: 3px solid var(--wpc-primary);
    display: block;
}

.wpc-avatar-initials {
    width: 96px;
    height: 96px;
    border-radius: 50%;
    background-color: var(--wpc-structure);
    color: var(--wpc-on-dark);
    font-family: var(--wpc-font-family), sans-serif;
    font-size: 2rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 3px solid var(--wpc-primary);
    flex-shrink: 0;
}

/* Larger avatar for the profile photo editor page */
.wpc-avatar-xl.wpc-avatar-circle,
.wpc-avatar-xl.wpc-avatar-initials {
    width: 140px;
    height: 140px;
    font-size: 3rem;
}

.wpc-avatar-circle-sm {
    width: 68px;
    height: 68px;
    border-radius: 50%;
    object-fit: cover;
    border: 2px solid var(--wpc-primary);
    display: block;
    flex-shrink: 0;
}

.wpc-avatar-initials-sm {
    width: 68px;
    height: 68px;
    border-radius: 50%;
    background-color: var(--wpc-structure);
    color: var(--wpc-on-dark);
    font-family: var(--wpc-font-family), sans-serif;
    font-size: 1.1rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 2px solid var(--wpc-primary);
    flex-shrink: 0;
}

/* Make the Cropper.js crop box appear circular */
.cropper-view-box,
.cropper-face {
    border-radius: 50%;
}

/* ── Mailing body editor ──────────────────────────────────────────────── */

/* Inline chip for a substitution token inside the contenteditable editor */
.mailing-chip {
    display: inline-block;
    background: var(--wpc-primary-soft);
    color: var(--wpc-primary);
    border: 1px solid var(--wpc-primary);
    border-radius: 10px;
    padding: 0 8px;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1.7;
    user-select: none;
    white-space: nowrap;
    vertical-align: middle;
    cursor: default;
}

/* Contenteditable body editor — styled to match MudTextField Outlined */
.mailing-body-editor {
    border: 1px solid var(--wpc-border-strong);
    border-radius: 4px;
    padding: 14px;
    min-height: 200px;
    font-size: 0.875rem;
    font-family: inherit;
    line-height: 1.6;
    outline: none;
    word-break: break-word;
    cursor: text;
    white-space: pre-wrap;
    color: var(--wpc-text-primary);
    transition: border-color 0.2s;
}
.mailing-body-editor:hover {
    border-color: var(--wpc-text-secondary);
}
.mailing-body-editor:focus {
    border: 2px solid var(--wpc-primary);
    padding: 13px; /* compensate for extra border pixel */
}

/* ── AI Critique markdown output ─────────────────────────────────────────── */
.wpc-ai-critique-body {
    line-height: 1.7;
    color: var(--wpc-text-primary);
    font-size: 0.95rem;
    overflow-wrap: break-word;
    word-break: break-word;
}
/* Revert MudBlazor/Bootstrap cascade resets back to browser UA defaults.
   Scoped tightly to this container — no wider side effects. */
.wpc-ai-critique-body h1,
.wpc-ai-critique-body h2,
.wpc-ai-critique-body h3,
.wpc-ai-critique-body h4,
.wpc-ai-critique-body p,
.wpc-ai-critique-body ul,
.wpc-ai-critique-body ol,
.wpc-ai-critique-body li,
.wpc-ai-critique-body strong,
.wpc-ai-critique-body em,
.wpc-ai-critique-body hr,
.wpc-ai-critique-body pre,
.wpc-ai-critique-body code {
    all: revert;
}
/* If a code block somehow slips through, make it wrap rather than overflow. */
.wpc-ai-critique-body pre {
    white-space: pre-wrap;
    word-break: break-word;
    overflow-x: auto;
    max-width: 100%;
}
/* Custom overrides applied on top of UA defaults */
.wpc-ai-critique-body h1,
.wpc-ai-critique-body h2,
.wpc-ai-critique-body h3,
.wpc-ai-critique-body h4 {
    color: var(--wpc-text-primary);
    font-weight: 700;
    margin-top: 1.4em;
    margin-bottom: 0.3em;
    line-height: 1.3;
}
.wpc-ai-critique-body h1 { font-size: 1.5rem; }
.wpc-ai-critique-body h2 { font-size: 1.25rem; }
.wpc-ai-critique-body h3 { font-size: 1.1rem; }
.wpc-ai-critique-body h4 { font-size: 1rem; }
.wpc-ai-critique-body p  { margin: 0 0 0.85em; line-height: 1.7; }
.wpc-ai-critique-body ul,
.wpc-ai-critique-body ol {
    padding-left: 1.6em;
    margin-bottom: 0.85em;
}
.wpc-ai-critique-body ul { list-style-type: disc; }
.wpc-ai-critique-body ol { list-style-type: decimal; }
.wpc-ai-critique-body li { margin-bottom: 0.3em; line-height: 1.7; }
.wpc-ai-critique-body strong { font-weight: 700; }
.wpc-ai-critique-body em    { font-style: italic; }
.wpc-ai-critique-body hr {
    border: none;
    border-top: 1px solid var(--wpc-border);
    margin: 1.2em 0;
}
.wpc-ai-critique-body > *:first-child { margin-top: 0; }

/* ── Immersive front page ───────────────────────────────────────────────
   When the admin enables "Use immersive front page" in Look and Feel,
   Home.razor renders a full-window stack of fading photos from the
   "Front Page" album under everything else, and pins the feature-cards
   row to the bottom of the viewport with translucent surfaces so the
   background photo shows through.

   Layer z-indexes:
     wpc-immersive-bg layers — assigned monotonically by Home.razor
       (1, 2, 3…) so the incoming layer always sits on top of the
       outgoing one. The wrapper itself sits at z-index 0.
     wpc-immersive-fc — 5, above the background and above the page's
       normal content stacking but below MudBlazor dialogs/popovers
       which use much higher z-indexes.
*/
.wpc-immersive-bg {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-color: var(--wpc-surface);
    /* Smooth dimming/blur as the inline style changes on navigation. */
    transition: opacity 0.4s ease-in-out, filter 0.4s ease-in-out;
}
/* Page background: fixed full-viewport photo shown on non-home pages when
   PageBackgroundEnabled is true. opacity is set inline by MainLayout. */
.wpc-page-bg {
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-size: cover;
    background-position: center center;
    background-repeat: no-repeat;
}
.wpc-immersive-bg-layer {
    position: absolute;
    inset: 0;
    opacity: 0;
    overflow: hidden;
    /* Only opacity transitions here — GPU-composited without repaints. */
    will-change: opacity;
}
/* The pseudo-element holds the actual background image so the Ken Burns
   animation targets transform only — never background-position.  Safari
   does not GPU-composite background-position changes, causing per-frame
   repaints and visible jitter.  Keeping the image in a ::before that only
   animates transform lets the compositor keep everything on the GPU.
   inset: -5% extends the pseudo-element 5% beyond each edge so translate
   panning never exposes the container background at the borders. */
.wpc-immersive-bg-layer::before {
    content: '';
    position: absolute;
    inset: -5%;
    background-image: var(--bg-url);
    background-size: cover;
    background-position: center center;
    background-repeat: no-repeat;
    transform-origin: center center;
    will-change: transform;
}
/* ── Ken Burns motion ────────────────────────────────────────────────────
   Pan+zoom via transform only on the ::before pseudo-element.
   --kb-x1/y1/z1 and --kb-x2/y2/z2 keep their background-position
   percentage semantics (0–100, 50 = centre).  The calc expressions convert
   them into translate offsets: (x% − 50%) × 0.15 maps the ±20 % range of
   the presets to ≈ ±3 % translate — enough visible motion while staying
   safely within the 5 % inset buffer.
   Two named keyframe pairs (wpc-kb-a / wpc-kb-b) let Home.razor alternate
   the class so the browser sees a fresh animation-name each cycle and
   restarts from frame 0 on the same element. */
@keyframes wpc-kb-a {
    from { transform: translate(calc((var(--kb-x1) - 50%) * 0.15), calc((var(--kb-y1) - 50%) * 0.15)) scale(var(--kb-z1)); }
    to   { transform: translate(calc((var(--kb-x2) - 50%) * 0.15), calc((var(--kb-y2) - 50%) * 0.15)) scale(var(--kb-z2)); }
}
@keyframes wpc-kb-b {
    from { transform: translate(calc((var(--kb-x1) - 50%) * 0.15), calc((var(--kb-y1) - 50%) * 0.15)) scale(var(--kb-z1)); }
    to   { transform: translate(calc((var(--kb-x2) - 50%) * 0.15), calc((var(--kb-y2) - 50%) * 0.15)) scale(var(--kb-z2)); }
}
.wpc-immersive-bg-layer.wpc-kb-anim-a::before { animation: wpc-kb-a var(--kb-dur, 10s) linear forwards; }
.wpc-immersive-bg-layer.wpc-kb-anim-b::before { animation: wpc-kb-b var(--kb-dur, 10s) linear forwards; }
@media (prefers-reduced-motion: reduce) {
    .wpc-immersive-bg-layer.wpc-kb-anim-a::before,
    .wpc-immersive-bg-layer.wpc-kb-anim-b::before { animation: none; }
}
/* Ken Burns disabled via admin setting or user reduce-animations preference.
   Class is on <html> so it can be set by the pre-paint inline script before
   the Blazor circuit connects, preventing any animation on the first paint. */
html.wpc-no-ken-burns .wpc-immersive-bg-layer.wpc-kb-anim-a::before,
html.wpc-no-ken-burns .wpc-immersive-bg-layer.wpc-kb-anim-b::before { animation: none; }
/* Title marquee disabled */
html.wpc-no-marquee .wpc-title-marquee-inner.wpc-marquee-active { animation: none; }
.wpc-immersive-fc {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    max-width: 1920px;   /* matches MudBlazor ExtraLarge container */
    margin: 0 auto;
    z-index: 5;
    padding: 1rem 1.5rem 1.25rem;
    pointer-events: none;  /* let clicks through gaps; cards re-enable */
    /* bottom is added so the consent banner can push cards up smoothly. */
    transition: bottom 0.3s ease, transform 0.6s ease, opacity 0.6s ease;
}

/* When the cookie consent banner is visible, shift feature cards above it. */
body.wpc-consent-banner-visible .wpc-immersive-fc {
    bottom: calc(var(--wpc-consent-banner-height, 80px) + 16px);
}
/* The feature-cards grid is the immediate child of wpc-immersive-fc.
   Re-enable pointer events on the actual cards so links remain clickable. */
.wpc-immersive-fc .wpc-feature-cards,
.wpc-immersive-fc .wpc-fc-carousel {
    pointer-events: auto;
    margin-bottom: 0 !important;
}
.wpc-immersive-fc .wpc-card,
.wpc-immersive-fc .mud-card {
    background-color: var(--wpc-structure) !important;
    color: var(--wpc-on-dark);
    border: 1px solid color-mix(in srgb, var(--wpc-on-dark) 18%, transparent);
}
/* Reduce feature card height by ~15% versus the default pa-6 (24 px) padding.
   Applies to all three transition modes since all cards live inside wpc-immersive-fc. */
.wpc-immersive-fc .mud-card-content {
    padding-top: 1.0rem !important;      /* 16 px, was 24 px (pa-6) */
    padding-bottom: 1.0rem !important;
}
.wpc-immersive-fc .wpc-fc-body {
    min-height: calc(1.5em * 2.6) !important;   /* was 3 lines */
}
.wpc-immersive-fc .wpc-card-title,
.wpc-immersive-fc .wpc-fc-body {
    color: var(--wpc-on-dark) !important;
}

/* ── Idle immersive mode (home only) ──────────────────────────────────────
   wpcIdleChrome (topnav.js) adds body.wpc-chrome-hidden after a few idle
   seconds. The whole nav bar (shadow included) slides off the top and the
   feature cards slide off the bottom, leaving the photo background. A ghost
   copy of the brand (logo + club name) fades in where the bar's brand sat, so
   the page is always identifiable. Any activity reverses it.

   The ghost is a sibling of the nav bar inside the page container; it is
   invisible (opacity 0) until the chrome hides, so on non-home pages — where
   wpc-chrome-hidden is never set — it stays hidden and inert. */
.wpc-brand-ghost {
    position: absolute;
    top: 16px;
    left: 16px;
    z-index: 11;                 /* above the bar so it shows as the bar fades out */
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 94px;            /* match the bar height so vertical centring lines up */
    padding: 0 0.5rem 0 0.75rem; /* mirror .wpc-topnav-brand's padding */
    color: var(--wpc-on-dark);
    pointer-events: none;
    opacity: 0;
    transition: opacity 0.6s ease;
}
@media (min-width: 960px) {       /* MudBlazor md breakpoint — matches pa-md-6 */
    .wpc-brand-ghost { top: 24px; left: 24px; }
}
body.wpc-chrome-hidden .wpc-brand-ghost { opacity: 1; }

body.wpc-chrome-hidden .wpc-topnav {
    transform: translateY(-150%);   /* clears the bar height + top page padding */
    opacity: 0;
    pointer-events: none;
}
body.wpc-chrome-hidden .wpc-immersive-fc {
    transform: translateY(110%);
    opacity: 0;
    pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
    .wpc-brand-ghost,
    body.wpc-chrome-hidden .wpc-topnav,
    body.wpc-chrome-hidden .wpc-immersive-fc {
        transition: none;
    }
}

/* ── Web Links page ─────────────────────────────────────────────────── */

/* Sidebar category nav button */
.wpc-weblink-cat {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 8px;
    padding: 7px 10px;
    border-radius: 6px;
    background: none;
    border: none;
    cursor: pointer;
    width: 100%;
    text-align: left;
    color: var(--wpc-text-secondary);
    font-size: 0.875rem;
    transition: background 0.15s ease, color 0.15s ease;
}
.wpc-weblink-cat:hover {
    background: var(--wpc-surface-sunken);
    color: var(--wpc-text-primary);
}
.wpc-weblink-cat.active {
    background: var(--wpc-primary-soft);
    color: var(--wpc-primary);
    font-weight: 600;
}

/* Category count pill */
.wpc-weblink-count {
    flex-shrink: 0;
    font-size: 0.72rem;
    padding: 1px 7px;
    border-radius: 99px;
    background: var(--wpc-surface-sunken);
    color: var(--wpc-text-muted);
    white-space: nowrap;
}
.wpc-weblink-cat.active .wpc-weblink-count {
    background: var(--wpc-primary-soft);
    color: var(--wpc-primary);
}

/* UI Thumbnails admin: responsive card grid */
.wpc-ui-thumb-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
    gap: 12px;
}

.wpc-ui-thumb-card {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 8px;
    overflow: hidden;
    background: var(--mud-palette-surface);
}

/* Compact link row */
.wpc-weblink-row {
    display: flex;
    gap: 14px;
    align-items: center;
    padding: 12px 14px;
}

/* OG image thumbnail */
.wpc-weblink-thumb {
    width: 80px;
    height: 56px;
    flex-shrink: 0;
    overflow: hidden;
    border-radius: 5px;
    background: var(--wpc-surface-sunken);
}

/* Fallback icon box when no OG image */
.wpc-weblink-icon {
    width: 40px;
    height: 40px;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--wpc-primary-soft);
    border-radius: 8px;
}

/* Text column */
.wpc-weblink-text {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.wpc-weblink-title {
    font-weight: 600;
    font-size: 0.9375rem;
    color: var(--wpc-primary);
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.wpc-weblink-title:hover { text-decoration: underline; }
.wpc-weblink-domain {
    font-size: 0.72rem;
    color: var(--wpc-text-muted);
}
.wpc-weblink-desc {
    font-size: 0.8125rem;
    color: var(--wpc-text-secondary);
    line-height: 1.4;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* On small screens collapse thumbnail to icon size */
@media (max-width: 600px) {
    .wpc-weblink-thumb {
        width: 48px;
        height: 48px;
        border-radius: 6px;
    }
}

/* ── File picker drop zone ───────────────────────────────────────────
   Native file input wired with drag-and-drop support via wpcFilePickerZone.
   The zone has a dashed border to indicate it's clickable/droppable. */

.wpc-fpz {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 2rem;
    border: 2px dashed var(--wpc-border-strong);
    border-radius: 6px;
    background-color: var(--wpc-surface-sunken);
    transition: border-color 0.2s ease, background-color 0.2s ease;
    cursor: pointer;
}

.wpc-fpz:hover {
    border-color: var(--wpc-primary);
    background-color: var(--wpc-primary-soft);
}

.wpc-fpz-dragover {
    border-color: var(--wpc-primary);
    background-color: var(--wpc-primary-soft);
}

/* ── Bootstrap form controls: theme-aware overrides ──────────────────
   The Account/* SSR pages use Bootstrap's form-control / form-floating /
   btn-* classes because they are static server-rendered forms that can't
   host interactive MudBlazor inputs. These rules remap Bootstrap's form
   chrome to the WPC CSS custom properties so all four themes apply
   automatically via the html[data-theme] cascade.                       */

.form-control {
    background-color: var(--wpc-surface-raised);
    color: var(--wpc-text-primary);
    border-color: var(--wpc-border);
}

.form-control:focus {
    background-color: var(--wpc-surface-raised);
    color: var(--wpc-text-primary);
    border-color: var(--wpc-primary);
    box-shadow: 0 0 0 0.2rem var(--wpc-focus-ring);
    outline: none;
}

.form-control::placeholder {
    color: var(--wpc-text-muted);
    opacity: 1;
}

.form-control:disabled,
.form-control[readonly] {
    background-color: var(--wpc-surface-sunken);
    color: var(--wpc-text-muted);
    border-color: var(--wpc-border);
    opacity: 1;
}

.form-floating > label {
    color: var(--wpc-text-secondary);
}

.input-group-text {
    background-color: var(--wpc-surface-sunken);
    color: var(--wpc-text-secondary);
    border-color: var(--wpc-border);
}

.btn-primary {
    background-color: var(--wpc-primary);
    border-color: var(--wpc-primary);
    color: var(--wpc-primary-contrast);
}

.btn-primary:hover,
.btn-primary:active,
.btn-primary:focus-visible {
    background-color: var(--wpc-primary-hover);
    border-color: var(--wpc-primary-hover);
    color: var(--wpc-primary-contrast);
}

.btn-link {
    color: var(--wpc-primary);
}

.btn-link:hover {
    color: var(--wpc-primary-hover);
}

/* ── Shared docs styles (SystemDocs + SystemApiDocs) ─────────────────────── */
.docs-layout {
    display: flex;
    gap: 2rem;
    align-items: flex-start;
    margin-top: 1.25rem;
}

.docs-toc {
    flex: 0 0 190px;
    position: sticky;
    top: 1rem;
    max-height: calc(100vh - 2rem);
    overflow-y: auto;
}

.docs-toc-inner {
    background: var(--mud-palette-surface);
    border: 1px solid var(--wpc-border);
    border-radius: 8px;
    padding: 0.875rem 1rem;
}

.docs-toc-heading {
    font-size: 0.65rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--wpc-text-secondary);
    margin: 0 0 0.5rem;
}

.docs-toc-list {
    list-style: none;
    padding: 0;
    margin: 0;
}

.docs-toc-list li { margin: 0; }

.docs-toc-list > li > a {
    display: block;
    padding: 4px 0;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--wpc-text-primary);
    text-decoration: none;
}

.docs-toc-list > li > a:hover,
.docs-toc-list ul a:hover { color: var(--wpc-primary); }

.docs-toc-list ul {
    list-style: none;
    padding: 0 0 0.25rem 0.75rem;
    margin: 0;
}

.docs-toc-list ul a {
    display: block;
    padding: 3px 0;
    font-size: 0.8rem;
    color: var(--wpc-text-secondary);
    text-decoration: none;
    line-height: 1.4;
}

.docs-content, .docs-body { flex: 1; min-width: 0; }

.docs-section { margin-bottom: 3rem; }

.docs-section-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    border-bottom: 2px solid var(--wpc-primary);
    padding-bottom: 0.6rem;
    margin-bottom: 1.25rem;
}

.docs-h2 {
    font-size: 1.3rem;
    font-weight: 700;
    color: var(--wpc-text-primary);
    margin: 0;
    line-height: 1.3;
}

.docs-lead {
    font-size: 0.9rem;
    color: var(--wpc-text-secondary);
    margin: 0.2rem 0 0;
}

.docs-subsection { margin-bottom: 2rem; }

.docs-h3 {
    font-size: 1.05rem;
    font-weight: 600;
    color: var(--wpc-text-primary);
    margin: 1.5rem 0 0.5rem;
    padding-top: 0.25rem;
    border-top: 1px solid var(--wpc-border);
}

.docs-h4 {
    font-size: 0.72rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--wpc-text-secondary);
    margin: 1rem 0 0.3rem;
}

.docs-content p, .docs-body p {
    color: var(--wpc-text-secondary);
    line-height: 1.7;
    margin: 0.4rem 0 0.75rem;
    font-size: 0.9rem;
}

.docs-content code, .docs-body code {
    background: rgba(128, 128, 128, 0.12);
    border-radius: 3px;
    padding: 0.1em 0.35em;
    font-size: 0.83em;
    font-family: monospace;
}

.docs-list {
    padding-left: 1.3rem;
    margin: 0.25rem 0 0.75rem;
}

.docs-list li {
    color: var(--wpc-text-secondary);
    font-size: 0.9rem;
    margin: 0.2rem 0;
    line-height: 1.6;
}

.docs-code-block {
    background: var(--mud-palette-surface);
    border: 1px solid var(--wpc-border);
    border-radius: 5px;
    padding: 0.6rem 0.875rem;
    font-family: monospace;
    font-size: 0.82rem;
    margin: 0.4rem 0 0.75rem;
    overflow-x: auto;
    white-space: pre;
    color: var(--wpc-text-primary);
}

.docs-code-output {
    background: var(--wpc-surface-sunken, var(--mud-palette-background));
    color: var(--wpc-text-muted);
    border-style: dashed;
}

.docs-callout {
    border-left: 3px solid var(--wpc-primary);
    background: var(--wpc-primary-soft);
    border-radius: 0 6px 6px 0;
    padding: 0.875rem 1.125rem;
    margin: 0.75rem 0 1rem;
}

.docs-callout-title {
    font-size: 0.7rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: var(--wpc-text-primary);
    margin: 0 0 0.75rem;
}

.docs-steps {
    padding-left: 1.25rem;
    margin: 0;
}

.docs-steps li {
    color: var(--wpc-text-secondary);
    font-size: 0.9rem;
    margin: 0.75rem 0;
    line-height: 1.6;
}

.docs-aside {
    display: block;
    font-size: 0.8rem;
    color: var(--wpc-text-muted);
    font-style: italic;
    margin-top: 0.2rem;
    line-height: 1.5;
}

.docs-table-wrap {
    overflow-x: auto;
    margin: 0.5rem 0 1rem;
}

.docs-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.85rem;
}

.docs-table th {
    text-align: left;
    padding: 7px 12px;
    background: var(--mud-palette-table-hover);
    border-bottom: 2px solid var(--wpc-border-strong);
    font-weight: 600;
    font-size: 0.78rem;
    white-space: nowrap;
}

.docs-table td {
    padding: 7px 12px;
    border-bottom: 1px solid var(--wpc-border);
    vertical-align: top;
    line-height: 1.55;
    color: var(--wpc-text-secondary);
    font-size: 0.85rem;
}

.docs-table tbody tr:hover { background: var(--mud-palette-table-hover); }

.docs-table td code { font-size: 0.8em; white-space: nowrap; }

/* ── Cookie consent banner ───────────────────────────────────────────── */
/* Matches the MudContainer MaxWidth.ExtraLarge pa-4 pa-md-6 page width
   so the banner aligns with the navbar instead of spanning edge-to-edge. */
.wpc-consent-banner {
    position: fixed;
    bottom: 0;
    left: 50%;
    transform: translateX(-50%);
    width: calc(100% - 32px);   /* 16px margin each side — matches pa-4 */
    max-width: 1920px;
    z-index: 9999;
    background-color: var(--wpc-structure);
    padding: 20px 20px;
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    box-shadow: 0 -4px 20px rgba(0,0,0,0.5);
    border-radius: 8px 8px 0 0;
}

@media (min-width: 960px) {
    .wpc-consent-banner {
        width: calc(100% - 48px);   /* 24px margin each side — matches pa-md-6 */
        padding: 24px 32px;
    }
}
