/* Framer positioning; Mobbin typography, white surface and pill actions. */
.landing-hero{max-width:1440px;margin:0 auto;padding:204px 64px 56px;color:#171717;background:#fff}
.landing-hero__copy{text-align:left}
.landing-hero h1{margin:0;font-family:"Hiragino Sans","Hiragino Kaku Gothic ProN",sans-serif;font-size:clamp(40px,4.2vw,60px);line-height:1.5;letter-spacing:-.025em;font-weight:500}
.landing-hero__actions .hero-actions{display:flex;justify-content:flex-start;gap:10px;margin:40px 0 88px}
.landing-hero__actions .button{min-height:44px;padding:11px 20px;border-radius:999px;font-size:14px;font-weight:600;line-height:1.5}
.landing-hero__actions .button-dark{background:#171717;color:#fff}
.landing-hero__actions .button-light{background:#f2f2f2;color:#171717}
.landing-hero__demo{display:block;width:100%;aspect-ratio:16/9;padding:24px;border-radius:28px;overflow:hidden;background:#f4f4f4}
.landing-hero__demo img{display:block;width:100%;height:100%;object-fit:cover;object-position:top;border-radius:16px}
.landing-hero__stats{margin-top:24px;text-align:left}
.landing-hero__stats p{font-size:13px;line-height:1.9;color:#777}
.landing-hero__stats strong{font-weight:500;color:inherit}
@media(max-width:760px){.landing-hero{padding:152px 24px 40px}.landing-hero h1{font-size:clamp(24px,7.2vw,42px);line-height:1.65;letter-spacing:-.025em}.landing-hero__actions .hero-actions{margin:32px 0 56px;gap:8px}.landing-hero__actions .button{min-height:42px;padding:10px 16px;font-size:12px}.landing-hero__demo{padding:10px;border-radius:18px;aspect-ratio:4/3}.landing-hero__demo img{border-radius:10px;object-fit:cover;object-position:left top}.landing-hero__stats p{font-size:11px}}

/* Slot geometry and entrance keyframes retained from Mobbin module 54140. */
.landing-hero h1{--icon-size:1em;--icon-drop:.075em;--icon-gap:.2em;--icon-cluster-gap:.12em;--slot-closed:.194em;--slot-open:calc(var(--icon-size) + 2 * var(--icon-gap))}
.landing-hero__line{display:block;white-space:nowrap}
@keyframes hero-slot-open {
          from { width: var(--slot-closed); margin-inline: 0; }
          to { width: var(--slot-open); margin-inline: var(--icon-gap); }
        }
        /* Pulls a slot up against the one before it — see `.hero-slot + .hero-slot` below. */
        @keyframes hero-slot-cluster {
          from { margin-left: 0; }
          to { margin-left: calc(var(--icon-cluster-gap) - 2 * var(--icon-gap)); }
        }
        @keyframes hero-slot-in {
          0% { opacity: 0; transform: translateX(-50%) scale(.72); filter: blur(7px); }
          45% { opacity: 1; transform: translateX(-50%) scale(1.02); filter: blur(0); }
          68% { transform: translateX(-50%) scale(.995); }
          85% { transform: translateX(-50%) scale(1.001); }
          100% { opacity: 1; transform: translateX(-50%) scale(1); filter: blur(0); }
        }
        .hero-line {
          display: block;
        }
        .hero-slot {
          position: relative;
          display: inline-block;
          height: 0;
          width: var(--slot-closed);
          animation: hero-slot-open 260ms cubic-bezier(0.16, 1, 0.3, 1) both;
        }
        /*
         * Each slot carries a gap on *both* sides, so two adjacent slots put two of them between
         * their icons. That reads fine when slots are separated by words, but the moment they sit
         * next to each other the pair looks twice as far apart as it should.
         *
         * This closes that back up to a single `--icon-cluster-gap`: the negative margin cancels
         * both facing gaps and re-adds one. It runs as a second animation on the same timing as
         * the slot's own opening (a single inline `animation-delay` applies to both), so it eases
         * in alongside the width rather than being a constant offset — the resting, pre-icon line
         * stays spaced exactly as its copy would be.
         */
        .hero-slot + .hero-slot {
          animation:
            hero-slot-open 260ms cubic-bezier(0.16, 1, 0.3, 1) both,
            hero-slot-cluster 260ms cubic-bezier(0.16, 1, 0.3, 1) both;
        }
        .hero-slot-inner {
          position: absolute;
          left: 50%;
          bottom: calc(-1 * var(--icon-drop));
          width: var(--icon-size);
          height: var(--icon-size);
          transform: translateX(-50%);
          animation: hero-slot-in 440ms ease-out both;
        }
        .hero-icon-button {
          position: relative;
          display: block;
          width: 100%;
          height: 100%;
          padding: 0;
          border: 0;
          border-radius: 20%;
          background: transparent;
          color: inherit;
          cursor: pointer;
        }
        .hero-icon-button:focus-visible {
          outline: 2px solid currentColor;
          outline-offset: 4px;
        }
        /* Motion owns both swap directions now (see `ICON_VARIANTS`); this only stacks the icon
           layers on top of each other so they can cross past each other in place. */
        .hero-icon-layer {
          position: absolute;
          inset: 0;
          display: block;
          border-radius: 30%;
        }
        /* The same inset border every app icon gets on mobbin.com
           (lib/apps/app-logo/AppLogo.tsx's `after:shadow-logo-inset`, applied unconditionally —
           its own `border` prop defaults to `true`), reproduced verbatim rather than only on
           icons whose source art needs it — via `var(--shadow-logo-inset)` (app/globals.css's own
           token for this exact value) rather than the literal, so it stays in sync with the token
           and resolves correctly if dark mode is ever wired up. */
        .hero-icon-layer::after {
          content: '';
          position: absolute;
          inset: 0;
          border-radius: 30%;
          box-shadow: var(--shadow-logo-inset);
          pointer-events: none;
        }
        @media (prefers-reduced-motion: reduce) {
          .hero-slot, .hero-slot-inner {
            animation: none;
          }
          .hero-slot {
            width: var(--slot-open);
            margin-inline: var(--icon-gap);
          }
        }

.hero-icon-layer{width:100%;height:100%;object-fit:cover}.hero-icon-button img{max-width:none}

/* Native inline video: no player chrome or interactive overlay. */
.landing-hero__demo{padding:0;aspect-ratio:16/9;position:relative}
.landing-hero__video{display:block;width:100%;height:100%;object-fit:contain;pointer-events:none;background:#fff}
.landing-hero__video::-webkit-media-controls,.landing-hero__video::-webkit-media-controls-enclosure,.landing-hero__video::-webkit-media-controls-panel,.landing-hero__video::-webkit-media-controls-start-playback-button{display:none!important;-webkit-appearance:none}

/* Keep the initial text contiguous; slot width and side gaps open together. */
.landing-hero__line{display:flex;align-items:center;gap:0}
.landing-hero h1{--slot-closed:0px;--slot-open:var(--icon-size)}
.landing-hero__line .hero-slot{height:var(--icon-size);flex-shrink:0;letter-spacing:0}
.landing-hero__line .hero-slot-inner{bottom:0}
.hero-line-text{letter-spacing:0}

.hero-icon-button .hero-icon-layer{object-fit:contain}

/* Read top-to-bottom, then open the icon slots once the copy has settled. */
@keyframes landing-hero-reveal{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
.landing-hero h1,.landing-hero__actions,.landing-hero__demo,.landing-hero__stats{animation:landing-hero-reveal 700ms cubic-bezier(.22,1,.36,1) both}
.landing-hero h1{animation-delay:0ms}
.landing-hero__actions{animation-delay:180ms}
.landing-hero__demo{animation-delay:360ms}
.landing-hero__stats{animation-delay:540ms}
.landing-hero__line{--hero-icon-start:1300ms}
.landing-hero__line:nth-child(2){--hero-icon-start:1380ms}
.landing-hero__line .hero-slot{animation-delay:var(--hero-icon-start)!important}
.landing-hero__line .hero-slot-inner{animation-delay:calc(var(--hero-icon-start) + 40ms)!important}
@media(prefers-reduced-motion:reduce){.landing-hero h1,.landing-hero__actions,.landing-hero__demo,.landing-hero__stats{animation:none}}
