:root {
    --bg-color: #fafafa;
    --nav-bg: rgba(250, 250, 250, 0.85);
    --nav-border: rgba(228, 228, 231, 0.6);
    --grad-1: rgba(79, 70, 229, 0.04);
    --grad-2: rgba(79, 70, 229, 0.02);
}

html.dark {
    --bg-color: #09090b;
    --nav-bg: rgba(9, 9, 11, 0.85);
    --nav-border: rgba(63, 63, 70, 0.6);
    --grad-1: rgba(99, 102, 241, 0.10);
    --grad-2: rgba(99, 102, 241, 0.05);
    color-scheme: dark;
}

/* ---------------------------------------------------------------------------
   Reserve the vertical scrollbar's gutter at all times.

   Pages whose content height crosses the viewport boundary (switching between
   servers on account.html, filtering the catalog, opening a modal) otherwise
   toggle the page scrollbar on/off. With a classic, space-consuming scrollbar
   (Windows/Linux, and macOS when "always show scrollbars" is set) that toggle
   changes the layout-viewport WIDTH by the scrollbar's thickness, which shifts
   every `mx-auto`-centred container sideways by ~half that — the visible
   horizontal "jitter" when the detail panel re-renders. Reserving the gutter
   keeps the width constant whether or not a scrollbar is drawn → zero shift.
   Also removes the classic "content jumps right when a modal opens" shift,
   since body.modal-open sets overflow:hidden. No-op where the UA uses overlay
   scrollbars (macOS default), which never reflow the page — so no regression.
   --------------------------------------------------------------------------- */
html {
    scrollbar-gutter: stable;
}

body {
    background-color: var(--bg-color);
    background-image:
        radial-gradient(at 100% 0%, var(--grad-1) 0px, transparent 50%),
        radial-gradient(at 0% 100%, var(--grad-2) 0px, transparent 50%);
    background-attachment: fixed;
    -webkit-font-smoothing: antialiased;
}

.glass-nav {
    background: var(--nav-bg);
    backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--nav-border);
}

.search-glow {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 100%;
    height: 100%;
    background: linear-gradient(90deg, rgba(79, 70, 229, 0.1) 0%, rgba(147, 51, 234, 0.05) 100%);
    filter: blur(40px);
    z-index: -1;
    border-radius: 9999px;
    opacity: 0;
    transition: opacity 0.4s ease;
}

.search-container:focus-within .search-glow { opacity: 1; }

.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }

/* ---- Horizontal chip-scroll fade affordance --------------------------
   The category-filter rows (#filter-chips on catalog.html and
   #hero-filter-chips on index.html) are `overflow-x-auto no-scrollbar`
   flex rows. Once the chips are wider than the container (e.g. after a
   new category like "Бесплатно" is added) the trailing chip is hard-
   clipped at the container edge — it looks chopped mid-word behind the
   page background rather than "scrollable". This helper softens the
   clip into a fade so it reads as "scroll for more", and adds trailing
   inline padding so the last chip isn't flush against the cut.

   Theme-agnostic: a mask fades to transparent, so it works identically
   in light and dark. Where the mask is unsupported the row simply
   scrolls as before (no regression).                                   */
.chip-scroll {
    /* room so the final chip can scroll fully past the right fade */
    padding-right: 1.5rem;
    -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent 100%);
            mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent 100%);
}

/* When the row is scrolled, also fade the left edge symmetrically and
   pull the right fade back as the end comes into view. Driven purely by
   scroll position — no JS. Falls back to the static right fade above
   where scroll-driven animations aren't supported. */
@supports (animation-timeline: scroll()) {
    .chip-scroll {
        animation: chip-scroll-fade linear;
        animation-timeline: scroll(self inline);
    }
    @keyframes chip-scroll-fade {
        0% {
            -webkit-mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent 100%);
                    mask-image: linear-gradient(to right, #000 calc(100% - 2rem), transparent 100%);
        }
        1%, 99% {
            -webkit-mask-image: linear-gradient(to right, transparent 0, #000 2rem, #000 calc(100% - 2rem), transparent 100%);
                    mask-image: linear-gradient(to right, transparent 0, #000 2rem, #000 calc(100% - 2rem), transparent 100%);
        }
        100% {
            -webkit-mask-image: linear-gradient(to right, transparent 0, #000 2rem);
                    mask-image: linear-gradient(to right, transparent 0, #000 2rem);
        }
    }
}

.card-disabled { filter: grayscale(0.6); opacity: 0.7; }

@keyframes scrollMarquee {
    0%   { transform: translate3d(0, 0, 0); }
    100% { transform: translate3d(calc(-100% / var(--marquee-copies, 2)), 0, 0); }
}

.animate-marquee {
    animation: scrollMarquee var(--marquee-duration, 30s) linear infinite;
    will-change: transform;
}

.animate-marquee:hover { animation-play-state: paused; }

[data-i18n],
[data-i18n-placeholder] { transition: opacity 180ms ease; }

.lang-switching [data-i18n],
.lang-switching [data-i18n-placeholder] { opacity: 0; }

@view-transition {
    navigation: auto;
}

::view-transition-old(root),
::view-transition-new(root) {
    animation-duration: 320ms;
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

::view-transition-group(app-nav),
::view-transition-group(app-footer) {
    animation-duration: 320ms;
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
}

.glass-nav { view-transition-name: app-nav; }
.site-footer { view-transition-name: app-footer; }

.theme-toggle .ph-sun { display: none; }
html.dark .theme-toggle .ph-sun { display: inline-block; }
html.dark .theme-toggle .ph-moon { display: none; }

.hero-shell {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.aurora {
    position: absolute;
    inset: -10% -10% -10% -10%;
    pointer-events: none;
    z-index: -1;
}

.aurora-blob {
    position: absolute;
    border-radius: 50%;
    filter: blur(80px);
    opacity: 0.55;
    mix-blend-mode: multiply;
    will-change: transform;
}

html.dark .aurora-blob {
    mix-blend-mode: screen;
    opacity: 0.40;
    filter: blur(90px);
}

.aurora-blob-1 {
    width: 520px; height: 520px;
    background: radial-gradient(circle, #818cf8 0%, transparent 70%);
    top: -120px; left: -80px;
    animation: floatBlob1 24s ease-in-out infinite;
}

.aurora-blob-2 {
    width: 460px; height: 460px;
    background: radial-gradient(circle, #c084fc 0%, transparent 70%);
    top: 40px; right: -120px;
    animation: floatBlob2 28s ease-in-out infinite;
}

.aurora-blob-3 {
    width: 380px; height: 380px;
    background: radial-gradient(circle, #f472b6 0%, transparent 70%);
    bottom: -140px; left: 35%;
    animation: floatBlob3 32s ease-in-out infinite;
}

.aurora-blob-4 {
    width: 360px; height: 360px;
    background: radial-gradient(circle, #38bdf8 0%, transparent 70%);
    bottom: -60px; right: 25%;
    animation: floatBlob4 26s ease-in-out infinite;
}

@keyframes floatBlob1 {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
    50%      { transform: translate3d(140px, 90px, 0) scale(1.1); }
}

@keyframes floatBlob2 {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
    50%      { transform: translate3d(-120px, 100px, 0) scale(0.95); }
}

@keyframes floatBlob3 {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
    50%      { transform: translate3d(100px, -130px, 0) scale(1.08); }
}

@keyframes floatBlob4 {
    0%, 100% { transform: translate3d(0, 0, 0) scale(1); }
    50%      { transform: translate3d(-90px, -80px, 0) scale(1.05); }
}

.hero-gradient-text {
    background: linear-gradient(90deg, #4f46e5 0%, #a855f7 20%, #ec4899 40%, #f59e0b 60%, #6366f1 80%, #4f46e5 100%);
    background-size: 200% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    animation: gradientShift 15s linear infinite;
}

html.dark .hero-gradient-text {
    background: linear-gradient(90deg, #818cf8 0%, #c084fc 20%, #f472b6 40%, #fbbf24 60%, #93c5fd 80%, #818cf8 100%);
    background-size: 200% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    animation: gradientShift 15s linear infinite;
}

@keyframes gradientShift {
    0%   { background-position: 0% 50%; }
    100% { background-position: -200% 50%; }
}

.logo-glow {
    position: relative;
}

.logo-glow::after {
    content: '';
    position: absolute;
    inset: -4px;
    border-radius: inherit;
    background: radial-gradient(circle, rgba(99, 102, 241, 0.5) 0%, transparent 70%);
    opacity: 0;
    animation: logoPulse 3.5s ease-in-out infinite;
    z-index: -1;
}

@keyframes logoPulse {
    0%, 100% { opacity: 0.3; transform: scale(1); }
    50%      { opacity: 0.7; transform: scale(1.25); }
}

.filter-chip[data-active="true"] {
    background-color: rgb(24 24 27);
    color: #fff;
    border-color: rgb(24 24 27);
}

html.dark .filter-chip[data-active="true"] {
    background-color: rgb(250 250 250);
    color: rgb(24 24 27);
    border-color: rgb(250 250 250);
}

/* === "Free" badge on catalog cards =========================
   Emerald accent (same tone as the devtools cards and the
   submit success panel). The badge is injected by catalog.js
   AFTER the Tailwind Play CDN's first DOM scan, so dynamic
   `dark:` emerald utilities can be missing during the brief
   regenerate window — same hazard as .copy-btn above. We pin
   the colours here so the badge renders correctly in both
   themes regardless of CDN timing. */
.free-badge {
    background-color: rgb(236 253 245);  /* emerald-50  */
    color: rgb(4 120 87);                /* emerald-700 */
}

html.dark .free-badge {
    background-color: rgba(2 44 34 / 0.4); /* emerald-950/40 */
    color: rgb(110 231 183);               /* emerald-300    */
}

/* === Copy button (catalog detail /catalog/<id>) ============
   The button markup is injected by server.js *after* the
   Tailwind Play CDN has done its first DOM scan, so its
   `text-white` / `dark:` utilities can be missing during the
   brief window before the CDN regenerates them — leaving the
   label the inherited body colour (dark) on a dark zinc-900
   pill, i.e. invisible in light theme. This rule pins the
   colours deterministically with the same inverted-button
   tokens as .filter-chip (dark-on-light in light theme,
   light-on-dark in dark theme), so contrast is correct
   regardless of CDN timing. */
.copy-btn {
    background-color: rgb(24 24 27);   /* zinc-900 */
    color: #fff;
}

.copy-btn:hover {
    background-color: rgb(39 39 42);   /* zinc-800 */
}

html.dark .copy-btn {
    background-color: rgb(250 250 250); /* zinc-50 */
    color: rgb(24 24 27);               /* zinc-900 */
}

html.dark .copy-btn:hover {
    background-color: rgb(228 228 231); /* zinc-200 */
}

/* Copied confirmation — emerald in both themes, always white text. */
.copy-btn.is-copied,
.copy-btn.is-copied:hover,
html.dark .copy-btn.is-copied,
html.dark .copy-btn.is-copied:hover {
    background-color: rgb(5 150 105);  /* emerald-600 */
    color: #fff;
}

html.dark .copy-btn.is-copied,
html.dark .copy-btn.is-copied:hover {
    background-color: rgb(16 185 129); /* emerald-500 */
}

.card-hidden { display: none !important; }

.catalog-grid {
    display: grid;
    grid-template-columns: repeat(1, minmax(0, 1fr));
    gap: 1.5rem;
}

@media (min-width: 768px) {
    .catalog-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 1024px) {
    .catalog-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* Catalog card description: clamp to a fixed 2 lines so the body block above
   the footer has a consistent height. Combined with the flex-column card
   (.catalog-grid stretches every cell in a row to equal height, the card is
   flex-col h-full, the content is flex-1, the footer is mt-auto), this keeps
   the "Add" button on the same horizontal line across a row regardless of how
   long each server's tagline is. Pinned in CSS rather than relying on the
   Tailwind line-clamp utility because the Tailwind Play CDN can mis-apply
   utilities to JS-injected nodes (same rationale as .free-badge above). */
.catalog-card-desc {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

.submit-card {
    background-image: linear-gradient(135deg, rgba(99, 102, 241, 0.04) 0%, rgba(168, 85, 247, 0.04) 100%);
}

html.dark .submit-card {
    background-image: linear-gradient(135deg, rgba(99, 102, 241, 0.08) 0%, rgba(168, 85, 247, 0.08) 100%);
}

.docs-shell {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    gap: 2.5rem;
}

@media (min-width: 1024px) {
    .docs-shell {
        grid-template-columns: minmax(0, 1fr) 240px;
        gap: 4rem;
    }
}

.docs-toc {
    align-self: start;
    order: -1;
}

@media (min-width: 1024px) {
    .docs-toc {
        order: initial;
        position: sticky;
        top: 5rem;
        max-height: calc(100vh - 6rem);
        overflow-y: auto;
    }
}

.docs-toc a {
    border-left: 2px solid transparent;
    padding-left: 0.75rem;
    margin-left: -0.75rem;
    transition: color 200ms ease, border-color 200ms ease;
}

.docs-toc a.toc-active {
    color: rgb(79 70 229);
    font-weight: 600;
    border-left-color: rgb(79 70 229);
}

html.dark .docs-toc a.toc-active {
    color: rgb(129 140 248);
    border-left-color: rgb(129 140 248);
}

.docs-content :not(pre) > code {
    background: rgb(244 244 245);
    padding: 0.125rem 0.4rem;
    border-radius: 0.375rem;
    font-size: 0.875em;
    color: rgb(67 56 202);
    font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, monospace;
    white-space: nowrap;
}

html.dark .docs-content :not(pre) > code {
    background: rgb(39 39 42);
    color: rgb(165 180 252);
}

.docs-content pre {
    background: rgb(24 24 27);
    color: rgb(244 244 245);
    border-radius: 0.875rem;
    padding: 1.125rem 1.25rem;
    overflow-x: auto;
    font-size: 0.875rem;
    line-height: 1.65;
    font-family: ui-monospace, "Cascadia Code", "Source Code Pro", Menlo, Consolas, monospace;
}

html.dark .docs-content pre {
    background: rgb(9 9 11);
    border: 1px solid rgb(39 39 42);
}

.docs-content pre code {
    background: transparent;
    padding: 0;
    color: inherit;
    font-size: inherit;
}

.docs-content .json-key   { color: rgb(165 180 252); }
.docs-content .json-str   { color: rgb(134 239 172); }
.docs-content .json-punct { color: rgb(161 161 170); }

.docs-tabs {
    display: flex;
    gap: 0.5rem;
    overflow-x: auto;
    padding-bottom: 0.5rem;
    margin-bottom: 2rem;
    border-bottom: 1px solid rgb(228 228 231);
    scrollbar-width: none;
}
.docs-tabs::-webkit-scrollbar { display: none; }
html.dark .docs-tabs { border-bottom-color: rgb(39 39 42); }

.docs-tab {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    white-space: nowrap;
    padding: 0.55rem 1rem;
    border-radius: 0.75rem;
    font-size: 0.9rem;
    font-weight: 600;
    color: rgb(113 113 122);
    background: transparent;
    border: 1px solid transparent;
    cursor: pointer;
    transition: color 150ms ease, background 150ms ease, border-color 150ms ease;
}
.docs-tab i { font-size: 1.1rem; }
.docs-tab:hover {
    color: rgb(24 24 27);
    background: rgb(244 244 245);
}
.docs-tab.is-active {
    color: rgb(67 56 202);
    background: rgb(238 242 255);
    border-color: rgb(224 231 255);
}
html.dark .docs-tab { color: rgb(161 161 170); }
html.dark .docs-tab:hover {
    color: rgb(244 244 245);
    background: rgb(39 39 42);
}
html.dark .docs-tab.is-active {
    color: rgb(165 180 252);
    background: rgb(49 46 129 / 0.35);
    border-color: rgb(67 56 202 / 0.4);
}

.docs-tabpanel { display: none; }
.docs-tabpanel.is-active {
    display: block;
    animation: docs-tab-fade 200ms ease;
}
@keyframes docs-tab-fade {
    from { opacity: 0; transform: translateY(4px); }
    to   { opacity: 1; transform: translateY(0); }
}

.screenshot-placeholder {
    border: 2px dashed rgb(228 228 231);
    background: rgb(250 250 250);
    border-radius: 0.875rem;
    padding: 3rem 1rem;
    text-align: center;
    color: rgb(113 113 122);
    transition: border-color 200ms ease, background 200ms ease;
}

html.dark .screenshot-placeholder {
    border-color: rgb(63 63 70);
    background: rgb(24 24 27);
    color: rgb(161 161 170);
}

.screenshot-placeholder .icon {
    font-size: 2rem;
    display: block;
    margin: 0 auto 0.5rem;
    color: rgb(161 161 170);
}

html.dark .screenshot-placeholder .icon {
    color: rgb(82 82 91);
}

.auth-modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    opacity: 0;
    visibility: hidden;
    transition: opacity 200ms ease, visibility 0s linear 200ms;
}

.auth-modal.is-open {
    opacity: 1;
    visibility: visible;
    transition: opacity 200ms ease, visibility 0s linear 0s;
}

.auth-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}

html.dark .auth-backdrop {
    background: rgba(0, 0, 0, 0.65);
}

.auth-card {
    transform: translateY(20px) scale(0.96);
    transition: transform 280ms cubic-bezier(0.22, 1, 0.36, 1);
}

.auth-modal.is-open .auth-card {
    transform: translateY(0) scale(1);
}

body.modal-open {
    overflow: hidden;
}

.mcpbay-toasts {
    position: fixed;
    z-index: 200;
    top: 4.5rem;
    right: 1rem;
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    pointer-events: none;
    max-width: calc(100vw - 2rem);
    width: min(420px, calc(100vw - 2rem));
}

.mcpbay-toast {
    display: flex;
    align-items: flex-start;
    gap: 0.625rem;
    padding: 0.75rem 0.875rem;
    border-radius: 0.875rem;
    background: rgba(255, 255, 255, 0.96);
    color: rgb(24 24 27);
    border: 1px solid rgba(228, 228, 231, 0.8);
    box-shadow: 0 12px 28px -16px rgba(15, 23, 42, 0.35), 0 4px 10px -6px rgba(15, 23, 42, 0.15);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    pointer-events: auto;
    opacity: 0;
    transform: translateY(-6px);
    transition: opacity 200ms ease, transform 240ms cubic-bezier(0.22, 1, 0.36, 1);
    font-size: 0.875rem;
    line-height: 1.45;
}

html.dark .mcpbay-toast {
    background: rgba(24, 24, 27, 0.96);
    color: rgb(244 244 245);
    border-color: rgba(63, 63, 70, 0.8);
    box-shadow: 0 12px 28px -16px rgba(0, 0, 0, 0.6), 0 4px 10px -6px rgba(0, 0, 0, 0.4);
}

.mcpbay-toast.is-visible {
    opacity: 1;
    transform: translateY(0);
}

.mcpbay-toast.is-leaving {
    opacity: 0;
    transform: translateY(-6px);
}

.mcpbay-toast__icon {
    flex: none;
    font-size: 1.125rem;
    margin-top: 0.0625rem;
    color: rgb(82 82 91);
}

.mcpbay-toast__msg {
    flex: 1 1 auto;
    min-width: 0;
    word-break: break-word;
}

.mcpbay-toast__close {
    flex: none;
    width: 1.5rem;
    height: 1.5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 9999px;
    color: rgb(161 161 170);
    background: transparent;
    border: 0;
    cursor: pointer;
    transition: color 150ms ease, background 150ms ease;
}

.mcpbay-toast__close:hover {
    color: rgb(24 24 27);
    background: rgba(0, 0, 0, 0.04);
}

html.dark .mcpbay-toast__close:hover {
    color: rgb(244 244 245);
    background: rgba(255, 255, 255, 0.06);
}

.mcpbay-toast--success .mcpbay-toast__icon { color: rgb(16 185 129); }
.mcpbay-toast--error   .mcpbay-toast__icon { color: rgb(239 68 68); }
.mcpbay-toast--info    .mcpbay-toast__icon { color: rgb(99 102 241); }

html.dark .mcpbay-toast--success .mcpbay-toast__icon { color: rgb(52 211 153); }
html.dark .mcpbay-toast--error   .mcpbay-toast__icon { color: rgb(248 113 113); }
html.dark .mcpbay-toast--info    .mcpbay-toast__icon { color: rgb(129 140 248); }

/* === Catalog loading indication =========================
   Drives the homepage and /catalog.html in-flight feedback
   for category/search filters WITHOUT shifting the layout
   (zero CLS). A 2px-tall track is always in the DOM; only
   its child bar animation + opacity changes between idle
   and loading. JS gates this with a 150ms delay so fast
   responses don't flash. The grid itself fades (stale-
   while-revalidate) so old cards stay in place.
*/
.catalog-progress {
    position: relative;
    height: 2px;
    width: 100%;
    overflow: hidden;
    border-radius: 9999px;
    background: transparent;
    transition: background 180ms ease;
}

.catalog-progress.is-loading {
    background: rgba(228, 228, 231, 0.55);
}

html.dark .catalog-progress.is-loading {
    background: rgba(63, 63, 70, 0.45);
}

.catalog-progress__bar {
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    opacity: 0;
    background: linear-gradient(90deg,
        rgba(79, 70, 229, 0) 0%,
        rgba(79, 70, 229, 0.85) 50%,
        rgba(79, 70, 229, 0) 100%
    );
    transition: opacity 180ms ease;
    will-change: transform;
}

html.dark .catalog-progress__bar {
    background: linear-gradient(90deg,
        rgba(129, 140, 248, 0) 0%,
        rgba(129, 140, 248, 0.9) 50%,
        rgba(129, 140, 248, 0) 100%
    );
}

.catalog-progress.is-loading .catalog-progress__bar {
    opacity: 1;
    animation: catalog-progress-slide 1.1s ease-in-out infinite;
}

@keyframes catalog-progress-slide {
    0%   { transform: translateX(-100%); }
    50%  { transform: translateX(0%); }
    100% { transform: translateX(100%); }
}

.catalog-grid-loading {
    opacity: 0.55;
    pointer-events: none;
    transition: opacity 180ms ease;
}

@media (prefers-reduced-motion: reduce) {
    .aurora-blob,
    .hero-gradient-text,
    .logo-glow::after,
    .animate-marquee,
    .animate-ping {
        animation: none !important;
    }

    .auth-modal,
    .auth-card,
    .mcpbay-toast {
        transition: none !important;
    }

    .catalog-progress.is-loading .catalog-progress__bar {
        animation: none !important;
        transform: translateX(0);
    }

    .catalog-grid-loading {
        transition: none !important;
    }

    @view-transition {
        navigation: none;
    }
}

/* ---------------------------------------------------------------------------
   Account settings (account.html) + email-change verification page.
   These component classes are deterministic and token-aligned so the dynamic
   nodes account-settings.js toggles (pending banner, inline form status, the
   language segmented control) render correctly under the Tailwind Play CDN
   without depending on runtime utility generation for dark/light variants.
   --------------------------------------------------------------------------- */

/* Pending email-change banner (amber, mirrors the verify-banner palette) */
.pending-banner {
    display: flex;
    align-items: flex-start;
    gap: 0.875rem;
    padding: 1rem 1.25rem;
    border-radius: 1rem;
    border: 1px solid rgb(252 211 77);          /* amber-300 */
    background: rgb(255 251 235);                /* amber-50 */
}
html.dark .pending-banner {
    border-color: rgba(180, 83, 9, 0.6);         /* amber-700/60 */
    background: rgba(69, 26, 3, 0.4);            /* amber-950/40 */
}
.pending-banner__icon {
    flex: none;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 0.75rem;
    display: flex;
    align-items: center;
    justify-content: center;
    background: rgb(254 243 199);               /* amber-100 */
    color: rgb(217 119 6);                       /* amber-600 */
    font-size: 1.125rem;
}
html.dark .pending-banner__icon {
    background: rgba(120, 53, 15, 0.4);          /* amber-900/40 */
    color: rgb(252 211 77);                      /* amber-300 */
}
.pending-banner__body { min-width: 0; }
.pending-banner__title {
    font-weight: 600;
    font-size: 0.875rem;
    color: rgb(120 53 15);                       /* amber-900 */
}
html.dark .pending-banner__title { color: rgb(254 243 199); }   /* amber-100 */
.pending-banner__text {
    font-size: 0.875rem;
    line-height: 1.45;
    margin-top: 0.125rem;
    color: rgb(146 64 14);                       /* amber-800 */
}
html.dark .pending-banner__text { color: rgba(253, 230, 138, 0.85); } /* amber-200/85 */
.pending-banner__email {
    font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
    font-weight: 600;
    word-break: break-all;
}

/* Inline form status line (success / error), used by both settings forms */
.form-status--ok {
    color: rgb(4 120 87);                         /* emerald-700 */
    background: rgb(236 253 245);                 /* emerald-50 */
    border: 1px solid rgb(167 243 208);           /* emerald-200 */
}
html.dark .form-status--ok {
    color: rgb(110 231 183);                      /* emerald-300 */
    background: rgba(2, 44, 34, 0.4);             /* emerald-950/40 */
    border-color: rgba(6, 78, 59, 0.4);          /* emerald-900/40 */
}
.form-status--err {
    color: rgb(220 38 38);                        /* red-600 */
    background: rgb(254 242 242);                 /* red-50 */
    border: 1px solid rgb(254 202 202);           /* red-200 */
}
html.dark .form-status--err {
    color: rgb(248 113 113);                      /* red-400 */
    background: rgba(69, 10, 10, 0.4);           /* red-950/40 */
    border-color: rgba(127, 29, 29, 0.4);        /* red-900/40 */
}

/* Language segmented control (radio group styled as a pill toggle) */
.lang-segment {
    display: inline-flex;
    padding: 0.25rem;
    gap: 0.25rem;
    border-radius: 0.875rem;
    background: rgb(244 244 245);                 /* zinc-100 */
    border: 1px solid rgb(228 228 231);           /* zinc-200 */
}
html.dark .lang-segment {
    background: rgba(39, 39, 42, 0.6);           /* zinc-800/60 */
    border-color: rgb(39 39 42);                  /* zinc-800 */
}
.lang-segment__option {
    position: relative;
    cursor: pointer;
}
.lang-segment__input {
    position: absolute;
    opacity: 0;
    width: 0;
    height: 0;
}
.lang-segment__label {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 5.5rem;
    padding: 0.5rem 1rem;
    border-radius: 0.625rem;
    font-size: 0.875rem;
    font-weight: 600;
    color: rgb(82 82 91);                         /* zinc-500 */
    transition: background 160ms ease, color 160ms ease, box-shadow 160ms ease;
}
html.dark .lang-segment__label { color: rgb(161 161 170); }     /* zinc-400 */
.lang-segment__option:hover .lang-segment__label { color: rgb(24 24 27); }
html.dark .lang-segment__option:hover .lang-segment__label { color: rgb(244 244 245); }
.lang-segment__input:checked + .lang-segment__label {
    background: rgb(255 255 255);
    color: rgb(24 24 27);                         /* zinc-900 */
    box-shadow: 0 1px 3px rgba(15, 23, 42, 0.12);
}
html.dark .lang-segment__input:checked + .lang-segment__label {
    background: rgb(9 9 11);                       /* zinc-950 */
    color: rgb(244 244 245);                      /* zinc-50 */
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.5);
}
.lang-segment__input:focus-visible + .lang-segment__label {
    outline: 2px solid rgb(99 102 241);           /* indigo-500 */
    outline-offset: 2px;
}

/* ---------------------------------------------------------------------------
   Header user menu (dropdown for a logged-in user).
   auth.js (renderHeaderAuthed) injects .user-menu / .user-menu__panel and
   toggles .is-open on the wrapper. These rules are deterministic and
   token-aligned (mirroring .auth-card / .pending-banner surfaces) because the
   markup is created at runtime — the Tailwind Play CDN never sees these class
   names, so utility generation can't cover them. Panel is hidden by default
   and revealed only when the wrapper carries .is-open.
   --------------------------------------------------------------------------- */

.user-menu {
    position: relative;
    display: inline-flex;
}
.user-menu__trigger {
    cursor: pointer;
}
.user-menu__caret {
    transition: transform 160ms ease;
}
.user-menu.is-open .user-menu__caret {
    transform: rotate(180deg);
}

.user-menu__panel {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    z-index: 60;
    /* Bridge the visual gap between trigger and panel so a desktop pointer
       moving from the name down to the items never leaves the wrapper's
       hover region (which would trigger the close timer mid-travel). */
}
.user-menu__panel::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 100%;
    height: 0.625rem;        /* covers the 0.5rem offset + a little slack */
}
.user-menu__panel {
    min-width: 13rem;
    padding: 0.375rem;
    border-radius: 1rem;
    background: rgb(255 255 255);
    border: 1px solid rgb(228 228 231);           /* zinc-200 */
    box-shadow: 0 12px 32px -8px rgba(15, 23, 42, 0.22),
                0 2px 8px -2px rgba(15, 23, 42, 0.12);
    /* Hidden by default; revealed by .is-open. */
    opacity: 0;
    visibility: hidden;
    transform: translateY(-4px);
    pointer-events: none;
    transition: opacity 140ms ease, transform 140ms ease, visibility 140ms ease;
}
html.dark .user-menu__panel {
    background: rgb(24 24 27);                     /* zinc-900 */
    border-color: rgb(39 39 42);                   /* zinc-800 */
    box-shadow: 0 12px 32px -8px rgba(0, 0, 0, 0.6),
                0 2px 8px -2px rgba(0, 0, 0, 0.4);
}
.user-menu.is-open .user-menu__panel {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    pointer-events: auto;
}

.user-menu__item {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    width: 100%;
    padding: 0.5rem 0.75rem;
    border-radius: 0.625rem;
    font-size: 0.875rem;
    font-weight: 500;
    text-align: left;
    color: rgb(39 39 42);                          /* zinc-800 */
    background: transparent;
    border: 0;
    cursor: pointer;
    text-decoration: none;
    transition: background 140ms ease, color 140ms ease;
}
html.dark .user-menu__item {
    color: rgb(228 228 231);                       /* zinc-200 */
}
.user-menu__item:hover,
.user-menu__item:focus-visible {
    background: rgb(244 244 245);                  /* zinc-100 */
    color: rgb(24 24 27);                          /* zinc-900 */
    outline: none;
}
html.dark .user-menu__item:hover,
html.dark .user-menu__item:focus-visible {
    background: rgba(39, 39, 42, 0.7);             /* zinc-800/70 */
    color: rgb(250 250 250);                       /* zinc-50 */
}
.user-menu__item-icon {
    flex: none;
    font-size: 1rem;
    color: rgb(113 113 122);                       /* zinc-500 */
}
html.dark .user-menu__item-icon {
    color: rgb(161 161 170);                       /* zinc-400 */
}
.user-menu__item:hover .user-menu__item-icon,
.user-menu__item:focus-visible .user-menu__item-icon {
    color: inherit;
}

.user-menu__item--danger {
    color: rgb(220 38 38);                         /* red-600 */
}
html.dark .user-menu__item--danger {
    color: rgb(248 113 113);                       /* red-400 */
}
.user-menu__item--danger .user-menu__item-icon {
    color: rgb(220 38 38);
}
html.dark .user-menu__item--danger .user-menu__item-icon {
    color: rgb(248 113 113);
}
.user-menu__item--danger:hover,
.user-menu__item--danger:focus-visible {
    background: rgb(254 242 242);                  /* red-50 */
    color: rgb(185 28 28);                         /* red-700 */
}
html.dark .user-menu__item--danger:hover,
html.dark .user-menu__item--danger:focus-visible {
    background: rgba(69, 10, 10, 0.5);            /* red-950/50 */
    color: rgb(252 165 165);                       /* red-300 */
}
.user-menu__item--danger:hover .user-menu__item-icon,
.user-menu__item--danger:focus-visible .user-menu__item-icon {
    color: inherit;
}

.user-menu__sep {
    height: 1px;
    margin: 0.375rem 0.25rem;
    background: rgb(228 228 231);                  /* zinc-200 */
}
html.dark .user-menu__sep {
    background: rgb(39 39 42);                      /* zinc-800 */
}

/* ---------------------------------------------------------------------------
   Account dashboard (account.html — sidebar master-detail).
   These component classes are deterministic and token-aligned because the
   sidebar items, filter chips, skeletons, command palette and mobile drawer
   are toggled/injected by account.js at runtime — the Tailwind Play CDN never
   sees their state classes, so utility generation can't cover the dark/light
   variants reliably (same hazard documented for .user-menu / .pending-banner).
   --------------------------------------------------------------------------- */

/* Sidebar nav items (Профиль + each server). Active = inverted surface + rail. */
.acct-item { position: relative; }
.acct-item[data-active="true"] {
    background-color: rgb(244 244 245);            /* zinc-100 */
    color: rgb(24 24 27);                          /* zinc-900 */
}
html.dark .acct-item[data-active="true"] {
    background-color: rgba(39, 39, 42, 0.7);       /* zinc-800/70 */
    color: rgb(250 250 250);                       /* zinc-50 */
}
.acct-rail {
    position: absolute;
    left: 0;
    top: 0.5rem;
    bottom: 0.5rem;
    width: 0.25rem;
    border-radius: 9999px;
    background: rgb(79 70 229);                     /* indigo-600 */
    opacity: 0;
    transition: opacity 150ms ease;
}
.acct-item[data-active="true"] .acct-rail { opacity: 1; }

/* Skeleton shimmer (sidebar list while /account/submissions resolves). */
@keyframes acct-shimmer { 100% { transform: translateX(100%); } }
.acct-skel {
    position: relative;
    overflow: hidden;
    background: rgb(244 244 245);                   /* zinc-100 */
}
html.dark .acct-skel { background: rgb(39 39 42); } /* zinc-800 */
.acct-skel::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.5), transparent);
    animation: acct-shimmer 1.4s infinite;
}
html.dark .acct-skel::after {
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.06), transparent);
}

/* Command palette (⌘K). Mirrors .auth-modal mechanics; opens on .is-open. */
.acct-palette {
    position: fixed;
    inset: 0;
    z-index: 120;
    display: flex;
    align-items: flex-start;
    justify-content: center;
    padding-top: 14vh;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.18s ease, visibility 0s linear 0.18s;
}
.acct-palette.is-open {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.18s ease;
}
.acct-palette__backdrop {
    position: absolute;
    inset: 0;
    background: rgba(0, 0, 0, 0.4);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
}
html.dark .acct-palette__backdrop { background: rgba(0, 0, 0, 0.65); }
.acct-palette__card {
    position: relative;
    transform: translateY(-10px) scale(0.98);
    transition: transform 0.26s cubic-bezier(0.22, 1, 0.36, 1);
}
.acct-palette.is-open .acct-palette__card { transform: translateY(0) scale(1); }
.acct-pal-item[data-active="true"] { background-color: rgb(244 244 245); }   /* zinc-100 */
html.dark .acct-pal-item[data-active="true"] { background-color: rgba(39, 39, 42, 0.7); }

/* Mobile drawer: below lg the sidebar slides in from the left. */
@media (max-width: 1023px) {
    #account-sidebar {
        position: fixed;
        top: 0;
        bottom: 0;
        left: 0;
        z-index: 90;
        width: 18rem;
        max-width: 85vw;
        transform: translateX(-100%);
        transition: transform 0.28s cubic-bezier(0.22, 1, 0.36, 1);
        overflow-y: auto;
    }
    #account-sidebar.is-open { transform: translateX(0); }
}

/* Smooth mount for the server-detail panel (header + analytics, rendered in one
   pass) and for async analytics fills. Opacity-only — no transform — so switching
   between servers crossfades cleanly without any positional "jump". */
@keyframes acct-fade-in {
    from { opacity: 0; }
    to   { opacity: 1; }
}
.acct-fade-in { animation: acct-fade-in 0.18s ease both; }

@media (prefers-reduced-motion: reduce) {
    .acct-skel::after { animation: none !important; }
    .acct-fade-in { animation: none !important; }
    .acct-palette,
    .acct-palette__card,
    #account-sidebar { transition: none !important; }
}
