/* ═══════════════════════════════════════════════════════════════════════
   The host's own furniture for the Kage landing page.

   The authored document is served byte-for-byte inside the frame and owns
   everything inside it. This stylesheet only dresses what the host adds: the
   Zora dock that keeps the dashboard's entry point on a page whose authored
   calls to action all point at Kage's own chapters, and the live stats strip
   that rides inside it.

   It is dressed in the page's own material — the night glass and hairline the
   authored navigation uses (rgba(5,7,10,.62) over a 14px blur, .13 alpha bone
   rules) — so it reads as part of the sanctuary rather than a banner bolted
   onto it. Grep for `--zora-` to retune it in one place.
   ═══════════════════════════════════════════════════════════════════════ */

.zora-dock {
    --zora-ink: 5, 7, 10;
    --zora-bone: #dfe7e0;
    --zora-bone-dim: #aab4ad;
    --zora-line: rgba(223, 231, 224, 0.13);
    --zora-vermilion: #e0231c;
    --zora-pad: clamp(20px, 3.4vw, 56px);

    position: fixed;
    left: 50%;
    /* The home indicator sits below the dock on an iPhone: the authored offset
       plus whatever the safe area reserves, so nothing is parked under the bar.
       The offset is measured in % of the viewport, not in vw, because iOS's vw
       ignores the safe-area insets entirely — that is what let the pill run
       under the notch in landscape. */
    bottom: calc(clamp(18px, 3.2vh, 34px) + env(safe-area-inset-bottom, 0px));
    z-index: 200;
    display: flex;
    align-items: center;
    gap: 10px;
    max-width: calc(100% - 24px);
    padding: 8px 10px 8px 12px;
    border: 1px solid var(--zora-line);
    border-radius: 999px;
    background: rgba(var(--zora-ink), 0.62);
    box-shadow: 0 18px 44px -22px rgba(0, 0, 0, 0.9);
    color: var(--zora-bone);
    /* the dashboard's own stack, so the dock is the same voice as the pages it
       leads into rather than the authored page's Onest */
    font-family: Inter, 'Public Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
    font-size: 13px;
    font-weight: 300;
    line-height: 1;
    transform: translateX(-50%);

    /* Only the reveal is animated. The centring transform is not in this list
       on purpose: the dock moves to the full gutter below 820px, and a
       transition there would slide it across the screen every time the frame
       is resized or a phone is turned. */
    transition: opacity 0.6s cubic-bezier(0.16, 1, 0.3, 1);

    /* The authored page opens on its own preloader, so the host's furniture
       waits for the frame to report ready before it appears over the scene.
       The frame script marks data-state, and its 4s safety net covers a frame
       that never loads. */
    opacity: 0;
    pointer-events: none;
    -webkit-backdrop-filter: blur(14px) saturate(1.1);
    backdrop-filter: blur(14px) saturate(1.1);
}

/* The authored page holds its own preloader up until the sanctuary is built, so
   the dock is revealed by the authored page's ready signal — not by the frame's
   load event, which fires while that preloader is still on screen. */
.landing-page-frame[data-threeui-world='ready'] ~ .zora-dock {
    opacity: 1;
    pointer-events: auto;
}

/* ── the mark ─────────────────────────────────────────────────────────────
   The dashboard's own Z, and the name it belongs to. */
.zora-dock__brand {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    color: var(--zora-bone);
    text-decoration: none;
}

.zora-dock__brand img {
    display: block;
    width: 26px;
    height: 26px;
    border-radius: 50%;
}

.zora-dock__word {
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -0.01em;
}

.zora-dock__rule {
    width: 1px;
    height: 20px;
    background: var(--zora-line);
}

/* ── the two destinations ─────────────────────────────────────────────────
   Login is the page's only way into the dashboard, so it carries the accent
   the authored page itself is built on. Adding the bot is the growth action;
   it stays a hairline outline so the dock keeps one focal point. */
.zora-dock__cta,
.zora-dock__ghost {
    display: inline-flex;
    align-items: center;
    height: 30px;
    padding: 0 14px;
    border-radius: 999px;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0.01em;
    text-decoration: none;
    white-space: nowrap;
    transition: background 0.28s ease, border-color 0.28s ease, color 0.28s ease;
}

.zora-dock__cta {
    color: #fff;
    background: var(--zora-vermilion);
}

.zora-dock__cta:hover {
    background: #ff5a3c;
}

.zora-dock__ghost {
    border: 1px solid var(--zora-line);
    color: var(--zora-bone-dim);
}

.zora-dock__ghost:hover {
    border-color: rgba(223, 231, 224, 0.3);
    color: var(--zora-bone);
}

/* ── the collapse ─────────────────────────────────────────────────────────
   A visitor who wants the authored page and nothing else can put the dock
   away. It collapses to the mark rather than disappearing, so the way back
   into the dashboard is never more than one click away. */
.zora-dock__toggle {
    display: inline-grid;
    place-items: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: 50%;
    color: var(--zora-bone-dim);
    background: transparent;
    font: inherit;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    transition: background 0.28s ease, color 0.28s ease;
}

.zora-dock__toggle:hover {
    color: var(--zora-bone);
    background: rgba(223, 231, 224, 0.08);
}

.zora-dock__toggle img {
    display: block;
    width: 24px;
    height: 24px;
    border-radius: 50%;
}

.zora-dock__show {
    display: none;
}

.zora-dock[data-open='0'] {
    gap: 0;
    padding: 6px;
}

.zora-dock[data-open='0'] .zora-dock__brand,
.zora-dock[data-open='0'] .zora-dock__rule,
.zora-dock[data-open='0'] .zora-stats,
.zora-dock[data-open='0'] .zora-dock__cta,
.zora-dock[data-open='0'] .zora-dock__ghost,
.zora-dock[data-open='0'] .zora-dock__hide {
    display: none;
}

.zora-dock[data-open='0'] .zora-dock__show {
    display: block;
}

.zora-dock[data-open='0'] .zora-dock__toggle {
    width: 34px;
    height: 34px;
}

/* ── the live stats strip ─────────────────────────────────────────────────
   Servers, members and gateway latency, read from the dashboard's own
   /api/stats. It rides inside the dock so it inherits the reveal, the glass,
   the pointer behaviour and the collapse for free; the script keeps it
   [hidden] until the first successful read, so the authored page is unchanged
   when the bot is down or the endpoint fails. */
.zora-stats {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    height: 30px;
    padding: 0 11px;
    border: 1px solid var(--zora-line);
    border-radius: 999px;
    color: var(--zora-bone-dim);
    font-size: 11px;
    letter-spacing: 0.01em;
    line-height: 1;
    white-space: nowrap;
}

.zora-stats[hidden] {
    display: none;
}

.zora-stats__item {
    display: inline-flex;
    align-items: baseline;
    gap: 5px;
}

.zora-stats__k {
    opacity: 0.62;
}

.zora-stats__v {
    color: var(--zora-bone);
    font-weight: 500;
    font-variant-numeric: tabular-nums;
}

.zora-stats__sep {
    width: 1px;
    height: 14px;
    background: var(--zora-line);
}

/* The client's own "I am up" light. The title on it carries the uptime, so the
   strip stays three numbers wide however long the bot has been running. */
.zora-stats__live {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: #57d38c;
    box-shadow: 0 0 0 3px rgba(87, 211, 140, 0.16);
    animation: zora-live-pulse 2.4s ease-in-out infinite;
}

@keyframes zora-live-pulse {
    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.4;
    }
}

/* ── narrow screens ───────────────────────────────────────────────────────
   Below 820px the authored page drops its own preview window, chapter rail and
   vertical caption, so the foot of the frame is free across its whole width
   and the dock takes the full gutter instead of the centre. The nameplate and
   the support link go: the pill has to stay a pill on a 390px screen. */
@media (max-width: 820px) {
    .zora-dock {
        right: 12px;
        left: 12px;
        bottom: 12px;
        flex-wrap: wrap;
        justify-content: center;
        transform: none;
    }

    .zora-dock__word,
    .zora-dock__ghost--support {
        display: none;
    }

    /* The strip takes the pill's first line so the three numbers read before
       the buttons; it is inside the glass already, so its own shell goes. It is
       allowed to wrap, because a bot can be in enough servers that the totals
       run the full width of a small phone. */
    .zora-stats {
        order: -1;
        flex-basis: 100%;
        flex-wrap: wrap;
        justify-content: center;
        height: auto;
        padding: 0;
        border: 0;
        white-space: normal;
    }
}

@media (prefers-reduced-motion: reduce) {
    .zora-dock {
        transition: none;
    }

    .zora-stats__live {
        animation: none;
    }
}
