/* ══════════════════════════════════════════════════════════════════
   site-header — the one page header.

   Markup and options: views/partials/site-header.ejs. This file is the
   static half; the partial emits only its per-render height variables
   inline, because those depend on whether a tab strip is rendering.

   Loaded via views/partials/mydreampark-ui-assets.ejs, so it is one
   cached request rather than ~13KB inlined into every page.

   Surface-specific colour goes through the custom properties this file
   reads, NOT through new rules:
     --site-header-bg          bar fill (set to `transparent` for a bar
                               whose colour the PAGE owns — see below)
     --site-header-blur        backdrop-filter value
     --site-header-border-w    border-bottom width
     --site-header-border-color  hairline colour, shown only when scrolled
     --site-header-max-w       inner max width. Default `none`: the bar
                               runs edge to edge, which is what the public
                               header, /download and the homepage always
                               did. Only surfaces that deliberately align
                               the bar to a centred content column set it
                               (the portals, and /assets).
     --site-header-tab-active  active tab ink + underline

   Not every surface wants this file to paint the bar at all. The public
   header (views/partials/header.ejs) is backgroundless by design: its
   pages decide what the bar looks like, because only they know what is
   behind it. views/share/share-head.ejs computes page luminance on the
   server and drives three different bar states plus an ink flip from it;
   views/dreamjam.ejs paints its own gradient. Those pages set the three
   properties above rather than fighting a fill from here.
   ══════════════════════════════════════════════════════════════════ */

    /* THIS FILE IS SERVED STATICALLY FROM public/ — no EJS may live in it.

       It shipped with an un-rendered EJS tag as its `position` value, and
       the CSS parser dropped that declaration along with the z-index
       below it. Every page got a position:static header, which then took
       72px of NORMAL FLOW while the page under it was ALSO padding itself
       down by --site-header-h — a header's height of dead space at the
       top of every layout on the site. On /download, a deliberately
       one-screen page, that dead space was the whole reason it scrolled.

       The partial already emits `dph-fixed` / `dph-sticky` (shRootClasses
       in views/partials/site-header.ejs), so position is a class here,
       and the zIndex prop arrives as a custom property from the partial's
       inline :root block. */
    .dph {
        position: fixed;
        top: 0;
        left: 0;
        right: 0;
        z-index: var(--site-header-z, 1000);
        transition: background 0.3s ease, backdrop-filter 0.3s ease, border-color 0.3s ease;
    }
    /* position: 'sticky' surfaces scroll with the document, so they stay
       in flow and must not be pinned across the viewport. */
    .dph-sticky {
        position: sticky;
        left: auto;
        right: auto;
    }

    .dph-bar {
        max-width: var(--site-header-max-w, none);
        margin: 0 auto;
        min-height: var(--site-header-bar-h);
        padding: 12px 24px;
        /* The notch. Padding rather than margin so the bar's background
           still paints behind the status bar on iOS. */
        padding-top: calc(env(safe-area-inset-top, 0px) + 12px);
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 12px;
        box-sizing: border-box;
    }

    /* ── The hairline ─────────────────────────────────────────────
       Only once the page has actually moved. At the top of a document
       there is nothing above the fold for the bar to be separated FROM,
       so the rule is just a line across the design.

       The border is always PRESENT and only ever changes colour, so
       turning it on cannot shift the bar by a pixel. Width and colour
       are separate properties for exactly that reason — a single
       shorthand var can't have its colour toggled independently. */
    .dph {
        border-bottom: var(--site-header-border-w, 1px) solid transparent;
    }
    .dph.is-scrolled {
        border-bottom-color: var(--site-header-border-color, transparent);
    }

    /* ── Chrome: dark ─────────────────────────────────────────────── */
    .dph-dark {
        --site-header-border-color: rgba(255, 255, 255, 0.10);
        background: var(--site-header-bg, rgba(11, 11, 16, 0.88));
        backdrop-filter: var(--site-header-blur, blur(14px));
        -webkit-backdrop-filter: var(--site-header-blur, blur(14px));
    }
    /* ── Chrome: light ────────────────────────────────────────────── */
    .dph-light {
        --site-header-border-color: rgba(11, 11, 15, 0.08);
        background: var(--site-header-bg, rgba(255, 255, 255, 0.82));
        backdrop-filter: var(--site-header-blur, blur(14px) saturate(150%));
        -webkit-backdrop-filter: var(--site-header-blur, blur(14px) saturate(150%));
    }

    /* ── Auto-hide on scroll ──────────────────────────────────────
       Down hides the bar, up brings it back — the phone-app pattern, so
       a long page gets its full viewport once you're reading. Hiding is
       a transform, NOT a height or display change: the bar keeps
       occupying --site-header-h as far as every clearance offset on the
       site is concerned, so nothing reflows when it goes and comes back.

       The reveal is quicker than the hide. Wanting the bar back is a
       deliberate act and should feel immediate; losing it is passive. */
    .dph[data-auto-hide] {
        transition: transform 0.26s cubic-bezier(0.16, 1, 0.3, 1),
                    background 0.3s ease, backdrop-filter 0.3s ease, border-color 0.3s ease;
    }
    /* No `will-change: transform` here, deliberately.
   
       It forces the header onto its own compositing layer PERMANENTLY,
       and mydreampark-badge carries its own backdrop-filter: blur(10px).
       A backdrop-filter element inside a permanently composited ancestor
       is the combination WebKit mis-rasterises during rubber-band
       overscroll — the badge draws offset and clipped while the page
       springs back. The old .header was never promoted, so this was a
       regression introduced with the auto-hide, not a pre-existing quirk.

       A 0.26s translate on one element composites fine without the hint.
       will-change is documented as a last resort for measured jank, not
       a default; if this ever needs it, add it for the duration of the
       transition and take it off again rather than leaving it on. */
    .dph[data-auto-hide].is-hidden {
        transform: translateY(-100%);
        transition-duration: 0.34s, 0.3s, 0.3s, 0.3s;
    }
    @media (prefers-reduced-motion: reduce) {
        .dph[data-auto-hide],
        .dph[data-auto-hide].is-hidden { transition: none; }
    }

    /* ── Chrome: transparent-over-hero ────────────────────────────
       Starts as a scrim and solidifies past 8px of scroll. */
    .dph-transparent {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
    }
    .dph-transparent.dph-dark {
        background: linear-gradient(180deg, rgba(12, 2, 32, 0.55) 0%, rgba(12, 2, 32, 0) 100%);
    }
    .dph-transparent.dph-light {
        background: linear-gradient(180deg, rgba(255, 255, 255, 0.82) 0%, rgba(255, 255, 255, 0) 100%);
    }
    .dph-transparent.dph-dark.is-scrolled {
        background: rgba(12, 2, 32, 0.78);
        backdrop-filter: blur(18px) saturate(160%);
        -webkit-backdrop-filter: blur(18px) saturate(160%);
        --site-header-border-color: rgba(255, 255, 255, 0.08);
    }
    .dph-transparent.dph-light.is-scrolled {
        background: rgba(255, 255, 255, 0.86);
        backdrop-filter: blur(18px) saturate(160%);
        -webkit-backdrop-filter: blur(18px) saturate(160%);
        --site-header-border-color: rgba(11, 11, 15, 0.08);
    }

    /* ── Brand ────────────────────────────────────────────────────── */
    .dph-brand-cluster {
        display: flex;
        align-items: center;
        gap: 12px;
        min-width: 0;
        flex: 0 1 auto;
    }
    .dph-brand {
        display: inline-flex;
        align-items: center;
        text-decoration: none;
        line-height: 0;
        flex: 0 0 auto;
    }
    .dph-brand img {
        display: block;
        width: auto;
        object-fit: contain;
        transform-origin: center center;
        transition: transform 0.2s ease;
    }
    .dph-mark-icon { height: 28px; }
    .dph-mark-text { height: 28px; }
    /* Icon mark can lift on hover. The big wordmark stays still —
       scaling a 13:1 lockup reads as the bar shoving itself. */
    .dph-brand:hover .dph-mark-icon { transform: scale(1.08); }
    .dph-brand:hover .dph-mark-text { transform: none; }

    /* 'responsive': wordmark on desktop, icon mark on small screens so a
       surface label still fits beside it. */
    .dph-brand-responsive .dph-mark-icon { display: none; }
    @media (max-width: 640px) {
        .dph-brand-responsive .dph-mark-text { display: none; }
        .dph-brand-responsive .dph-mark-icon { display: block; height: 30px; }
    }

    /* Dim uppercase text, not a bordered pill: the pill used to get
       clipped by the action button on narrow screens, and text
       truncates gracefully where a pill gets cut off mid-border. */
    .dph-surface {
        display: inline-block;
        min-width: 0;
        font-family: var(--mdp-font-body, 'Inter', system-ui, sans-serif);
        font-size: 11px;
        font-weight: 700;
        letter-spacing: 0.14em;
        text-transform: uppercase;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        padding-left: 12px;
    }
    .dph-dark  .dph-surface { color: rgba(255, 255, 255, 0.62); border-left: 1px solid rgba(255, 255, 255, 0.16); }
    .dph-light .dph-surface { color: rgba(21, 10, 36, 0.55);   border-left: 1px solid rgba(21, 10, 36, 0.14); }

    /* ── Centred title ────────────────────────────────────────────── */
    .dph-center {
        flex: 1 1 auto;
        display: flex;
        justify-content: center;
        min-width: 0;
        padding: 0 12px;
    }
    .dph-title {
        max-width: min(52vw, 560px);
        font-family: var(--mdp-ui-heading, var(--mdp-font-display, 'Inter', system-ui, sans-serif));
        font-size: 1.15rem;
        font-weight: 800;
        letter-spacing: -0.02em;
        line-height: 1.1;
        text-align: center;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }
    .dph-dark  .dph-title { color: #fff; }
    .dph-light .dph-title { color: #150a24; }

    /* ── Inline nav ───────────────────────────────────────────────── */
    .dph-nav { display: flex; align-items: center; gap: 6px; }
    .dph-nav a {
        position: relative;
        padding: 10px 14px;
        border-radius: 999px;
        font-family: var(--mdp-font-body, 'Inter', system-ui, sans-serif);
        font-size: 0.82rem;
        font-weight: 500;
        letter-spacing: 0.02em;
        text-decoration: none;
        white-space: nowrap;
        transition: color 0.2s ease, background 0.2s ease;
    }
    .dph-dark  .dph-nav a { color: rgba(246, 239, 225, 0.78); }
    .dph-dark  .dph-nav a:hover,
    .dph-dark  .dph-nav a.is-active { color: #f6efe1; background: rgba(255, 255, 255, 0.08); }
    .dph-light .dph-nav a { color: rgba(11, 11, 15, 0.62); }
    .dph-light .dph-nav a:hover,
    .dph-light .dph-nav a.is-active { color: #0b0b0f; background: rgba(11, 11, 15, 0.06); }

    /* Hamburger. Same chrome as the badge beside it — 48px, the badge's
       outer pill height, so the two never sit at different heights. */
    .dph-nav-toggle {
        display: none;
        width: 48px; height: 48px; padding: 0;
        border-radius: 999px;
        border: 1px solid var(--mdp-border, rgba(255, 255, 255, 0.284));
        background: var(--mdp-bg, linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1)));
        color: var(--mdp-text, #fff);
        cursor: pointer;
        align-items: center;
        justify-content: center;
        transition: border-color 0.25s ease;
    }
    .dph-nav-toggle:hover { border-color: var(--mdp-border-hover, rgba(255, 255, 255, 0.45)); }
    .dph-nav-toggle svg { width: 18px; height: 18px; }

    @media (max-width: 760px) {
        .dph-nav {
            position: fixed;
            top: calc(var(--site-header-bar-h) + env(safe-area-inset-top, 0px));
            left: 12px; right: 12px;
            flex-direction: column;
            align-items: stretch;
            padding: 10px;
            border-radius: 18px;
            display: none;
        }
        .dph-nav.is-open { display: flex; }
        .dph-nav-toggle { display: inline-flex; }
        .dph-dark  .dph-nav { background: rgba(12, 2, 32, 0.95); border: 1px solid rgba(255, 255, 255, 0.1); }
        .dph-light .dph-nav { background: rgba(255, 255, 255, 0.96); border: 1px solid rgba(11, 11, 15, 0.1); box-shadow: 0 18px 48px rgba(11, 11, 15, 0.12); }
    }

    /* ── Two labels, one link ─────────────────────────────────────
       A nav item may ship a shortLabel beside its label: the full words
       for the bar at desktop width, one word for a phone. Both spans are
       in the DOM and CSS picks, which is the only version of this that
       survives a server-rendered page — there is no viewport at render
       time to choose from. Only one is ever displayed, so nothing
       measures or reads both.

       dph-nav-mobile-only is for an item that exists ONLY once the links
       go inline: the homepage's 'app', which is the same /download link
       its GET button is and only appears where that button doesn't. */
    .dph-nav-short { display: none; }
    .dph-nav-mobile-only { display: none; }

    /* ── Inline nav on phones ─────────────────────────────────────
       navInline: true. The sheet above exists because several multi-word
       links cannot sit in a 360px bar. Two or three short words can, and
       a hamburger that hides two words costs a tap to reveal what would
       have fit. So the links stay in the bar, drop to their shortLabel,
       and the toggle never renders.

       Every property the sheet set is unset here rather than overridden
       selectively — same specificity, later in the file — so the nav is
       a plain flex row again and not a positioned card wearing row
       styles. */
    @media (max-width: 760px) {
        .dph-nav-inline .dph-nav {
            position: static;
            top: auto; left: auto; right: auto;
            display: flex;
            flex-direction: row;
            align-items: center;
            gap: 2px;
            padding: 0;
            border: 0;
            border-radius: 0;
            background: none;
            box-shadow: none;
        }
        .dph-nav-inline .dph-nav-toggle { display: none; }
        .dph-nav-inline .dph-nav a { padding: 8px 8px; font-size: 0.76rem; }
        .dph-nav-inline .dph-nav .dph-nav-full { display: none; }
        .dph-nav-inline .dph-nav .dph-nav-short { display: inline; }
        .dph-nav-inline .dph-nav .dph-nav-mobile-only { display: inline-block; }
    }
    /* Small phones: the words stay, the air between them goes. Four
       labels and a signed-in avatar do not fit a 320px bar at any type
       size that is still readable, so the row is allowed to shrink past
       its content and scroll — which is what the tab strip above does,
       for the same reason.

       The alternative was letting the nav push the document wider than
       the viewport, and a homepage that scrolls sideways is a worse
       failure than a link you have to swipe to. min-width: 0 is the
       load-bearing half: a flex item refuses to shrink below its content
       without it, so overflow-x alone would have done nothing. */
    @media (max-width: 640px) {
        .dph-nav-inline .dph-nav {
            min-width: 0;
            flex: 0 1 auto;
            overflow-x: auto;
            overscroll-behavior-x: contain;
            -webkit-overflow-scrolling: touch;
            scrollbar-width: none;
        }
        .dph-nav-inline .dph-nav::-webkit-scrollbar { display: none; }
        .dph-nav-inline .dph-nav a { flex: 0 0 auto; padding: 8px 6px; font-size: 0.72rem; }
    }

    /* ── Right cluster ────────────────────────────────────────────── */
    .dph-actions {
        display: inline-flex;
        align-items: center;
        gap: 12px;
        flex: 0 0 auto;
        position: relative;
    }

    /* ── CTA ──────────────────────────────────────────────────────
       Height pinned to 48px, the badge's outer pill (34px avatar + 6px
       padding x2 + 1px border x2). Pinned rather than left to padding so
       the two stay on one line whatever the badge's avatar or point
       count does. */
    .dph-cta {
        position: relative;
        display: inline-flex;
        align-items: center;
        gap: 8px;
        height: 48px;
        padding: 0 20px;
        border-radius: 999px;
        font-family: var(--mdp-font-body, 'Inter', system-ui, sans-serif);
        font-weight: 800;
        font-size: 0.84rem;
        letter-spacing: 0.04em;
        text-decoration: none;
        white-space: nowrap;
        box-sizing: border-box;
        transition: transform 0.16s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.16s ease, border-color 0.2s ease, background 0.2s ease;
    }
    .dph-cta:hover { transform: translateY(-1px); }
    .dph-cta svg { flex: none; }

    .dph-cta-primary {
        border: 1px solid rgba(119, 0, 255, 0.5);
        background: linear-gradient(180deg, rgba(255,255,255,0.18) 0%, transparent 48%),
                    linear-gradient(135deg, #7700ff 0%, #9d4edd 55%, #c77dff 100%);
        color: #fff;
        box-shadow: 0 8px 24px rgba(119, 0, 255, 0.30), inset 0 1px 0 rgba(255,255,255,0.28);
    }
    .dph-cta-primary:hover { box-shadow: 0 12px 30px rgba(119, 0, 255, 0.42), inset 0 1px 0 rgba(255,255,255,0.34); }

    .dph-cta-gold {
        border: 1px solid rgba(255, 209, 102, 0.65);
        background: rgba(255, 209, 102, 0.12);
        color: #fff;
        text-transform: uppercase;
    }
    .dph-cta-gold:hover { background: rgba(255, 209, 102, 0.2); }

    .dph-cta-discord {
        border: 1px solid rgba(88, 101, 242, 0.75);
        background: linear-gradient(180deg, rgba(255,255,255,0.16) 0%, transparent 48%),
                    linear-gradient(135deg, #5865F2 0%, #7289DA 100%);
        color: #fff;
        box-shadow: 0 8px 24px rgba(88, 101, 242, 0.32), inset 0 1px 0 rgba(255,255,255,0.28);
    }
    .dph-cta-discord:hover { box-shadow: 0 12px 30px rgba(88, 101, 242, 0.45), inset 0 1px 0 rgba(255,255,255,0.34); }

    /* Inherits the badge's own tokens, so it flips with the theme for
       free instead of needing a light and a dark rule. */
    .dph-cta-ghost {
        border: 1px solid var(--mdp-border, rgba(255, 255, 255, 0.284));
        background: var(--mdp-bg, linear-gradient(to bottom, rgba(255,255,255,0), rgba(255,255,255,0.1)));
        color: var(--mdp-text, #fff);
        backdrop-filter: blur(10px);
        -webkit-backdrop-filter: blur(10px);
    }
    .dph-cta-ghost:hover { border-color: var(--mdp-border-hover, rgba(255, 255, 255, 0.45)); }

    /* ── Discord ghost ────────────────────────────────────────────
       The ghost button, wearing Discord's filled blurple on hover.
       Add it ALONGSIDE .dph-cta-ghost, never instead of it: the resting
       state is the plain glass pill, and the brand fill (same as
       .dph-cta-discord: white text/icon on the blurple gradient) only
       arrives under the cursor.

       It lives here, not on a page, because two surfaces use it —
       /download's header CTA and the homepage grid break — and the first
       version had it written inline in views/download.ejs scoped to
       `body.dl-light`. That made the two buttons identical at rest and
       different on hover, which is a worse outcome than them simply
       looking unrelated. One class, one place, both surfaces. */
    .dph-cta-discord-ghost:hover {
        border: 1px solid rgba(88, 101, 242, 0.75);
        background: linear-gradient(180deg, rgba(255,255,255,0.16) 0%, transparent 48%),
                    linear-gradient(135deg, #5865F2 0%, #7289DA 100%);
        color: #fff;
    }
    .dph-cta-discord-ghost:hover svg {
        color: #fff;
        fill: #fff;
    }

    /* ── Tab strip ────────────────────────────────────────────────
       Fixed 46px so --site-header-tabs-h is exact. Links are centred in
       the strip rather than padded into it, which is what makes the
       published height trustworthy. */
    .dph-tabs { border-top: 1px solid rgba(255, 255, 255, 0.08); }
    .dph-light .dph-tabs { border-top-color: rgba(11, 11, 15, 0.08); }
    .dph-tabs-inner {
        max-width: var(--site-header-max-w, none);
        margin: 0 auto;
        padding: 0 24px;
        height: var(--site-header-tabs-h);
        display: flex;
        align-items: stretch;
        gap: 4px;
        /* More tabs than a phone is wide: scroll the STRIP, never the
           page. */
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        scrollbar-width: none;
        box-sizing: border-box;
    }
    .dph-tabs-inner::-webkit-scrollbar { display: none; }
    .dph-tab {
        position: relative;
        flex: 0 0 auto;
        display: inline-flex;
        align-items: center;
        padding: 0 14px;
        font-family: var(--mdp-font-body, 'Inter', system-ui, sans-serif);
        font-size: 0.9rem;
        font-weight: 500;
        line-height: 1;
        text-decoration: none;
        white-space: nowrap;
        transition: color 0.15s ease;
    }
    .dph-dark  .dph-tab { color: rgba(255, 255, 255, 0.68); }
    .dph-dark  .dph-tab:hover { color: #fff; }
    .dph-light .dph-tab { color: rgba(21, 10, 36, 0.6); }
    .dph-light .dph-tab:hover { color: #150a24; }
    .dph-tab.is-active { color: var(--site-header-tab-active, #fff); }
    .dph-light .dph-tab.is-active { color: var(--site-header-tab-active, #150a24); }
    .dph-tab.is-active::after {
        content: '';
        position: absolute;
        left: 10px; right: 10px; bottom: 0;
        height: 2px;
        border-radius: 2px 2px 0 0;
        background: var(--site-header-tab-active, currentColor);
    }

    @media (max-width: 720px) {
        .dph-bar { padding-left: 16px; padding-right: 16px; }
        .dph-tabs-inner { padding: 0 16px; }
        .dph-cta { padding: 0 14px; }
        /* Keep the mark, drop the word — the badge must never be
           squeezed to make room for a CTA label. A CTA with no icon has
           nothing left to show, so it keeps its label. */
        .dph-cta-has-icon .dph-cta-label { display: none; }
    }
    /* The badge goes to its avatar circle on small screens, which is
       what .header-profile-trigger did on the old public header. Doing
       it here means every surface gets it, and the CTA beside it keeps
       its 48px partner rather than being crowded. */
    @media (max-width: 768px) {
        .dph-actions .mdp-badge { padding: 6px; gap: 0; }
        .dph-actions .mdp-meta { display: none; }
    }

    @media (max-width: 480px) {
        .dph-bar { gap: 10px; }
        .dph-actions { gap: 10px; }
        .dph-center { padding: 0 6px; }
        .dph-title { max-width: min(42vw, 220px); font-size: 0.86rem; }
        .dph-surface { font-size: 10px; letter-spacing: 0.1em; }
    }

/* ── Public marketing header (dp-header) ──
   Homepage chrome, reused wherever publicNav is on. Tokens live on
   .dp-header itself so they work without a .dp-dark/.dp-light body
   class (the portals do not have those). Homepage still defines the
   same tokens under .dp-light/.dp-dark in dp-home.css; identical
   values, so loading both is a no-op rather than a fight. */

.dp-header {
    --dp-violet: #7700ff;
    --dp-violet-2: #9d4edd;
    --dp-violet-3: #c77dff;
    --dp-violet-fill:
        linear-gradient(180deg, rgba(255, 255, 255, .24) 0%, transparent 46%),
        linear-gradient(135deg, var(--dp-violet) 0%, var(--dp-violet-2) 55%, var(--dp-violet-3) 115%);
    --dp-violet-edge: rgba(199, 125, 255, .55);
    --dp-ease: cubic-bezier(.16, 1, .3, 1);
}

/* Public marketing header: frosted glass over whatever the page is.
   Dark pages stay dark, light pages stay light. Not a purple slab.
   Admin and other .dph surfaces keep their own --site-header-bg. */
.dp-header.dph-dark {
    --site-header-bg: rgba(0, 0, 0, 0.18);
    --site-header-blur: blur(18px) saturate(160%);
}
.dp-header.dph-light {
    --site-header-bg: rgba(255, 255, 255, 0.32);
    --site-header-blur: blur(18px) saturate(160%);
}

/* Download still passes transparent:true (the old hero-scrim). On the
   public bar that must not reintroduce a purple gradient or a
   solidify-to-purple scroll state. Glass is the bar, always. */
.dp-header.dph-transparent,
.dp-header.dph-transparent.dph-dark,
.dp-header.dph-transparent.dph-light,
.dp-header.dph-transparent.is-scrolled,
.dp-header.dph-transparent.dph-dark.is-scrolled,
.dp-header.dph-transparent.dph-light.is-scrolled {
    background: var(--site-header-bg);
    backdrop-filter: var(--site-header-blur);
    -webkit-backdrop-filter: var(--site-header-blur);
}

/* Bigger wordmark; swap to the icon mark at 900px (not the partial's 640)
   because this bar also carries the public nav + GET + badge. */
.dp-header .dph-mark-text { height: clamp(24px, 2.4vw, 34px); }

@media (min-width: 901px) {
    .dp-header .dph-bar { position: relative; }
    .dp-header .dph-nav {
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        margin: 0;
    }
}

@media (max-width: 900px) {
    .dp-header .dph-brand-responsive .dph-mark-text { display: none; }
    .dp-header .dph-brand-responsive .dph-mark-icon { display: block; height: 30px; }
}

/* GET pill. Same object as the homepage header CTA. */
.dp-cta {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    height: 44px;
    padding: 0 26px;
    border: 1px solid var(--dp-violet-edge, rgba(199, 125, 255, .55));
    border-radius: 999px;
    cursor: pointer;
    text-decoration: none;
    color: #fff;
    font-family: var(--mdp-ui-heading, 'Outfit', system-ui, sans-serif);
    font-size: 13px;
    font-weight: 800;
    line-height: 1;
    letter-spacing: .05em;
    text-transform: uppercase;
    white-space: nowrap;
    isolation: isolate;
    overflow: hidden;
    background: var(--dp-violet-fill, linear-gradient(135deg, #7700ff 0%, #9d4edd 55%, #c77dff 115%));
    box-shadow:
        0 10px 32px rgba(119, 0, 255, .38),
        inset 0 1px 0 rgba(255, 255, 255, .35);
    animation: dpBreathe 2.8s ease-in-out infinite;
    transition: transform .18s var(--dp-ease, cubic-bezier(.16, 1, .3, 1)), box-shadow .18s ease, filter .18s ease;
}
.dp-cta::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(105deg, transparent 38%, rgba(255, 255, 255, .55) 50%, transparent 62%);
    transform: translateX(-120%);
    animation: dpGlisten 4.4s ease-in-out infinite;
    pointer-events: none;
}
.dp-cta:hover {
    transform: translateY(-2px) scale(1.02);
    filter: brightness(1.08);
    box-shadow: 0 16px 44px rgba(119, 0, 255, .5), 0 0 26px rgba(199, 125, 255, .38),
                inset 0 1px 0 rgba(255, 255, 255, .45);
}
.dp-cta:active { transform: translateY(0) scale(.975); }
.dp-cta:focus-visible { outline: 3px solid var(--dp-violet, #7700ff); outline-offset: 3px; }

.dph-dark .dp-cta {
    box-shadow:
        0 12px 40px rgba(119, 0, 255, .55),
        0 0 22px rgba(199, 125, 255, .28),
        inset 0 1px 0 rgba(255, 255, 255, .35);
}
.dph-dark .dp-cta:hover {
    box-shadow:
        0 18px 52px rgba(119, 0, 255, .65),
        0 0 34px rgba(199, 125, 255, .45),
        inset 0 1px 0 rgba(255, 255, 255, .45);
}
.dph-dark .dp-cta:focus-visible { outline-color: var(--dp-violet-3, #c77dff); }

@media (max-width: 760px) {
    .dp-header .dp-cta { display: none; }
}

@keyframes dpBreathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.022); } }
@keyframes dpGlisten { 0%, 62% { transform: translateX(-120%); } 86%, 100% { transform: translateX(120%); } }

@media (prefers-reduced-motion: reduce) {
    .dp-cta, .dp-cta::after { animation: none; }
    .dp-cta { transition: none; }
}
