@import url("mz-menu.css"); /* login-control styles (.mz-user / .mz-gbtn) */
@import url("cosmic-rail.css?v=r2"); /* canonical vertical rail (single source — do NOT redeclare .rail*) */
/* Align the home login icon with the top-bar login slot on every other page:
   the right edge of the centered 1080 content column (minus its 24px + 2px insets). */
.mz-auth-home { position: fixed; top: 26px; right: max(18px, calc((100vw - 1080px) / 2 + 26px)); z-index: 6000; }
.mz-auth-home:empty { display: none; }
/* css/landing.css — Mazmazika "Music Planet" landing hub.
   Extracted from the design prototype; component-injected CSS (tweaks panel,
   shared hero) ships inside js/landing/mz-ui.jsx. */

  *, *::before, *::after { box-sizing: border-box; }
  html, body { height: 100%; margin: 0; }
  body {
    font-family: var(--font-body, "Geist", system-ui, sans-serif);
    color: var(--ink, #f3efff);
    background: var(--bg, #080611);
    overflow: hidden;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
  }
  #root { height: 100%; }

  .app {
    position: relative;
    height: 100dvh;
    width: 100%;
    overflow: hidden;
    color: var(--ink);
    transition: color .5s ease;
    /* Centre the hub (sun + wheel + card, all left:50%) in the area to the RIGHT
       of the fixed rail, not the raw viewport — otherwise it sits ~half a rail
       width left of the usable centre (very visible on tablets). A transparent
       BORDER insets the containing block for the absolute children; the fixed
       background + rail still span edge-to-edge. Width MUST track the rail:
       66px normally, 56px on touch (hover:none) and ≤760px — see the overrides
       (cosmic-rail.css sets the matching rail widths). */
    border-left: 66px solid transparent;
  }
  /* Touch devices (incl. iPads at any width) use the 56px rail → match it. */
  @media (hover: none) { .app { border-left-width: 56px; } }

  /* ── Background ───────────────────────────────────────────── */
  .bg { position: fixed; inset: 0; z-index: 0; pointer-events: none; overflow: hidden; }
  .bg-base {
    position: absolute; inset: 0;
    background:
      radial-gradient(120% 95% at 50% 12%, var(--bg3), transparent 56%),
      radial-gradient(110% 80% at 50% 118%, var(--bg2), transparent 62%),
      var(--bg);
    transition: background .5s ease;
  }
  .bg-nebula {
    position: absolute; inset: -22%;
    background:
      radial-gradient(52% 58% at 24% 26%, color-mix(in srgb, var(--glow) 30%, transparent), transparent 76%),
      radial-gradient(56% 60% at 80% 80%, color-mix(in srgb, var(--accent) 26%, transparent), transparent 78%),
      radial-gradient(48% 52% at 84% 20%, color-mix(in srgb, var(--accent2) 20%, transparent), transparent 78%);
    filter: blur(54px);
    opacity: .5;
    transition: opacity .5s ease;
  }
  .app[data-motion="1"] .bg-nebula { animation: nebula-drift 38s ease-in-out infinite alternate; }
  @keyframes nebula-drift {
    0%   { transform: translate3d(0,0,0) scale(1); }
    100% { transform: translate3d(2.5%, -2%, 0) scale(1.08); }
  }
  .is-light .bg-nebula { opacity: .4; }

  .bg-stars { position: absolute; inset: 0; color: #fff; }
  .bg-stars span {
    position: absolute; border-radius: 50%;
    background: currentColor;
    box-shadow: 0 0 6px color-mix(in srgb, currentColor 70%, transparent);
  }
  .app[data-motion="1"] .bg-stars.twinkle span { animation: twinkle linear infinite; }
  @keyframes twinkle { 0%,100% { opacity: .2; } 50% { opacity: 1; } }
  .is-light .bg-stars { color: var(--accent); opacity: .3; }

  .bg-grain {
    position: absolute; inset: 0; mix-blend-mode: overlay; opacity: .5;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
  }
  .bg-vignette {
    position: absolute; inset: 0;
    background: radial-gradient(115% 100% at 50% 42%, transparent 52%, color-mix(in srgb, var(--bg) 92%, black) 100%);
    transition: background .5s ease;
  }

  /* ── Hero (siblings share root stacking context for depth) ─ */
  .hero { position: absolute; inset: 0; pointer-events: none; }

  /* welcome wordmark — moved to the TOP of the page */
  .hero-text {
    position: absolute; left: 50%; top: 30px; transform: translateX(-50%);
    z-index: 650; text-align: center; pointer-events: none; width: min(94vw, 920px);
  }
  .hero-eyebrow {
    font-family: var(--font-body); font-size: 12px; font-weight: 600;
    letter-spacing: .42em; text-indent: .42em; color: var(--sub);
    text-transform: uppercase; margin-bottom: 10px; opacity: .9;
  }
  .wordmark {
    margin: 0; font-family: var(--font-display); font-style: var(--display-style);
    font-weight: 600; line-height: .9; letter-spacing: -.01em;
    font-size: clamp(40px, 7vw, 100px);
    color: var(--ink);
    text-shadow: 0 2px 40px color-mix(in srgb, var(--glow) 45%, transparent);
  }
  .is-dark .wordmark { color: #fff; }
  .tagline {
    margin: 8px 0 0; font-family: var(--font-display); font-style: var(--display-style);
    font-size: clamp(16px, 2.2vw, 24px); color: var(--ink); opacity: .82;
    letter-spacing: .01em;
  }

  /* decorative orbit rings around the sun */
  .orbits { position: absolute; inset: 0; z-index: 120; }
  .orbit {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
    border: 1px solid color-mix(in srgb, var(--ink) 13%, transparent);
    border-radius: 50%;
  }
  .orbit-1 { width: 760px; height: 232px; }
  .orbit-2 { width: 1040px; height: 318px; border-color: color-mix(in srgb, var(--ink) 8%, transparent); }

  /* ── Musical Sun — realistic warm star, smaller & lifted above the bubbles ── */
  .sun {
    position: absolute; left: 50%; top: 46%; transform: translate(-50%,-50%);
    width: 300px; height: 300px; z-index: 300; pointer-events: none;
  }
  .sun-glow {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
    width: 400px; height: 400px; border-radius: 50%;
    background: radial-gradient(circle,
      rgba(255,170,80,.5) 0%,
      rgba(255,120,40,.28) 26%,
      color-mix(in srgb, var(--glow) 22%, transparent) 48%,
      transparent 64%);
    filter: blur(30px); opacity: .9; transition: background .5s ease;
  }
  .app[data-motion="1"] .sun-glow { animation: sunglow 6s ease-in-out infinite; }
  @keyframes sunglow { 0%,100% { opacity: .72; } 50% { opacity: 1; } }
  .is-light .sun-glow { opacity: .62; }

  .sun-ripple {
    position: absolute; left: 50%; top: 50%; width: 250px; height: 250px; border-radius: 50%;
    border: 1.5px solid rgba(255,190,120,.45);
    transform: translate(-50%,-50%) scale(.55); opacity: 0;
  }
  .app[data-motion="1"] .sun-ripple { animation: sunripple 4.4s ease-out infinite; }
  .sr2 { animation-delay: 1.5s !important; }
  .sr3 { animation-delay: 3s !important; }
  @keyframes sunripple {
    0% { transform: translate(-50%,-50%) scale(.5); opacity: 0; }
    14% { opacity: .5; }
    100% { transform: translate(-50%,-50%) scale(1.5); opacity: 0; }
  }

  .sun-eq { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible;
    filter: drop-shadow(0 0 7px rgba(255,150,60,.5)); }
  .eq-bar { transform-box: fill-box; transform-origin: 50% 100%; transform: scaleY(var(--base)); }
  .app[data-motion="1"] .eq-bar { animation-name: eq; animation-timing-function: ease-in-out;
    animation-iteration-count: infinite; animation-direction: alternate; }
  @keyframes eq {
    from { transform: scaleY(calc(var(--base) * .4)); }
    to   { transform: scaleY(calc(var(--base) * 1.3)); }
  }

  .sun-core {
    position: absolute; left: 50%; top: 50%; transform: translate(-50%,-50%);
    width: 140px; height: 140px; border-radius: 50%; display: grid; place-items: center; overflow: hidden;
    background:
      radial-gradient(circle at 42% 37%,
        #fffdf4 0%, #ffe7a2 15%, #ffc24d 38%, #ff8a32 64%, #ef5a1c 85%, #be3a11 100%);
    box-shadow:
      0 0 64px 2px rgba(255,150,60,.5),
      inset -9px -13px 30px rgba(140,38,8,.6),
      inset 7px 9px 24px rgba(255,244,210,.5);
    color: rgba(255,255,255,.96);
  }
  .sun-surface {
    position: absolute; inset: 0; border-radius: 50%;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='p'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.035' numOctaves='3' seed='7'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23p)'/%3E%3C/svg%3E");
    background-size: 150% 150%; mix-blend-mode: soft-light; opacity: .6;
  }
  .app[data-motion="1"] .sun-surface { animation: boil 16s linear infinite; }
  @keyframes boil {
    0% { background-position: 0% 0%; transform: scale(1); }
    50% { transform: scale(1.12); }
    100% { background-position: 120% 90%; transform: scale(1); }
  }
  .sun-flare {
    position: absolute; inset: 0; border-radius: 50%; mix-blend-mode: screen;
    background: radial-gradient(38% 30% at 64% 30%, rgba(255,246,210,.85), transparent 60%),
                radial-gradient(30% 24% at 32% 66%, rgba(255,170,90,.6), transparent 62%);
  }
  .app[data-motion="1"] .sun-flare { animation: flare 9s ease-in-out infinite; }
  @keyframes flare { 0%,100% { opacity: .8; transform: rotate(0deg) scale(1); } 50% { opacity: 1; transform: rotate(8deg) scale(1.05); } }
  .sun-core-sheen { position: absolute; inset: 0; border-radius: 50%;
    background: radial-gradient(50% 40% at 38% 26%, rgba(255,255,255,.7), transparent 56%); }
  .sun-wave { position: relative; width: 96px; height: 38px; z-index: 1;
    filter: drop-shadow(0 1px 3px rgba(120,40,0,.5)); }
  .wave-path { color: rgba(255,255,255,.96); }
  .app[data-motion="1"] .wave-path { animation: wavebreathe 3.4s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
  @keyframes wavebreathe { 0%,100% { transform: scaleY(.7); } 50% { transform: scaleY(1.15); } }

  /* Fixed-size shell: it holds perfectly still while the wheel turns — a constant
     width band (NOT shrink-wrapped to the text) and a constant height (see .no-desc
     min-height + 2-line clamp), so the card no longer resizes or re-slides on each
     rotation step. Only the text inside dissolves (see .no-stage / .no-layer).
     The `nowin` slide now plays ONCE on mount (the card is no longer re-keyed). */
  .now-orbit {
    position: absolute; left: 50%; bottom: 54px; transform: translateX(-50%);
    z-index: 720; display: block;
    width: min(92vw, 720px);
    padding: 24px 38px 24px 30px; border-radius: 30px;
    background: color-mix(in srgb, var(--bg2) 72%, transparent);
    border: 1px solid var(--line);
    -webkit-backdrop-filter: blur(18px) saturate(160%); backdrop-filter: blur(18px) saturate(160%);
    box-shadow: 0 24px 70px -22px rgba(0,0,0,.7), inset 0 1px 0 rgba(255,255,255,.08);
    font-family: var(--font-body); pointer-events: none;
    animation: nowin .5s cubic-bezier(.2,.7,.3,1);
  }
  @keyframes nowin { from { transform: translate(-50%, 10px); } to { transform: translateX(-50%); } }
  /* Crossfade stage: the current text sits in normal flow (it defines the card's —
     now constant — size); the outgoing text is overlaid absolutely and dissolves
     out, so the two cross-fade in place with no layout shift. Opacity-only, so it
     stays smooth (and reduced-motion friendly) regardless of the motion toggle. */
  .no-stage { position: relative; width: 100%; }
  .no-layer { display: flex; align-items: center; gap: 26px; width: 100%; }
  /* SEQUENTIAL fade, not simultaneous: the outgoing text fades OUT, then the
     incoming fades IN (in-delay ≈ out-duration). Two different strings are never
     both readable at once — a simultaneous crossfade ghosts them together
     ("Blog Center", "Mazmazikaver"). The shell holds still throughout, so the
     swap reads as one clean in-place text change. */
  .no-layer.no-out { position: absolute; inset: 0; pointer-events: none; animation: nolayerout .22s ease both; }
  .no-layer.no-in  { animation: nolayerin .28s ease .18s both; }
  @keyframes nolayerin  { from { opacity: 0; } to { opacity: 1; } }
  @keyframes nolayerout { from { opacity: 1; } to { opacity: 0; } }
  .no-dot { width: 16px; height: 16px; border-radius: 50%; flex-shrink: 0;
    background: var(--accent); box-shadow: 0 0 16px 2px var(--accent); }
  .app[data-motion="1"] .no-dot { animation: blip 1.8s ease-in-out infinite; }
  @keyframes blip { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
  .no-stack { display: flex; flex-direction: column; gap: 6px; align-items: flex-start; min-width: 0; flex: 1 1 auto; }
  .no-label { font-family: var(--font-display); font-style: var(--display-style);
    font-weight: 600; font-size: clamp(28px, 3.4vw, 40px); line-height: 1; color: var(--ink); white-space: nowrap;
    text-shadow: 0 2px 18px color-mix(in srgb, var(--glow) 30%, transparent); }
  .no-desc { font-size: clamp(16px, 1.5vw, 21px); line-height: 1.4; color: var(--ink); opacity: .82;
    text-wrap: pretty;
    /* Clamp to 2 lines AND reserve 2 lines of height, so a one-line blurb and a
       two-line one give the card the SAME height — no vertical jump between tools. */
    display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
    min-height: 2.8em; }
  .no-open { pointer-events: auto; flex-shrink: 0; margin-left: 6px; padding: 13px 24px; border-radius: 999px;
    background: var(--accent); color: #fff; font-size: 16px; font-weight: 600; text-decoration: none; white-space: nowrap;
    box-shadow: 0 0 22px -2px color-mix(in srgb, var(--accent) 70%, transparent); transition: filter .15s ease, transform .12s ease; }
  .no-open:hover { filter: brightness(1.1); transform: translateY(-1px); }
  /* Mono palette: --accent is grayscale (near-white in dark, near-black in light),
     so white button text goes low-contrast. --bg is always the opposite luminance
     of --accent in Mono, giving a readable label in BOTH appearances. */
  .app[data-palette="mono"] .no-open { color: var(--bg); }

  .explore-hint {
    position: absolute; left: 50%; bottom: 34px; transform: translateX(-50%);
    z-index: 720; font-family: var(--font-body); font-size: 11px; letter-spacing: .18em;
    text-transform: uppercase; color: var(--sub); opacity: .6; pointer-events: none;
  }

  /* ── Wheel ────────────────────────────────────────────────── */
  .wheel-stage { position: absolute; inset: 0; cursor: grab; touch-action: none; }
  .wheel-stage.grabbing { cursor: grabbing; }
  .wheel-ring { position: absolute; inset: 0; }

  .bubble {
    position: absolute; left: 50%; top: 50%;
    width: 176px; display: flex; flex-direction: column; align-items: center;
    text-decoration: none; cursor: pointer;
    will-change: transform, filter, opacity;
  }
  .bubble-orb {
    position: relative; width: 152px; height: 152px; border-radius: 50%;
    display: grid; place-items: center;
    background:
      radial-gradient(circle at 34% 25%, rgba(255,255,255,.58), rgba(255,255,255,.06) 36%, transparent 56%),
      radial-gradient(circle at 64% 84%, color-mix(in srgb, var(--bubbleColor) 32%, transparent), transparent 64%),
      color-mix(in srgb, var(--bubbleColor) 9%, transparent);
    border: 1.5px solid color-mix(in srgb, var(--bubbleColor) 48%, white 30%);
    -webkit-backdrop-filter: blur(5px) saturate(150%); backdrop-filter: blur(5px) saturate(150%);
    box-shadow:
      inset 0 6px 24px rgba(255,255,255,.30),
      inset 0 -28px 48px color-mix(in srgb, var(--bubbleColor) 28%, transparent),
      inset 0 0 0 1px rgba(255,255,255,.07),
      0 20px 54px -18px color-mix(in srgb, var(--bubbleColor) 45%, transparent);
    transition: transform .25s cubic-bezier(.3,.7,.4,1), box-shadow .4s ease, border-color .4s ease, background .4s ease;
  }
  .is-light .bubble-orb {
    background:
      radial-gradient(circle at 34% 25%, rgba(255,255,255,.9), rgba(255,255,255,.12) 38%, transparent 58%),
      radial-gradient(circle at 64% 84%, color-mix(in srgb, var(--bubbleColor) 28%, transparent), transparent 64%),
      color-mix(in srgb, var(--bubbleColor) 12%, rgba(255,255,255,.16));
    border-color: color-mix(in srgb, var(--bubbleColor) 42%, white 12%);
    box-shadow:
      inset 0 6px 22px rgba(255,255,255,.72),
      inset 0 -24px 44px color-mix(in srgb, var(--bubbleColor) 20%, transparent),
      inset 0 0 0 1px rgba(255,255,255,.5),
      0 20px 50px -20px color-mix(in srgb, var(--bubbleColor) 38%, transparent);
  }
  .bubble-sheen {
    position: absolute; inset: 9px; border-radius: 50%; pointer-events: none;
    background: radial-gradient(62% 42% at 38% 19%, rgba(255,255,255,.62), rgba(255,255,255,0) 70%);
  }
  .bubble-icon { color: #ffffff; display: grid; place-items: center;
    filter: drop-shadow(0 1px 7px color-mix(in srgb, var(--bubbleColor) 45%, transparent)); }
  .is-light .bubble-icon { color: #0b0b12; filter: drop-shadow(0 1px 4px rgba(0,0,0,.16)); }
  .bubble-icon svg { display: block; width: 54px; height: 54px; }

  .bubble-label {
    margin-top: 17px; font-family: var(--font-body); font-weight: 600; font-size: 16px;
    color: var(--ink); white-space: nowrap; letter-spacing: .005em;
    text-shadow: 0 2px 16px color-mix(in srgb, var(--bg) 82%, transparent);
    transition: color .3s ease;
  }
  .bubble.is-front .bubble-label { color: var(--ink); }
  /* Bubble-only short labels for narrow viewports (<1024px): the rotating
     planets crowd together on smaller screens, so a few long tool names collapse
     to shorter forms ON THE BUBBLE ONLY. The readout card title, the vertical
     rail and the horizontal menu all keep the full names. */
  .bubble-label .bl-short { display: none; }
  @media (max-width: 1023.98px) {
    .bubble-label .bl-full { display: none; }
    .bubble-label .bl-short { display: inline; }
  }
  .bubble.is-front .bubble-orb {
    border-color: color-mix(in srgb, var(--bubbleColor) 70%, white 30%);
    box-shadow:
      inset 0 6px 26px rgba(255,255,255,.38),
      inset 0 -30px 52px color-mix(in srgb, var(--bubbleColor) 36%, transparent),
      inset 0 0 0 1px rgba(255,255,255,.12),
      0 26px 64px -16px color-mix(in srgb, var(--bubbleColor) 52%, transparent),
      0 0 34px -4px color-mix(in srgb, var(--bubbleColor) 36%, transparent);
  }
  .bubble.is-hover .bubble-orb { transform: translateY(-6px); }

  .bubble-desc {
    position: absolute; top: calc(100% + 6px); left: 50%; transform: translate(-50%, 6px);
    width: 196px; padding: 11px 14px; border-radius: 13px;
    font-family: var(--font-body); font-size: 12.5px; line-height: 1.45; color: var(--ink);
    background: color-mix(in srgb, var(--bg2) 80%, transparent);
    border: 1px solid var(--line);
    -webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
    box-shadow: 0 14px 40px -16px rgba(0,0,0,.7);
    opacity: 0; pointer-events: none; transition: opacity .2s ease, transform .2s ease;
    text-wrap: pretty; z-index: 5;
  }
  .bubble.is-hover .bubble-desc { opacity: 1; transform: translate(-50%, 0); }
  /* Bottom-arc bubbles (is-low, set by the wheel layout) sit just above the
     readout card — their tooltip would overlap it, and the card already shows
     the hovered tool's description, so it stays hidden there. */
  .bubble.is-low .bubble-desc { display: none; }

  /* Menu rail → css/cosmic-rail.css (single source, imported at top). */

  /* ── Tweak panel: custom theme swatch grid ────────────────── */
  .mz-swatches { display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px; }
  .mz-sw { height: 26px; border-radius: 7px; border: 0; cursor: pointer; padding: 0;
    box-shadow: 0 0 0 .5px rgba(0,0,0,.15), 0 1px 2px rgba(0,0,0,.12);
    transition: transform .12s ease, box-shadow .12s ease; }
  .mz-sw:hover { transform: translateY(-1px); }
  .mz-sw.on { box-shadow: 0 0 0 2px rgba(20,20,30,.9), 0 2px 6px rgba(0,0,0,.2); }

  /* ── responsive ───────────────────────────────────────────── */
  @media (max-width: 760px) {
    /* Centre the whole hub in the area to the RIGHT of the fixed rail (mobile
       only — desktop is unchanged). A transparent BORDER, not padding: an
       absolutely-positioned child's containing block is the padding box (inside
       the border), so left:50% now centres past the rail; padding would have left
       it spanning the full width. The fixed background + rail span edge-to-edge. */
    .app { border-left: 56px solid transparent; }
    .sun { width: 300px; height: 300px; }
    .sun-glow { width: 300px; height: 300px; }
    .sun-core { width: 120px; height: 120px; }
    .sun-wave { width: 84px; height: 34px; }
    .orbit-1 { width: 460px; height: 150px; } .orbit-2 { width: 640px; height: 200px; }
    /* Smaller bubbles by default on phones (fewer + smaller + a wider ring keeps
       them apart — labels stay, every bubble keeps its own). */
    .bubble { width: 92px; } .bubble-orb { width: 52px; height: 52px; }
    .bubble-icon svg { width: 22px; height: 22px; }
    .bubble-label { font-size: 12px; margin-top: 8px; }
    .hero-text { top: 18px; width: 92vw; }
    /* The focused-page card floats ABOVE the corner tweaks FAB and shows its FULL
       description — no line clamp. A column layout gives the text the whole card
       width so long taglines are never cut off. (FAB override just below.) */
    /* A consistent, comfortably WIDE card (a fixed-width band, not shrink-wrapped
       to the text) centred in the content area with even left/right breathing. */
    .now-orbit { padding: 16px 18px; width: min(90%, 380px); bottom: 84px; border-radius: 22px; }
    .no-layer { flex-direction: column; align-items: flex-start; gap: 9px; }
    .now-orbit .no-dot { display: none; }
    .no-stack { width: 100%; gap: 5px; }
    .no-label { font-size: clamp(21px, 5.6vw, 27px); white-space: normal; line-height: 1.1; }
    /* Phones show the FULL blurb (deliberate — see note above), so release the
       desktop 2-line clamp and its reserved height here. */
    .no-desc { display: block; overflow: visible; -webkit-line-clamp: unset;
      min-height: 0; font-size: 14px; line-height: 1.4; }
    .no-open { align-self: flex-start; margin-left: 0; padding: 10px 20px; font-size: 15px; }
    /* Tweaks FAB (and the panel it opens) sit in the bottom-right CORNER on the
       home landing, with the card floating above them. This overrides the shared
       component's mobile "lift" (mz-ui.jsx) WITHOUT touching it — the `.app`
       scope outranks its plain `.mzp-*` rules, so only home is affected. */
    .app .mzp-fab   { bottom: 18px; right: 18px; }
    .app .mzp-panel { bottom: 18px; right: 18px; max-height: calc(100dvh - 36px); }
    .explore-hint { display: none; }
    /* rail mobile behaviour lives in cosmic-rail.css */
  }
  @media (max-width: 460px) {
    .sun { width: 248px; height: 248px; }
    .sun-glow { width: 248px; height: 248px; }
    .sun-core { width: 104px; height: 104px; }
    .sun-wave { width: 74px; height: 30px; }
    .orbit-1 { width: 360px; height: 116px; } .orbit-2 { width: 500px; height: 158px; }
    .bubble { width: 80px; } .bubble-orb { width: 44px; height: 44px; }
    .bubble-icon svg { width: 18px; height: 18px; }
    .bubble-label { font-size: 10.5px; margin-top: 7px; }
    .wordmark { font-size: clamp(32px, 11vw, 46px); }
    .tagline { font-size: clamp(14px, 4.2vw, 18px); }
    .now-orbit { gap: 8px; padding: 14px 16px; bottom: 84px; border-radius: 18px; width: min(92%, 340px); }
    .no-label { font-size: clamp(19px, 6vw, 24px); }
    .no-open { padding: 9px 16px; font-size: 14px; }
  }
  /* ── Tablet band (761–1023px): bubbles render BETWEEN the phone size (≤760px,
        above) and the desktop base (≥1024px, the 152px orb defined earlier), so
        the default bubbleSize:1 reads as a logical, proportionate size at every
        viewport instead of jumping straight to full desktop size on a narrow
        screen. Size only — the ring's radius is width-driven in JS, and the Ry
        clamp reads the live bubble height, so both adapt automatically. */
  @media (min-width: 761px) and (max-width: 1023.98px) {
    .bubble { width: 124px; }
    .bubble-orb { width: 104px; height: 104px; }
    .bubble-icon svg { width: 38px; height: 38px; }
    .bubble-label { margin-top: 12px; font-size: 14px; }
  }
  /* ── Wide / short-height desktops (e.g. ultrawide monitors, non-maximised or
        32:9 windows) ───────────────────────────────────────────────────────────
     The wheel is centred on the viewport, so when the usable HEIGHT shrinks the
     front bubble descends into the bottom info card and overlaps it. Width alone
     is fine — the ring radius caps at 560px — so the collision is HEIGHT-driven.
     Lift the hub (sun + orbits + ring) and tuck the card lower on short viewports
     so the front bubble always clears the card. Desktop only (≥761px); phones use
     the mobile layout above. 1920×1080 is unaffected (height > 920). */
  @media (min-width: 761px) and (max-height: 920px) {
    .sun    { top: 43%; }
    .orbit  { top: 46%; }
    .bubble { top: 46%; }
    /* Keep the card clear of the front bubble AND well above the explore hint:
       raise it a touch, give it more vertical padding, and tuck the hint to the
       very bottom so the description never sticks to the "DRAG · SCROLL…" line. */
    .now-orbit { bottom: 56px; padding: 26px 38px 26px 30px; }
    .no-label { font-size: clamp(26px, 3.2vw, 34px); }
    .explore-hint { bottom: 14px; }
  }
  @media (min-width: 761px) and (max-height: 860px) {
    /* Shortest laptops: the description can wrap to 2 lines (narrower widths),
       making the card taller. Lift the RING a little more (the sun can't rise
       further without touching the tagline) and drop the card slightly so the
       front bubble still clears it, keeping the hint pinned low for separation. */
    .sun    { top: 40%; }
    .orbit  { top: 41%; }
    .bubble { top: 41%; }
    .now-orbit { bottom: 50px; padding: 22px 32px 22px 26px; }
    .no-label { font-size: clamp(24px, 3vw, 32px); }
    .no-desc  { font-size: clamp(14px, 1.4vw, 18px); }
    .explore-hint { bottom: 12px; }
  }
  @media (prefers-reduced-motion: reduce) {
    .bg-nebula, .sun-glow, .sun-surface, .sun-flare, .sun-ripple, .eq-bar, .wave-path, .no-dot, .bg-stars span { animation: none !important; }
  }

/* No-JS / crawler fallback nav (rendered only inside <noscript>) */
.landing-noscript { padding: 24px; font-family: system-ui, sans-serif; color: #f3efff; background: #080611; }
.landing-noscript a { color: #a35bff; }
