/* ══════════════════════════════════════════════════════════════════════════════════════════
   SOCIAL DOCK — THE SINGLE STYLESHEET.

   Served from the Blazor client wwwroot at /css/social-dock.css, which the host also serves
   at the site root. BOTH public front-ends load this one file:
     · the Razor Pages site  (/, /about, /achivements, /contact, /courses, /whyus)
         via Pages/Shared/_SocialDock.cshtml
     · the Blazor site       (/events, /franchise, /gallery, /locations, /webvirtualtool, ...)
         via Shared/HeropageLayout.razor
   One file, so the two can never drift apart. Change a colour here and it changes everywhere.
   ══════════════════════════════════════════════════════════════════════════════════════════ */
/* ── WHERE IT SITS, AND WHY IT CHANGES SHAPE ───────────────────────────────────────────────
     >=576px  right edge, vertically centred. A side rail is out of the reading column, so it
              never sits on top of body text, and mid-height is where the eye already is.
     <576px   bottom-right, horizontal. A phone has no room for a mid-height rail without
              covering the content, and the bottom-right corner is the one place a thumb
              reaches and no layout puts text.

   Z-INDEX 1020 is deliberate: BELOW the page modals and the Gallery lightbox (2000 / 3000),
   so a fullscreen image is never interrupted by two social buttons floating over it, and
   below Bootstrap's .fixed-top navbar (1030).
   ────────────────────────────────────────────────────────────────────────────────────────── */
.social-dock {
    position: fixed;
    top: 50%;
    right: 0;
    /* translateZ(0) promotes the rail to its own compositor layer. Verified first that nothing
       can break the fixed positioning — body has overflow-x:hidden on several pages but NO
       transform, so it is not the containing block and cannot clip or re-anchor this. The layer
       is for SMOOTHNESS: without it iOS Safari repaints a fixed element on every frame of a
       momentum scroll, which shows as the rail trembling as the page flicks past. */
    transform: translateY(-50%) translateZ(0);
    z-index: 1020;
    display: flex;
    flex-direction: column;
    align-items: flex-end;   /* each pill grows LEFTWARD from the edge */
    gap: 10px;
    padding-right: 14px;
    pointer-events: none;    /* the gaps stay click-through; the pills re-enable it */
}

.dock-btn {
    pointer-events: auto;
    display: flex;
    /* row-reverse, so the ICON stays welded to the right edge and the label unrolls to its LEFT.
       In normal row order the icon renders first (left); the pill's right edge is pinned by the
       rail's align-items:flex-end, so expanding would slide the icon leftward — out from under
       the very cursor that opened it. The eye should see a word appear beside a button that has
       not moved, not a button running away. */
    flex-direction: row-reverse;
    align-items: center;
    height: 50px;
    padding: 0;
    border-radius: 999px;
    text-decoration: none;
    position: relative;      /* the ::after halo anchors to this */
    -webkit-tap-highlight-color: transparent;   /* no grey flash on a phone tap */
    /* Frosted base so the rail reads as a floating control, not a sticker, whatever is behind it. */
    background: rgba(255, 255, 255, 0.92);
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
    /* Two shadows and a FAINT NAVY hairline, not a white one. Most of this site is white, and a
       white border on a near-white pill left the shape relying on its shadow alone — it read as a
       smudge rather than as a control. The navy tint is the site's own --blue at 9%. */
    box-shadow: 0 6px 22px rgba(0, 31, 84, 0.16), 0 1px 3px rgba(0, 31, 84, 0.10);
    border: 1px solid rgba(0, 31, 84, 0.09);
    transition: transform .28s cubic-bezier(.34,1.3,.5,1),
                box-shadow .28s ease,
                background .28s ease,
                border-color .28s ease;
    /* Staggered entrance — the rail arrives after the page has painted, so it reads as an
       invitation rather than as part of the furniture the eye has already skipped. */
    /* backwards, NOT both. "both" == "forwards" at the end, and a filled animation value
       OUTRANKS normal author declarations — the final transform:translateX(0) would stick and
       silently cancel every :hover and :active transform below. "backwards" applies the start
       frame during the delay (so it waits off-screen) and then lets CSS take back control. */
    animation: dockIn .55s cubic-bezier(.22,1,.36,1) backwards;
}

.dock-btn:nth-child(1) { animation-delay: .45s; }
.dock-btn:nth-child(2) { animation-delay: .58s; }

/* The circle that always shows. Fixed square so the rail stays perfectly aligned whether or
   not a label is open. */
.dock-ic {
    flex: 0 0 50px;          /* width only */
    /* Height STRETCHES rather than being stated. Bootstrap sets box-sizing:border-box, so the
       button's 50px already includes its 1px border — a fixed 50px icon box was 2px taller than
       the content box it sits in and hung 1px over each edge. Stretching also means the three
       breakpoints below only have to restate the WIDTH. */
    align-self: stretch;
    width: 50px;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.32rem;
    line-height: 1;
    transition: color .28s ease;
}

/* The label. max-width (not width) is what animates — it is the one property that can go from
   "nothing" to "as wide as the word needs" without hard-coding a pixel width per language. */
.dock-label {
    max-width: 0;
    overflow: hidden;      /* clips the word while the pill is closed - was on .dock-btn, where
                              it also clipped the halo ring and killed the pulse entirely */
    opacity: 0;
    white-space: nowrap;
    font-size: .85rem;
    font-weight: 700;
    letter-spacing: .2px;
    color: #fff;
    /* The Instagram pill is a 45deg gradient whose LIGHTEST stop (#f09433 orange) sits at the
       bottom-left — which, now that the label unrolls leftward, is exactly where the word lands.
       White on that orange is about 2.3:1 and simply does not read. The shadow is what keeps it
       legible across every stop of both gradients without touching the brand colours. */
    text-shadow: 0 1px 2px rgba(0, 0, 0, .38);
    transition: max-width .34s cubic-bezier(.22,1,.36,1), opacity .22s ease, padding .34s ease;
    padding: 0;
}

.dock-btn:hover .dock-label,
.dock-btn:focus-visible .dock-label {
    max-width: 132px;
    opacity: 1;
    padding-left: 18px;
}

.dock-btn:hover,
.dock-btn:focus-visible {
    /* No translateX: the pill already travels leftward as it widens, and a second simultaneous
       slide reads as a wobble. The scale alone is the lift. */
    transform: scale(1.04);
    box-shadow: 0 14px 34px rgba(0, 31, 84, 0.26);
    border-color: transparent;
}

/* Keyboard users get a real ring. :focus-visible only, so a mouse click leaves nothing behind. */
.dock-btn:focus-visible {
    /* Fallback is not optional: --yellow is declared in the Blazor layout only. On the Razor
       Pages site the bare var() is invalid and the browser drops the WHOLE declaration, which
       would leave keyboard users with no focus ring on the main public pages. */
    outline: 3px solid var(--yellow, #FFD200);
    outline-offset: 3px;
}

/* ── Brand identities. Resting state tints only the glyph; hover floods the whole pill, which
     is what makes the label legible in white. ── */
.dock-ig .dock-ic { color: #c1328e; }
.dock-fb .dock-ic { color: #1877F2; }

.dock-ig:hover,
.dock-ig:focus-visible {
    background: linear-gradient(45deg, #f09433 0%, #e6683c 25%, #dc2743 50%, #cc2366 75%, #bc1888 100%);
}

.dock-fb:hover,
.dock-fb:focus-visible {
    background: linear-gradient(135deg, #1877F2 0%, #0b5fd0 100%);
}

.dock-btn:hover .dock-ic,
.dock-btn:focus-visible .dock-ic {
    color: #fff;
}

/* A single quiet halo, three times, then silence. Enough to be noticed on arrival; not a
   blinking advert for the rest of the visit. */
.dock-btn::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: 999px;
    pointer-events: none;
}

.dock-ig::after {
    animation: dockHalo 2.4s ease-out 1.6s 3;
}

@keyframes dockIn {
    from { opacity: 0; transform: translateX(26px) scale(.86); }
    to   { opacity: 1; transform: translateX(0)    scale(1);   }
}

@keyframes dockHalo {
    0%   { box-shadow: 0 0 0 0   rgba(220, 39, 67, .45); }
    70%  { box-shadow: 0 0 0 16px rgba(220, 39, 67, 0);  }
    100% { box-shadow: 0 0 0 0   rgba(220, 39, 67, 0);   }
}

/* ── FULL-NAV WIDTHS (>=1200px): TOP-RIGHT, UNDER THE LOGIN BUTTON ──────────────────────────
   1200px is not an arbitrary number — it is exactly where the header's own `navbar-expand-xl`
   switches from a hamburger to the full nav. So this rule applies precisely where the Login
   button actually exists in the top-right corner, and nowhere else.

   Below 1200px the corner belongs to the HAMBURGER: the dock would sit directly under it, and
   the open menu panel would drop straight over it. Those widths keep the mid-right rail, which
   the breakpoint below restores.

   Anchored to --nav-height so it tracks the header rather than guessing: every page the dock
   appears on declares it (6 .cshtml + HeropageLayout), and the fallback covers anything new.
   ────────────────────────────────────────────────────────────────────────────────────────── */
@media (min-width: 1200px) {
    .social-dock {
        top: calc(var(--nav-height, 75px) + 18px);
        bottom: auto;
        /* No vertical centring here — the base rule's translateY(-50%) must go, but the
           compositor layer stays for the same momentum-scroll reason. */
        transform: translateZ(0);
    }
}

/* ── TABLET / SMALL LAPTOP ───────────────────────────────────────────────────────────────── */
@media (max-width: 991.98px) {
    .social-dock { gap: 9px; padding-right: 11px; }
    .dock-btn    { height: 46px; }
    .dock-ic     { flex-basis: 46px; width: 46px; font-size: 1.2rem; }
}

/* ── PHONE ───────────────────────────────────────────────────────────────────────────────
   Bottom-right, horizontal, and the label is dropped entirely: there is no hover on a touch
   screen, so an invisible label is only dead weight. 46px keeps the tap target comfortable.
   env(safe-area-inset-*) keeps it clear of the iPhone home bar and of a landscape notch. ── */
@media (max-width: 575.98px) {
    .social-dock {
        top: auto;
        bottom: calc(16px + env(safe-area-inset-bottom, 0px));
        right: calc(4px + env(safe-area-inset-right, 0px));
        /* No vertical centring down here, but KEEP the compositor layer — a phone is exactly
           where the momentum-scroll tremble shows. */
        transform: translateZ(0);
        flex-direction: row;
        align-items: center;
        gap: 10px;
        padding-right: 12px;
    }

    .dock-btn {
        height: 46px;
        box-shadow: 0 5px 18px rgba(0, 31, 84, 0.22);
    }

        .dock-btn:hover,
        .dock-btn:focus-visible {
            transform: translateY(-4px) scale(1.03);
        }

    .dock-ic { flex-basis: 46px; width: 46px; font-size: 1.22rem; }

    /* Never let a label open on a phone — it would push the pill off the right edge. */
    .dock-label,
    .dock-btn:hover .dock-label,
    .dock-btn:focus-visible .dock-label {
        display: none;
    }
}

/* A short landscape phone has almost no vertical room; shrink rather than crowd the viewport. */
@media (max-height: 420px) and (orientation: landscape) {
    .social-dock { gap: 8px; }
    .dock-btn    { height: 42px; }
    .dock-ic     { flex-basis: 42px; width: 42px; font-size: 1.1rem; }
}

/* Honour the OS setting. The rail still appears and still works — it just stops moving. */
/* TOUCH DEVICES — no hover state at all.
   A tap leaves :hover latched on the element until the user taps somewhere else, so on a phone
   or a touch tablet the pill would sit lifted — and between 576px and 991px, sitting OPEN with
   its label out — long after the finger has gone. Nothing should respond to hover where there is
   no pointer to hover with. :active below still fires, so the press feedback is untouched. */
@media (hover: none) {
    .dock-btn:hover {
        transform: none;
        box-shadow: 0 6px 22px rgba(0, 31, 84, 0.16), 0 1px 3px rgba(0, 31, 84, 0.10);
        border-color: rgba(0, 31, 84, 0.09);
        background: rgba(255, 255, 255, 0.92);
    }

        .dock-btn:hover .dock-label {
            max-width: 0;
            opacity: 0;
            padding-left: 0;
        }

    .dock-ig:hover .dock-ic { color: #c1328e; }
    .dock-fb:hover .dock-ic { color: #1877F2; }
}

/* PRESSED. Declared down here, AFTER every breakpoint, on purpose: the phone block above also
   sets a transform on :hover, and a tap fires :hover and :active together. Same specificity, so
   source order decides — the press has to be the last word or it is silently cancelled on the
   one device that needs it most. A control that does not answer a finger feels broken when there
   is no hover to confirm the tap landed. */
.dock-btn:active {
    transform: scale(.94);
    transition-duration: .09s;
}

@media (prefers-reduced-motion: reduce) {
    .dock-btn {
        animation: none;
        transition: background .2s ease, box-shadow .2s ease;
    }

        .dock-btn:hover,
        .dock-btn:active,
        .dock-btn:focus-visible {
            transform: none;
        }

        .dock-ig::after {
            animation: none;
        }

    .dock-label { transition: none; }
}

@media print {
    .social-dock { display: none !important; }
}
