/* ==========================================================================
   PakRace ETS — brand layer on top of Bootstrap 5
   ========================================================================== */

:root {
    --pr-navy-950: #0a1b33;
    --pr-navy-900: #102a43;
    --pr-navy-800: #1b3a5c;
    --pr-blue: #2563eb;
    --pr-blue-rgb: 37, 99, 235;
    --pr-blue-dark: #1d4ed8;
    --pr-blue-accent: #3b82f6;
    --pr-blue-soft: #eff6ff;
    --pr-blue-tint: #dbeafe;
    /* the pale blue that carries accents on dark backgrounds, where
     --pr-blue-accent is too dark to clear contrast against navy */
    --pr-blue-light: #93c5fd;
    --pr-border: #d9e2ec;
    --pr-amber: #f59e0b;
    --pr-amber-rgb: 245, 158, 11;
    --pr-amber-light: #fef3c7;
    --pr-pink: #ec4899;
    --pr-pink-light: #f9a8d4;
    --pr-success: #16a34a;
    --pr-success-rgb: 22, 163, 74;
    --pr-success-bg: #dcfce7;
    --pr-error: #dc2626;
    --pr-error-bg: #fee2e2;
    --pr-navy-900-rgb: 16, 42, 67;
    --pr-bg: #faf9f6;
    --pr-surface: #fff;
    --pr-text: #486581;
    --pr-heading: #102a43;
    --pr-muted: #486581;
    --pr-muted-2: #829ab1;
    --pr-gradient: linear-gradient(135deg, var(--pr-blue), var(--pr-blue-dark));

    --bs-body-font-family: "Manrope", system-ui, sans-serif;
    --bs-body-color: var(--pr-text);
    --bs-body-bg: var(--pr-bg);
    --bs-link-color: var(--pr-blue);
    --bs-link-hover-color: var(--pr-blue-dark);
    --bs-primary: var(--pr-blue);
    --bs-primary-rgb: 37, 99, 235;
}

/* ---- dark mode (Bootstrap 5.3 color mode) ---- */
[data-bs-theme="dark"] {
    --pr-bg: #0a1b33;
    --pr-surface: #102a43;
    --pr-text: #b7c4d9;
    --pr-heading: #f3f6fb;
    --pr-muted: #93a5bd;
    --pr-muted-2: #6e84a0;
    --pr-border: rgba(255, 255, 255, 0.14);
}
[data-bs-theme="dark"] .pr-eyebrow {
    color: var(--pr-blue-accent);
}
[data-bs-theme="dark"] .pr-navbar {
    background: rgba(10, 27, 51, 0.85);
}
[data-bs-theme="dark"] .pr-navbar .nav-link {
    color: #e2e8f0;
}
[data-bs-theme="dark"] .btn-pr-outline {
    border-color: rgba(255, 255, 255, 0.16);
}
[data-bs-theme="dark"] .pr-card {
    border-color: rgba(255, 255, 255, 0.08);
    box-shadow: 0 2px 14px rgba(0, 0, 0, 0.35);
}
[data-bs-theme="dark"] .pr-card.pr-hover:hover {
    box-shadow: 0 16px 36px rgba(0, 0, 0, 0.45);
}
[data-bs-theme="dark"] .pr-filter-chip {
    border-color: rgba(255, 255, 255, 0.14);
}
[data-bs-theme="dark"] .pr-step-dot {
    background: rgba(255, 255, 255, 0.18);
}
[data-bs-theme="dark"] #roleLabel {
    color: var(--pr-blue-accent);
}

body {
    -webkit-font-smoothing: antialiased;
}

h1,
h2,
h3,
h4,
h5,
h6,
.pr-display {
    font-family: "Fraunces", Georgia, serif;
    font-weight: 600;
    color: var(--pr-heading);
    letter-spacing: -0.01em;
}

a {
    text-decoration: none;
}

.pr-container {
    max-width: 1280px;
}

.pr-eyebrow {
    display: inline-block;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--pr-blue-dark);
    margin-bottom: 0.75rem;
}
.pr-eyebrow.text-on-dark {
    color: #4ade80;
}

/* ---- buttons ---- */
.btn-pr-primary {
    background: var(--pr-gradient);
    border: none;
    color: #fff;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 700;
    border-radius: 0.75rem;
    padding: 0.85rem 1.75rem;
    box-shadow: 0 6px 18px rgba(29, 78, 216, 0.22);
    transition:
        transform 0.15s ease,
        box-shadow 0.15s ease;
}
.btn-pr-primary:hover,
.btn-pr-primary:focus {
    color: #fff;
    transform: translateY(-2px);
    box-shadow: 0 10px 24px rgba(29, 78, 216, 0.3);
}
.btn-pr-secondary {
    background: rgba(255, 255, 255, 0.06);
    border: 1.5px solid rgba(255, 255, 255, 0.24);
    color: #fff;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 600;
    border-radius: 0.75rem;
    padding: 0.78rem 1.6rem;
}
.btn-pr-secondary:hover {
    background: rgba(255, 255, 255, 0.12);
    color: #fff;
}
.btn-pr-outline {
    background: var(--pr-surface);
    border: 1.5px solid rgba(16, 42, 67, 0.14);
    color: var(--pr-heading);
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 600;
    border-radius: 0.65rem;
    padding: 0.7rem 1.4rem;
}
.btn-pr-outline:hover {
    border-color: var(--pr-blue);
    color: var(--pr-blue-dark);
}
.btn-pr-white {
    background: #fff;
    border: none;
    color: var(--pr-navy-900);
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 700;
    border-radius: 0.75rem;
    padding: 0.85rem 1.75rem;
}

/* ---- surfaces ---- */
.pr-card {
    background: var(--pr-surface);
    border-radius: 1.1rem;
    border: 1px solid rgba(16, 42, 67, 0.07);
    box-shadow: 0 2px 10px rgba(16, 42, 67, 0.05);
    transition:
        transform 0.2s ease,
        box-shadow 0.2s ease;
}
.pr-card.pr-hover:hover {
    transform: translateY(-4px);
    box-shadow: 0 16px 32px rgba(16, 42, 67, 0.08);
}
.pr-card.pr-featured {
    border: 1.5px solid rgba(29, 78, 216, 0.35);
}

.pr-icon-badge {
    width: 3.25rem;
    height: 3.25rem;
    border-radius: 0.85rem;
    background: var(--pr-gradient);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.pr-icon-badge.pr-soft {
    background: rgba(37, 99, 235, 0.1);
}
.pr-icon-badge.pr-soft svg {
    stroke: var(--pr-blue-dark);
}

/* ---- dark sections ---- */
.pr-dark {
    background: radial-gradient(
        120% 100% at 50% 0%,
        var(--pr-navy-800) 0%,
        var(--pr-navy-900) 55%,
        var(--pr-navy-950) 100%
    );
    color: #fff;
}
.text-muted-light {
    color: rgba(255, 255, 255, 0.62) !important;
}
.text-muted-2 {
    color: var(--pr-muted-2) !important;
}
.pr-photo-bg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    z-index: 0;
}
.pr-photo-bg.pr-screen {
    mix-blend-mode: screen;
}
.pr-scrim {
    position: absolute;
    inset: 0;
    z-index: 1;
}

/* The race's own DB ref (e.g. "r-05") — shown next to every race across the
   dashboard and the public site now, on request, so one specific race is
   easy to find/report against (the race name itself stays hidden
   everywhere). Deliberately bigger/bolder than the plain muted text it
   usually sits beside, since it's meant to be the thing your eye catches
   first when scanning a list. Uppercased with text-transform, not PHP —
   the stored ref, the URL query string and every route/link built from it
   all stay lowercase; only the on-screen text reads as caps. */
.pr-ref-tag {
    display: inline-flex;
    align-items: center;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 800;
    font-size: 1rem;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--pr-blue-dark);
    background: var(--pr-blue-soft);
    padding: 0.15rem 0.55rem;
    border-radius: 0.45rem;
    line-height: 1.3;
}
/* On a dark banner (race control's own header, the club dashboard's "race
   in the air" card) — same shape, light-on-dark colours instead. */
.pr-ref-tag.on-dark {
    color: #fff;
    background: rgba(255, 255, 255, 0.18);
}

/* ---- nav ---- */
.pr-navbar {
    background: rgba(250, 249, 246, 0.88);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
}
.pr-navbar .nav-link {
    white-space: nowrap;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 600;
    color: #102a43;
}
.pr-navbar .nav-link:hover {
    color: var(--pr-blue-dark);
}

/* Hamburger that morphs into an X. Bootstrap flips `aria-expanded` on the
   button, so the open state needs no JS of its own. */
.pr-toggler.navbar-toggler {
    border: 1px solid var(--pr-border);
    border-radius: 0.7rem;
    padding: 0.45rem 0.55rem;
    line-height: 0;
    box-shadow: none;
}
.pr-toggler.navbar-toggler:focus-visible {
    box-shadow: 0 0 0 0.2rem rgba(37, 99, 235, 0.35);
}
.pr-toggler-box {
    position: relative;
    display: block;
    width: 1.375rem;
    height: 1rem;
}
.pr-toggler-bar {
    position: absolute;
    left: 0;
    width: 100%;
    height: 2px;
    border-radius: 2px;
    background: var(--pr-heading);
    transition:
        transform 0.25s ease,
        opacity 0.18s ease,
        top 0.25s ease;
}
.pr-toggler-bar:nth-child(1) {
    top: 0;
}
.pr-toggler-bar:nth-child(2) {
    top: calc(50% - 1px);
}
.pr-toggler-bar:nth-child(3) {
    top: calc(100% - 2px);
}
.pr-toggler[aria-expanded="true"] .pr-toggler-bar:nth-child(1) {
    top: calc(50% - 1px);
    transform: rotate(45deg);
}
.pr-toggler[aria-expanded="true"] .pr-toggler-bar:nth-child(2) {
    opacity: 0;
}
.pr-toggler[aria-expanded="true"] .pr-toggler-bar:nth-child(3) {
    top: calc(50% - 1px);
    transform: rotate(-45deg);
}

/* Menu sheet: at EVERY width the hamburger opens onto four entry-point cards
   instead of a link list — desktop keeps its inline links and buttons and gets
   the same sheet from its own toggler. The panel is a full-screen sheet under
   the bar; it overlays the page instead of pushing it down. */
.pr-navbar .pr-nav-sheet {
    /* NOT fixed: the navbar's own backdrop-filter makes it the containing block
     for fixed descendants, so `fixed` would resolve against the bar and
     collapse to nothing. Absolute against the sticky bar tracks the viewport
     just the same. */
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    /* Bootstrap animates the collapse by writing an inline height, which has to
     be overridden for the sheet to be full-height. Killing the transition
     also keeps Bootstrap's hide callback immediate. */
    height: calc(100svh - var(--pr-nav-h, 4.5rem)) !important;
    transition: none !important;
    overflow-y: auto;
    overscroll-behavior: contain;
    z-index: 20;
    background: var(--pr-bg);
}
.pr-navbar .pr-nav-sheet.show {
    animation: prMenuIn 0.22s ease both;
}
/* Bootstrap swaps .collapse for .collapsing one frame before .show lands, and
   the height override above already sizes the panel full-screen in that frame —
   without this the sheet paints fully opaque, then prMenuIn restarts it from
   opacity 0, which reads as a flicker. Hold it hidden until .show arrives. */
.pr-navbar .pr-nav-sheet.collapsing {
    opacity: 0;
}
/* the sheet covers the page, so the page behind it must not scroll. Locking the
   scroll takes the scrollbar away with it, so its width is given back as
   padding — otherwise the whole page jumps sideways as the menu opens. */
body.pr-menu-open {
    overflow: hidden;
    padding-right: var(--pr-sbw, 0px);
}
/* navbar-expand-xl hides the toggler at xl — this one stays at every width */
.pr-navbar .navbar-toggler.pr-toggler {
    display: inline-block;
}
@keyframes prMenuIn {
    from {
        opacity: 0;
        transform: translateY(-0.75rem);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

.pr-nav-cards {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.875rem;
    padding: 1.25rem;
    /* the sheet is full-screen, the tiles keep their own height at the top of it */
    align-content: start;
    max-width: 34rem;
    margin-inline: auto;
}
.pr-nav-card {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.15rem;
    padding: 1rem 0.95rem;
    border-radius: 1.1rem;
    border: 1px solid var(--pr-border);
    /* the sheet itself is --pr-bg, so the tiles sit a shade in front of it */
    background: var(--pr-surface);
    box-shadow: 0 2px 10px rgba(16, 42, 67, 0.05);
    text-decoration: none;
    transition:
        transform 0.18s ease,
        box-shadow 0.18s ease,
        border-color 0.18s ease;
}
.pr-nav-card:active {
    transform: scale(0.98);
}
.pr-nav-card:hover {
    border-color: rgba(37, 99, 235, 0.4);
    box-shadow: 0 12px 24px rgba(16, 42, 67, 0.09);
}
/* the sign-out tile posts a form, so it is a <button> wearing the card */
button.pr-nav-card {
    width: 100%;
    font: inherit;
    text-align: left;
    cursor: pointer;
}
.pr-icon-badge.pr-nav-card-icon {
    width: 2.4rem;
    height: 2.4rem;
    border-radius: 0.7rem;
    margin-bottom: 0.45rem;
}
/* the shared <use> pigeon is a fill silhouette — outrank the badge's stroke rule */
.pr-icon-badge.pr-soft .pr-pigeon-glyph {
    fill: var(--pr-blue-dark);
    stroke: none;
}
[data-bs-theme="dark"] .pr-icon-badge.pr-soft .pr-pigeon-glyph {
    fill: var(--pr-blue-accent);
}
/* province maps are silhouettes too — an outline this small reads as a blob */
.pr-icon-badge.pr-soft .pr-prov-glyph {
    fill: var(--pr-blue-dark);
    stroke: none;
}
[data-bs-theme="dark"] .pr-icon-badge.pr-soft .pr-prov-glyph {
    fill: var(--pr-blue-accent);
}
.pr-nav-card-title {
    font-family: "Plus Jakarta Sans", system-ui, sans-serif;
    font-weight: 700;
    font-size: 0.98rem;
    line-height: 1.25;
    color: var(--pr-heading);
}
.pr-nav-card-sub {
    font-size: 0.78rem;
    line-height: 1.3;
    color: var(--pr-muted-2);
}
@media (max-width: 359.98px) {
    .pr-nav-cards {
        grid-template-columns: minmax(0, 1fr);
    }
}
.pr-logo-badge {
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.7rem;
    background: var(--pr-gradient);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(29, 78, 216, 0.24);
}
.pr-logo-mark {
    width: auto;
    height: 2.5rem;
    flex-shrink: 0;
    fill: currentColor;
    color: #08293b;
}
/* logo sits on a permanently dark panel (footer, login) or in dark mode */
.pr-logo-mark.pr-logo-light,
[data-bs-theme="dark"] .pr-logo-mark {
    color: #fff;
}
.pr-wordmark {
    display: inline-flex;
    flex-direction: column;
    font-family: "Fraunces", Georgia, serif;
    font-weight: 700;
    font-size: 1.3rem;
    line-height: 1.05;
    letter-spacing: -0.01em;
    color: var(--pr-heading);
}
.pr-dark .pr-wordmark,
.pr-wordmark.text-light-mark {
    color: #fff;
}
/* second line of the lockup: "ETS system" set in sans, tracked out, brand blue */
.pr-ets {
    display: block;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 700;
    font-size: 0.46em;
    line-height: 1.2;
    letter-spacing: 0.16em;
    margin-top: 0.15em;
    color: var(--pr-blue);
}
.pr-dark .pr-ets,
.pr-wordmark.text-light-mark .pr-ets,
.pr-footer .pr-ets {
    color: var(--pr-blue-accent);
}

/* ---- hero ---- */
.pr-hero {
    position: relative;
    overflow: hidden;
    padding: 6.5rem 0;
}
.pr-hero-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    background: rgba(255, 255, 255, 0.1);
    border: 1px solid rgba(255, 255, 255, 0.32);
    border-radius: 100px;
    padding: 0.45rem 1rem;
    margin-bottom: 1.6rem;
}
.pr-live-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--pr-success);
    box-shadow: 0 0 0 4px rgba(22, 163, 74, 0.25);
}

/* Pins a subtree to the light-mode token values regardless of data-bs-theme —
   used for elements (like a floating card) that must stay a fixed light
   surface on top of an always-dark section such as the hero photo. */
.pr-force-light {
    --pr-bg: #faf9f6;
    --pr-surface: #fff;
    --pr-text: #486581;
    --pr-heading: #102a43;
    --pr-muted: #486581;
    --pr-muted-2: #829ab1;
    --pr-border: #d9e2ec;
}

/* ---- flying pigeon SVG ----
   Travel is linear and the x-steps are evenly spaced, so the birds hold one
   speed instead of stalling at every waypoint while the wings keep beating.
   A wingbeat is a real-world constant (~.65s) no matter how far away the bird
   is, so all three beat at nearly the same rate; what scales with apparent
   size is px/s. Durations are set so each bird covers ~2.4 of its own body
   lengths per beat: lead 38px/13s, mid 29px/16s, trail 22px/23s. */
@keyframes flyAcross {
    0% {
        transform: translate(-180px, 30px);
    }
    12.5% {
        transform: translate(45px, -6px);
    }
    25% {
        transform: translate(270px, -50px);
    }
    37.5% {
        transform: translate(495px, -22px);
    }
    50% {
        transform: translate(720px, 15px);
    }
    62.5% {
        transform: translate(945px, -12px);
    }
    75% {
        transform: translate(1170px, -45px);
    }
    87.5% {
        transform: translate(1395px, -14px);
    }
    100% {
        transform: translate(1620px, 20px);
    }
}
@keyframes flyAcrossSlow {
    0% {
        transform: translate(-160px, -20px) scale(0.9);
    }
    12.5% {
        transform: translate(60px, 8px) scale(0.9);
    }
    25% {
        transform: translate(280px, 40px) scale(0.9);
    }
    37.5% {
        transform: translate(500px, 12px) scale(0.9);
    }
    50% {
        transform: translate(720px, -25px) scale(0.9);
    }
    62.5% {
        transform: translate(940px, 2px) scale(0.9);
    }
    75% {
        transform: translate(1160px, 28px) scale(0.9);
    }
    87.5% {
        transform: translate(1380px, 6px) scale(0.9);
    }
    100% {
        transform: translate(1600px, 30px) scale(0.9);
    }
}
/* The dove is one traced path, so the old two-frame wing swap is gone: the
   beat is a squash-and-stretch on the whole bird, hinged at the shoulder.
   The squash peaks before the midpoint — a downstroke is quicker than the
   recovery that follows it. */
@keyframes prFlap {
    0%,
    100% {
        transform: scaleY(1);
    }
    38% {
        transform: scaleY(0.84) scaleX(1.04);
    }
}
.fly-lead {
    animation: flyAcross 13s linear infinite;
}
.fly-mid {
    animation: flyAcross 16s linear infinite;
    animation-delay: -6.5s;
}
.fly-trail {
    animation: flyAcrossSlow 23s linear infinite;
}
.pr-flap {
    transform-box: fill-box;
    transform-origin: 50% 42%;
    animation: prFlap 0.65s ease-in-out infinite;
}
/* offset so the flock never beats in lockstep */
.fly-mid .pr-flap {
    animation-duration: 0.62s;
    animation-delay: -0.21s;
}
.fly-trail .pr-flap {
    animation-duration: 0.68s;
    animation-delay: -0.37s;
}
@media (prefers-reduced-motion: reduce) {
    .fly-lead,
    .fly-mid,
    .fly-trail,
    .pr-flap {
        animation: none;
    }
}

/* ---- loading screen ---- */
@keyframes orbit {
    0% {
        transform: translate(0, 0) rotate(-4deg);
    }
    25% {
        transform: translate(58px, -26px) rotate(7deg);
    }
    50% {
        transform: translate(0, -50px) rotate(-2deg);
    }
    75% {
        transform: translate(-58px, -26px) rotate(-9deg);
    }
    100% {
        transform: translate(0, 0) rotate(-4deg);
    }
}
@keyframes barSlide {
    0% {
        transform: translateX(-110%);
    }
    100% {
        transform: translateX(220%);
    }
}
@keyframes dotPulse {
    0%,
    80%,
    100% {
        opacity: 0.25;
        transform: scale(0.85);
    }
    40% {
        opacity: 1;
        transform: scale(1);
    }
}
.loading-pigeon {
    animation: orbit 4.2s ease-in-out infinite;
}
.bar-fill {
    animation: barSlide 1.6s ease-in-out infinite;
}
.pr-dot {
    animation: dotPulse 1.4s ease-in-out infinite;
}
.pr-dot:nth-child(2) {
    animation-delay: 0.18s;
}
.pr-dot:nth-child(3) {
    animation-delay: 0.36s;
}
@media (prefers-reduced-motion: reduce) {
    .loading-pigeon,
    .bar-fill,
    .pr-dot {
        animation: none;
    }
}

/* ---- animated ETS pigeon (loading screen hero) ---- */
.pr-load-stage {
    position: relative;
    width: min(480px, 86vw);
    aspect-ratio: 3 / 2;
}
.pr-load-stage > * {
    position: absolute;
}

/* soft blue bloom behind the bird */
.pr-load-glow {
    left: 50%;
    top: 54%;
    width: 82%;
    aspect-ratio: 1;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: radial-gradient(
        circle,
        rgba(37, 99, 235, 0.45) 0%,
        rgba(37, 99, 235, 0.16) 42%,
        transparent 70%
    );
    filter: blur(10px);
    z-index: 0;
    animation: prGlowPulse 3.4s ease-in-out infinite;
}
@keyframes prGlowPulse {
    0%,
    100% {
        opacity: 0.6;
        transform: translate(-50%, -50%) scale(1);
    }
    50% {
        opacity: 1;
        transform: translate(-50%, -50%) scale(1.12);
    }
}

/* dashed flight-path ellipse */
.pr-load-ring {
    left: -6%;
    top: 7%;
    width: 112%;
    height: 86%;
    z-index: 1;
    opacity: 0.45;
}
.pr-load-ring ellipse {
    animation: prDash 9s linear infinite;
}
@keyframes prDash {
    to {
        stroke-dashoffset: -120;
    }
}

/* speed streaks sweeping in behind the wing */
.pr-load-streak {
    left: 0;
    height: 2px;
    width: 46%;
    border-radius: 2px;
    background: linear-gradient(
        90deg,
        transparent,
        rgba(147, 197, 253, 0.5),
        transparent
    );
    filter: blur(1.2px);
    transform-origin: 50% 50%;
    z-index: 1;
    animation: prStreak 2.8s ease-in-out infinite;
}
.pr-load-streak:nth-of-type(1) {
    top: 56%;
    animation-delay: 0s;
}
.pr-load-streak:nth-of-type(2) {
    top: 64%;
    width: 34%;
    animation-delay: 0.7s;
}
.pr-load-streak:nth-of-type(3) {
    top: 48%;
    width: 28%;
    animation-delay: 1.5s;
}
@keyframes prStreak {
    0% {
        opacity: 0;
        transform: translateX(-30%) rotate(-7deg) scaleX(0.5);
    }
    35% {
        opacity: 0.85;
    }
    100% {
        opacity: 0;
        transform: translateX(70%) rotate(-7deg) scaleX(1.15);
    }
}

/* the bird itself: entrance + endless soar, with a subtle wing beat */
.pr-load-flight {
    inset: 0;
    z-index: 2;
    transform-origin: 62% 60%;
    animation:
        prBirdIn 1.15s cubic-bezier(0.2, 0.75, 0.25, 1) both,
        prSoar 4.6s ease-in-out 1.15s infinite;
    will-change: transform;
}
.pr-load-beat {
    position: absolute;
    inset: 0;
    transform-origin: 62% 60%;
    animation: prWingBeat 1.6s ease-in-out infinite;
}
.pr-load-bird {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* the traced dove is cropped tight to the ink, so it needs its own margin
     inside the stage that the old PNG carried as transparent padding */
    transform: scale(0.82);
    filter: drop-shadow(0 20px 42px rgba(37, 99, 235, 0.45));
}
@keyframes prBirdIn {
    0% {
        opacity: 0;
        transform: translate(-16%, 18%) scale(0.84) rotate(-9deg);
    }
    100% {
        opacity: 1;
        transform: translate(0, 0) scale(1) rotate(0);
    }
}
@keyframes prSoar {
    0%,
    100% {
        transform: translateY(0) rotate(0deg);
    }
    25% {
        transform: translateY(-4%) rotate(1.8deg);
    }
    50% {
        transform: translateY(-1.2%) rotate(0deg);
    }
    75% {
        transform: translateY(2.6%) rotate(-1.8deg);
    }
}
@keyframes prWingBeat {
    0%,
    100% {
        transform: scaleY(1) scaleX(1);
    }
    50% {
        transform: scaleY(0.955) scaleX(1.012);
    }
}

/* ETS leg-band broadcasting rings (ride along with the bird) */
.pr-load-ping {
    position: absolute;
    left: 56.5%;
    top: 72%;
    width: 9%;
    aspect-ratio: 1;
    margin: -4.5% 0 0 -4.5%;
    border-radius: 50%;
    border: 1.5px solid rgba(96, 165, 250, 0.75);
    opacity: 0;
    z-index: 3;
    animation: prPing 2.4s cubic-bezier(0.2, 0.6, 0.3, 1) infinite;
}
.pr-load-ping:nth-of-type(2) {
    animation-delay: 0.8s;
}
.pr-load-ping:nth-of-type(3) {
    animation-delay: 1.6s;
}
@keyframes prPing {
    0% {
        opacity: 0;
        transform: scale(0.4);
    }
    15% {
        opacity: 0.8;
    }
    100% {
        opacity: 0;
        transform: scale(2.7);
    }
}

/* drifting feathers shed behind the flight path */
.pr-load-feather {
    z-index: 4;
    opacity: 0;
    animation: prFeather 6s ease-in-out infinite;
}
.pr-load-feather.pr-f1 {
    left: 30%;
    top: 46%;
    animation-delay: 0.6s;
}
.pr-load-feather.pr-f2 {
    left: 38%;
    top: 60%;
    animation-delay: 2.4s;
}
.pr-load-feather.pr-f3 {
    left: 24%;
    top: 68%;
    animation-delay: 4.1s;
}
@keyframes prFeather {
    0% {
        opacity: 0;
        transform: translate(0, 0) rotate(0deg) scale(0.9);
    }
    12% {
        opacity: 0.85;
    }
    70% {
        opacity: 0.35;
    }
    100% {
        opacity: 0;
        transform: translate(-90px, 58px) rotate(-150deg) scale(0.65);
    }
}

@media (prefers-reduced-motion: reduce) {
    .pr-load-glow,
    .pr-load-ring ellipse,
    .pr-load-streak,
    .pr-load-flight,
    .pr-load-beat,
    .pr-load-ping,
    .pr-load-feather {
        animation: none;
    }
    .pr-load-streak,
    .pr-load-feather,
    .pr-load-ping {
        opacity: 0;
    }
}
/* ---- misc components ---- */
.pr-stat {
    background: rgba(255, 255, 255, 0.04);
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-radius: 0.85rem;
    padding: 1rem;
}
.pr-filter-chip {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.8125rem;
    font-weight: 600;
    border-radius: 100px;
    padding: 0.5rem 1.1rem;
    border: 1.5px solid rgba(16, 42, 67, 0.12);
    background: var(--pr-surface);
    color: var(--pr-heading);
}
.pr-filter-chip.active {
    background: var(--pr-navy-900);
    color: #fff;
    border-color: var(--pr-navy-900);
}

.pr-medal {
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 800;
    font-size: 0.8rem;
}
.pr-medal-1 {
    background: linear-gradient(135deg, #e8b65e, #c99a46);
    color: #3a2e1c;
}
.pr-medal-2 {
    background: #e4e1da;
    color: #5b615c;
}
.pr-medal-3 {
    background: #efdcc4;
    color: #6b4b34;
}

.pr-progress {
    height: 6px;
    border-radius: 4px;
    background: rgba(255, 255, 255, 0.08);
    overflow: hidden;
}
.pr-progress .bar {
    height: 100%;
    background: linear-gradient(90deg, var(--pr-blue-accent), var(--pr-blue));
    border-radius: 4px;
}

.pr-phone {
    width: 290px;
    background: var(--pr-navy-900);
    border-radius: 2.5rem;
    padding: 0.875rem;
    box-shadow: 0 30px 60px rgba(16, 42, 67, 0.25);
}
.pr-phone-screen {
    background: var(--pr-bg);
    border-radius: 1.75rem;
    overflow: hidden;
}

.accordion-button:not(.collapsed) {
    color: var(--pr-blue-dark);
    background-color: rgba(37, 99, 235, 0.06);
    box-shadow: none;
}
.accordion-button:focus {
    box-shadow: 0 0 0 0.2rem rgba(37, 99, 235, 0.2);
}

.pr-role-select {
    cursor: pointer;
    border-radius: 1rem;
    padding: 1.4rem 1rem;
    text-align: center;
    border: 1.5px solid rgba(255, 255, 255, 0.1);
    background: rgba(255, 255, 255, 0.04);
    transition:
        transform 0.15s ease,
        box-shadow 0.15s ease,
        border-color 0.15s ease;
}
.pr-role-select:hover {
    transform: translateY(-3px);
    border-color: rgba(37, 99, 235, 0.4);
}
.pr-role-select.selected {
    border-color: var(--pr-blue);
    background: rgba(37, 99, 235, 0.08);
}

.pr-onb-card {
    cursor: pointer;
}
.pr-onb-card.selected {
    border: 1.5px solid var(--pr-blue) !important;
    box-shadow: 0 14px 28px rgba(37, 99, 235, 0.14);
}

/* ---- services / province coverage cards (index) ----
   The card must not change size when it is opened, so the office line and the
   contact lines are stacked in a single grid cell (`grid-area: 1/1`): the cell
   is always as tall as the taller of the two, and opening just cross-fades one
   for the other. Nothing here may add height on `.is-open`. */
.pr-prov {
    cursor: pointer;
    overflow: hidden;
}
.pr-prov-toggle {
    display: block;
    width: 100%;
    padding: 1.5rem 1.5rem 0.9rem;
    background: none;
    border: 0;
    text-align: left;
    color: inherit;
}
.pr-prov-toggle .pr-icon-badge {
    margin-bottom: 0.9rem;
}
.pr-prov-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}
.pr-prov-name {
    font-family: "Plus Jakarta Sans", system-ui, sans-serif;
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.3;
    color: var(--pr-heading);
}
.pr-prov-chev {
    flex: 0 0 auto;
    stroke: var(--pr-muted-2);
    transition:
        transform 0.25s ease,
        stroke 0.2s ease;
}
.pr-prov.is-open .pr-prov-chev {
    transform: rotate(180deg);
    stroke: var(--pr-blue);
}

.pr-prov-body {
    display: grid;
    padding: 0 1.5rem 1.5rem;
}
.pr-prov-body > * {
    grid-area: 1 / 1; /* both states share one cell — no reflow on open */
    margin: 0;
    transition:
        opacity 0.22s ease,
        visibility 0.22s;
}
.pr-prov-sub {
    font-size: 0.8125rem;
    color: var(--pr-muted);
}
.pr-prov.is-open .pr-prov-sub {
    opacity: 0;
    visibility: hidden;
}
.pr-prov-panel {
    opacity: 0;
    visibility: hidden;
}
.pr-prov.is-open .pr-prov-panel {
    opacity: 1;
    visibility: visible;
}
.pr-prov-line {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.8125rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--pr-muted);
    text-decoration: none;
    word-break: break-word;
}
.pr-prov-line + .pr-prov-line {
    margin-top: 0.4rem;
}
.pr-prov-line svg {
    flex: 0 0 auto;
    stroke: var(--pr-blue);
}
.pr-prov-line:hover {
    color: var(--pr-blue);
}
@media (prefers-reduced-motion: reduce) {
    .pr-prov-body > *,
    .pr-prov-chev {
        transition: none;
    }
}

.pr-step-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: rgba(16, 42, 67, 0.15);
}
.pr-step-dot.active {
    background: var(--pr-blue);
    width: 24px;
    border-radius: 4px;
}

footer.pr-footer a {
    color: rgba(255, 255, 255, 0.5);
}
footer.pr-footer a:hover {
    color: #fff;
}

.form-control:focus {
    border-color: var(--pr-blue);
    box-shadow: 0 0 0 0.2rem rgba(37, 99, 235, 0.15);
}

/* ---- password field with show/hide toggle ---- */
.pr-pass {
    position: relative;
}
.pr-pass .form-control {
    padding-right: 2.6rem;
}
.pr-pass-toggle {
    position: absolute;
    top: 50%;
    right: 0.5rem;
    transform: translateY(-50%);
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.75rem;
    height: 1.75rem;
    padding: 0;
    border: 0;
    border-radius: 0.4rem;
    background: transparent;
    color: var(--pr-muted);
    cursor: pointer;
}
.pr-pass-toggle:hover {
    color: var(--pr-blue);
    background: rgba(37, 99, 235, 0.08);
}
.pr-pass-toggle:focus-visible {
    outline: 2px solid var(--pr-blue);
    outline-offset: 1px;
}
.pr-pass-toggle .pr-icon-eye-off {
    display: none;
}
.pr-pass-toggle.is-on .pr-icon-eye {
    display: none;
}
.pr-pass-toggle.is-on .pr-icon-eye-off {
    display: block;
}

/* ---- theme toggle ---- */
.pr-theme-toggle {
    width: 2.25rem;
    height: 2.25rem;
    flex-shrink: 0;
    border-radius: 50%;
    border: 1.5px solid rgba(16, 42, 67, 0.14);
    background: var(--pr-surface);
    color: var(--pr-heading);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition:
        border-color 0.15s ease,
        color 0.15s ease;
}
.pr-theme-toggle:hover {
    border-color: var(--pr-blue);
    color: var(--pr-blue-dark);
}
[data-bs-theme="dark"] .pr-theme-toggle {
    border-color: rgba(255, 255, 255, 0.16);
}
.pr-theme-toggle .pr-icon-moon {
    display: block;
}
.pr-theme-toggle .pr-icon-sun {
    display: none;
}
[data-bs-theme="dark"] .pr-theme-toggle .pr-icon-moon {
    display: none;
}
[data-bs-theme="dark"] .pr-theme-toggle .pr-icon-sun {
    display: block;
}

/* ==========================================================================
   HERO v2 — light photo hero
   The hero photo is always bright, so the readability veil, its pills and the
   headline accent are tokenised and flipped by color mode rather than being
   hardcoded white/navy.
   ========================================================================== */
:root {
    --pr-veil-1: rgba(255, 255, 255, 0.97);
    --pr-veil-2: rgba(255, 255, 255, 0.88);
    --pr-veil-3: rgba(255, 255, 255, 0.44);
    --pr-veil-0: rgba(255, 255, 255, 0);
    --pr-veil-pill: rgba(255, 255, 255, 0.92);
    --pr-veil-pill-bd: rgba(16, 42, 67, 0.1);
    --pr-hero-accent: var(--pr-blue);
    --pr-hero-flock: rgba(16, 42, 67, 0.62);
    --pr-hero-title-shadow:
        0 1px 2px rgba(16, 42, 67, 0.16), 0 10px 26px rgba(16, 42, 67, 0.12);
}
[data-bs-theme="dark"] {
    --pr-veil-1: rgba(10, 27, 51, 0.96);
    --pr-veil-2: rgba(10, 27, 51, 0.88);
    --pr-veil-3: rgba(10, 27, 51, 0.5);
    --pr-veil-0: rgba(10, 27, 51, 0);
    --pr-veil-pill: rgba(16, 42, 67, 0.74);
    --pr-veil-pill-bd: rgba(255, 255, 255, 0.18);
    --pr-hero-accent: var(--pr-blue-accent);
    --pr-hero-flock: rgba(255, 255, 255, 0.66);
    --pr-hero-title-shadow:
        0 1px 2px rgba(0, 0, 0, 0.38), 0 12px 30px rgba(0, 0, 0, 0.45);
}

/* The hero is exactly one screen: nav + hero == the visible viewport, never
   more. `--pr-nav-h` is measured by js/main.js; the literal is the fallback.
   svh (smallest viewport) keeps mobile honest while the URL bar is showing. */
.pr-hero-photo {
    position: relative;
    overflow: hidden;
    isolation: isolate;
    height: calc(100vh - var(--pr-nav-h, 84px));
    height: calc(100svh - var(--pr-nav-h, 84px));
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    padding: 0;
    background: var(--pr-bg);
    color: var(--pr-text);
}
.pr-hero-photo > .container {
    width: 100%;
}

/* The photo is deliberately wider than the hero and anchored to the right so
   the bird drifts left of the live-race card — its head and the iridescent
   neck stay in the clear gap between the copy and the card. */
.pr-hero-photo .pr-hero-img {
    left: auto;
    right: -3%;
    width: 122%;
    object-position: 50% 30%;
    transform-origin: 58% 40%;
    /* no white wash over the bird — just more colour and bite in the plumage */
    filter: saturate(1.3) contrast(1.1) brightness(1.01);
    animation: prHeroPan 32s ease-in-out infinite alternate;
}

/* specular highlight that travels across the bird every few seconds; the
   radial mask keeps it off the headline so the copy never washes out */
.pr-hero-sheen {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    overflow: hidden;
    opacity: 0.5;
    -webkit-mask-image: radial-gradient(
        ellipse 38% 56% at 60% 40%,
        #000 0%,
        rgba(0, 0, 0, 0.7) 44%,
        transparent 76%
    );
    mask-image: radial-gradient(
        ellipse 38% 56% at 60% 40%,
        #000 0%,
        rgba(0, 0, 0, 0.7) 44%,
        transparent 76%
    );
}
.pr-hero-sheen::after {
    content: "";
    position: absolute;
    top: -25%;
    bottom: -25%;
    left: -35%;
    width: 27%;
    background: linear-gradient(
        100deg,
        transparent 0%,
        rgba(255, 255, 255, 0.5) 44%,
        rgba(239, 246, 255, 0.85) 50%,
        rgba(255, 255, 255, 0.5) 56%,
        transparent 100%
    );
    transform: skewX(-14deg);
    filter: blur(7px);
}
.pr-hero-sheen {
    --sheen-play: prSheenSweep 9s cubic-bezier(0.4, 0, 0.2, 1) 1.8s infinite;
}
.pr-hero-sheen::after {
    animation: var(--sheen-play);
}
@keyframes prSheenSweep {
    0% {
        left: -35%;
        opacity: 0;
    }
    10% {
        opacity: 1;
    }
    44%,
    100% {
        left: 116%;
        opacity: 0;
    }
}
@keyframes prHeroPan {
    0% {
        transform: scale(1.01) translate3d(0, 0, 0);
    }
    100% {
        transform: scale(1.05) translate3d(-1%, -1.2%, 0);
    }
}

/* Readability shade sits behind the copy ONLY — an elliptical scrim anchored
   to the left edge that has fully faded out before it reaches the bird. */
.pr-hero-scrim {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    background: radial-gradient(
        112% 118% at -14% 52%,
        var(--pr-veil-1) 0%,
        var(--pr-veil-1) 26%,
        var(--pr-veil-2) 40%,
        var(--pr-veil-3) 52%,
        var(--pr-veil-0) 64%
    );
}

/* drifting silhouette flock across the open sky */
.pr-hero-flock-layer {
    position: absolute;
    inset: 0;
    z-index: 1;
    pointer-events: none;
    overflow: hidden;
}
.pr-hero-flock-layer svg {
    position: absolute;
    fill: var(--pr-hero-flock);
}

/* ---- hero layout ------------------------------------------------------
   copy | live-race card on top, feature strip docked across the base. The
   rail wrapper is `display: contents` here so its two children drop straight
   into this grid; on mobile it becomes a real horizontal snap slider. */
.pr-hero-inner {
    position: relative;
    z-index: 2;
    display: grid;
    grid-template-columns: minmax(0, 1.16fr) minmax(320px, 0.84fr);
    grid-template-areas: "copy aside" "bar bar";
    align-items: center;
    column-gap: clamp(1.25rem, 3vw, 3rem);
    row-gap: clamp(0.75rem, 2.4vh, 2rem);
    padding-top: clamp(1rem, 4vh, 3rem);
}
.pr-hero-rail {
    display: contents;
}
.pr-hero-copy {
    grid-area: copy;
}
.pr-hero-aside {
    grid-area: aside;
}
.pr-hero-bar {
    grid-area: bar;
}
.pr-rail-dots {
    display: none;
}

.pr-hero-title {
    margin: clamp(0.9rem, 2.4vh, 1.6rem) 0 0;
    line-height: 1.04;
    letter-spacing: -0.015em;
    max-width: 26ch;
    text-shadow: var(--pr-hero-title-shadow);
    /* the vh term shrinks the headline on short laptop screens so the whole
     hero keeps fitting inside one viewport */
    font-size: clamp(1.9rem, min(3.9vw, 6.1vh), 3.1rem);
}
/* keeps "Pakistan's Next-Generation" on one line instead of breaking at the hyphen */
.pr-hero-line {
    white-space: nowrap;
}
.pr-hero-lead {
    margin: clamp(1rem, 2.6vh, 1.75rem) 0 0;
    max-width: 460px;
    color: var(--pr-heading);
    font-size: clamp(1rem, min(1.35vw, 2.1vh), 1.25rem);
}
.pr-hero-sub {
    margin: clamp(0.5rem, 1.6vh, 1rem) 0 0;
    max-width: 460px;
    color: var(--pr-muted);
}
.pr-hero-cta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.85rem;
    margin-top: clamp(1rem, 2.8vh, 1.75rem);
}

/* single card-shaped CTA in the hero — same tile language as the mobile nav
   cards (.pr-nav-card), sized up so it can carry the hero on its own */
.pr-cta-card {
    display: flex;
    align-items: center;
    gap: 0.9rem;
    width: 100%;
    max-width: 25rem;
    padding: 0.95rem 1.1rem;
    border-radius: 1.15rem;
    border: 1px solid var(--pr-border);
    background: var(--pr-surface);
    box-shadow: 0 14px 34px rgba(16, 42, 67, 0.14);
    text-decoration: none;
    transition:
        transform 0.18s ease,
        box-shadow 0.18s ease,
        border-color 0.18s ease;
}
.pr-cta-card:hover {
    transform: translateY(-2px);
    border-color: rgba(37, 99, 235, 0.4);
    box-shadow: 0 22px 46px rgba(16, 42, 67, 0.2);
}
.pr-cta-card:active {
    transform: scale(0.99);
}
.pr-icon-badge.pr-cta-card-icon {
    width: 2.9rem;
    height: 2.9rem;
    border-radius: 0.85rem;
}
.pr-cta-card-text {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}
.pr-cta-card-title {
    font-family: "Plus Jakarta Sans", system-ui, sans-serif;
    font-weight: 700;
    font-size: 1.05rem;
    line-height: 1.25;
    color: var(--pr-heading);
}
.pr-cta-card-sub {
    font-size: 0.82rem;
    line-height: 1.3;
    color: var(--pr-muted-2);
}
.pr-cta-card-arrow {
    margin-left: auto;
    flex-shrink: 0;
    color: var(--pr-hero-accent);
    transition: transform 0.18s ease;
}
.pr-cta-card:hover .pr-cta-card-arrow {
    transform: translateX(3px);
}
.pr-hero-note {
    margin: clamp(0.9rem, 2.4vh, 1.5rem) 0 0;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--pr-muted-2);
}

/* short viewports: drop the secondary paragraph rather than let the hero
   spill past the fold */
@media (min-width: 992px) and (max-height: 760px) {
    .pr-hero-sub,
    .pr-hero-note {
        display: none;
    }
    .pr-hero-card {
        padding: 1.25rem !important;
    }
    .pr-hero-card .mb-4 {
        margin-bottom: 0.9rem !important;
    }
    .pr-hero-card .mt-4 {
        margin-top: 1rem !important;
    }
}

/* pill above the headline */
.pr-hero-pill {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    background: var(--pr-veil-pill);
    border: 1px solid var(--pr-veil-pill-bd);
    border-radius: 100px;
    padding: 0.5rem 1.1rem;
    box-shadow: 0 6px 20px rgba(16, 42, 67, 0.1);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
.pr-hero-pill span {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: var(--pr-heading);
}
.pr-hero-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--pr-hero-accent);
    animation: prBluePulse 2.2s ease-out infinite;
}
@keyframes prBluePulse {
    0% {
        box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.5);
    }
    70% {
        box-shadow: 0 0 0 9px rgba(37, 99, 235, 0);
    }
    100% {
        box-shadow: 0 0 0 0 rgba(37, 99, 235, 0);
    }
}

/* flourish that draws itself in under the headline */
.pr-hero-rule {
    display: flex;
    align-items: center;
    gap: 0.55rem;
    margin-top: 1.15rem;
}
.pr-hero-rule i {
    display: block;
    height: 3px;
    width: 0;
    border-radius: 3px;
    background: linear-gradient(
        90deg,
        var(--pr-hero-accent),
        rgba(37, 99, 235, 0)
    );
    animation: prRuleGrow 0.9s cubic-bezier(0.2, 0.7, 0.25, 1) 0.6s forwards;
}
@keyframes prRuleGrow {
    to {
        width: 96px;
    }
}
.pr-hero-glyph {
    fill: var(--pr-hero-accent);
    opacity: 0.75;
    animation: prGlyphBob 4.5s ease-in-out infinite;
}
@keyframes prGlyphBob {
    0%,
    100% {
        transform: translateY(0) rotate(0deg);
    }
    50% {
        transform: translateY(-3px) rotate(-3deg);
    }
}

/* staggered entrance — per-element delays are set inline */
.pr-rise {
    opacity: 0;
    animation: prRise 0.85s cubic-bezier(0.2, 0.7, 0.25, 1) both;
}
@keyframes prRise {
    from {
        opacity: 0;
        transform: translate3d(0, 22px, 0);
    }
    to {
        opacity: 1;
        transform: none;
    }
}
.pr-rise-side {
    opacity: 0;
    animation: prRiseSide 1s cubic-bezier(0.2, 0.7, 0.25, 1) both;
}
@keyframes prRiseSide {
    from {
        opacity: 0;
        transform: translate3d(36px, 26px, 0) scale(0.97);
    }
    to {
        opacity: 1;
        transform: none;
    }
}

/* live race card */
.pr-hero-card {
    background: var(--pr-surface);
    border: 1px solid var(--pr-border);
    border-radius: 1.25rem;
    box-shadow: 0 30px 70px rgba(10, 27, 51, 0.28);
    animation: prCardFloat 7.5s ease-in-out 1.4s infinite;
}
@keyframes prCardFloat {
    0%,
    100% {
        transform: translateY(0);
    }
    50% {
        transform: translateY(-9px);
    }
}
.pr-chip-live {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    background: var(--pr-gradient);
    border-radius: 100px;
    padding: 0.45rem 1rem;
    color: #fff;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    box-shadow: 0 6px 16px rgba(29, 78, 216, 0.28);
}
.pr-wave {
    animation: prWave 1.8s ease-in-out infinite;
}
.pr-wave-2 {
    animation-delay: 0.35s;
}
@keyframes prWave {
    0%,
    100% {
        opacity: 0.35;
    }
    45% {
        opacity: 1;
    }
}

/* ripple rings on the latest-arrival avatar */
.pr-ping-wrap {
    position: relative;
}
.pr-ping-wrap::before,
.pr-ping-wrap::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    border: 1.5px solid rgba(37, 99, 235, 0.5);
    animation: prRipple 2.8s cubic-bezier(0.2, 0.6, 0.3, 1) infinite;
}
.pr-ping-wrap::after {
    animation-delay: 1.4s;
}
@keyframes prRipple {
    0% {
        opacity: 0.75;
        transform: scale(1);
    }
    100% {
        opacity: 0;
        transform: scale(2);
    }
}

/* light-surface secondary button (the hero sits on a bright photo) */
.btn-pr-light {
    background: var(--pr-surface);
    border: 1.5px solid var(--pr-border);
    color: var(--pr-heading);
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 700;
    border-radius: 0.75rem;
    padding: 0.85rem 1.6rem;
    box-shadow: 0 6px 18px rgba(16, 42, 67, 0.1);
    transition:
        transform 0.15s ease,
        box-shadow 0.15s ease,
        border-color 0.15s ease,
        color 0.15s ease;
}
.btn-pr-light:hover,
.btn-pr-light:focus {
    color: var(--pr-blue-dark);
    border-color: rgba(37, 99, 235, 0.45);
    transform: translateY(-2px);
    box-shadow: 0 10px 24px rgba(16, 42, 67, 0.14);
}

/* light sweep across the primary CTA */
.pr-shine {
    position: relative;
    overflow: hidden;
}
.pr-shine::after {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: -45%;
    width: 34%;
    background: linear-gradient(
        100deg,
        transparent,
        rgba(255, 255, 255, 0.4),
        transparent
    );
    transform: skewX(-18deg);
    animation: prShine 6s ease-in-out 2s infinite;
    pointer-events: none;
}
@keyframes prShine {
    0% {
        left: -45%;
    }
    24%,
    100% {
        left: 130%;
    }
}

/* bottom feature strip, docked to the base of the hero */
.pr-hero-bar {
    position: relative;
    z-index: 2;
    display: flex;
    border-radius: 1.25rem 1.25rem 0 0;
    padding: clamp(0.9rem, 2vh, 1.5rem);
    /* the leaf cluster owns the left corner */
    padding-left: clamp(9rem, 13vw, 12.5rem);
    background: linear-gradient(
        100deg,
        rgba(10, 27, 51, 0.95),
        rgba(23, 55, 102, 0.93)
    );
    border: 1px solid rgba(255, 255, 255, 0.08);
    border-bottom: none;
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    box-shadow: 0 -12px 44px rgba(10, 27, 51, 0.24);
}
.pr-bar-item {
    display: flex;
    align-items: center;
    gap: 0.8rem;
    flex: 1 1 0;
    min-width: 0;
}
.pr-bar-item + .pr-bar-item {
    border-left: 1px solid rgba(255, 255, 255, 0.12);
    padding-left: clamp(0.75rem, 1.6vw, 1.25rem);
}
/* number over label — the strip reads as a stat row, not a feature list */
.pr-bar-value {
    font-family: "Plus Jakarta Sans", system-ui, sans-serif;
    font-weight: 800;
    color: #fff;
    font-size: clamp(1.1rem, 1.6vw, 1.45rem);
    line-height: 1.1;
    letter-spacing: -0.01em;
}
.pr-bar-label {
    font-size: clamp(0.72rem, 0.9vw, 0.82rem);
    color: rgba(255, 255, 255, 0.62);
    margin-top: 0.15rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* bare accent glyph, no badge disc */
.pr-bar-icon {
    width: 2.6rem;
    height: 2.6rem;
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--pr-blue-accent);
    transition: transform 0.2s ease;
}
.pr-bar-item:hover .pr-bar-icon {
    transform: translateY(-2px) scale(1.06);
}

/* leafy branch layered in front of the feature strip's left corner */
.pr-hero-leaves {
    position: absolute;
    z-index: 3;
    /* tracks the container edge so the cluster always straddles the strip's
     left corner instead of drifting into the gutter on wide screens */
    left: max(0px, calc(50% - 652px));
    bottom: 0;
    width: clamp(140px, 13vw, 190px);
    height: auto;
    pointer-events: none;
    filter: drop-shadow(0 10px 22px rgba(6, 26, 14, 0.42));
}
.pr-leaf-sway {
    transform-origin: 8% 100%;
    animation: prLeafSway 7s ease-in-out infinite alternate;
}
.pr-leaf-back {
    animation-duration: 9s;
    animation-delay: -2s;
    opacity: 0.9;
}
@keyframes prLeafSway {
    from {
        transform: rotate(0deg);
    }
    to {
        transform: rotate(var(--sway, 2deg));
    }
}

@media (prefers-reduced-motion: reduce) {
    .pr-hero-photo .pr-photo-bg,
    .pr-rise,
    .pr-rise-side,
    .pr-hero-card,
    .pr-hero-rule i,
    .pr-hero-dot,
    .pr-hero-glyph,
    .pr-wave,
    .pr-leaf-sway {
        animation: none;
    }
    .pr-rise,
    .pr-rise-side {
        opacity: 1;
    }
    .pr-hero-rule i {
        width: 96px;
    }
    .pr-shine::after,
    .pr-ping-wrap::before,
    .pr-ping-wrap::after,
    .pr-hero-sheen::after {
        display: none;
    }
}

/* ---- ETS hardware illustrations ---- */
/* Broadcasting arcs on the ring and the reader, plus the reader link LED.
   These animate the `opacity` presentation attributes set inline on the SVG. */
.pr-ets-wave {
    animation: prEtsWave 2.6s ease-in-out infinite;
}
.pr-ets-wave.pr-w2 {
    animation-delay: 0.4s;
}
.pr-ets-wave.pr-w3 {
    animation-delay: 0.8s;
}
@keyframes prEtsWave {
    0%,
    100% {
        opacity: 0.12;
    }
    40% {
        opacity: 0.85;
    }
}
.pr-ets-led {
    animation: prEtsLed 2s ease-in-out infinite;
}
@keyframes prEtsLed {
    0%,
    100% {
        opacity: 0.35;
    }
    45% {
        opacity: 1;
    }
}
@media (prefers-reduced-motion: reduce) {
    .pr-ets-wave,
    .pr-ets-led {
        animation: none;
    }
}

/* ==========================================================================
   HERO — tablet & phone
   The hero stays exactly one screen tall, so instead of stacking (and
   overflowing) the live-race card and the four feature items become slides of
   one horizontal snap rail docked to the base. The bird keeps the top band to
   itself; the copy sits on a scrim that only covers the copy.
   ========================================================================== */
@media (max-width: 991.98px) {
    /* with the stats block below the slideshow the stack can outgrow one
     screen on a short phone — grow instead of clipping the card */
    .pr-hero-photo {
        height: auto;
        min-height: calc(100svh - var(--pr-nav-h, 84px));
    }

    .pr-hero-photo .pr-hero-img {
        left: 0;
        right: auto;
        width: 100%;
        object-position: 56% 24%;
        /* zoomed in on the bird so it still reads big on a phone */
        transform-origin: 94% 96%;
        animation-name: prHeroPanPhone;
        /* a touch cooler and punchier so the bird still reads on a small screen */
        filter: saturate(1.34) contrast(1.12) brightness(1.02);
    }
    @keyframes prHeroPanPhone {
        0% {
            transform: scale(1.2) translate3d(0, 0, 0);
        }
        100% {
            transform: scale(1.26) translate3d(-1.5%, -1%, 0);
        }
    }

    /* the photo keeps the whole top band; only the base is washed so the
     docked rail has something to sit on */
    .pr-hero-scrim {
        background: linear-gradient(
            to bottom,
            var(--pr-veil-0) 0%,
            var(--pr-veil-0) 42%,
            var(--pr-veil-3) 66%,
            var(--pr-veil-2) 82%,
            var(--pr-veil-1) 100%
        );
    }
    .pr-hero-sheen {
        opacity: 0.35;
    }

    .pr-hero-inner {
        display: flex;
        flex-direction: column;
        align-items: stretch;
        height: 100%;
        padding-top: clamp(0.75rem, 2.5vh, 1.5rem);
        padding-bottom: 0;
        row-gap: 0;
    }
    /* the bird gets the space above the copy; the copy carries its own shade so
     the readability wash follows the text instead of covering the photo */
    .pr-hero-copy {
        position: relative;
        margin: auto -0.75rem 0;
        padding: 2.75rem 0.75rem 0.5rem;
        background: linear-gradient(
            to bottom,
            var(--pr-veil-0) 0%,
            var(--pr-veil-3) 22%,
            var(--pr-veil-2) 44%,
            var(--pr-veil-1) 68%
        );
    }
    .pr-hero-title {
        max-width: 100%;
        font-size: clamp(1.75rem, min(9vw, 5.6vh), 2.6rem);
    }
    .pr-hero-line {
        white-space: normal;
    }
    .pr-hero-lead {
        max-width: 100%;
        font-size: 1rem;
    }
    .pr-hero-sub,
    .pr-hero-note,
    .pr-hero-rule {
        display: none;
    }
    .pr-hero-cta {
        gap: 0.6rem;
    }
    .pr-cta-card {
        max-width: 100%;
        padding: 0.85rem 0.95rem;
    }

    /* rail */
    .pr-hero-rail {
        display: flex;
        align-items: stretch;
        gap: 0.75rem;
        margin: clamp(0.5rem, 2vh, 1.25rem) -0.75rem 0;
        padding: 0.25rem 0.75rem 0;
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-x: contain;
    }
    .pr-hero-rail::-webkit-scrollbar {
        display: none;
    }
    /* one slide today, so it fills the rail rather than peeking a neighbour */
    .pr-hero-aside {
        flex: 0 0 100%;
        scroll-snap-align: center;
    }
    .pr-hero-aside {
        display: flex;
    }
    .pr-hero-card {
        width: 100%;
        padding: 1.15rem !important;
        border-radius: 1.15rem 1.15rem 0 0;
        animation: none;
    }
    .pr-hero-card .mb-4 {
        margin-bottom: 0.85rem !important;
    }
    .pr-hero-card .mt-4 {
        margin-top: 0.9rem !important;
    }
    .pr-hero-card h3 {
        font-size: 1.15rem !important;
    }
    /* the latest-arrival panel lives in full in the live-tracking section */
    .pr-card-extra {
        display: none;
    }

    /* the strip stays one panel, but it leaves the rail: it sits under the
     slideshow as a 2x2 block docked to the hero base. */
    .pr-hero-bar {
        order: 3; /* copy, dots, rail, then the stats */
        display: grid;
        grid-template-columns: 1fr 1fr;
        grid-template-rows: 1fr 1fr;
        column-gap: 0.9rem;
        row-gap: 0.25rem;
        margin: 0.5rem -0.75rem 0;
        padding: 0.35rem 0.9rem; /* also drops the desktop leaf gutter */
        border-radius: 1rem 1rem 0 0;
    }
    .pr-bar-item {
        align-items: center;
        flex-direction: row;
        justify-content: flex-start;
        gap: 0.55rem;
        min-width: 0;
        padding: 0;
    }
    .pr-bar-item > div {
        min-width: 0;
    }
    /* dividers follow the grid, not the source order */
    .pr-bar-item + .pr-bar-item {
        border-left: 0;
        padding-left: 0;
    }
    .pr-bar-item:nth-child(even) {
        border-left: 1px solid rgba(255, 255, 255, 0.12);
        padding-left: 0.9rem;
    }
    .pr-bar-item:nth-child(n + 3) {
        border-top: 1px solid rgba(255, 255, 255, 0.1);
        padding-top: 0.3rem;
    }
    .pr-bar-icon {
        width: 1.4rem;
        height: 1.4rem;
    }
    .pr-bar-icon svg {
        width: auto;
        height: 1.2rem;
    }
    .pr-bar-value {
        font-size: 0.9rem;
        line-height: 1.15;
    }
    .pr-bar-label {
        font-size: 0.66rem;
        margin-top: 0;
    }

    /* rail position dots — a translucent pill so they read on the white race
     card (js/main.js hides them while the rail holds a single slide) */
    .pr-rail-dots {
        display: flex;
        align-items: center;
        justify-content: center;
        gap: 0.35rem;
        position: static;
        order: 1; /* sits between the copy and the rail */
        align-self: center;
        margin: 0.4rem 0 0.1rem;
        padding: 0.2rem 0;
        z-index: 4;
        pointer-events: none;
    }
    .pr-hero-rail {
        order: 2;
    }
    .pr-rail-dots i {
        width: 6px;
        height: 6px;
        border-radius: 50%;
        background: rgba(16, 42, 67, 0.3);
        box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.55);
        transition:
            width 0.2s ease,
            background 0.2s ease;
    }
    .pr-rail-dots i.on {
        width: 16px;
        border-radius: 100px;
        background: var(--pr-hero-accent);
    }

    /* the full-bleed stats block owns the hero base here, so the branch —
     which exists to straddle the strip's left corner — has nowhere to sit */
    .pr-hero-leaves {
        display: none;
    }
}

/* phones */
@media (max-width: 575.98px) {
    .pr-hero-cta {
        flex-direction: row;
        flex-wrap: nowrap;
    }
    .pr-cta-card {
        gap: 0.75rem;
        padding: 0.8rem 0.9rem;
    }
    .pr-icon-badge.pr-cta-card-icon {
        width: 2.6rem;
        height: 2.6rem;
    }
    .pr-cta-card-title {
        font-size: 1rem;
    }
    .pr-cta-card-sub {
        font-size: 0.78rem;
    }
    .pr-hero-pill {
        padding: 0.4rem 0.85rem;
    }
    .pr-hero-pill span {
        font-size: 0.68rem;
    }
}

/* phones: the stats block now shares the stack, so the secondary paragraph
   goes first — same trade as the shorter-screen rules below */
@media (max-width: 991.98px) and (max-height: 900px) {
    .pr-hero-lead {
        display: none;
    }
    .pr-hero-copy {
        padding-top: 1.9rem;
    }
}

/* very short phones — protect the bird band by trimming the copy further */
@media (max-width: 991.98px) and (max-height: 700px) {
    .pr-hero-lead {
        display: none;
    }
    /* the stats block must not push the bird band off a short screen */
    .pr-hero-bar {
        row-gap: 0.35rem;
        padding: 0.45rem 0.9rem;
    }
    .pr-bar-icon {
        width: 1.4rem;
        height: 1.4rem;
    }
    .pr-bar-icon svg {
        height: 1.2rem;
    }
    .pr-hero-card {
        padding: 0.95rem !important;
    }
    .pr-hero-card .mb-4 {
        margin-bottom: 0.6rem !important;
    }
    .pr-hero-card .mt-4 {
        margin-top: 0.65rem !important;
    }
}

/* ==========================================================================
   MOBILE RAILS — card rows that would otherwise stack into a long column
   become horizontal snap sliders on phones. Applied to a Bootstrap row, so
   the desktop grid is untouched; only the phone breakpoint swaps behaviour.
   ========================================================================== */
@media (max-width: 767.98px) {
    .pr-rail-sm {
        flex-wrap: nowrap !important;
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
        scroll-padding-left: 0.75rem;
        padding-bottom: 0.5rem;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-x: contain;
    }
    .pr-rail-sm::-webkit-scrollbar {
        display: none;
    }
    .pr-rail-sm > * {
        flex: 0 0 min(84%, 330px);
        scroll-snap-align: start;
    }
}

/* dots for the section rails (the hero's own rules live with the hero) */
@media (min-width: 768px) {
    .pr-rail-dots {
        display: none !important;
    }
}
@media (max-width: 767.98px) {
    .pr-rail-dots {
        margin-top: 1rem;
    }
}

/* ---- phone density: two-up grids instead of a single tall column ---- */
@media (max-width: 575.98px) {
    .pr-grid-2-sm > .col {
        flex: 0 0 auto;
        width: 50%;
    }
    .pr-grid-2-sm .pr-card {
        padding: 1rem !important;
    }
    .pr-grid-2-sm .pr-card h3 {
        font-size: 0.95rem !important;
    }
    .pr-grid-2-sm .pr-icon-badge {
        width: 2.5rem;
        height: 2.5rem;
        border-radius: 0.7rem;
    }
    .pr-grid-2-sm .pr-icon-badge svg {
        width: 18px;
        height: 18px;
    }
}

/* icons in a flex row must never be squeezed by the label beside them */
.d-flex > svg {
    flex-shrink: 0;
}

/* a badge that sits above a card must not be clipped by the rail */
@media (max-width: 767.98px) {
    .pr-rail-sm {
        padding-top: 0.9rem;
    }
    /* let the table scroll sideways instead of squeezing every column */
    .table-responsive > table th,
    .table-responsive > table td {
        white-space: nowrap;
    }
}

/* a 3rem horizontal gutter is wider than the container's own padding, so on
   phones those rows hang 12px past the viewport — keep the vertical gutter */
@media (max-width: 767.98px) {
    .row.g-5,
    .row.gx-5 {
        --bs-gutter-x: 1.5rem;
    }
}

/* From 768px up the container is still edge-to-edge on many laptops, so its
   padding has to be at least half of the widest row gutter (g-5 = 3rem) or
   those rows hang past the viewport. */
@media (min-width: 768px) {
    .pr-container {
        padding-left: 1.5rem;
        padding-right: 1.5rem;
    }
}

/* Landscape phones: a ~340px-tall viewport cannot hold the bird, the copy and
   the rail at once, so here the hero is allowed to grow past one screen rather
   than clipping content away. */
@media (max-width: 991.98px) and (max-height: 520px) {
    .pr-hero-photo {
        height: auto;
        min-height: calc(100svh - var(--pr-nav-h, 84px));
    }
    .pr-hero-inner {
        padding-top: 1.25rem;
    }
    .pr-hero-copy {
        margin-top: 1.5rem;
    }
}
/* --------------------------------------------------------------------------
   Product slider ("promo")
   One card per slide, cards stacked in place so the height never jumps.
   Two mountings share this component:
     .pr-hero-promo  - inside the hero aside, the no-race fallback. `data-race`
                       on `.pr-hero-aside` decides which is shown: "live" =>
                       the race card, "none" => these product cards.
     .pr-promo-lg    - the standalone section version (light background).
   -------------------------------------------------------------------------- */
.pr-hero-promo {
    display: none;
}
.pr-hero-aside[data-race="none"] .pr-hero-race {
    display: none;
}
.pr-hero-aside[data-race="none"] .pr-hero-promo {
    display: block;
}

/* the top padding is the room the tag pill needs to straddle the card edge */
.pr-promo-track {
    position: relative;
    padding-top: 0.85rem;
    min-height: clamp(19rem, 45vh, 23rem);
    touch-action: pan-y;
}
.pr-hero-promo .pr-promo-track {
    animation: prCardFloat 7.5s ease-in-out 1.4s infinite;
}

.pr-promo-card {
    position: absolute;
    left: 0;
    right: 0;
    top: 0.85rem;
    bottom: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: clamp(1.4rem, 3.2vh, 2rem) clamp(1.1rem, 2.2vw, 1.6rem)
        clamp(1.1rem, 2.4vh, 1.5rem);
    border-radius: 1.25rem;
    background: linear-gradient(160deg, #0f2745, var(--pr-navy-950) 72%);
    border: 1px solid rgba(59, 130, 246, 0.42);
    box-shadow:
        0 24px 60px rgba(10, 27, 51, 0.45),
        0 0 42px rgba(37, 99, 235, 0.3);
    /* slides travel: the incoming card waits on the right, the outgoing one
     leaves to the left, so the change reads as a direction, not a blink */
    opacity: 0;
    visibility: hidden;
    transform: translateX(26px) scale(0.97);
    transition:
        opacity 0.5s ease,
        transform 0.55s cubic-bezier(0.22, 0.85, 0.3, 1),
        visibility 0.55s;
}
.pr-promo-card.is-on {
    opacity: 1;
    visibility: visible;
    transform: none;
}
.pr-promo-card.is-out {
    transform: translateX(-26px) scale(0.97);
}
/* hairline of light along the top edge so the card catches the page glow */
.pr-promo-card::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
    background: linear-gradient(
        180deg,
        rgba(255, 255, 255, 0.14),
        rgba(255, 255, 255, 0) 38%
    );
    mix-blend-mode: overlay;
}

/* label pill straddling the card's top edge */
.pr-promo-tag {
    position: absolute;
    top: 0;
    left: 50%;
    transform: translate(-50%, -50%);
    background: var(--pr-gradient);
    border-radius: 100px;
    padding: 0.4rem 1.1rem;
    color: #fff;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.03em;
    white-space: nowrap;
    box-shadow: 0 8px 20px rgba(29, 78, 216, 0.45);
    z-index: 2;
}

/* the art sits on a lit stage: a glow behind it, a soft floor shadow under it */
.pr-promo-art {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: clamp(7rem, 19vh, 11rem);
}
.pr-promo-art::before {
    content: "";
    position: absolute;
    z-index: 0;
    left: 50%;
    top: 46%;
    transform: translate(-50%, -50%);
    width: 118%;
    height: 128%;
    background: radial-gradient(
        ellipse at center,
        rgba(59, 130, 246, 0.3),
        rgba(59, 130, 246, 0) 68%
    );
}
.pr-promo-art::after {
    content: "";
    position: absolute;
    z-index: 0;
    left: 50%;
    bottom: 2%;
    transform: translateX(-50%);
    width: 58%;
    height: 12%;
    border-radius: 50%;
    background: radial-gradient(
        ellipse at center,
        rgba(0, 0, 0, 0.42),
        rgba(0, 0, 0, 0) 72%
    );
}
.pr-promo-art > * {
    position: relative;
    z-index: 1;
}
.pr-promo-art svg {
    height: 100%;
    width: auto;
    max-width: 82%;
}
.pr-promo-photo {
    max-height: 100%;
    width: auto;
    max-width: 96%;
    filter: drop-shadow(0 16px 28px rgba(0, 0, 0, 0.55));
}

.pr-promo-text {
    margin: clamp(0.8rem, 2vh, 1.15rem) 0 0;
    max-width: 27ch;
    font-size: 0.9rem;
    line-height: 1.45;
    color: rgba(255, 255, 255, 0.66);
}
.pr-promo-price {
    margin-top: auto;
    padding-top: 0.8rem;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 800;
    font-size: clamp(1.45rem, min(2.2vw, 3.4vh), 1.9rem);
    letter-spacing: -0.01em;
    color: var(--pr-blue-accent);
}
.pr-promo-unit {
    margin-top: 0.2rem;
    font-size: 0.72rem;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.42);
}

/* discounted items keep the list price struck through beside the new one,
   with the saving called out on the unit line */
.pr-promo-was {
    margin-left: 0.45rem;
    font-size: 0.56em;
    font-weight: 700;
    vertical-align: 0.3em;
    text-decoration-thickness: 0.07em;
    color: rgba(255, 255, 255, 0.42);
}
.pr-promo-save {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.1rem 0.45rem;
    border-radius: 100px;
    background: rgba(245, 158, 11, 0.18);
    color: var(--pr-amber);
    letter-spacing: 0.08em;
}
.pr-promo-link {
    margin-top: 0.9rem;
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.85rem;
    font-weight: 700;
    text-decoration: none;
    color: var(--pr-blue-accent);
}
.pr-promo-link span {
    transition: transform 0.2s ease;
}
.pr-promo-link:hover {
    color: var(--pr-blue);
}
.pr-promo-link:hover span {
    transform: translateX(3px);
}

/* the dots double as an autoplay progress bar: the active one fills over the
   dwell time and pauses with the timer while the card is hovered or focused */
.pr-promo-nav {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    margin-top: clamp(0.7rem, 1.8vh, 1.1rem);
}
.pr-promo-dots {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 0.4rem;
    margin-top: clamp(0.7rem, 1.8vh, 1.1rem);
}
.pr-promo-nav .pr-promo-dots {
    margin-top: 0;
}
.pr-promo-dots button {
    width: 0.55rem;
    height: 0.55rem;
    padding: 0;
    border: none;
    border-radius: 100px;
    background: rgba(255, 255, 255, 0.28);
    overflow: hidden;
    cursor: pointer;
    transition:
        background 0.25s ease,
        width 0.3s cubic-bezier(0.22, 0.85, 0.3, 1);
}
.pr-promo-dots button.on {
    width: 1.9rem;
    background: rgba(255, 255, 255, 0.22);
}
.pr-promo-dots button i {
    display: block;
    height: 100%;
    width: 0;
    border-radius: 100px;
    background: var(--pr-blue-accent);
}
.pr-promo.is-auto .pr-promo-dots button.on i {
    animation: prPromoFill var(--pr-promo-delay, 5s) linear forwards;
}
.pr-promo.is-auto.is-held .pr-promo-dots button.on i {
    animation-play-state: paused;
}
.pr-promo:not(.is-auto) .pr-promo-dots button.on i {
    width: 100%;
}
@keyframes prPromoFill {
    from {
        width: 0;
    }
    to {
        width: 100%;
    }
}

.pr-promo-arrow {
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 100px;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.06);
    color: #fff;
    cursor: pointer;
    transition:
        background 0.2s ease,
        border-color 0.2s ease,
        transform 0.2s ease;
}
.pr-promo-arrow:hover {
    background: var(--pr-blue);
    border-color: var(--pr-blue);
    transform: translateY(-1px);
}

/* ---- light mounting, for the white ETS section ---- */
.pr-promo-lg {
    max-width: 26.5rem;
    margin-inline: auto;
}
.pr-promo-lg .pr-promo-track {
    min-height: clamp(23rem, 30vw, 26.5rem);
}
.pr-promo-lg .pr-promo-art {
    height: clamp(9.5rem, 13vw, 12rem);
}
.pr-promo-lg .pr-promo-text {
    font-size: 0.95rem;
}
.pr-promo-lg .pr-promo-price {
    font-size: clamp(1.7rem, 2.6vw, 2.1rem);
}

/* the card stays a white surface in either color scheme, so its markup also
   carries .pr-force-light to pin the neutral tokens it reads */
.pr-promo-light .pr-promo-card {
    background: linear-gradient(170deg, #fff 55%, var(--pr-blue-soft));
    border: 1px solid var(--pr-border);
    box-shadow:
        0 22px 48px rgba(16, 42, 67, 0.12),
        0 2px 6px rgba(16, 42, 67, 0.06);
}
.pr-promo-light .pr-promo-card::after {
    background: linear-gradient(
        180deg,
        rgba(37, 99, 235, 0.06),
        rgba(37, 99, 235, 0) 45%
    );
    mix-blend-mode: normal;
}
.pr-promo-light .pr-promo-art::before {
    background: radial-gradient(
        ellipse at center,
        rgba(59, 130, 246, 0.16),
        rgba(59, 130, 246, 0) 68%
    );
}
.pr-promo-light .pr-promo-art::after {
    background: radial-gradient(
        ellipse at center,
        rgba(16, 42, 67, 0.2),
        rgba(16, 42, 67, 0) 72%
    );
}
.pr-promo-light .pr-promo-photo {
    filter: drop-shadow(0 14px 24px rgba(16, 42, 67, 0.28));
}
.pr-promo-light .pr-promo-text {
    color: var(--pr-muted);
}
.pr-promo-light .pr-promo-price {
    color: var(--pr-blue-dark);
}
.pr-promo-light .pr-promo-unit {
    color: var(--pr-muted-2);
}
.pr-promo-light .pr-promo-was {
    color: var(--pr-muted-2);
}
.pr-promo-light .pr-promo-save {
    background: rgba(245, 158, 11, 0.16);
    color: #92400e;
}
.pr-promo-light .pr-promo-dots button {
    background: rgba(16, 42, 67, 0.16);
}
.pr-promo-light .pr-promo-dots button.on {
    background: rgba(16, 42, 67, 0.12);
}
.pr-promo-light .pr-promo-dots button i {
    background: var(--pr-blue);
}
.pr-promo-light .pr-promo-arrow {
    border-color: var(--pr-border);
    background: #fff;
    color: var(--pr-heading);
    box-shadow: 0 2px 6px rgba(16, 42, 67, 0.08);
}
.pr-promo-light .pr-promo-arrow:hover {
    background: var(--pr-blue);
    border-color: var(--pr-blue);
    color: #fff;
}

@media (min-width: 992px) and (max-height: 760px) {
    .pr-hero-promo .pr-promo-track {
        min-height: 17rem;
    }
    .pr-hero-promo .pr-promo-art {
        height: 5.5rem;
    }
    .pr-hero-promo .pr-promo-text {
        font-size: 0.85rem;
    }
}
@media (max-width: 991.98px) {
    /* in the mobile rail the aside is a flex slide, so the card must fill it.
     It is also sized down to leave room for the stats block below. */
    .pr-hero-promo {
        width: 100%;
    }
    .pr-hero-promo .pr-promo-track {
        animation: none;
        min-height: 16rem;
    }
    .pr-hero-promo .pr-promo-card {
        padding: 1.1rem 1.15rem 0.9rem;
    }
    .pr-hero-promo .pr-promo-art {
        height: 4.5rem;
    }
    .pr-hero-promo .pr-promo-price {
        font-size: 1.45rem;
    }
}
@media (max-width: 575.98px) {
    .pr-hero-promo .pr-promo-track {
        min-height: 15rem;
    }
    .pr-hero-promo .pr-promo-art {
        height: 4rem;
    }
    .pr-promo-lg .pr-promo-track {
        min-height: 23.5rem;
    }
    .pr-promo-lg .pr-promo-art {
        height: 8rem;
    }
}
@media (prefers-reduced-motion: reduce) {
    .pr-promo-card {
        transition: opacity 0.2s linear;
        transform: none;
    }
    .pr-promo-card.is-out {
        transform: none;
    }
    .pr-hero-promo .pr-promo-track {
        animation: none;
    }
}

/* ==========================================================================
   ETS FLOW — the six-step ring-to-results band. One row of steps with dotted
   connectors running between the icon wells; below lg the connectors are
   dropped (they can't survive a wrapped grid) and on phones the row turns
   into the same horizontal snap rail the card sections use.
   ========================================================================== */
.pr-flow {
    padding-top: 6rem;
    padding-bottom: 6rem;
    background: var(--pr-surface);
    border-top: 1px solid var(--pr-border);
}
.pr-flow-rings {
    position: absolute;
    z-index: 0;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -42%);
    pointer-events: none;
}
.pr-flow-title {
    color: var(--pr-heading);
    text-transform: uppercase;
    letter-spacing: 0.01em;
}

.pr-flow-track {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(6, minmax(0, 1fr));
    gap: 1rem 0.5rem;
    counter-reset: none;
}
.pr-flow-step {
    position: relative;
    text-align: center;
    padding: 0 0.35rem;
}

/* connector: a dotted run from this step's icon to the next one's, plus an
   arrow tip. Both are anchored to the step on the left of the gap. */
.pr-flow-step:not(:last-child)::after,
.pr-flow-step:not(:last-child)::before {
    content: "";
    position: absolute;
    z-index: 0;
}
.pr-flow-step:not(:last-child)::after {
    top: 2.4rem;
    left: calc(50% + 3.1rem);
    right: calc(-50% + 3.4rem);
    border-top: 2px dotted rgba(37, 99, 235, 0.35);
}
.pr-flow-step:not(:last-child)::before {
    top: calc(2.4rem - 3px);
    right: calc(-50% + 2.9rem);
    width: 0;
    height: 0;
    border-left: 6px solid rgba(37, 99, 235, 0.55);
    border-top: 4px solid transparent;
    border-bottom: 4px solid transparent;
}

.pr-flow-art {
    position: relative;
    z-index: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 4.8rem;
    height: 4.8rem;
    margin: 0 auto;
    border-radius: 1.1rem;
    background: rgba(37, 99, 235, 0.07);
    border: 1px solid rgba(37, 99, 235, 0.14);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.pr-flow-art svg {
    stroke: var(--pr-blue-dark);
    fill: none;
}
.pr-flow-num {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    margin: 0.9rem 0 0.55rem;
    border-radius: 50%;
    background: var(--pr-gradient);
    color: #fff;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.8rem;
    font-weight: 700;
    box-shadow: 0 6px 16px rgba(37, 99, 235, 0.35);
}
.pr-flow-name {
    color: var(--pr-heading);
    font-size: 0.95rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin: 0 0 0.4rem;
}
.pr-flow-copy {
    margin: 0;
    font-size: 0.8125rem;
    line-height: 1.5;
    color: var(--pr-muted);
}

@media (max-width: 991.98px) {
    .pr-flow {
        padding-top: 4.5rem;
        padding-bottom: 4.5rem;
    }
    .pr-flow-track {
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 2rem 1rem;
    }
    .pr-flow-step::after,
    .pr-flow-step::before {
        display: none;
    }
}
@media (max-width: 767.98px) {
    .pr-flow-track {
        grid-template-columns: none;
        grid-auto-flow: column;
        grid-auto-columns: min(62%, 220px);
        gap: 1rem;
        overflow-x: auto;
        overflow-y: hidden;
        scroll-snap-type: x mandatory;
        scroll-padding-left: 0.75rem;
        padding-bottom: 0.5rem;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-x: contain;
    }
    .pr-flow-track::-webkit-scrollbar {
        display: none;
    }
    .pr-flow-step {
        scroll-snap-align: start;
    }
}

/* the flow band follows the surface token, so only its blue-tinted icon wells
   need a nudge to stay legible in dark mode */
[data-bs-theme="dark"] .pr-flow-art {
    background: rgba(59, 130, 246, 0.12);
    border-color: rgba(255, 255, 255, 0.12);
    box-shadow: none;
}
[data-bs-theme="dark"] .pr-flow-art svg {
    stroke: var(--pr-blue-accent);
}

/* ---- race records cloud / data-security band ---- */
.pr-secure {
    padding: 5.5rem 0;
    color: #fff;
    background:
        radial-gradient(
            64% 110% at 22% 46%,
            rgba(37, 99, 235, 0.34) 0%,
            rgba(10, 27, 51, 0) 64%
        ),
        radial-gradient(
            120% 100% at 50% 0%,
            var(--pr-navy-800) 0%,
            var(--pr-navy-900) 55%,
            var(--pr-navy-950) 100%
        );
}
.pr-eyebrow.text-on-dark-blue {
    color: var(--pr-blue-accent);
}

.pr-sec-lead {
    max-width: 52ch;
}
.pr-secure-art {
    max-width: 400px;
    margin-inline: auto;
}
.pr-secure-art svg {
    display: block;
    width: 100%;
    height: auto;
}

/* glass tiles, same recipe as the live-tracking panel */
.pr-sec-tile {
    padding: 1.15rem 1.25rem;
    border-radius: 1rem;
    background: rgba(27, 58, 92, 0.45);
    border: 1px solid rgba(255, 255, 255, 0.1);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    transition:
        transform 0.2s ease,
        background 0.2s ease,
        border-color 0.2s ease;
}
.pr-sec-tile:hover {
    transform: translateY(-4px);
    background: rgba(27, 58, 92, 0.68);
    border-color: rgba(59, 130, 246, 0.45);
}

/* the badge twin of .pr-icon-badge.pr-soft, tuned for a dark ground — the
   stroke has to come from a rule here, an inline attribute would lose to it */
.pr-icon-badge.pr-soft-dark {
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 0.75rem;
    background: rgba(59, 130, 246, 0.16);
    border: 1px solid rgba(59, 130, 246, 0.3);
}
.pr-icon-badge.pr-soft-dark svg {
    stroke: #93c5fd;
}

/* illustration motion: the cloud drifts, records stream up, the seal breathes */
.pr-sec-cloud {
    animation: prSecDrift 7.5s ease-in-out infinite;
}
.pr-sec-bird {
    animation: prSecDrift 5.6s ease-in-out infinite;
}
.pr-sec-bird-2 {
    animation-duration: 6.9s;
    animation-delay: -2.2s;
}
.pr-sec-stream {
    stroke-dasharray: 6 8;
    animation: prSecFlow 2.2s linear infinite;
}
.pr-sec-seal-ring {
    transform-box: view-box;
    transform-origin: 180px 196px;
    animation: prSecSeal 3.4s ease-in-out infinite;
}
@keyframes prSecDrift {
    0%,
    100% {
        transform: translateY(0);
    }
    50% {
        transform: translateY(-6px);
    }
}
@keyframes prSecFlow {
    to {
        stroke-dashoffset: -70;
    }
}
@keyframes prSecSeal {
    0%,
    100% {
        opacity: 0.45;
        transform: scale(1);
    }
    50% {
        opacity: 0.12;
        transform: scale(1.13);
    }
}
@media (prefers-reduced-motion: reduce) {
    .pr-sec-cloud,
    .pr-sec-bird,
    .pr-sec-stream,
    .pr-sec-seal-ring {
        animation: none;
    }
}

@media (max-width: 991.98px) {
    .pr-secure {
        padding: 4rem 0;
        text-align: center;
    }
    .pr-secure .pr-sec-lead {
        margin-inline: auto;
    }
    .pr-secure-art {
        max-width: 300px;
    }
    .pr-sec-tile {
        text-align: left;
    }
}

/* on phones the tiles read better as compact rows than as four tall cards */
@media (max-width: 575.98px) {
    .pr-sec-tile {
        display: grid;
        grid-template-columns: auto 1fr;
        column-gap: 0.85rem;
        align-items: center;
        padding: 0.95rem 1rem;
    }
    .pr-sec-tile .pr-icon-badge {
        grid-row: span 2;
        margin-bottom: 0 !important;
        width: 2.5rem;
        height: 2.5rem;
    }
    .pr-sec-tile h3 {
        align-self: end;
    }
    .pr-sec-tile p {
        align-self: start;
    }
}

/* ===== CLUB DIRECTORY =====
   Glass cards on the dark flock photo (index #clubs and the full clubs.html
   listing share this block). The province chips filter the grid in place;
   a filtered-out card gets [hidden], hence the display override. */
.pr-club-chips {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.5rem;
    margin-bottom: 2.25rem;
}
.pr-club-chip {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.8125rem;
    font-weight: 600;
    border-radius: 100px;
    padding: 0.5rem 1.05rem;
    color: rgba(255, 255, 255, 0.72);
    background: rgba(255, 255, 255, 0.05);
    border: 1.5px solid rgba(255, 255, 255, 0.14);
    transition:
        background 0.18s ease,
        color 0.18s ease,
        border-color 0.18s ease;
}
.pr-club-chip span {
    margin-left: 0.3rem;
    opacity: 0.55;
    font-variant-numeric: tabular-nums;
}
.pr-club-chip:hover {
    background: rgba(255, 255, 255, 0.1);
    color: #fff;
}
.pr-club-chip.is-on {
    background: #fff;
    border-color: #fff;
    color: var(--pr-navy-950);
}

.pr-club-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(258px, 1fr));
    gap: 1rem;
}
/* the index teaser shows six clubs, so it caps at three columns rather than
   leaving a ragged four-plus-two row on wide screens */
.pr-club-grid.is-3up {
    max-width: 940px;
    margin-inline: auto;
}

.pr-club-card {
    position: relative;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    padding: 1.35rem 1.35rem 1.15rem;
    border-radius: 1.15rem;
    background: rgba(27, 58, 92, 0.5);
    backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.12);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.28);
    transition:
        transform 0.22s ease,
        border-color 0.22s ease,
        box-shadow 0.22s ease;
}
/* brand hairline that wipes across the top edge on hover */
.pr-club-card::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 2px;
    background: linear-gradient(90deg, var(--pr-blue-accent), var(--pr-amber));
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.32s ease;
}
.pr-club-card:hover,
.pr-club-card:focus-within {
    transform: translateY(-4px);
    border-color: rgba(255, 255, 255, 0.26);
    box-shadow: 0 26px 56px rgba(0, 0, 0, 0.4);
}
.pr-club-card:hover::before,
.pr-club-card:focus-within::before {
    transform: scaleX(1);
}
.pr-club-card[hidden] {
    display: none;
}

.pr-club-top {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    margin-bottom: 0.9rem;
}
.pr-club-avatar {
    position: relative;
    flex: 0 0 auto;
}
/* initials tile with the dove tucked into its corner */
.pr-club-mark {
    position: relative;
    flex: 0 0 auto;
    width: 3rem;
    height: 3rem;
    border-radius: 0.9rem;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background: var(--pr-gradient);
    box-shadow: 0 8px 18px rgba(37, 99, 235, 0.32);
}
/* the dove is a line-art outline, so it needs size and opacity to read at
   this size — a solid silhouette would show at half of both */
.pr-club-dove {
    position: absolute;
    right: -22%;
    bottom: -20%;
    width: 2.9rem;
    fill: rgba(255, 255, 255, 0.42);
}
.pr-club-initials {
    position: relative;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 800;
    font-size: 0.95rem;
    color: #fff;
}
/* a real uploaded logo replaces the dove + initials placeholder */
.pr-club-mark img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* the club profile's own header: a bigger mark straddling the cover photo's
   bottom edge, the same half-in-half-out plate the pigeon eye close-up uses */
.pr-club-mark-hero {
    width: 6.5rem;
    height: 6.5rem;
    border-radius: 1.4rem;
    border: 3px solid var(--pr-navy-900, #0c1c30);
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.35);
}
.pr-club-mark-hero .pr-club-dove {
    width: 5.6rem;
}
.pr-club-mark-hero .pr-club-initials {
    font-size: 1.9rem;
}

.pr-club-status {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.3rem 0.6rem;
    border-radius: 100px;
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: rgba(255, 255, 255, 0.55);
    background: rgba(255, 255, 255, 0.06);
    white-space: nowrap;
}
.pr-club-status.is-live {
    color: #4ade80;
    background: rgba(22, 163, 74, 0.15);
}
.pr-club-status.is-finished {
    color: var(--pr-blue-dark);
    background: rgba(37, 99, 235, 0.12);
}
.pr-club-status.is-district {
    color: #0f766e;
    background: rgba(20, 184, 166, 0.16);
}
.pr-club-status .pr-live-dot {
    width: 6px;
    height: 6px;
}

.pr-club-name {
    margin: 0;
    font-size: 1.02rem;
    font-weight: 700;
    line-height: 1.3;
    color: #fff;
}
/* verified tick, pinned to the monogram's corner — inline in the name it kept
   orphaning onto a line of its own once the club name wrapped */
.pr-club-verified {
    position: absolute;
    right: -4px;
    bottom: -4px;
    width: 1.15rem;
    height: 1.15rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #fff;
    background: var(--pr-blue-accent);
    box-shadow: 0 0 0 2px rgba(12, 28, 48, 0.92);
}
.pr-club-loc {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin: 0.35rem 0 0;
    font-size: 0.8125rem;
    color: rgba(255, 255, 255, 0.5);
}
.pr-club-loc svg {
    flex: 0 0 auto;
}

.pr-club-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.5rem;
    margin: auto 0 0; /* pins the stats + link to the bottom of the card */
    padding-top: 0.9rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.pr-club-stats > div {
    min-width: 0;
}
.pr-club-stats dt {
    font-size: 0.625rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.07em;
    color: rgba(255, 255, 255, 0.4);
}
.pr-club-stats dd {
    margin: 0.15rem 0 0;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 800;
    font-size: 0.95rem;
    color: #fff;
    font-variant-numeric: tabular-nums;
}

.pr-club-link {
    margin-top: 1rem;
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.8125rem;
    font-weight: 700;
    color: #fff;
    text-decoration: none;
}
.pr-club-link svg {
    transition: transform 0.2s ease;
}
.pr-club-card:hover .pr-club-link svg {
    transform: translateX(3px);
}
/* the whole card is the hit area */
.pr-club-link::after {
    content: "";
    position: absolute;
    inset: 0;
}

/* the club profile page (pages/club.blade.php) reuses pr-club-stats and
   pr-club-link inside pr-res-card — a light, theme-aware surface, not the
   dark glass pr-club-card the directory always puts them on — so the
   hardcoded white above would go invisible in light mode. */
.pr-res-card .pr-club-stats {
    border-top-color: var(--pr-border);
}
.pr-res-card .pr-club-stats dt {
    color: var(--pr-muted);
}
.pr-res-card .pr-club-stats dd {
    color: var(--pr-heading);
}
.pr-res-card .pr-club-link {
    color: var(--pr-blue-accent);
}

.pr-club-empty {
    margin: 2.25rem 0 0;
    text-align: center;
    color: rgba(255, 255, 255, 0.55);
}
.pr-club-reg {
    color: #fff;
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* directory page: search field above the same grid */
.pr-club-search {
    position: relative;
    max-width: 420px;
    margin: 0 auto 1.25rem;
}
.pr-club-search svg {
    position: absolute;
    left: 1rem;
    top: 50%;
    transform: translateY(-50%);
    color: rgba(255, 255, 255, 0.45);
    pointer-events: none;
}
.pr-club-search input {
    width: 100%;
    padding: 0.8rem 1rem 0.8rem 2.75rem;
    border-radius: 100px;
    color: #fff;
    background: rgba(255, 255, 255, 0.06);
    border: 1.5px solid rgba(255, 255, 255, 0.14);
    font-size: 0.9rem;
}
.pr-club-search input::placeholder {
    color: rgba(255, 255, 255, 0.4);
}
.pr-club-search input:focus {
    outline: none;
    border-color: var(--pr-blue-accent);
    background: rgba(255, 255, 255, 0.09);
}

/* same field on a themed page body (club page's pigeon search) rather than
   the dark hero — follows the surface/text/border variables so it reads in
   both themes */
.pr-club-search.is-themed svg {
    color: var(--pr-muted);
}
.pr-club-search.is-themed input {
    color: var(--pr-text);
    background: var(--pr-surface);
    border-color: var(--pr-border);
}
.pr-club-search.is-themed input::placeholder {
    color: var(--pr-muted);
}

@media (prefers-reduced-motion: reduce) {
    .pr-club-card,
    .pr-club-card::before,
    .pr-club-link svg {
        transition: none;
    }
    .pr-club-card:hover,
    .pr-club-card:focus-within {
        transform: none;
    }
}

@media (max-width: 575.98px) {
    .pr-club-chips {
        flex-wrap: nowrap;
        overflow-x: auto;
        justify-content: flex-start;
        scroll-snap-type: x mandatory;
        -ms-overflow-style: none;
        scrollbar-width: none;
    }
    .pr-club-chips::-webkit-scrollbar {
        display: none;
    }
    .pr-club-chip {
        flex: 0 0 auto;
        scroll-snap-align: start;
    }
}

/* ===== BACK LINK =====
   The "back" affordance every sub-page carries (clubs, login, register,
   loading). Light-section default; .pr-back-light is the on-dark variant.
   The arrow slides left on hover — the icon is a plain <svg> child so the
   markup stays the same everywhere. */
.pr-back-link {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--pr-muted);
    text-decoration: none;
    transition: color 0.18s ease;
}
.pr-back-link svg {
    transition: transform 0.18s ease;
}
.pr-back-link:hover,
.pr-back-link:focus-visible {
    color: var(--pr-orange);
}
.pr-back-link:hover svg,
.pr-back-link:focus-visible svg {
    transform: translateX(-3px);
}

/* On-dark variant — also used unscoped so it works on sections that set a
   dark background inline rather than via .pr-dark. */
.pr-back-light {
    color: rgba(255, 255, 255, 0.62);
}
.pr-back-light:hover,
.pr-back-light:focus-visible {
    color: #fff;
}

@media (prefers-reduced-motion: reduce) {
    .pr-back-link,
    .pr-back-link svg {
        transition: none;
    }
    .pr-back-link:hover svg,
    .pr-back-link:focus-visible svg {
        transform: none;
    }
}

/* "Copy link" on the result sheet's own dark header — the same on-dark
   ghost-pill treatment as .pr-back-light, just as a real button (it needs
   a click handler, not a navigation) rather than a link. */
.pr-share-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.5rem 0.9rem;
    border-radius: 0.65rem;
    border: 1px solid rgba(255, 255, 255, 0.22);
    background: rgba(255, 255, 255, 0.06);
    color: rgba(255, 255, 255, 0.85);
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.82rem;
    font-weight: 700;
    text-decoration: none;
    cursor: pointer;
    transition:
        background 0.18s ease,
        color 0.18s ease,
        border-color 0.18s ease;
}
.pr-share-btn:hover,
.pr-share-btn:focus-visible {
    color: #fff;
    background: rgba(255, 255, 255, 0.14);
    border-color: rgba(255, 255, 255, 0.4);
}
.pr-share-btn.is-copied {
    color: #fff;
    background: rgba(22, 163, 74, 0.35);
    border-color: rgba(22, 163, 74, 0.6);
}

/* ==========================================================================
   RACE RESULT SHEET (result.html)
   The dark race banner reuses the .pr-dark treatment; everything below it
   sits on the page surface so the sheet reads light-first and flips with
   [data-bs-theme="dark"] like the rest of the site. Numbers are Manrope with
   tabular figures throughout — headings stay Fraunces.
   ========================================================================== */

/* ---- race banner ---- */
.pr-race-head {
    position: relative;
    overflow: hidden;
    display: flex;
    align-items: center;
    border-radius: 1.4rem;
    padding: 1.6rem clamp(21rem, 24%, 13.5rem) 1.5rem 1.6rem;
    background: rgba(27, 58, 92, 0.5);
    backdrop-filter: blur(16px);
    border: 1px solid rgba(255, 255, 255, 0.12);
    box-shadow: 0 22px 48px rgba(0, 0, 0, 0.32);
}
/* same brand hairline the club cards carry, but always drawn */
.pr-race-head::before {
    content: "";
    position: absolute;
    inset: 0 0 auto 0;
    height: 2px;
    background: linear-gradient(90deg, var(--pr-blue-light), var(--pr-blue));
}
/* flex-basis, not a hard width — the gauge beside it (.pr-race-gauge) is
   what actually claims the wide gutter this card used to just leave empty
   next to a 62ch-capped column */
.pr-race-head-body {
    position: relative;
    z-index: 1;
    flex: 1 1 28rem;
    max-width: 62ch;
}

/* the cutout bleeds off the right edge and is masked out where the copy runs */
.pr-race-bird {
    position: absolute;
    right: -1.5rem;
    bottom: -1rem;
    width: min(19rem, 34%);
    object-fit: contain;
    opacity: 0.9;
    pointer-events: none;
    -webkit-mask-image:
        linear-gradient(to right, transparent, #000 38%),
        linear-gradient(to bottom, transparent, #000 26%);
    mask-image:
        linear-gradient(to right, transparent, #000 38%),
        linear-gradient(to bottom, transparent, #000 26%);
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
    filter: drop-shadow(0 18px 30px rgba(0, 0, 0, 0.45));
}

/* the state pill and the race's own markers (Shield, night pause) — one
   wrapping row, so on a phone they read as a group under the head rather
   than each dropping into its own grid cell */
.pr-race-badges {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.4rem 0.5rem;
}
/* the markers sit in the same row as the state pill, so they are sized to
   match it — same height and type scale — rather than the larger standalone
   chip they were before */
.pr-race-badges > .pr-res-district-chip,
.pr-race-badges > .pr-res-shield-chip,
.pr-race-badges > .pr-res-night-chip {
    margin-left: 0;
    max-width: 100%;
    gap: 0.3rem;
    padding: 0.32rem 0.7rem;
    font-size: 0.6875rem;
    letter-spacing: 0.04em;
    line-height: normal;
}
.pr-race-badges > .pr-res-district-chip svg,
.pr-race-badges > .pr-res-shield-chip svg,
.pr-race-badges > .pr-res-night-chip svg {
    width: 12px;
    height: 12px;
    flex: 0 0 auto;
}

.pr-race-state {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.32rem 0.7rem;
    border-radius: 100px;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.6875rem;
    font-weight: 800;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    /* neutral default — every non-live, non-cancelled state (Complete,
     Locked, In Review, Planned, Open, Basketing) reads as a plain status,
     not good or bad news */
    color: rgba(255, 255, 255, 0.7);
    background: rgba(255, 255, 255, 0.12);
}
/* Live is the one state that's actually good news happening right now —
   green, not red; red was backwards (it read like something was wrong
   while birds were simply in the air). */
.pr-race-state.is-live {
    color: #4ade80;
    background: rgba(22, 163, 74, 0.18);
}
.pr-race-state.is-cancelled {
    color: #f87171;
    background: rgba(220, 38, 38, 0.18);
}
.pr-race-state-dot {
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: currentColor;
    animation: prLiveBlink 1.2s ease-in-out infinite;
}
@keyframes prLiveBlink {
    0%,
    100% {
        opacity: 1;
    }
    50% {
        opacity: 0.25;
    }
}
@media (prefers-reduced-motion: reduce) {
    .pr-race-state-dot {
        animation: none;
    }
}

.pr-race-title {
    margin: 0.75rem 0 0.35rem;
    font-size: clamp(1.45rem, 3.2vw, 2.15rem);
    line-height: 1.18;
    color: #fff;
}
.pr-race-arrow {
    vertical-align: -0.15em;
    color: var(--pr-blue-accent);
    margin: 0 0.15rem;
}
.pr-race-club {
    margin: 0;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 700;
    font-size: 0.95rem;
    color: var(--pr-blue-light);
}
.pr-race-club span {
    color: rgba(255, 255, 255, 0.45);
    font-weight: 600;
}

.pr-race-meta {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem 1.6rem;
    margin: 1.1rem 0 0;
}
.pr-race-meta dt {
    display: flex;
    align-items: center;
    gap: 0.38rem;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.07em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.45);
}
.pr-race-meta dt svg {
    color: var(--pr-blue-accent);
    flex: 0 0 auto;
}
.pr-race-meta dd {
    margin: 0.12rem 0 0;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.9375rem;
    color: rgba(255, 255, 255, 0.82);
    font-variant-numeric: tabular-nums;
}
.pr-race-meta dd b {
    color: #fff;
    font-weight: 700;
}
/* milliseconds ride along at a smaller size so the seconds stay readable */
.pr-race-ms {
    font-size: 0.78em;
    opacity: 0.55;
}

.pr-race-clockrow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem 1.75rem;
    margin-top: 1.35rem;
    padding-top: 1.25rem;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.pr-race-clock-label {
    display: block;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.45);
}
.pr-race-clock-value {
    display: block;
    margin-top: 0.1rem;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: clamp(1.9rem, 4.4vw, 2.6rem);
    font-weight: 800;
    letter-spacing: 0.02em;
    line-height: 1;
    color: var(--pr-blue-light);
    font-variant-numeric: tabular-nums;
}
.pr-race-clock-value i {
    font-style: normal;
    opacity: 0.45;
    margin: 0 0.06em;
}

/* the empty gutter beside .pr-race-head-body used to just waste — flex: 1
   lets this claim whatever's left between the copy column and the reserved
   .pr-race-bird strip (.pr-race-head's own right padding) and centers
   itself in it, so the dial sits in the middle of the card rather than
   fighting the cutout for the same pixels on the right edge */
.pr-race-gauge {
    position: relative;
    z-index: 1;
    flex: 1 1 10rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0 0.5rem;
}
.pr-race-gauge .pr-speedo-face {
    width: clamp(9rem, 15vw, 13rem);
    filter: drop-shadow(0 6px 16px rgba(0, 0, 0, 0.4));
}
/* A little wider than the plain dial so the six numbers have breathing
   room, but sized off the same clamp shape rather than 62vw — that was
   tuned for when this gauge sat in its own full-width row (see the removed
   mobile grid-stack above), and made the face balloon well past what this
   shared row has room for.

   filter: none overrides the drop-shadow set above: that filter rasterises
   the whole SVG — the tick numbers along with the ring — and a 16px blur
   radius is what was actually softening the digits into the halo they had
   even at the right size, not the width. The plain dial (no text) still
   gets its drop-shadow; only the labelled face drops it. */
.pr-race-gauge .pr-speedo-face.has-scale {
    width: clamp(10rem, 24vw, 14rem);
    filter: none;
}
/* Every speed gauge shares the same colourful dial now (base .pr-speedo-*
   rules plus their [data-bs-theme="dark"] counterparts) — what's special
   about this one card is only that .pr-race-head is a dark hero
   unconditionally, regardless of the site's own light/dark toggle, so it
   always needs the "dark theme" needle/tick/hub treatment even when the
   rest of the page is in light mode. Restating that treatment here, keyed
   off .pr-race-gauge rather than [data-bs-theme="dark"], is what makes that
   true; the .pr-race-head ancestor on every selector is purely to
   out-specify [data-bs-theme="dark"] .pr-speedo-* on the (fairly common)
   afternoon someone views this page in dark mode too, where the two would
   otherwise tie on specificity and whichever is later in this file would
   silently win. stroke-width is bumped slightly past the small gauge's own
   for the bigger dial. */
.pr-race-head .pr-race-gauge .pr-speedo-track {
    stroke: url(#prSpeedoGrad);
    stroke-width: 9;
}
.pr-race-head .pr-race-gauge .pr-speedo-ticks {
    stroke: rgba(255, 255, 255, 0.85);
    opacity: 0.8;
}
.pr-race-head .pr-race-gauge .pr-speedo-tick-mid {
    stroke: #fff;
    opacity: 1;
}
.pr-race-head .pr-race-gauge .pr-speedo-tick-label {
    fill: rgba(255, 255, 255, 0.85);
}
.pr-race-head .pr-race-gauge .pr-speedo-needle-tip {
    stroke: #fff;
    stroke-width: 5;
    filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.85));
}
.pr-race-head .pr-race-gauge .pr-speedo-needle-tail {
    stroke: #fff;
    opacity: 0.65;
}
.pr-race-head .pr-race-gauge .pr-speedo-hub-ring {
    fill: rgba(15, 32, 54, 0.85);
    stroke: #fff;
    stroke-width: 2;
}
.pr-race-head .pr-race-gauge .pr-speedo-hub {
    fill: #fff;
}
.pr-race-gauge-value {
    display: flex;
    align-items: baseline;
    gap: 0.3rem;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 800;
    color: #fff;
    font-variant-numeric: tabular-nums;
    /* Bold white text sitting on .pr-race-head's backdrop-filter: blur(16px)
     glass renders noticeably soft under the browser's default subpixel
     antialiasing — grayscale smoothing keeps the glyph edges crisp instead
     of picking up a blurred halo from the frosted background behind them. */
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}
.pr-race-gauge-value i {
    font-style: normal;
    opacity: 0.55;
    font-size: 0.55em;
}

.pr-race-note {
    flex: 1 1 20rem;
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    margin: 0;
    padding: 0.8rem 0.95rem;
    border-radius: 0.85rem;
    font-size: 0.8125rem;
    line-height: 1.5;
    color: rgba(255, 255, 255, 0.78);
    background: rgba(220, 38, 38, 0.14);
    border: 1px solid rgba(220, 38, 38, 0.4);
}
.pr-race-note svg {
    flex: 0 0 auto;
    margin-top: 0.1rem;
    color: #fca5a5;
}
.pr-race-note b {
    color: #fca5a5;
}

/* the cutout is a desktop-only flourish — on tablet and phone widths there
   is no gutter to spare for it, so it's hidden outright. Everything above
   the flight clock (state, title, club, distance/liberation/release point)
   stays full width, single column; only the last row — the Members/Birds/
   Arrived/In Flight stats and the gauge — splits into two columns, gauge on
   the right, so the gauge sits under the clock beside the stats instead of
   centered against the whole card (a plain flex row centers it against the
   tall column next to it, roughly mid-card, not where it belongs). */
@media (max-width: 991.98px) {
    .pr-race-bird {
        display: none;
    }

    .pr-race-head {
        display: grid;
        grid-template-columns: 1fr auto;
        grid-template-areas:
            "state state"
            "title title"
            "club club"
            "facts facts"
            "clock gauge"
            "stats stats";
        align-items: start;
        row-gap: 0.35rem;
        column-gap: 1rem;
        padding-right: 1.6rem;
    }
    .pr-race-head-body {
        display: contents;
    }
    .pr-race-head-body > .pr-race-badges {
        grid-area: state;
    }
    .pr-race-head-body > .pr-race-title {
        grid-area: title;
    }
    .pr-race-head-body > .pr-race-club {
        grid-area: club;
    }
    .pr-race-head-body > .pr-race-meta:not(.pr-race-meta-stats) {
        grid-area: facts;
        margin-top: 0.5rem;
    }
    .pr-race-clockrow {
        grid-area: clock;
        align-self: center;
        margin-top: 0;
        padding-top: 0;
        border-top: 0;
    }
    .pr-race-head-body > .pr-race-meta-stats {
        grid-area: stats;
        display: grid;
        grid-template-columns: repeat(3, minmax(0, 1fr));
        gap: 0.55rem 1.6rem;
        margin-top: 0.9rem;
        padding-top: 0.9rem;
        border-top: 1px solid rgba(255, 255, 255, 0.1);
    }
    /* label on the left, figure on the right — five stats read as one tidy
       table instead of a tall stack of label-over-value pairs */
    .pr-race-meta-stats > div {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 0.75rem;
    }
    .pr-race-meta-stats dd {
        margin: 0;
    }
    .pr-race-gauge {
        grid-area: gauge;
        align-self: center;
        padding: 0;
    }
}

/* Narrow phones: the clock value's own font-size floor (clamp(1.9rem, ...))
   and the gauge's own width floor (clamp(9rem, ...)) were both sized for
   sharing a row on a tablet, not a 360px phone — shrink both floors here so
   "Flight time duration" has room to actually fit beside the dial instead
   of the two fighting over the same narrow row. */
@media (max-width: 400px) {
    .pr-race-clock-value {
        font-size: 1.5rem;
    }
    .pr-race-gauge .pr-speedo-face {
        width: 6.5rem;
    }
    .pr-race-gauge-value {
        font-size: 1.1rem;
    }
}

/* Phones: the flight clock stays on the left and the dial on the right, as on
   a wide screen; the counts drop to the full-width row under them, two per
   row. Both halves are sized down so "Flight time duration" and the dial's
   reading fit side by side on a 320-390px card. */
@media (max-width: 575.98px) {
    .pr-race-head {
        grid-template-columns: minmax(0, 1fr) auto;
        column-gap: 0.75rem;
        padding: 1.3rem 1.15rem 1.25rem;
    }
    .pr-race-head-body > .pr-race-meta-stats {
        grid-template-columns: repeat(2, minmax(0, 1fr));
    }
    .pr-race-clock-label {
        font-size: 0.5625rem;
        letter-spacing: 0.05em;
    }
    .pr-race-clock-value {
        font-size: clamp(1.45rem, 7.4vw, 2rem);
    }
    .pr-race-gauge {
        gap: 0.3rem;
    }
    .pr-race-gauge .pr-speedo-face,
    .pr-race-gauge .pr-speedo-face.has-scale {
        width: 6rem;
    }
    .pr-race-gauge-value {
        flex-wrap: wrap;
        justify-content: center;
        font-size: 1.05rem;
        line-height: 1.2;
    }
    .pr-res-shield-chip {
        white-space: nowrap;
    }
}

/* the dove is an outline path, so it takes fill rather than stroke */
.pr-res-glyph {
    fill: currentColor;
    stroke: none;
    flex: 0 0 auto;
}

.pr-res-hero {
    padding-top: 3.25rem;
    padding-bottom: 2.75rem;
}
.pr-res-body {
    padding: 2.5rem 0 5rem;
}
/* the hero, the body and the tab bar each add their own breathing room —
   stacked on a phone that read as a ~115px empty band under the header */
@media (max-width: 575.98px) {
    .pr-res-hero {
        padding-top: 2.25rem;
        padding-bottom: 1.5rem;
    }
    .pr-res-body {
        padding-top: 1.25rem;
    }
    .pr-res-scope {
        margin-top: 1.1rem;
    }
}

/* ---- count bar / weather strip ----
   Both are the same dark panel of .pr-bar-items the hero uses; they collapse
   to a grid on small screens rather than scrolling. */
.pr-res-bar,
.pr-res-weather {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.25rem;
    padding: 1.15rem 1rem;
    border-radius: 1.15rem;
    background: linear-gradient(135deg, var(--pr-navy-900), var(--pr-navy-950));
    border: 1px solid rgba(255, 255, 255, 0.1);
    box-shadow: 0 16px 34px rgba(16, 42, 67, 0.18);
}
.pr-res-weather {
    grid-template-columns: repeat(6, 1fr);
    margin-top: 2.5rem;
}
.pr-res-bar .pr-bar-item,
.pr-res-weather .pr-bar-item {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.15rem;
    text-align: center;
    padding: 0.35rem 0.5rem;
}
.pr-res-bar .pr-bar-item + .pr-bar-item,
.pr-res-weather .pr-bar-item + .pr-bar-item {
    border-left: 1px solid rgba(255, 255, 255, 0.1);
}
.pr-res-bar .pr-bar-icon,
.pr-res-weather .pr-bar-icon {
    color: var(--pr-blue-accent);
    margin-bottom: 0.1rem;
}
.pr-res-bar .pr-bar-value,
.pr-res-weather .pr-bar-value {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 1.5rem;
    font-weight: 800;
    line-height: 1.1;
    color: #fff;
    font-variant-numeric: tabular-nums;
}
.pr-res-weather .pr-res-wx {
    font-size: 0.9375rem;
}
.pr-res-bar .pr-bar-label,
.pr-res-weather .pr-bar-label {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.45);
}

/* ---- leaderboard scope tabs ---- */
.pr-res-scope {
    display: flex;
    gap: 0.3rem;
    margin: 2rem 0 1.1rem;
    padding: 0.3rem;
    border-radius: 1rem;
    background: var(--pr-surface);
    border: 1px solid var(--pr-border);
    overflow-x: auto;
    -ms-overflow-style: none;
    scrollbar-width: none;
}
.pr-res-scope::-webkit-scrollbar {
    display: none;
}
.pr-res-scope-btn {
    flex: 1 1 0;
    min-width: max-content;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.45rem;
    padding: 0.65rem 1rem;
    border: 0;
    border-radius: 0.75rem;
    background: transparent;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--pr-muted);
    white-space: nowrap;
    cursor: pointer;
    transition:
        background 0.18s ease,
        color 0.18s ease,
        box-shadow 0.18s ease;
}
.pr-res-scope-btn:hover {
    color: var(--pr-heading);
    background: rgba(37, 99, 235, 0.07);
}
.pr-res-scope-btn.is-on {
    color: #fff;
    background: var(--pr-gradient);
    box-shadow: 0 8px 18px rgba(37, 99, 235, 0.3);
}
.pr-res-scope-btn.is-on .pr-res-glyph {
    fill: #fff;
}

/* Phones: three tabs no longer fit with their icons, so "All Pigeons" was cut
   off. Drop the icons and tighten the padding; a fourth tab (My Birds) still
   scrolls sideways. */
@media (max-width: 575.98px) {
    .pr-res-scope {
        gap: 0.2rem;
        scroll-snap-type: x proximity;
    }
    .pr-res-scope-btn {
        padding: 0.6rem 0.75rem;
        font-size: 0.8125rem;
        scroll-snap-align: center;
    }
    .pr-res-scope-btn svg {
        display: none;
    }
}

/* ---- district race: club filter chips ---- */
.pr-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin: 0 0 1.5rem;
}
.pr-chip {
    display: inline-flex;
    align-items: center;
    padding: 0.5rem 1.1rem;
    border-radius: 100px;
    border: 1px solid var(--pr-border);
    background: var(--pr-surface);
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--pr-muted);
    text-decoration: none;
    white-space: nowrap;
    transition:
        background 0.18s ease,
        color 0.18s ease,
        border-color 0.18s ease,
        box-shadow 0.18s ease;
}
.pr-chip:hover {
    color: var(--pr-heading);
    background: rgba(37, 99, 235, 0.07);
    border-color: rgba(37, 99, 235, 0.25);
}
.pr-chip.is-on {
    color: #fff;
    background: var(--pr-gradient);
    border-color: transparent;
    box-shadow: 0 8px 18px rgba(37, 99, 235, 0.3);
}

/* visually hidden but still focusable — the scan card's hidden scanner
   input needs to keep receiving the physical scanner's keystrokes, so
   display:none/hidden would break it the same way it would in the
   dashboard (see dashboard.css's own .pr-sr, this page just never loads
   that stylesheet). */
.pr-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* ---- scan your pigeon home ---- */
.pr-res-scan {
    margin: 0 0 1.5rem;
    padding: 1.1rem 1.25rem;
    border-radius: 1rem;
    background: var(--pr-surface);
    border: 1px solid var(--pr-border);
}
.pr-res-scan-head {
    display: flex;
    gap: 0.85rem;
    align-items: flex-start;
    margin-bottom: 0.85rem;
}
.pr-res-scan-icon {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 0.75rem;
    background: var(--pr-blue-soft, rgba(37, 99, 235, 0.1));
    color: var(--pr-blue, #2563eb);
}
.pr-res-scan-text h2 {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 1rem;
    font-weight: 800;
    margin: 0 0 0.2rem;
    color: var(--pr-heading);
}
.pr-res-scan-text p {
    margin: 0;
    font-size: 0.85rem;
    color: var(--pr-muted);
}
.pr-res-scan-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem;
}
.pr-res-scan-listening {
    font-size: 0.85rem;
    font-weight: 700;
    color: var(--pr-blue, #2563eb);
}
.pr-res-scan-location {
    margin: 0.6rem 0 0;
    font-size: 0.8rem;
    color: var(--pr-muted);
}
.pr-res-scan-location.text-danger {
    color: var(--bs-danger, #dc2626) !important;
}
.pr-res-scan-log {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    margin-top: 0.75rem;
}
.pr-res-scan-log:empty {
    display: none;
}
.pr-res-scan-log .pr-feed-item {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.5rem 0.65rem;
    border-radius: 0.6rem;
    background: rgba(37, 99, 235, 0.05);
    font-size: 0.82rem;
    color: var(--pr-heading);
}
/* A refused scan (wrong location, unknown chip, already home, …) used to
   read in the same plain heading colour as a successful one — only the
   small round mark next to it was ever red. The whole line now tints red
   too, on request, so a failure reads as a failure at a glance. */
.pr-res-scan-log .pr-feed-item.is-stop {
    background: rgba(220, 38, 38, 0.08);
    color: var(--pr-error);
}
.pr-res-scan-log .pr-feed-mark {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 999px;
}
.pr-res-scan-log .pr-feed-mark.is-ok {
    background: rgba(22, 163, 74, 0.15);
    color: #16a34a;
}
.pr-res-scan-log .pr-feed-mark.is-stop {
    background: rgba(220, 38, 38, 0.15);
    color: #dc2626;
}

/* ---- result rows ---- */
.pr-res-list {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}
.pr-res-card {
    position: relative;
    overflow: hidden;
    padding: 1.15rem 1.25rem 1.25rem;
    border-radius: 1.15rem;
    background: var(--pr-surface);
    border: 1px solid var(--pr-border);
    box-shadow: 0 4px 18px rgba(16, 42, 67, 0.06);
    transition:
        transform 0.22s ease,
        box-shadow 0.22s ease,
        border-color 0.22s ease;
}
.pr-res-card:hover {
    transform: translateY(-3px);
    border-color: rgba(37, 99, 235, 0.3);
    box-shadow: 0 18px 38px rgba(16, 42, 67, 0.12);
}
.pr-res-card[hidden] {
    display: none;
}
/* the winner carries the brand gradient down its leading edge */
.pr-res-card.is-first::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 4px;
    background: linear-gradient(
        180deg,
        var(--pr-blue-accent),
        var(--pr-blue-dark)
    );
}

/* ---- club contacts carousel (pages/club.blade.php) ----
   Unlike .pr-promo (one big card swapped for another, see main.js), this
   keeps several .pr-res-card contact cards on screen at once and slides the
   row forward by one card at a time — [data-contacts-carousel] in main.js
   drives the actual motion. */
.pr-contacts-viewport {
    overflow: hidden;
}
.pr-contacts-track {
    display: flex;
    gap: 1.25rem;
    transition: transform 0.6s cubic-bezier(0.22, 0.85, 0.3, 1);
}
/* mobile-first: one card on a phone, two once there's room (tablet), three
   on a laptop-width screen and up — [data-contacts-carousel] in main.js
   measures the rendered card width itself, so it always slides by exactly
   one card and only rotates when more contacts exist than currently fit. */
.pr-contacts-card {
    flex: 0 0 100%;
}
@media (min-width: 768px) {
    .pr-contacts-card {
        flex: 0 0 calc(50% - 0.625rem);
    }
}
@media (min-width: 992px) {
    .pr-contacts-card {
        flex: 0 0 calc((100% - 2.5rem) / 3);
    }
}
.pr-contact-link {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--pr-blue-accent);
    text-decoration: none;
}
.pr-contact-link:hover {
    text-decoration: underline;
}
@media (prefers-reduced-motion: reduce) {
    .pr-contacts-track {
        transition: none;
    }
}

/* ---- leaderboard rows ----
   Each is a native <details>/<summary> — clicking anywhere on the summary
   expands that fancier's own birds inline, no JS required for the toggle
   itself (js/main.js only drives the scope tabs and the live-speed ticks).
   Deliberately its own class rather than reusing .pr-res-card (which
   pages/club.blade.php also uses) so the two pages' styles never fight. */
.pr-res-row {
    position: relative;
    overflow: hidden;
    border-radius: 0.9rem;
    background: var(--pr-surface);
    border: 1px solid var(--pr-border);
    box-shadow: 0 2px 10px rgba(16, 42, 67, 0.05);
    transition:
        box-shadow 0.2s ease,
        border-color 0.2s ease;
}
.pr-res-row + .pr-res-row {
    margin-top: 0.5rem;
}
.pr-res-row:hover,
.pr-res-row[open] {
    border-color: rgba(37, 99, 235, 0.28);
    box-shadow: 0 8px 20px rgba(16, 42, 67, 0.09);
}
.pr-res-row[hidden] {
    display: none;
}
/* the winner carries the brand gradient down its leading edge */
.pr-res-row.is-first::before {
    content: "";
    position: absolute;
    inset: 0 auto 0 0;
    width: 4px;
    background: linear-gradient(
        180deg,
        var(--pr-blue-accent),
        var(--pr-blue-dark)
    );
}

.pr-res-row summary {
    list-style: none;
    cursor: pointer;
}
.pr-res-row summary::-webkit-details-marker {
    display: none;
}
/* One card, two stacked blocks: .pr-res-card-head (square photo + the two
   identity lines + tally/chevron) on top, the full-width time/distance/speed
   bar (.pr-res-card-stats) underneath — same shape at every viewport width,
   no separate mobile grid to keep in step with this one. */
.pr-res-row-summary {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    padding: 0.8rem 0.9rem;
}
.pr-res-row-summary:focus-visible {
    outline: 2px solid var(--pr-blue);
    outline-offset: -2px;
}

.pr-res-card-head {
    display: flex;
    align-items: center;
    gap: 0.8rem;
}

/* Square member photo — .pr-res-photo, distinct from the circular .pr-avatar
   dashboard.css uses elsewhere, per this card's own square-image layout. */
.pr-res-photo {
    width: 3rem;
    height: 3rem;
    border-radius: 0.65rem;
    flex: 0 0 auto;
    overflow: hidden;
    display: grid;
    place-items: center;
    background: var(--pr-gradient);
    color: #fff;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 800;
    font-size: 0.9rem;
}
.pr-res-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
/* Bigger for the leaderboard/"By Fancier" card now that its own identity
   block carries three lines (placing+name, club, sex/ring/ETS) instead of
   two, so the photo needs the extra height to still feel proportional. */
.pr-res-photo-lg {
    width: 3.75rem;
    height: 3.75rem;
    font-size: 1.05rem;
}

/* The trophy badge before the owner's name (row 1), top 3 only. Its own
   class — deliberately not .pr-res-rank/.pr-res-bird-rank (partials/result-
   bird-identity.blade.php's per-bird badge) — so restyling this one never
   disturbs that shared badge. Renders the real trophy-gold/silver/bronze.png
   image (public/assets/img) with no background tint of its own — the image
   already carries its own gold/silver/bronze colour. */
.pr-res-owner-rank {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    flex: 0 0 auto;
}
.pr-res-owner-rank img {
    width: 100%;
    height: 100%;
    object-fit: contain;
}

/* "N/total" right after the placing badge — how many fanciers are on this
   leaderboard, not to be confused with .pr-res-tally's arrived/birds count
   further along the same row. Same pill treatment as .pr-res-owner-rank
   (plain tint by default, gold/silver/bronze for the top 3 via the shared
   .pr-medal-1/2/3 classes) rather than bare text, so the two badges read as
   one connected placing, not a number followed by unrelated grey text. */
.pr-res-rank-total {
    display: inline-flex;
    align-items: center;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--pr-muted-2);
    background: var(--pr-blue-soft);
    padding: 0.15rem 0.5rem;
    border-radius: 1rem;
    flex: 0 0 auto;
}
.pr-res-rank-total.pr-medal-1 {
    background: linear-gradient(135deg, #e8b65e, #c99a46);
    color: #3a2e1c;
}
.pr-res-rank-total.pr-medal-2 {
    background: #e4e1da;
    color: #5b615c;
}
.pr-res-rank-total.pr-medal-3 {
    background: #efdcc4;
    color: #6b4b34;
}

.pr-res-id {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    flex: 1 1 auto;
    text-align: left;
}
.pr-res-line {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-width: 0;
    flex-wrap: wrap;
}
.pr-res-club {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: clamp(0.72rem, 3vw, 0.8125rem);
    color: var(--pr-muted-2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* Loft distance line under the club name — "By Fancier" only. */
.pr-res-line-dist {
    display: none;
}
#prResList.is-by-fancier .pr-res-row-summary .pr-res-line-dist {
    display: flex;
}
.pr-res-dist-label {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: clamp(0.72rem, 3vw, 0.8125rem);
    color: var(--pr-muted-2);
}
.pr-res-club-dist {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: clamp(0.72rem, 3vw, 0.8125rem);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--pr-success);
    white-space: nowrap;
}
.pr-res-bird-name {
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 700;
    font-size: 0.875rem;
    color: var(--pr-heading);
}
/* partials/result-bird-identity.blade.php reuses this same class for
   Pigeon::identity() — "Owner Name · Birth Ring" — not just a bare owner
   name, so this can run a lot longer than the leaderboard card head's own
   plain name. The trailing sex icon (partials/pigeon-sex.blade.php) sits
   inside this same span too, so a hard ellipsis on a long identity string
   could clip the icon along with the ring. Shrinks first (clamp keeps the
   original 1.0625rem everywhere it already fit) and wraps rather than
   truncating if it still doesn't fit even then — same treatment as
   .pr-res-leader-stat-value--time above. */
.pr-res-name {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.35rem;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 800;
    font-size: clamp(0.85rem, 3.8vw, 1.0625rem);
    color: var(--pr-heading);
    line-height: 1.3;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: break-word;
    max-width: 100%;
}
.pr-res-star {
    color: var(--pr-blue);
    flex: 0 0 auto;
}
.pr-res-sub {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.8125rem;
    color: var(--pr-muted-2);
    white-space: nowrap;
}
.pr-res-tick {
    width: 0.9rem;
    height: 0.9rem;
    padding: 0.12rem;
    border-radius: 50%;
    background: var(--pr-blue);
    color: #fff;
    flex: 0 0 auto;
}

/* the three readouts, inline as one group so the row stays one line on
   anything wider than a phone — no more boxed tile per stat */
.pr-res-stats {
    display: flex;
    align-items: center;
    gap: 1.15rem;
    flex-wrap: wrap;
}
/* Leaderboard card only (the per-bird dropdown/flat rows below keep the
   plain inline .pr-res-stats group above): full-width bar under the photo
   and identity lines, spread edge to edge with a hairline above it. */
.pr-res-card-stats {
    justify-content: space-between;
    width: 100%;
    padding-top: 0.85rem;
    border-top: 1px dashed var(--pr-border);
}
.pr-res-stat {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-family: "Manrope", system-ui, sans-serif;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.pr-res-stat b {
    font-weight: 800;
    font-size: 0.9375rem;
}
.pr-res-stat i {
    font-style: normal;
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--pr-muted-2);
    margin-left: 0.15rem;
}
.pr-res-stat-time b {
    color: var(--pr-blue-dark);
}
.pr-res-stat-dist b {
    color: var(--pr-success);
}
.pr-res-stat-speed b {
    color: var(--pr-navy-800);
}

/* partials/result-leader-stats.blade.php — the leaderboard/"By Fancier"
   card's compact readout for a bird that has actually landed: four equal
   columns (icon, muted label, coloured value) in one row inside a bordered
   box, replacing the plain .pr-res-card-stats inline row for this one card.
   Always four columns, even on a phone — font/icon/padding shrink instead
   of wrapping to two rows, so Time/Distance/Speed stay side by side the way
   the reference design has them. */
.pr-res-leader-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.5rem clamp(0.2rem, 1.5vw, 0.4rem);
    width: 100%;
    padding: 0.25rem;
    border: 1px solid var(--pr-border);
    border-radius: 0.65rem;
    background: var(--pr-bg);
}
.pr-res-leader-stat {
    display: flex;
    flex-direction: column;
    align-items: center;
    min-width: 0;
    text-align: center;
    color: var(--pr-muted-2);
}
.pr-res-leader-stat svg {
    width: clamp(13px, 4vw, 16px);
    height: clamp(13px, 4vw, 16px);
    flex: 0 0 auto;
}
/* Same scale as the rest of the sheet's stat readouts (.pr-res-stat b/i) —
   this box shrunk well past legible on a first pass; three columns instead
   of the original four leaves enough room to read at the normal size. */
.pr-res-leader-stat-label {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: clamp(0.625rem, 2.6vw, 0.75rem);
    font-weight: 700;
    color: var(--pr-muted-2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
/* Base size for Distance/Speed (and the "By Fancier" card's Total/Landed
   counts, which reuse this same class) — shrinks on a narrow phone the same
   way .pr-res-leader-stat-value--time does below, so the whole three-column
   box stays legible and in-bounds together instead of only the time column
   being handled. */
.pr-res-leader-stat-value {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: clamp(0.78rem, 3.2vw, 0.9375rem);
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    color: var(--pr-heading);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
/* Milliseconds add "." + 3 digits onto the arrival time ("13:00:03.482",
   or "Day 4, 13:00:03.482" once a day prefix joins it) — enough to hit the
   base rule's nowrap+ellipsis and clip to "..." on a narrow phone. Shrinks
   first (clamp keeps the original 0.9375rem everywhere it still fits) and
   only wraps to a second line, rather than truncating, if even the smaller
   size isn't enough. */
.pr-res-leader-stat-value--time {
    color: var(--pr-blue-dark);
    font-size: clamp(0.72rem, 3.6vw, 0.9375rem);
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: break-word;
}
.pr-res-leader-stat-value--dist {
    color: var(--pr-success);
}
/* The second, smaller line under a stat's headline value — the gap behind
   the leader under Time, "km"/"m/min" under Distance/Speed. */
.pr-res-leader-stat-sub {
    font-family: "Manrope", system-ui, sans-serif;
    font-size: clamp(0.625rem, 2.6vw, 0.75rem);
    font-weight: 700;
    color: var(--pr-muted-2);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 100%;
}
.pr-res-leader-stat-sub--gap {
    color: var(--pr-error);
}

.pr-res-loft {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    width: 100%;
    padding-top: 0.85rem;
}

.pr-res-loft::before,
.pr-res-loft::after {
    content: "";
    flex: 1 1 auto;
    height: 1px;
}

.pr-res-loft::before {
    background: linear-gradient(
        90deg,
        transparent,
        var(--pr-blue-light) 60%,
        var(--pr-blue) 100%
    );
}

.pr-res-loft::after {
    background: linear-gradient(
        270deg,
        transparent,
        var(--pr-blue-light) 60%,
        var(--pr-blue) 100%
    );
}

.pr-res-loft > span {
    flex: 0 0 auto;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.8125rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--pr-muted);
    white-space: nowrap;
    max-width: 70%;
    overflow: hidden;
    text-overflow: ellipsis;
}

[data-bs-theme="dark"] .pr-res-loft::before {
    background: linear-gradient(
        90deg,
        transparent,
        rgba(147, 197, 253, 0.35),
        var(--pr-blue-accent)
    );
}
[data-bs-theme="dark"] .pr-res-loft::after {
    background: linear-gradient(
        270deg,
        transparent,
        rgba(147, 197, 253, 0.35),
        var(--pr-blue-accent)
    );
}
[data-bs-theme="dark"] .pr-res-loft > span {
    color: var(--pr-muted);
}
.pr-res-loft-link {
    display: inline-flex;
    color: var(--pr-muted-2);
    margin-left: 0.1rem;
}
.pr-res-loft-link:hover,
.pr-res-loft-link:focus-visible {
    color: var(--pr-blue);
}

/* "By Fancier" (js/main.js's showScope() toggles #prResList.is-by-fancier)
   collapses each row to a plain member profile — placing, name, total/landed
   pigeon counts and loft distance only, no per-bird identity/time/speed,
   since one fancier's birds can each carry a different ring/chip/sex/speed.
   Scoped to .pr-res-row-summary specifically so the expanded dropdown
   underneath (.pr-res-panel, unlocked only in this same scope) keeps its
   full per-pigeon detail untouched. */
#prResList.is-by-fancier .pr-res-row-summary .pr-res-line-bird {
    display: none;
}
/* Same reasoning as .pr-res-line-bird above: .pr-res-tally's compact
   "arrived/birds" pill next to the chevron would just repeat the same two
   numbers .pr-res-fancier-stats already spells out as labelled Total
   Pigeons/Landed Pigeons tiles further down this same card. */
#prResList.is-by-fancier .pr-res-row-summary .pr-res-tally {
    display: none;
}
/* Swap the Time/Distance/Speed box (partials/result-leader-stats.blade.php
   or .pr-res-card-stats/result-stats.blade.php, whichever this bird's own
   landed state rendered) for .pr-res-fancier-stats — the Total
   Pigeons/Landed Pigeons/Distance tiles pages/result.blade.php renders right
   after it, on every row, for exactly this scope to reveal. */
#prResList.is-by-fancier
    .pr-res-row-summary
    > .pr-res-leader-stats:not(.pr-res-fancier-stats),
#prResList.is-by-fancier .pr-res-row-summary .pr-res-card-stats {
    display: none;
}
.pr-res-fancier-stats {
    display: none;
}
#prResList.is-by-fancier .pr-res-row-summary .pr-res-fancier-stats {
    display: grid;
}

/* the arrival time stacked over "Day N · +gap" — every row keeps this same
   two-line shape whether or not it actually trails the leader, so the
   times stay lined up reading down the list; the gap itself (how far
   behind the first bird home) is the one red figure on the sheet. */
.pr-res-time-col {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.05rem;
}
.pr-res-gap {
    color: var(--pr-error);
    font-weight: 800;
}

.pr-res-tally {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    flex: 0 0 auto;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.9375rem;
    font-weight: 800;
    color: var(--pr-heading);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}
.pr-res-tally i {
    font-style: normal;
    color: var(--pr-muted-2);
    font-weight: 600;
}
.pr-res-tally .pr-res-glyph {
    fill: var(--pr-success);
}

.pr-res-chevron {
    flex: 0 0 auto;
    color: var(--pr-muted-2);
    transition: transform 0.2s ease;
}
.pr-res-row[open] .pr-res-chevron {
    transform: rotate(180deg);
}
/* The per-fancier dropdown only expands in the "By Fancier" scope (see
   js/main.js's showScope() — it blocks the summary's click there and
   collapses any row left open when leaving the scope). Everywhere else
   (the Leaderboard included) the chevron is hidden and the row reads as a
   plain, non-interactive card. */
#prResList:not(.is-by-fancier) .pr-res-chevron {
    display: none;
}
#prResList:not(.is-by-fancier) .pr-res-row summary {
    cursor: default;
}

/* the dropdown — that fancier's own birds, indented under the photo/identity
   block so it reads as "belonging" to the row above it. Each bird is its own
   .pr-res-subrow-flat card, exactly like the "All Pigeons"/"My Birds" flat
   rows below (same border/background/radius, same mobile stacking) — not a
   lighter secondary style. */
.pr-res-panel {
    padding: 0.15rem 1rem 0.85rem calc(3rem + 0.8rem + 1rem);
    border-top: 1px solid var(--pr-border);
}
.pr-res-subempty {
    padding: 0.6rem 0;
    font-size: 0.875rem;
    color: var(--pr-muted-2);
}

/* Reused as-is by the leaderboard dropdown above (see the comment on
   .pr-res-panel) — one class, one look, in both places. Reuses .pr-res-id
   and .pr-res-stats (identity + the speed gauge) so this view matches the
   Leaderboard row's size, font and speedometer exactly, not a smaller
   secondary style. */
.pr-res-subrow-flat {
    display: flex;
    align-items: center;
    justify-content: space-between;
    flex-wrap: wrap;
    gap: 0.6rem 1rem;
    background: var(--pr-surface);
    border: 1px solid var(--pr-border);
    border-radius: 0.9rem;
    padding: 0.85rem 1rem;
}
.pr-res-subrow-flat[hidden] {
    display: none;
}
.pr-res-subrow-flat + .pr-res-subrow-flat {
    margin-top: 0.5rem;
}

/* partials/result-bird-identity.blade.php — one pigeon's trophy/position +
   name/sex + ring/chip, shared by the "All Pigeons"/"My Birds" flat rows and
   the leaderboard's per-owner dropdown rows — both are .pr-res-subrow-flat
   cards now, so this reads identically in either place. That parent spaces
   its direct children apart with justify-content:space-between, so grouping
   the rank badge with the name/sub-line as one flex item here keeps them
   sitting together instead of a second gap prising the badge away from the
   name. */
.pr-res-bird-lead {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    min-width: 0;
}

/* This is a small standalone circle rather than a grid/rank slot (see the
   comment above .pr-res-subrow-flat) — a solid, bright badge on purpose (not
   the muted --pr-blue-soft tint most other badges on this sheet use) so the
   position is the first thing the eye lands on in each pigeon row, on the
   "All Pigeons"/"My Birds" flat rows and the leaderboard's per-fancier
   dropdown alike. Top 3 still pick up their own gold/silver/bronze via the
   shared .pr-medal-1/2/3 modifier classes — kept entirely separate from the
   leaderboard card's own .pr-res-owner-rank. The .pr-medal-N overrides have
   to be repeated below (not just inherited from the shared .pr-medal-1/2/3
   rule near the top of this file) because that shared rule and this one
   carry equal specificity, and this one comes later in the file — without
   repeating them here, this rule's own background/color would win instead
   and every position, medal or not, would render the same solid blue. */
.pr-res-bird-rank {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: 50%;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 800;
    font-size: 0.75rem;
    color: #fff;
    background: var(--pr-gradient);
    box-shadow: 0 2px 8px rgba(var(--pr-blue-rgb), 0.4);
}
.pr-res-bird-rank.pr-medal-1 {
    background: linear-gradient(135deg, #e8b65e, #c99a46);
    color: #3a2e1c;
    box-shadow: 0 2px 8px rgba(201, 154, 70, 0.4);
}
.pr-res-bird-rank.pr-medal-2 {
    background: #e4e1da;
    color: #5b615c;
    box-shadow: 0 2px 8px rgba(91, 97, 92, 0.3);
}
.pr-res-bird-rank.pr-medal-3 {
    background: #efdcc4;
    color: #6b4b34;
    box-shadow: 0 2px 8px rgba(107, 75, 52, 0.3);
}

/* The "All Pigeons"/"My Birds" flat rows' "3/5" reading — the circle widens
   into a pill so the fraction sits inside the same tinted badge (medal
   colours included) instead of a separate element trailing off it. The
   position keeps the badge's bold weight; "/total" rides along at a lighter
   weight and slightly reduced opacity so the eye still lands on the
   position first. */
.pr-res-bird-rank-pill {
    width: auto;
    min-width: 2.1rem;
    height: 2.1rem;
    padding: 0 0.65rem;
    border-radius: 1.1rem;
    gap: 0.15rem;
    font-size: 1rem;
}
.pr-res-bird-rank-pill i {
    font-style: normal;
    font-weight: 600;
    font-size: 0.8rem;
    opacity: 0.7;
}

/* speed gauge — a half-circle dial with a rotating needle beside the digital
   reading, sized to fit inside a single-line row (partials/speed-gauge.blade.php,
   shared by every Speed stat on this sheet). The scale arc carries a fixed
   calm-to-fast tint (#prSpeedoGrad, defined once in partials/dove.blade.php
   and reused via url(#...) the same way #prDove is) with a ring of tick
   marks around it — neither is a fill, only the needle carries the actual
   reading. The needle pivots on the hub's own SVG coordinate, (50, 50) in
   the face's 0 0 100 56 viewBox — transform-box: view-box makes
   transform-origin read as an absolute point in that viewBox rather than a
   percentage of the needle group's own bounding box, which would have been
   wrong here anyway (the tip line runs 50→14 and the tail 50→56, so the
   group's bbox is not centered on the hub at all: a percentage origin lands
   off-center and the needle sweeps out of true). Rotating it is still one
   CSS custom property away from the server-rendered angle or a live JS
   tick; the short tail behind the pivot and the two-layer hub are what make
   it read as a needle rather than a bar. */
.pr-speedo-face {
    width: 46px;
    height: auto;
    flex: 0 0 auto;
    overflow: visible;
}
.pr-speedo-track {
    fill: none;
    stroke: url(#prSpeedoGrad);
    stroke-width: 8;
    stroke-linecap: round;
}
.pr-speedo-ticks {
    stroke: var(--pr-muted-2);
    stroke-width: 1.4;
    stroke-linecap: round;
    opacity: 0.55;
}
.pr-speedo-tick-mid {
    stroke-width: 2;
    opacity: 1;
    stroke: var(--pr-muted);
}
.pr-speedo-tick-label {
    fill: var(--pr-heading);
    font-family: "Manrope", system-ui, sans-serif;
    font-weight: 700;
    font-size: 11px;
    font-variant-numeric: tabular-nums;
    text-rendering: optimizeLegibility;
}
.pr-speedo-needle {
    transform-box: view-box;
    transform-origin: 50px 50px;
    transform: rotate(var(--pr-speedo-angle, -90deg));
    transition: transform 0.6s cubic-bezier(0.2, 0.7, 0.2, 1);
    filter: drop-shadow(0 1px 1px rgba(16, 42, 67, 0.25));
}
.pr-speedo-needle-tip {
    stroke: var(--pr-blue);
    stroke-width: 4.5;
    stroke-linecap: round;
}
.pr-speedo-needle-tail {
    stroke: var(--pr-blue);
    stroke-width: 3;
    stroke-linecap: round;
    opacity: 0.55;
}
.pr-speedo-hub-ring {
    fill: var(--pr-surface);
    stroke: var(--pr-blue);
    stroke-width: 1.6;
}
.pr-speedo-hub {
    fill: var(--pr-blue);
}

.pr-res-empty {
    margin: 1.25rem 0 0;
    text-align: center;
    font-size: 0.9375rem;
    color: var(--pr-muted-2);
}

/* ---- race note ---- */
.pr-res-quote {
    position: relative;
    margin: 2.5rem 0 0;
    padding: 1.5rem 1.6rem 1.35rem 3.4rem;
    border-radius: 1.15rem;
    background: var(--pr-surface);
    border: 1px solid var(--pr-border);
    border-left: 4px solid var(--pr-blue);
    box-shadow: 0 4px 18px rgba(16, 42, 67, 0.06);
}
.pr-res-quote-mark {
    position: absolute;
    left: 1.15rem;
    top: 1.3rem;
    color: var(--pr-blue-accent);
    opacity: 0.35;
}
.pr-res-quote blockquote {
    margin: 0;
    font-size: 0.9375rem;
    line-height: 1.65;
    color: var(--pr-text);
}
.pr-res-quote figcaption {
    margin-top: 0.6rem;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.75rem;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--pr-muted-2);
}

/* ---- dark mode ----
   The banner and the two dark strips are already dark by construction; only
   the light-surface pieces need remapping. */
[data-bs-theme="dark"] .pr-race-bird {
    opacity: 0.8;
}
[data-bs-theme="dark"] .pr-res-bar,
[data-bs-theme="dark"] .pr-res-weather {
    background: linear-gradient(135deg, var(--pr-surface), #081527);
    box-shadow: 0 16px 34px rgba(0, 0, 0, 0.35);
}
[data-bs-theme="dark"] .pr-res-scope {
    border-color: rgba(255, 255, 255, 0.1);
}
[data-bs-theme="dark"] .pr-res-scope-btn:hover {
    background: rgba(255, 255, 255, 0.06);
    color: #fff;
}
[data-bs-theme="dark"] .pr-chip {
    border-color: rgba(255, 255, 255, 0.1);
}
[data-bs-theme="dark"] .pr-chip:hover {
    background: rgba(255, 255, 255, 0.06);
    color: #fff;
}
[data-bs-theme="dark"] .pr-res-card,
[data-bs-theme="dark"] .pr-res-quote {
    border-color: rgba(255, 255, 255, 0.08);
    box-shadow: 0 2px 14px rgba(0, 0, 0, 0.35);
}
[data-bs-theme="dark"] .pr-res-card:hover {
    box-shadow: 0 18px 38px rgba(0, 0, 0, 0.45);
}
[data-bs-theme="dark"] .pr-res-row {
    border-color: rgba(255, 255, 255, 0.08);
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
[data-bs-theme="dark"] .pr-res-row:hover,
[data-bs-theme="dark"] .pr-res-row[open] {
    border-color: rgba(59, 130, 246, 0.35);
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.4);
}
[data-bs-theme="dark"] .pr-res-panel {
    border-top-color: rgba(255, 255, 255, 0.08);
}
[data-bs-theme="dark"] .pr-res-subrow-flat {
    background: rgba(255, 255, 255, 0.04);
    border-color: rgba(255, 255, 255, 0.08);
}
[data-bs-theme="dark"] .pr-res-stat-time b {
    color: #93c5fd;
}
[data-bs-theme="dark"] .pr-res-stat-dist b {
    color: #4ade80;
}
[data-bs-theme="dark"] .pr-res-stat-speed b {
    color: var(--pr-heading);
}
[data-bs-theme="dark"] .pr-res-gap {
    color: #f87171;
}
/* same colourful dial in dark theme as .pr-race-gauge already always shows
   (that card is dark regardless of site theme) — white needle/ticks and a
   dark-filled hub read clearly against a dark card the way the light
   theme's blue needle reads against a white one. */
[data-bs-theme="dark"] .pr-speedo-track {
    stroke: url(#prSpeedoGrad);
}
[data-bs-theme="dark"] .pr-speedo-ticks {
    stroke: rgba(255, 255, 255, 0.85);
    opacity: 0.8;
}
[data-bs-theme="dark"] .pr-speedo-tick-mid {
    stroke: #fff;
    opacity: 1;
}
[data-bs-theme="dark"] .pr-speedo-tick-label {
    fill: rgba(255, 255, 255, 0.85);
}
[data-bs-theme="dark"] .pr-speedo-needle-tip {
    stroke: #fff;
    filter: drop-shadow(0 0 5px rgba(255, 255, 255, 0.85));
}
[data-bs-theme="dark"] .pr-speedo-needle-tail {
    stroke: #fff;
}
[data-bs-theme="dark"] .pr-speedo-hub-ring {
    fill: rgba(15, 32, 54, 0.85);
    stroke: #fff;
}
[data-bs-theme="dark"] .pr-speedo-hub {
    fill: #fff;
}
[data-bs-theme="dark"] .pr-res-tick {
    background: var(--pr-blue-accent);
}
[data-bs-theme="dark"] .pr-res-star {
    color: var(--pr-blue-light);
}
[data-bs-theme="dark"]
    .pr-res-rank-total:not(.pr-medal-1):not(.pr-medal-2):not(.pr-medal-3) {
    background: rgba(255, 255, 255, 0.08);
    color: var(--pr-muted);
}
/* No dark-mode override here (unlike .pr-res-rank-total above) — .pr-res-
   bird-rank is now an opaque solid-blue/gold/silver/bronze badge rather than
   a translucent tint, so it reads exactly as bright against a dark page as
   a light one, the same way .pr-res-photo's gradient monogram circle
   already does. */

/* partials/pigeon-sex.blade.php's badge — dashboard.css already styles this
   the same way for dashboard photo frames, but public pages (this result
   sheet's "All Pigeons"/"My Birds" rows) never load dashboard.css, which
   left the badge's white icon with no coloured circle behind it to sit on,
   i.e. invisible. Base shape only — .is-overlay (pinned to a photo frame
   corner) is a dashboard-only placement, not needed here. */
.pr-sex-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    flex: 0 0 auto;
}
.pr-sex-badge svg {
    width: 62%;
    height: 62%;
}
.pr-sex-badge.is-male {
    background: var(--pr-blue-accent);
}
.pr-sex-badge.is-female {
    background: var(--pr-pink);
}

@media (max-width: 767.98px) {
    .pr-res-bar {
        grid-template-columns: repeat(2, 1fr);
        row-gap: 0.9rem;
    }
    .pr-res-weather {
        grid-template-columns: repeat(2, 1fr);
        row-gap: 0.9rem;
    }
    /* dividers follow the grid, not source order */
    .pr-res-bar .pr-bar-item + .pr-bar-item {
        border-left: 0;
    }
    .pr-res-bar .pr-bar-item:nth-child(even) {
        border-left: 1px solid rgba(255, 255, 255, 0.1);
    }
    .pr-res-bar .pr-bar-item:nth-child(n + 3) {
        border-top: 1px solid rgba(255, 255, 255, 0.1);
        padding-top: 0.9rem;
    }
    .pr-res-weather .pr-bar-item + .pr-bar-item {
        border-left: 0;
    }
    .pr-res-weather .pr-bar-item:nth-child(even) {
        border-left: 1px solid rgba(255, 255, 255, 0.1);
    }
    .pr-res-weather .pr-bar-item:nth-child(n + 3) {
        border-top: 1px solid rgba(255, 255, 255, 0.1);
        padding-top: 0.9rem;
    }

    .pr-res-row-summary {
        padding: 1rem;
    }
    .pr-res-panel {
        padding-left: 0.85rem;
    }
    .pr-res-quote {
        padding-left: 1.4rem;
        padding-top: 3rem;
    }
    .pr-res-quote-mark {
        left: 1.3rem;
        top: 1.1rem;
    }

    /* "All Pigeons"/"My Birds" flat rows: on a phone the identity and stats
     halves no longer fit one line and wrap, same as they always could — this
     just gives that wrapped state its own full-width line with a hairline
     above it (matching the leaderboard card's own stats bar) instead of the
     stats trailing directly under the identity block with nothing to
     separate them. */
    .pr-res-subrow-flat {
        align-items: flex-start;
    }
    .pr-res-subrow-flat .pr-res-stats {
        width: 100%;
        justify-content: space-between;
        padding-top: 0.75rem;
        border-top: 1px dashed var(--pr-border);
    }
}

@media (prefers-reduced-motion: reduce) {
    .pr-res-card,
    .pr-res-row,
    .pr-res-scope-btn {
        transition: none;
    }
    .pr-res-card:hover {
        transform: none;
    }
    .pr-speedo-needle {
        transition: none;
    }
}

/* ==========================================================================
   CROP MODAL (partials/image-crop-modal) — shared by every page with an
   input[type=file][data-crop], dashboard and public/auth alike, so it lives
   here rather than in dashboard.css.
   ========================================================================== */

.pr-crop-stage {
    width: 100%;
    max-height: 60vh;
    overflow: hidden;
    background: var(--pr-navy-900);
    border-radius: 0.7rem;
}
.pr-crop-stage img {
    display: block;
    max-width: 100%;
}
/* Cropper.js draws a rectangular crop box; a round mask over the view box and
   face is the standard recipe for making it read as a circle for the eye
   close-up while the underlying math stays rectangular. */
.pr-crop-stage.is-circle .cropper-view-box,
.pr-crop-stage.is-circle .cropper-face {
    border-radius: 50%;
}
/* The frame itself never moves or resizes (see image-cropper.js) — only the
   image pans and zooms behind it — so its resize handles are dead weight. */
.pr-crop-stage .cropper-point,
.pr-crop-stage .cropper-line {
    display: none;
}
.pr-crop-stage .cropper-face {
    cursor: move;
}
.pr-crop-zoom {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-top: 1rem;
    color: var(--pr-muted);
}
.pr-crop-zoom .form-range {
    flex: 1;
}

/* A tall camera photo can still push .pr-crop-stage's own 60vh close to the
   whole viewport on a short mobile screen, leaving no room for the modal's
   header/footer — modal-dialog-scrollable (see the partial) keeps those
   pinned, but the stage itself is trimmed further here so the Cancel/"Use
   this photo" buttons are reachable without hunting for a scrollbar. */
@media (max-width: 575.98px) {
    .pr-crop-stage {
        max-height: 42vh;
    }
}

/* ---- PWA install button ---- */
/* Hidden until pwa-install.js decides the browser can actually install
   (beforeinstallprompt fired) or is iOS Safari (no such event, manual
   Add to Home Screen instructions instead). */
.pr-pwa-install {
    position: fixed;
    right: 1rem;
    bottom: calc(1rem + env(safe-area-inset-bottom, 0px));
    z-index: 1040;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.6rem 1.1rem;
    border: none;
    border-radius: 999px;
    background: var(--pr-gradient);
    color: #fff;
    font-weight: 600;
    font-size: 0.9rem;
    box-shadow: 0 10px 24px rgba(var(--pr-blue-rgb), 0.35);
    transition:
        transform 0.15s ease,
        box-shadow 0.15s ease;
}
.pr-pwa-install:hover {
    transform: translateY(-1px);
    box-shadow: 0 14px 28px rgba(var(--pr-blue-rgb), 0.4);
    color: #fff;
}
.pr-pwa-install svg {
    width: 1.1rem;
    height: 1.1rem;
    flex-shrink: 0;
}
.pr-dash-body .pr-pwa-install {
    bottom: calc(
        1rem + var(--pr-tabbar-h, 0px) + env(safe-area-inset-bottom, 0px)
    );
}

/* ==========================================================================
   SHIELD on the result sheet — the race's mark beside its state pill, and a
   pigeon's own Shield status (verified / awaiting its Hidden Code /
   disqualified). .pr-pill only exists in dashboard.css, which public pages
   never load, so these carry their own look.
   ========================================================================== */
.pr-res-night-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-left: 0.5rem;
    padding: 0.3rem 0.75rem;
    border-radius: 999px;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    color: #c7d2fe;
    background: rgba(129, 140, 248, 0.18);
    border: 1px solid rgba(129, 140, 248, 0.45);
    vertical-align: middle;
}
.pr-res-night-chip.is-paused {
    color: #e0e7ff;
    background: rgba(129, 140, 248, 0.32);
}
.pr-res-district-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-left: 0.5rem;
    padding: 0.3rem 0.75rem;
    border-radius: 999px;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    color: #cbd5e1;
    background: rgba(148, 163, 184, 0.18);
    border: 1px solid rgba(148, 163, 184, 0.45);
    vertical-align: middle;
}
.pr-res-district-chip.is-district {
    color: #5eead4;
    background: rgba(20, 184, 166, 0.18);
    border-color: rgba(20, 184, 166, 0.5);
}
.pr-res-shield-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-left: 0.5rem;
    padding: 0.3rem 0.75rem;
    border-radius: 999px;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.78rem;
    font-weight: 800;
    letter-spacing: 0.02em;
    color: #fcd34d;
    background: rgba(245, 158, 11, 0.18);
    border: 1px solid rgba(245, 158, 11, 0.45);
    vertical-align: middle;
}
.pr-res-shield {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-left: 0.4rem;
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.7rem;
    font-weight: 800;
    line-height: 1.4;
    white-space: nowrap;
}
.pr-res-shield.is-verified {
    color: #1d4ed8;
    background: rgba(37, 99, 235, 0.12);
}
.pr-res-shield.is-unverified {
    color: #475569;
    background: #e2e8f0;
}
.pr-res-shield.is-stop {
    color: #991b1b;
    background: #fee2e2;
}
[data-bs-theme="dark"] .pr-res-shield.is-verified {
    color: #93c5fd;
    background: rgba(59, 130, 246, 0.24);
}
[data-bs-theme="dark"] .pr-res-shield.is-unverified {
    color: #cbd5e1;
    background: rgba(148, 163, 184, 0.2);
}
[data-bs-theme="dark"] .pr-res-shield.is-stop {
    color: #fca5a5;
    background: rgba(239, 68, 68, 0.22);
}
/* a disqualified pigeon stays on the sheet — last in "All Pigeons" — but
   visibly out of the running */
.pr-res-subrow-flat.is-disqualified {
    opacity: 0.66;
}

/* ETS reader status inside the result sheet's "Scan your pigeon home" card
   (partials/device-reader.blade.php, js/device-reader.js) */
.pr-reader {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    max-width: 100%;
    font-family: "Manrope", system-ui, sans-serif;
    font-size: 0.78rem;
    font-weight: 700;
    color: var(--pr-muted);
}
.pr-reader.is-inline {
    display: flex;
    flex-wrap: wrap;
    margin-top: 0.75rem;
}
.pr-reader-dot {
    flex: 0 0 auto;
    width: 0.55rem;
    height: 0.55rem;
    border-radius: 50%;
    background: #94a3b8;
}
.pr-reader-dot.is-ok {
    background: #16a34a;
    box-shadow: 0 0 0 3px rgba(22, 163, 74, 0.2);
}
.pr-reader-dot.is-warn {
    background: #f59e0b;
    box-shadow: 0 0 0 3px rgba(245, 158, 11, 0.2);
}
.pr-reader-connect {
    white-space: nowrap;
}
