/* network-plot.css — "The Origin Plot" identity for the home + onboarding pages.
   Named with an `n` so Dash serves it AFTER main.css (assets load alphabetically)
   and equal-specificity rules here win. Every class and keyframe is `.np-` /
   `np-` prefixed; nothing in here touches app-shell ids. Fonts: Spline Sans
   (display — a spline is a plotted curve) + Spline Sans Mono (axis labels,
   coordinates, domains); body text stays Inter from the theme. */
@import url('https://fonts.googleapis.com/css2?family=Spline+Sans:wght@500;600;700&family=Spline+Sans+Mono:wght@400;500;600&display=swap');

/* ---------- per-app accent (one class, used by plot nodes, wires, carousel
   slides, and tour cards alike) ---------- */
.np-k-hub       { --np-accent: light-dark(var(--mantine-color-brand-6),  var(--mantine-color-brand-4)); }
.np-k-pirates   { --np-accent: light-dark(var(--mantine-color-yellow-7), var(--mantine-color-yellow-5)); }
.np-k-buzz      { --np-accent: light-dark(var(--mantine-color-orange-6), var(--mantine-color-orange-4)); }
.np-k-xyz       { --np-accent: light-dark(var(--mantine-color-teal-6),   var(--mantine-color-teal-4)); }
.np-k-media     { --np-accent: light-dark(var(--mantine-color-grape-6),  var(--mantine-color-grape-4)); }
.np-k-cast      { --np-accent: light-dark(var(--mantine-color-cyan-6),   var(--mantine-color-cyan-4)); }
.np-k-dev       { --np-accent: light-dark(var(--mantine-color-blue-6),   var(--mantine-color-blue-4)); }
.np-k-oss       { --np-accent: light-dark(var(--mantine-color-indigo-6), var(--mantine-color-indigo-4)); }
.np-k-scheduler { --np-accent: light-dark(var(--mantine-color-green-6),  var(--mantine-color-green-4)); }
.np-k-charts    { --np-accent: light-dark(var(--mantine-color-lime-7),   var(--mantine-color-lime-4)); }
.np-k-leaflet   { --np-accent: light-dark(var(--mantine-color-green-7),  var(--mantine-color-green-4)); }
.np-k-email     { --np-accent: light-dark(var(--mantine-color-red-6),    var(--mantine-color-red-4)); }
.np-k-flows     { --np-accent: light-dark(var(--mantine-color-cyan-7),   var(--mantine-color-cyan-5)); }
.np-k-boilerplate { --np-accent: light-dark(var(--mantine-color-gray-6), var(--mantine-color-gray-4)); }
.np-k-pannellum { --np-accent: light-dark(var(--mantine-color-pink-6),   var(--mantine-color-pink-4)); }
.np-k-flexlayout { --np-accent: light-dark(var(--mantine-color-indigo-7), var(--mantine-color-indigo-5)); }
.np-k-emojimart { --np-accent: light-dark(var(--mantine-color-yellow-6), var(--mantine-color-yellow-3)); }
.np-k-llms      { --np-accent: light-dark(var(--mantine-color-violet-6), var(--mantine-color-violet-4)); }

/* ---------- type utilities ---------- */
/* !important so these win against Mantine's runtime-injected component styles,
   which land after this stylesheet in the document head. */
.np-display {
    font-family: 'Spline Sans', 'Inter', sans-serif !important;
    letter-spacing: -0.01em;
}

.np-mono {
    font-family: 'Spline Sans Mono', ui-monospace, SFMono-Regular, Menlo, monospace !important;
}

.np-eyebrow {
    font-family: 'Spline Sans Mono', ui-monospace, monospace !important;
    font-weight: 600;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: light-dark(var(--mantine-color-brand-8), var(--mantine-color-brand-4));
}

/* ---------- hero shell: ambient drafting-table backdrop ---------- */
.np-hero {
    position: relative;
    padding-block: clamp(0.5rem, 2vw, 1.5rem);
}

.np-hero::before {
    content: "";
    position: absolute;
    inset: -2rem -3rem;
    pointer-events: none;
    background-image:
        linear-gradient(to right, light-dark(rgba(51, 153, 255, 0.07), rgba(51, 153, 255, 0.09)) 1px, transparent 1px),
        linear-gradient(to bottom, light-dark(rgba(51, 153, 255, 0.07), rgba(51, 153, 255, 0.09)) 1px, transparent 1px);
    background-size: 44px 44px;
    -webkit-mask-image: radial-gradient(ellipse 75% 90% at 62% 40%, black 30%, transparent 78%);
    mask-image: radial-gradient(ellipse 75% 90% at 62% 40%, black 30%, transparent 78%);
}

.np-hero > * { position: relative; }

/* orchestrated page-load rise for the hero copy */
.np-rise {
    opacity: 0;
    transform: translateY(14px);
    animation: np-rise 0.65s cubic-bezier(0.22, 0.8, 0.3, 1) forwards;
}

.np-rise--1 { animation-delay: 0.05s; }
.np-rise--2 { animation-delay: 0.15s; }
.np-rise--3 { animation-delay: 0.25s; }
.np-rise--4 { animation-delay: 0.38s; }
.np-rise--5 { animation-delay: 0.5s; }

.np-hero-title {
    font-family: 'Spline Sans', 'Inter', sans-serif !important;
    font-size: clamp(2.4rem, 5vw, 3.6rem) !important;
    line-height: 1.05 !important;
    letter-spacing: -0.025em;
}

.np-hero-caption {
    font-family: 'Spline Sans Mono', ui-monospace, monospace !important;
    letter-spacing: 0.08em;
}

/* lede paragraph — the first, slightly larger line of hero prose */
.np-hero-lede {
    font-size: clamp(1rem, 1.25vw, 1.12rem) !important;
    color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-gray-4)) !important;
}

/* the Plotly Champion credential link, in the hub accent */
.np-hero-cred {
    color: light-dark(var(--mantine-color-brand-7), var(--mantine-color-brand-4)) !important;
    font-weight: 600;
    text-decoration-color: color-mix(in srgb, currentColor 45%, transparent);
    text-underline-offset: 3px;
    transition: color 0.15s ease, text-decoration-color 0.15s ease;
}

.np-hero-cred:hover {
    color: light-dark(var(--mantine-color-brand-8), var(--mantine-color-brand-3)) !important;
    text-decoration-color: currentColor;
}

/* wordmark swaps with the color scheme (same pattern as the theme-toggle
   icons in main.css — classes, not the reserved ids) */
:root[data-mantine-color-scheme="light"] .np-logo-dark { display: none; }
:root[data-mantine-color-scheme="dark"] .np-logo-light { display: none; }

/* ---------- the network plot (hero signature) ---------- */
.np-plot {
    --np-grid-major: light-dark(rgba(51, 153, 255, 0.15), rgba(51, 153, 255, 0.17));
    --np-grid-minor: light-dark(rgba(51, 153, 255, 0.055), rgba(51, 153, 255, 0.07));
    --np-axis: light-dark(rgba(29, 86, 143, 0.42), rgba(137, 196, 255, 0.4));
    position: relative;
    width: 100%;
    max-width: 500px;
    aspect-ratio: 1 / 1;
    margin-inline: auto;
    border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
    border-radius: var(--mantine-radius-xl);
    background:
        radial-gradient(circle at 50% 50%,
            light-dark(rgba(51, 153, 255, 0.06), rgba(51, 153, 255, 0.09)) 0%,
            transparent 55%),
        light-dark(linear-gradient(180deg, #ffffff 0%, #f7fbff 100%),
                   linear-gradient(180deg, var(--mantine-color-dark-7) 0%, var(--mantine-color-dark-8) 100%));
    box-shadow:
        inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.05)),
        0 1px 2px rgba(10, 30, 60, 0.06),
        0 12px 32px -12px light-dark(rgba(29, 86, 143, 0.25), rgba(0, 0, 0, 0.6)),
        0 0 60px -20px light-dark(rgba(51, 153, 255, 0.25), rgba(51, 153, 255, 0.15));
    overflow: hidden;
}

/* graph paper: minor squares at 5%, major squares at 20% */
.np-plot-grid {
    position: absolute;
    inset: 0;
    background-image:
        linear-gradient(to right, var(--np-grid-major) 1px, transparent 1px),
        linear-gradient(to bottom, var(--np-grid-major) 1px, transparent 1px),
        linear-gradient(to right, var(--np-grid-minor) 1px, transparent 1px),
        linear-gradient(to bottom, var(--np-grid-minor) 1px, transparent 1px);
    background-size: 20% 20%, 20% 20%, 5% 5%, 5% 5%;
}

/* axes through the origin, with arrowheads at the positive ends */
.np-axis {
    position: absolute;
    background: var(--np-axis);
}

.np-axis--x { left: 3%; right: 3.5%; top: 50%; height: 1px; }
.np-axis--y { top: 3.5%; bottom: 3%; left: 50%; width: 1px; }

.np-axis--x::after,
.np-axis--y::after {
    content: "";
    position: absolute;
    border: 4px solid transparent;
}

.np-axis--x::after {
    right: -5px;
    top: -3.5px;
    border-left: 6px solid var(--np-axis);
}

.np-axis--y::after {
    top: -5px;
    left: -3.5px;
    border-bottom: 6px solid var(--np-axis);
}

.np-axis-label {
    position: absolute;
    font-family: 'Spline Sans Mono', ui-monospace, monospace;
    font-size: 0.625rem;
    color: var(--np-axis);
    line-height: 1;
}

.np-axis-label--x { right: 4%; top: calc(50% + 7px); }
.np-axis-label--y { left: calc(50% + 7px); top: 4%; }

/* the legend — quiet engineering annotation, bottom-left corner */
.np-plot-legend {
    position: absolute;
    left: 12px;
    bottom: 10px;
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: 'Spline Sans Mono', ui-monospace, monospace;
    font-size: 0.575rem;
    letter-spacing: 0.06em;
    color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-dark-2));
    z-index: 3;
}

.np-plot-legend .np-marker { width: 7px; height: 7px; box-shadow: none; }
.np-plot-legend .np-marker--hollow { width: 6px; height: 6px; border-width: 1.5px; }

/* plot wires: dashed lines from the origin that DRAW themselves on load, then
   carry a traveling signal pulse. The outer div gets width + rotation inline
   (computed in Python); the line + pulse are children so their animations
   don't fight the inline rotate transform. */
.np-wire {
    position: absolute;
    left: 50%;
    top: 50%;
    height: 2px;
    margin-top: -1px;
    transform-origin: 0 50%;
    pointer-events: none;
}

.np-wire-line {
    position: absolute;
    inset: 0;
    background-image: repeating-linear-gradient(90deg,
        color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-5)) 55%, transparent) 0 6px,
        transparent 6px 12px);
    background-size: 200% 100%;
    transform: scaleX(0);
    transform-origin: left center;
    animation: np-wire-draw 0.8s cubic-bezier(0.3, 0, 0.2, 1) forwards;
}

/* the signal: a small glowing packet traveling origin → app, forever */
.np-wire-pulse {
    position: absolute;
    top: 50%;
    left: 0;
    width: 7px;
    height: 7px;
    margin: -3.5px 0 0 -3.5px;
    border-radius: 50%;
    background: var(--np-accent, var(--mantine-color-brand-5));
    box-shadow: 0 0 8px 1px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-5)) 70%, transparent);
    opacity: 0;
    animation: np-signal 5.6s ease-in-out infinite;
}

/* nodes: each app is a plotted, linked point */
.np-node {
    position: absolute;
    transform: translate(-50%, -50%);
    z-index: 2;
    text-decoration: none;
    color: inherit;
}

.np-node-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    opacity: 0;
    animation:
        np-plot-in 0.5s cubic-bezier(0.2, 0.9, 0.3, 1.25) forwards,
        np-float 7s ease-in-out infinite;
}

/* future/claimed markers plot in late but don't float — they're not live */
.np-node-inner--still {
    animation: np-plot-in 0.5s ease forwards;
}

.np-marker {
    display: inline-block;
    width: 12px;
    height: 12px;
    border-radius: 50%;
    background: var(--np-accent, var(--mantine-color-brand-6));
    border: 2px solid light-dark(#ffffff, var(--mantine-color-dark-8));
    box-shadow:
        0 0 0 2px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 30%, transparent),
        0 0 10px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 35%, transparent);
    transition: transform 140ms ease, box-shadow 140ms ease;
}

.np-marker--hollow {
    flex-shrink: 0;
    width: 10px;
    height: 10px;
    background: transparent;
    border: 2px dashed light-dark(var(--mantine-color-gray-5), var(--mantine-color-dark-3));
    box-shadow: none;
}

.np-node-label {
    font-family: 'Spline Sans Mono', ui-monospace, monospace;
    font-size: 0.625rem;
    line-height: 1.2;
    white-space: nowrap;
    padding: 2px 7px;
    border-radius: 5px;
    color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-gray-4));
    background: light-dark(rgba(255, 255, 255, 0.88), rgba(26, 27, 30, 0.82));
    border: 1px solid light-dark(rgba(29, 86, 143, 0.12), rgba(255, 255, 255, 0.07));
    backdrop-filter: blur(2px);
    transition: color 140ms ease, border-color 140ms ease;
}

.np-node-label--future {
    color: light-dark(var(--mantine-color-gray-5), var(--mantine-color-dark-2));
    border-style: dashed;
}

a.np-node:hover .np-marker,
a.np-node:focus-visible .np-marker {
    transform: scale(1.4);
    box-shadow:
        0 0 0 3px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 35%, transparent),
        0 0 16px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 55%, transparent);
}

a.np-node:hover .np-node-label,
a.np-node:focus-visible .np-node-label {
    color: light-dark(var(--mantine-color-dark-8), #ffffff);
    border-color: color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 55%, transparent);
}

a.np-node:focus-visible {
    outline: 2px solid var(--mantine-color-brand-6);
    outline-offset: 3px;
    border-radius: 4px;
}

/* the origin hub: crosshair + core + double pulse ring */
.np-hub .np-node-inner { animation: np-plot-in 0.5s ease forwards; }

.np-hub-marker {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
}

/* fine crosshair ticks extending past the core */
.np-hub-marker::before,
.np-hub-marker::after {
    content: "";
    position: absolute;
    background: light-dark(rgba(29, 86, 143, 0.5), rgba(137, 196, 255, 0.55));
}

.np-hub-marker::before { left: -8px; right: -8px; top: 50%; height: 1px; }
.np-hub-marker::after  { top: -8px; bottom: -8px; left: 50%; width: 1px; }

.np-hub-core {
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: var(--mantine-color-brand-6);
    border: 2.5px solid light-dark(#ffffff, var(--mantine-color-dark-8));
    box-shadow:
        0 0 0 1.5px var(--mantine-color-brand-6),
        0 0 14px rgba(51, 153, 255, 0.55);
    z-index: 1;
}

.np-pulse {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 1.5px solid var(--mantine-color-brand-5);
    animation: np-pulse 2.6s ease-out infinite;
}

.np-pulse--2 { animation-delay: 1.3s; }

/* ---------- the app showcase carousel ---------- */
.np-carousel { position: relative; }

.np-car-control {
    width: 40px;
    height: 40px;
    border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
    background: light-dark(rgba(255, 255, 255, 0.85), rgba(26, 27, 30, 0.75));
    backdrop-filter: blur(6px);
    box-shadow: 0 4px 14px -4px rgba(10, 30, 60, 0.3);
    color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-gray-3));
    opacity: 1;
    transition: transform 140ms ease, border-color 140ms ease;
}

.np-car-control:hover {
    transform: scale(1.08);
    border-color: var(--mantine-color-brand-5);
}

.np-car-indicators { gap: 8px; bottom: -1.6rem; }

.np-car-indicator {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-3));
    box-shadow: none;
    transition: transform 140ms ease, background-color 140ms ease;
}

.np-car-indicator[data-active] {
    background: var(--mantine-color-brand-6);
    transform: scale(1.35);
}

/* one slide = one app's hero card */
.np-slide-card {
    position: relative;
    min-height: clamp(380px, 46vh, 440px);
    height: 100%;
    display: flex;
    border-radius: var(--mantine-radius-xl);
    border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
    background: light-dark(linear-gradient(180deg, #ffffff 0%, #fafcff 100%),
                           linear-gradient(180deg, var(--mantine-color-dark-7) 0%, var(--mantine-color-dark-8) 100%));
    box-shadow:
        inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.05)),
        0 16px 40px -18px light-dark(rgba(29, 86, 143, 0.28), rgba(0, 0, 0, 0.65));
    overflow: hidden;
}

/* accent edge: a soft bloom rising from the bottom of the slide */
.np-slide-card::after {
    content: "";
    position: absolute;
    inset: auto 0 0 0;
    height: 40%;
    pointer-events: none;
    background: linear-gradient(to top,
        color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 10%, transparent),
        transparent);
}

.np-slide-content {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.9rem;
    padding: clamp(1.5rem, 4vw, 3rem);
    max-width: 60%;
}

.np-slide-eyebrow {
    font-family: 'Spline Sans Mono', ui-monospace, monospace !important;
    font-weight: 600;
    font-size: 0.7rem;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--np-accent, var(--mantine-color-brand-6));
}

.np-slide-title {
    font-family: 'Spline Sans', 'Inter', sans-serif !important;
    font-size: clamp(1.8rem, 3.4vw, 2.6rem) !important;
    line-height: 1.08 !important;
    letter-spacing: -0.02em;
}

.np-slide-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 54px;
    height: 54px;
    border-radius: 16px;
    color: var(--np-accent, var(--mantine-color-brand-6));
    background: color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 12%, transparent);
    border: 1px solid color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 30%, transparent);
    box-shadow: 0 0 24px -6px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 45%, transparent);
}

/* the app's plot coordinate — the lore chip tying the carousel to the hero */
.np-slide-coord {
    position: absolute;
    top: 16px;
    right: 20px;
    z-index: 3;
    font-family: 'Spline Sans Mono', ui-monospace, monospace;
    font-size: 0.65rem;
    letter-spacing: 0.08em;
    padding: 3px 9px;
    border-radius: 6px;
    color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-gray-4));
    background: light-dark(rgba(255, 255, 255, 0.75), rgba(26, 27, 30, 0.6));
    border: 1px solid light-dark(rgba(29, 86, 143, 0.14), rgba(255, 255, 255, 0.08));
    backdrop-filter: blur(3px);
}

/* the big ghost icon floating on the scene side */
.np-slide-ghost {
    position: absolute;
    z-index: 1;
    right: clamp(4%, 8vw, 10%);
    top: 50%;
    color: var(--np-accent, var(--mantine-color-brand-6));
    opacity: 0.5;
    filter: drop-shadow(0 0 30px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 55%, transparent));
    animation: np-bob 7s ease-in-out infinite;
    pointer-events: none;
}

/* ---------- per-app scenes: subtle animated backdrops, masked so the
   content side stays calm. Two paint layers each (::before / ::after). ---------- */
.np-scene {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    -webkit-mask-image: linear-gradient(100deg, transparent 26%, rgba(0, 0, 0, 0.5) 48%, black 72%);
    mask-image: linear-gradient(100deg, transparent 26%, rgba(0, 0, 0, 0.5) 48%, black 72%);
}

.np-scene::before,
.np-scene::after {
    content: "";
    position: absolute;
    inset: 0;
}

/* pirates — two rolling swells drifting at different speeds */
.np-scene--pirates::before,
.np-scene--pirates::after {
    inset: auto 0 0 0;
    height: 52%;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 160' preserveAspectRatio='none'%3E%3Cpath d='M0,70 C150,110 300,30 450,70 C600,110 750,30 900,70 C1050,110 1200,30 1350,70 L1350,160 L0,160 Z' fill='%23eab30822'/%3E%3C/svg%3E");
    background-size: 900px 100%;
    background-repeat: repeat-x;
    animation: np-drift 26s linear infinite;
}

.np-scene--pirates::after {
    height: 38%;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1200 160' preserveAspectRatio='none'%3E%3Cpath d='M0,80 C200,120 400,40 600,80 C800,120 1000,40 1200,80 L1200,160 L0,160 Z' fill='%23eab30836'/%3E%3C/svg%3E");
    background-size: 640px 100%;
    animation: np-drift 15s linear infinite reverse;
}

/* buzz — honeycomb lattice with a slow breathing glow */
.np-scene--buzz::before {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='56' height='97' viewBox='0 0 56 97'%3E%3Cg fill='none' stroke='%23f7670028' stroke-width='1.5'%3E%3Cpath d='M28 0L56 16.2v32.3L28 64.7 0 48.5V16.2z'/%3E%3Cpath d='M28 64.7L56 80.8v32.3L28 129.4 0 113.1V80.8z'/%3E%3C/g%3E%3C/svg%3E");
    background-size: 56px 97px;
}

.np-scene--buzz::after {
    background: radial-gradient(circle at 72% 45%, #f7670030 0%, transparent 45%);
    animation: np-breathe 5s ease-in-out infinite;
}

/* xyz — two organic cells slowly morphing and drifting */
.np-scene--xyz::before,
.np-scene--xyz::after {
    inset: auto;
    width: 240px;
    height: 240px;
    background: radial-gradient(circle at 35% 35%, #12b88633, #12b88611 60%, transparent 75%);
    border: 1.5px solid #12b88630;
    border-radius: 46% 54% 60% 40% / 50% 44% 56% 50%;
    animation: np-morph 13s ease-in-out infinite;
}

.np-scene--xyz::before { right: 8%; top: 12%; }

.np-scene--xyz::after {
    width: 130px;
    height: 130px;
    right: 30%;
    bottom: 6%;
    animation-duration: 17s;
    animation-direction: reverse;
}

/* media — editing-timeline tracks with clips gliding by */
.np-scene--media::before {
    background-image: repeating-linear-gradient(to bottom,
        transparent 0 56px, #be4bdb1d 56px 58px);
    background-position: 0 26px;
}

.np-scene--media::after {
    background-image:
        linear-gradient(90deg, #be4bdb30 0 100%),
        linear-gradient(90deg, #be4bdb22 0 100%),
        linear-gradient(90deg, #be4bdb3a 0 100%),
        linear-gradient(90deg, #be4bdb26 0 100%);
    background-size: 180px 26px, 120px 26px, 90px 26px, 150px 26px;
    background-position: 130% 42px, 60% 100px, 88% 158px, 55% 216px;
    background-repeat: no-repeat;
    border-radius: 4px;
    animation: np-clips 18s linear infinite;
}

/* cast — a wireframe browser window with a sweeping scanline */
.np-scene--cast::before {
    inset: 18% 8% 18% 42%;
    border: 1.5px solid #15aabf3d;
    border-radius: 10px;
    background:
        radial-gradient(circle 2.5px at 14px 13px, #15aabf80 98%, transparent),
        radial-gradient(circle 2.5px at 26px 13px, #15aabf59 98%, transparent),
        radial-gradient(circle 2.5px at 38px 13px, #15aabf3d 98%, transparent),
        linear-gradient(to bottom, #15aabf24 0 26px, transparent 26px);
}

.np-scene--cast::after {
    inset: 18% 8% 18% 42%;
    border-radius: 10px;
    overflow: hidden;
    background: linear-gradient(90deg, transparent, #15aabf3d 45%, #15aabf55 50%, #15aabf3d 55%, transparent);
    background-size: 45% 100%;
    background-repeat: no-repeat;
    animation: np-scan 4.5s ease-in-out infinite;
}

/* dev — a terminal window typing lines of code, prompt-first */
.np-scene--dev::before {
    inset: 18% 8% 18% 42%;
    border: 1.5px solid #228be63d;
    border-radius: 10px;
    background:
        radial-gradient(circle 2.5px at 14px 13px, #228be680 98%, transparent),
        radial-gradient(circle 2.5px at 26px 13px, #228be659 98%, transparent),
        radial-gradient(circle 2.5px at 38px 13px, #228be63d 98%, transparent),
        linear-gradient(to bottom, #228be624 0 26px, transparent 26px);
}

.np-scene--dev::after {
    inset: 18% 8% 18% 42%;
    background-image:
        linear-gradient(90deg, #228be642 0 100%),
        linear-gradient(90deg, #228be62c 0 100%),
        linear-gradient(90deg, #228be636 0 100%),
        linear-gradient(90deg, #228be620 0 100%);
    background-position: 16px 42px, 16px 60px, 16px 78px, 16px 96px;
    background-repeat: no-repeat;
    border-radius: 2px;
    animation: np-type 9s linear infinite;
}

@keyframes np-type {
    0%        { background-size: 0 8px, 0 8px, 0 8px, 0 8px; }
    16%       { background-size: 38% 8px, 0 8px, 0 8px, 0 8px; }
    34%       { background-size: 38% 8px, 26% 8px, 0 8px, 0 8px; }
    52%       { background-size: 38% 8px, 26% 8px, 46% 8px, 0 8px; }
    70%, 90%  { background-size: 38% 8px, 26% 8px, 46% 8px, 20% 8px; }
    100%      { background-size: 0 8px, 0 8px, 0 8px, 0 8px; }
}

/* oss — a component grid with cells lighting up */
.np-scene--oss::before {
    background-image:
        linear-gradient(to right, #4c6ef522 1px, transparent 1px),
        linear-gradient(to bottom, #4c6ef522 1px, transparent 1px);
    background-size: 44px 44px;
}

.np-scene--oss::after {
    background: linear-gradient(#4c6ef538 0 100%);
    background-size: 43px 43px;
    background-repeat: no-repeat;
    border-radius: 3px;
    animation: np-cells 9s steps(1) infinite;
}

/* scheduler — a week grid with an event block gliding between days */
.np-scene--scheduler::before {
    background-image:
        linear-gradient(to right, #40c05724 1px, transparent 1px),
        linear-gradient(to bottom, transparent 0 44px, #40c05719 44px 45px);
    background-size: 90px 100%, 100% 45px;
}

.np-scene--scheduler::after {
    background: linear-gradient(90deg, #40c0573d, #40c05726);
    background-size: 80px 36px;
    background-repeat: no-repeat;
    background-position: 60% 25%;
    border-radius: 6px;
    animation: np-agenda 12s steps(1) infinite;
}

/* ---------- the origin-aware return band (home, ?returnTo=) ---------- */
.np-return {
    display: flex;
    align-items: center;
    gap: 18px;
    flex-wrap: wrap;
    padding: 18px 22px;
    border-radius: var(--mantine-radius-lg);
    border: 1px solid color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 40%, transparent);
    background:
        linear-gradient(115deg,
            color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 12%, transparent),
            transparent 60%),
        light-dark(#ffffff, var(--mantine-color-dark-7));
    box-shadow: 0 8px 28px -18px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 55%, transparent);
    opacity: 0;
    transform: translateY(14px);
    animation: np-rise 0.5s ease 0.05s both;
}

.np-return-icon {
    display: grid;
    place-items: center;
    width: 54px;
    height: 54px;
    flex: none;
    border-radius: 14px;
    color: var(--np-accent, var(--mantine-color-brand-6));
    background: color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 30%, transparent);
}

/* the visitor's own app on the hero plot — a steady focus ring */
.np-node--focus .np-marker {
    box-shadow:
        0 0 0 4px color-mix(in srgb, var(--np-accent) 28%, transparent),
        0 0 18px color-mix(in srgb, var(--np-accent) 55%, transparent);
}

.np-node--focus .np-node-label {
    font-weight: 700;
    opacity: 1;
}

/* ---------- tour app cards (onboarding groups) ---------- */
.np-app-card {
    position: relative;
    background: light-dark(linear-gradient(180deg, #ffffff 0%, #fbfcfe 100%),
                           linear-gradient(180deg, var(--mantine-color-dark-6) 0%, var(--mantine-color-dark-7) 100%)) !important;
    box-shadow:
        inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.04)),
        0 1px 2px rgba(10, 30, 60, 0.05) !important;
    transition: transform 160ms ease, box-shadow 160ms ease, border-color 160ms ease;
}

.np-app-card:hover {
    transform: translateY(-4px);
    border-color: color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 45%, transparent) !important;
    box-shadow:
        inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.04)),
        0 14px 30px -14px light-dark(rgba(29, 86, 143, 0.35), rgba(0, 0, 0, 0.7)),
        0 0 30px -10px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 40%, transparent) !important;
}

.np-card-icon-tile {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    flex-shrink: 0;
    border-radius: 12px;
    color: var(--np-accent, var(--mantine-color-brand-6));
    background: color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 11%, transparent);
    border: 1px solid color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 26%, transparent);
    transition: box-shadow 160ms ease;
}

.np-app-card:hover .np-card-icon-tile {
    box-shadow: 0 0 18px -4px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-6)) 55%, transparent);
}

.np-role {
    font-family: 'Spline Sans Mono', ui-monospace, monospace !important;
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-gray-5));
}

.np-card-cta {
    color: var(--np-accent, var(--mantine-color-brand-6)) !important;
}

.np-card-cta svg { transition: transform 140ms ease; }
.np-card-cta:hover svg { transform: translate(2px, -2px); }

/* status dot (live / beta) */
.np-dot {
    display: inline-block;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    flex-shrink: 0;
}

.np-dot--live {
    background: var(--mantine-color-green-6);
    box-shadow: 0 0 0 2.5px color-mix(in srgb, var(--mantine-color-green-6) 22%, transparent);
}

.np-dot--beta {
    background: var(--mantine-color-yellow-6);
    box-shadow: 0 0 0 2.5px color-mix(in srgb, var(--mantine-color-yellow-6) 22%, transparent);
}

/* ---------- quadrant group headers (onboarding tour) ---------- */
.np-quadrant {
    display: flex;
    align-items: center;
    gap: 10px;
}

.np-quad-glyph {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 2px;
    width: 16px;
    height: 16px;
    flex-shrink: 0;
}

.np-quad-glyph span {
    border: 1px solid light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-3));
    border-radius: 2px;
}

.np-quad-glyph span.np-quad-on {
    background: var(--mantine-color-brand-6);
    border-color: var(--mantine-color-brand-6);
    box-shadow: 0 0 6px rgba(51, 153, 255, 0.5);
}

.np-quad-label {
    font-family: 'Spline Sans Mono', ui-monospace, monospace !important;
    font-weight: 600;
    font-size: 0.65rem;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: light-dark(var(--mantine-color-gray-6), var(--mantine-color-gray-5));
}

/* ---------- the round trip (sign-in story, shared by both pages) ---------- */
.np-roundtrip {
    display: grid;
    grid-template-columns: 1fr minmax(48px, 150px) 1fr minmax(48px, 150px) 1fr;
    align-items: start;
    gap: clamp(0.75rem, 2vw, 1.5rem);
    padding: clamp(1.5rem, 3vw, 2.5rem) !important;
    border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4)) !important;
    border-radius: var(--mantine-radius-xl) !important;
    background: light-dark(linear-gradient(180deg, #ffffff 0%, #f8fbff 100%),
                           linear-gradient(180deg, var(--mantine-color-dark-7) 0%, var(--mantine-color-dark-8) 100%)) !important;
    box-shadow:
        inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.05)),
        0 12px 32px -16px light-dark(rgba(29, 86, 143, 0.25), rgba(0, 0, 0, 0.6)) !important;
}

.np-station {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.6rem;
    min-width: 0;
}

.np-station-disc {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    color: light-dark(var(--mantine-color-brand-7), var(--mantine-color-brand-4));
    background: light-dark(rgba(51, 153, 255, 0.08), rgba(51, 153, 255, 0.12));
    border: 1.5px solid light-dark(rgba(51, 153, 255, 0.35), rgba(51, 153, 255, 0.4));
}

/* the middle station IS the origin — it gets the pulse ring */
.np-station--origin .np-station-disc {
    color: #ffffff;
    background: var(--mantine-color-brand-6);
    border-color: var(--mantine-color-brand-6);
    box-shadow: 0 0 20px rgba(51, 153, 255, 0.5);
}

.np-station--origin .np-station-disc::after {
    content: "";
    position: absolute;
    inset: -1.5px;
    border-radius: 50%;
    border: 1.5px solid var(--mantine-color-brand-5);
    animation: np-pulse 2.6s ease-out infinite;
}

.np-station-coord {
    font-family: 'Spline Sans Mono', ui-monospace, monospace;
    font-size: 0.6rem;
    letter-spacing: 0.1em;
    color: light-dark(var(--mantine-color-gray-5), var(--mantine-color-dark-2));
}

/* legs: dashes flowing in the direction of travel, with an arrowhead */
.np-leg {
    position: relative;
    align-self: start;
    margin-top: 25px;              /* centers on the 52px station disc */
    height: 2px;
    width: 100%;
    min-width: 40px;
    background-image: repeating-linear-gradient(90deg,
        light-dark(rgba(51, 153, 255, 0.55), rgba(51, 153, 255, 0.6)) 0 6px,
        transparent 6px 12px);
    animation: np-dashflow 0.9s linear infinite;
}

.np-leg::after {
    content: "";
    position: absolute;
    right: -2px;
    top: -3px;
    border: 4px solid transparent;
    border-left: 6px solid light-dark(rgba(51, 153, 255, 0.7), rgba(51, 153, 255, 0.75));
}

/* ---------- the component fleet (hero radial chart) ---------- */
.np-fleet-card {
    display: flex;
    flex-direction: column;
    gap: 6px;
    width: 100%;
    max-width: 500px;
    margin-inline: auto;
    padding: 1.1rem 1.1rem 0.9rem;
    border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
    border-radius: var(--mantine-radius-xl);
    background:
        radial-gradient(circle at 50% 45%,
            light-dark(rgba(51, 153, 255, 0.06), rgba(51, 153, 255, 0.09)) 0%,
            transparent 60%),
        light-dark(linear-gradient(180deg, #ffffff 0%, #f7fbff 100%),
                   linear-gradient(180deg, var(--mantine-color-dark-7) 0%, var(--mantine-color-dark-8) 100%));
    box-shadow:
        inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.05)),
        0 1px 2px rgba(10, 30, 60, 0.06),
        0 12px 32px -12px light-dark(rgba(29, 86, 143, 0.25), rgba(0, 0, 0, 0.6)),
        0 0 60px -20px light-dark(rgba(51, 153, 255, 0.25), rgba(51, 153, 255, 0.15));
    overflow: hidden;
}

.np-fleet-card .np-eyebrow { text-align: center; }

/* the bubble field — the fleet as circles, area = downloads. Shares the
   graph-paper vars so the np-plot-grid layer inside it draws the same
   paper as the origin plot. */
.np-bubble-field {
    --np-grid-major: light-dark(rgba(51, 153, 255, 0.15), rgba(51, 153, 255, 0.17));
    --np-grid-minor: light-dark(rgba(51, 153, 255, 0.055), rgba(51, 153, 255, 0.07));
    position: relative;
    width: 100%;
    aspect-ratio: 1 / 1;
    overflow: hidden;
    border-radius: var(--mantine-radius-lg);
    container-type: inline-size;   /* the cqw label sizes below */
}

.np-bubble {
    position: absolute;
    aspect-ratio: 1 / 1;
    border-radius: 50%;
    text-decoration: none;
    /* the JS parallax writes --np-px/--np-py; the base translate keeps the
       packing coordinates meaning "circle center" */
    transform: translate(-50%, -50%)
               translate3d(var(--np-px, 0px), var(--np-py, 0px), 0);
    will-change: transform;
}

.np-bubble-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1px;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    border: 1.5px solid var(--np-accent, var(--mantine-color-brand-5));
    background:
        radial-gradient(circle at 32% 28%,
            light-dark(rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0.14)) 0%,
            transparent 42%),
        color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-5)) 14%,
                  light-dark(rgba(255, 255, 255, 0.6), rgba(0, 0, 0, 0.25)));
    box-shadow:
        inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.08)),
        0 6px 18px -10px color-mix(in srgb,
            var(--np-accent, var(--mantine-color-brand-5)) 55%, transparent);
    animation: np-bubble-float var(--np-float-dur, 7s) ease-in-out
               var(--np-float-delay, 0s) infinite alternate;
    transition: border-color 120ms ease, box-shadow 120ms ease;
    overflow: hidden;
}

.np-bubble:hover .np-bubble-inner {
    border-width: 2px;
    box-shadow:
        inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.08)),
        0 10px 26px -10px color-mix(in srgb,
            var(--np-accent, var(--mantine-color-brand-5)) 80%, transparent);
}

@keyframes np-bubble-float {
    from { transform: translateY(-3.5%); }
    to   { transform: translateY(3.5%); }
}

@media (prefers-reduced-motion: reduce) {
    .np-bubble-inner { animation: none; }
}

.np-bubble-label {
    font-family: 'Spline Sans Mono', ui-monospace, monospace;
    font-size: clamp(0.5rem, 1.7cqw, 0.72rem);
    font-weight: 600;
    letter-spacing: 0.02em;
    color: light-dark(var(--mantine-color-gray-8), var(--mantine-color-gray-1));
    max-width: 92%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.np-bubble-count {
    font-family: 'Spline Sans Mono', ui-monospace, monospace;
    font-size: clamp(0.48rem, 1.4cqw, 0.62rem);
    color: var(--np-accent, var(--mantine-color-brand-5));
}

/* iOS-only motion-permission chip; fleet_bubbles.js reveals it */
.np-bubble-gyro {
    display: none;
    position: absolute;
    right: 10px;
    bottom: 10px;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    border: 1px solid light-dark(var(--mantine-color-gray-4), var(--mantine-color-dark-3));
    border-radius: 999px;
    background: light-dark(rgba(255, 255, 255, 0.85), rgba(20, 22, 28, 0.85));
    font-family: 'Spline Sans Mono', ui-monospace, monospace;
    font-size: 0.62rem;
    color: light-dark(var(--mantine-color-gray-7), var(--mantine-color-dark-1));
    cursor: pointer;
    backdrop-filter: blur(4px);
}

.np-fleet-caption {
    font-family: 'Spline Sans Mono', ui-monospace, monospace !important;
    font-size: 0.62rem !important;
    letter-spacing: 0.05em;
    text-align: center;
}

/* ---------- the 2plot.* domain rows ---------- */
.np-domain-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 0.7rem 0.9rem;
    border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
    border-radius: var(--mantine-radius-lg);
    background: light-dark(#ffffff, var(--mantine-color-dark-7));
    text-decoration: none;
    color: inherit;
}

.np-domain-row--link {
    transition: border-color 120ms ease, transform 120ms ease,
                box-shadow 120ms ease;
}

.np-domain-row--link:hover {
    border-color: var(--np-accent, var(--mantine-color-brand-5));
    transform: translateY(-1px);
    box-shadow: 0 10px 24px -16px light-dark(rgba(29, 86, 143, 0.45),
                                             rgba(0, 0, 0, 0.65));
}

.np-domain-row--link:hover .np-community-arrow {
    transform: translate(2px, -2px);
    opacity: 1;
}

/* ---------- the onboarding locator ("you are here") ---------- */
.np-locator {
    position: relative;
    width: 100%;
    max-width: 320px;
    aspect-ratio: 1 / 1;
    margin-inline: auto;
    border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
    border-radius: 50%;
    background:
        radial-gradient(circle,
            light-dark(rgba(51, 153, 255, 0.07), rgba(51, 153, 255, 0.1)) 0%,
            transparent 62%),
        light-dark(#ffffff, var(--mantine-color-dark-8));
    box-shadow:
        inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.05)),
        0 12px 32px -14px light-dark(rgba(29, 86, 143, 0.28), rgba(0, 0, 0, 0.6));
    overflow: hidden;
}

.np-locator-ring {
    position: absolute;
    border-radius: 50%;
    border: 1px solid light-dark(rgba(51, 153, 255, 0.22), rgba(51, 153, 255, 0.26));
}

.np-locator-ring--1 { inset: 33%; }
.np-locator-ring--2 { inset: 18%; }
.np-locator-ring--3 { inset: 5%; border-style: dashed; }

/* crosshair */
.np-locator::before,
.np-locator::after {
    content: "";
    position: absolute;
    background: light-dark(rgba(29, 86, 143, 0.25), rgba(137, 196, 255, 0.28));
}

.np-locator::before { left: 6%; right: 6%; top: 50%; height: 1px; }
.np-locator::after  { top: 6%; bottom: 6%; left: 50%; width: 1px; }

/* the radar sweep — a soft conic beam scanning the plane */
.np-locator-sweep {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    background: conic-gradient(from 0deg,
        transparent 0deg,
        light-dark(rgba(51, 153, 255, 0.16), rgba(51, 153, 255, 0.2)) 55deg,
        transparent 70deg);
    animation: np-sweep 7s linear infinite;
}

.np-locator-you {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    z-index: 2;
}

/* satellite blips around the locator (positions inline from Python) */
.np-locator-blip {
    position: absolute;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    transform: translate(-50%, -50%);
    background: var(--np-accent, var(--mantine-color-brand-5));
    border: 1.5px solid light-dark(#ffffff, var(--mantine-color-dark-8));
    box-shadow: 0 0 8px color-mix(in srgb, var(--np-accent, var(--mantine-color-brand-5)) 55%, transparent);
    animation: np-blip 7s linear infinite;
}

/* ---------- community band ---------- */
.np-community-card {
    display: block;
    padding: 1.1rem 1.3rem;
    border: 1px solid light-dark(var(--mantine-color-gray-3), var(--mantine-color-dark-4));
    border-radius: var(--mantine-radius-lg);
    background: light-dark(linear-gradient(180deg, #ffffff 0%, #fbfcfe 100%),
                           linear-gradient(180deg, var(--mantine-color-dark-6) 0%, var(--mantine-color-dark-7) 100%));
    box-shadow: inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.04));
    color: inherit;
    text-decoration: none;
    transition: transform 140ms ease, border-color 140ms ease, box-shadow 140ms ease;
}

.np-community-card:hover {
    transform: translateY(-3px);
    border-color: var(--mantine-color-brand-5);
    box-shadow:
        inset 0 1px 0 light-dark(rgba(255, 255, 255, 0.9), rgba(255, 255, 255, 0.04)),
        0 12px 26px -14px light-dark(rgba(29, 86, 143, 0.3), rgba(0, 0, 0, 0.65));
}

.np-community-card:focus-visible {
    outline: 2px solid var(--mantine-color-brand-6);
    outline-offset: 2px;
}

.np-community-arrow {
    margin-left: auto;
    color: light-dark(var(--mantine-color-gray-5), var(--mantine-color-dark-2));
    transition: transform 140ms ease, color 140ms ease;
}

.np-community-card:hover .np-community-arrow {
    transform: translate(2px, -2px);
    color: var(--mantine-color-brand-5);
}

/* ---------- motion ---------- */
@keyframes np-rise {
    to { opacity: 1; transform: translateY(0); }
}

@keyframes np-wire-draw {
    to { transform: scaleX(1); }
}

@keyframes np-plot-in {
    from { opacity: 0; transform: scale(0.3); }
    to   { opacity: 1; transform: scale(1); }
}

@keyframes np-signal {
    0%   { left: 0; opacity: 0; }
    6%   { opacity: 1; }
    38%  { left: calc(100% - 4px); opacity: 1; }
    46%  { left: calc(100% - 4px); opacity: 0; }
    100% { left: calc(100% - 4px); opacity: 0; }
}

@keyframes np-float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-5px); }
}

@keyframes np-pulse {
    from { transform: scale(1); opacity: 0.55; }
    to   { transform: scale(2.1); opacity: 0; }
}

@keyframes np-bob {
    0%, 100% { transform: translateY(-54%) rotate(-2deg); }
    50%      { transform: translateY(-46%) rotate(2deg); }
}

@keyframes np-drift {
    from { background-position-x: 0; }
    to   { background-position-x: 900px; }
}

@keyframes np-breathe {
    0%, 100% { opacity: 0.45; }
    50%      { opacity: 1; }
}

@keyframes np-morph {
    0%, 100% { border-radius: 46% 54% 60% 40% / 50% 44% 56% 50%; transform: translate(0, 0); }
    33%      { border-radius: 58% 42% 44% 56% / 42% 58% 42% 58%; transform: translate(-14px, 10px); }
    66%      { border-radius: 40% 60% 54% 46% / 56% 42% 58% 44%; transform: translate(10px, -8px); }
}

@keyframes np-clips {
    from { background-position: 130% 42px, 60% 100px, 88% 158px, 55% 216px; }
    to   { background-position: 45% 42px, 145% 100px, 50% 158px, 140% 216px; }
}

@keyframes np-scan {
    0%, 100% { background-position-x: -80%; }
    50%      { background-position-x: 180%; }
}

@keyframes np-cells {
    0%   { background-position: 45% 30%; }
    20%  { background-position: 70% 55%; }
    40%  { background-position: 55% 75%; }
    60%  { background-position: 85% 35%; }
    80%  { background-position: 62% 50%; }
    100% { background-position: 45% 30%; }
}

@keyframes np-agenda {
    0%   { background-position: 60% 25%; }
    25%  { background-position: 75% 60%; }
    50%  { background-position: 48% 45%; }
    75%  { background-position: 88% 30%; }
    100% { background-position: 60% 25%; }
}

@keyframes np-dashflow {
    from { background-position-x: 0; }
    to   { background-position-x: 12px; }
}

@keyframes np-sweep {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

/* blips flash as the radar beam passes (roughly in phase with np-sweep) */
@keyframes np-blip {
    0%, 100% { opacity: 0.55; }
    12%      { opacity: 1; }
}

@media (prefers-reduced-motion: reduce) {
    .np-rise,
    .np-wire-line,
    .np-wire-pulse,
    .np-node-inner,
    .np-pulse,
    .np-marker,
    .np-app-card,
    .np-community-card,
    .np-card-cta svg,
    .np-community-arrow,
    .np-slide-ghost,
    .np-scene::before,
    .np-scene::after,
    .np-scene--buzz::after,
    .np-leg,
    .np-station--origin .np-station-disc::after,
    .np-locator-sweep,
    .np-locator-blip,
    .np-car-control,
    .np-car-indicator {
        animation: none !important;
        transition: none !important;
    }

    /* entrance animations must not strand elements invisible */
    .np-rise { opacity: 1; transform: none; }
    .np-node-inner { opacity: 1; }
    .np-wire-line { transform: scaleX(1); }
    .np-wire-pulse { opacity: 0; }

    .np-app-card:hover,
    .np-community-card:hover { transform: none; }
}

/* ---------- small screens ---------- */
@media (max-width: 992px) {
    .np-slide-content { max-width: 100%; }

    .np-slide-ghost { display: none; }

    .np-scene {
        -webkit-mask-image: linear-gradient(to bottom, transparent 30%, rgba(0, 0, 0, 0.45) 100%);
        mask-image: linear-gradient(to bottom, transparent 30%, rgba(0, 0, 0, 0.45) 100%);
    }
}

@media (max-width: 768px) {
    .np-roundtrip { grid-template-columns: 1fr; justify-items: center; }

    .np-leg {
        margin-top: 0;
        height: 34px;
        min-width: 2px;
        width: 2px;
        background-image: repeating-linear-gradient(180deg,
            light-dark(rgba(51, 153, 255, 0.55), rgba(51, 153, 255, 0.6)) 0 6px,
            transparent 6px 12px);
        animation: none;
    }

    .np-leg::after {
        right: -3px;
        top: auto;
        bottom: -2px;
        border: 4px solid transparent;
        border-top: 6px solid light-dark(rgba(51, 153, 255, 0.7), rgba(51, 153, 255, 0.75));
    }

    .np-domain-row { flex-wrap: wrap; }
}

@media (max-width: 480px) {
    .np-plot { max-width: 340px; }

    .np-slide-card { min-height: 420px; }
}
