/* SENTINEL MOTION LAYER v1 — clean, springy, reduced-motion safe.
   Everything is gated behind html.sm-on (added by motion.js only when the
   user does NOT prefer reduced motion), so no-JS and reduced-motion users
   get a fully visible, static page. */

/* ── Motion language ─────────────────────────────────────────────────────
   Declared once so the site moves like one product. An audit across index,
   blog, signup, login and dashboard found twelve different cubic-bezier
   spellings for roughly eight actual curves — the same curve written as
   both `.22,1,.36,1` and `0.22, 1, 0.36, 1` — plus durations bunched at
   0.12/0.15/0.16/0.18/0.2s all doing the same job. Individually invisible;
   collectively it is why the UI reads as assembled rather than designed.

   --sm-ease is the house curve: a pure decelerate, no overshoot. Interface
   chrome should arrive and settle, never bounce past its mark. --sm-spring
   keeps the overshoot available, but it is for deliberate accents (the logo
   wiggle), not for anything that carries layout.

   Three durations, matched to what the motion means: tap-feedback must feel
   instant, a state change should be perceptible, an entrance can breathe. */
:root {
    --sm-ease:       cubic-bezier(0.16, 1, 0.3, 1);
    --sm-ease-out:   cubic-bezier(0.22, 1, 0.36, 1);
    --sm-ease-inout: cubic-bezier(0.4, 0, 0.2, 1);
    --sm-spring:     cubic-bezier(0.34, 1.56, 0.64, 1);
    --sm-t-tap:   130ms;
    --sm-t-state: 260ms;
    --sm-t-enter: 560ms;
}

/* Sticky nav is 14px offset + a 60px pill. Without this, every in-page
   anchor, every find-in-page hit and every keyboard focus jump lands its
   target underneath the nav and the user has to scroll back up. */
html { scroll-padding-top: 88px; }

/* ── Scroll reveal (elements tagged .sm-reveal by motion.js) ── */
.sm-on .sm-reveal { opacity: 0; transform: translateY(16px); }
.sm-on .sm-reveal.sm-in {
    opacity: 1; transform: none;
    transition: opacity 0.65s var(--sm-ease), transform 0.65s var(--sm-ease);
    transition-delay: var(--sm-delay, 0ms);
}

/* ── Nav entrance: pill drops in softly ── */
.sm-on .nav-inner { animation: smNav 0.55s var(--sm-ease) both; }
@keyframes smNav { from { opacity: 0; transform: translateY(-16px); } to { opacity: 1; transform: none; } }

/* ── Logo mark: playful wiggle on hover ── */
.nav-logo .logo-mark { transition: transform 0.35s var(--sm-spring); }
.nav-logo:hover .logo-mark { transform: rotate(-10deg) scale(1.12); }

/* ── Lime CTA: shine sweep on hover ── */
.sm-on .btn-bracket-accent, .sm-on .btn-primary, .sm-on .btn-accent, .sm-on .submit-btn {
    position: relative; overflow: hidden;
}
.sm-on .btn-bracket-accent::after, .sm-on .btn-primary::after, .sm-on .btn-accent::after, .sm-on .submit-btn::after {
    content: ''; position: absolute; top: 0; left: -70%; width: 45%; height: 100%;
    background: linear-gradient(100deg, transparent, rgba(255,255,255,0.55), transparent);
    transform: skewX(-20deg); transition: left 0.55s ease; pointer-events: none;
}
.sm-on .btn-bracket-accent:hover::after, .sm-on .btn-primary:hover::after,
.sm-on .btn-accent:hover::after, .sm-on .submit-btn:hover::after { left: 130%; }

/* ── Nav links: underline slides in ── */
.sm-on .nav-links a { position: relative; }
.sm-on .nav-links a::after {
    content: ''; position: absolute; left: 14px; right: 14px; bottom: 5px; height: 2px;
    border-radius: 2px; background: #CCFF00; transform: scaleX(0); transform-origin: left;
    transition: transform 0.25s var(--sm-ease);
}
.sm-on .nav-links a:hover::after { transform: scaleX(1); }

/* ── Footer mascot: gentle bob ── */
.sm-on .mascot-footer img { animation: smBob 6s ease-in-out infinite; }
@keyframes smBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-9px); } }

/* ── Card cursor feedback everywhere (only adds where missing) ── */
.sm-on a[class*="card"]:active, .sm-on button:active { transform: scale(0.985); }

/* ── Cursor-tracking lime glow inside cards ── */
.sm-on .sm-glow { position: relative; }
.sm-on .sm-glow::before {
    content: ''; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
    background: radial-gradient(220px circle at var(--gx, 50%) var(--gy, 50%), rgba(204,255,0,0.16), transparent 65%);
    opacity: 0; transition: opacity 0.3s ease; z-index: 0;
}
.sm-on .sm-glow:hover::before { opacity: 1; }
.sm-on .sm-glow > * { position: relative; z-index: 1; }

/* ── Scan progress bar (top of page) ── */
.sm-progress { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 1500; pointer-events: none; }
.sm-progress-fill {
    height: 100%; width: 100%; transform: scaleX(0); transform-origin: left;
    background: linear-gradient(90deg, #bff000, #CCFF00);
    box-shadow: 0 0 10px rgba(204,255,0,0.55);
}

/* ── Human verified chip (first click) ── */
.sm-human {
    position: fixed; transform: translate(-50%, -140%); z-index: 1950; pointer-events: none;
    background: #101410; color: #CCFF00; font-family: 'Space Grotesk', sans-serif;
    font-size: 0.78rem; font-weight: 700; padding: 6px 12px; border-radius: 999px;
    box-shadow: 0 8px 24px rgba(16,20,16,0.3);
    animation: smHuman 1.5s var(--sm-ease) both;
}
@keyframes smHuman {
    0% { opacity: 0; transform: translate(-50%, -80%) scale(0.6); }
    18% { opacity: 1; transform: translate(-50%, -150%) scale(1.05); }
    30% { transform: translate(-50%, -140%) scale(1); }
    80% { opacity: 1; }
    100% { opacity: 0; transform: translate(-50%, -190%) scale(0.95); }
}

/* ── Hero letter wave ── */
.sm-word { display: inline-block; } /* keeps words unbreakable across lines */
.sm-ch { display: inline-block; }
.sm-waving .sm-ch { animation: smChWave 0.55s var(--sm-spring) calc(var(--i, 0) * 26ms) 1 both; }
@keyframes smChWave { 0%,100% { transform: translateY(0); } 40% { transform: translateY(-9px); } }

/* ── Soft page-exit transition ── */
.sm-on body { transition: opacity 0.17s ease, transform 0.17s ease; }
.sm-exit body { opacity: 0; transform: translateY(8px); }

/* ── Senti drag state ── */
.senti-drag .senti-bot { cursor: grabbing; }
.senti-drag .senti-antenna { animation: sentiAlarm 0.3s ease-in-out infinite; }

/* ── Senti, the mascot buddy ── */
.senti {
    position: fixed; right: 22px; bottom: 22px; z-index: 900;
    display: flex; flex-direction: column; align-items: flex-end;
    filter: drop-shadow(0 10px 24px rgba(16,20,16,0.18));
    animation: sentiIn 0.7s var(--sm-spring) 1s both;
}
@keyframes sentiIn { from { opacity: 0; transform: translateY(60px) scale(0.6); } to { opacity: 1; transform: none; } }
.senti-bot { cursor: pointer; transition: transform 0.3s var(--sm-spring); }
.senti-bot:hover { transform: translateY(-4px) rotate(-3deg); }
.senti-pupil { transition: transform 0.12s ease-out; }
.senti-antenna { animation: sentiPulse 2.4s ease-in-out infinite; transform-origin: 60px 6px; }
@keyframes sentiPulse { 0%,100% { opacity: 1; } 50% { opacity: 0.45; } }
.senti-wave .senti-bot { animation: sentiWiggle 0.7s var(--sm-spring); }
@keyframes sentiWiggle { 0%,100% { transform: rotate(0); } 25% { transform: rotate(-10deg); } 60% { transform: rotate(8deg); } }
.senti-hop { animation: sentiHop 0.45s var(--sm-spring) 2; }
@keyframes sentiHop { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-14px); } }
.senti-bubble {
    max-width: 230px; margin-bottom: 10px; padding: 10px 14px;
    background: #ffffff; border: 1px solid rgba(10,20,10,0.12); border-radius: 14px 14px 4px 14px;
    box-shadow: 0 10px 30px rgba(16,20,16,0.14);
    font-family: 'Space Grotesk', sans-serif; font-size: 0.85rem; line-height: 1.45; color: #101410;
    opacity: 0; transform: translateY(8px) scale(0.94); transform-origin: bottom right;
    transition: opacity 0.28s var(--sm-ease), transform 0.28s var(--sm-ease);
    pointer-events: none;
}
.senti-bubble.on { opacity: 1; transform: none; }
.senti-close {
    position: absolute; top: 14px; right: -6px; width: 22px; height: 22px;
    border-radius: 50%; border: 1px solid rgba(10,20,10,0.14); background: #fff; color: #68706a;
    font-size: 14px; line-height: 1; cursor: pointer; opacity: 0; transition: opacity 0.2s;
    display: flex; align-items: center; justify-content: center;
}
.senti:hover .senti-close { opacity: 1; }
.senti-close:hover { color: #101410; }

/* ── Sonar ping on click ── */
.sm-ping {
    position: fixed; width: 14px; height: 14px; margin: -7px 0 0 -7px;
    border: 2px solid rgba(120,160,10,0.75); border-radius: 50%;
    pointer-events: none; z-index: 1900;
    animation: smPing 0.6s var(--sm-ease) both;
}
@keyframes smPing { from { transform: scale(0.4); opacity: 1; } to { transform: scale(3.2); opacity: 0; } }

/* ── Confetti particles ── */
.sm-confetti {
    position: fixed; width: 8px; height: 12px; border-radius: 2px;
    pointer-events: none; z-index: 1950;
    animation: smConfetti 0.95s cubic-bezier(0.2,0.6,0.35,1) both;
}
@keyframes smConfetti {
    from { transform: translate(0,0) rotate(0); opacity: 1; }
    to { transform: translate(var(--cx, 0), calc(var(--cy, -80px) + 160px)) rotate(var(--cr, 180deg)); opacity: 0; }
}

/* ── Senti alert state (threat detected) ── */
.senti-alert .senti-antenna { fill: #ff4444; animation: sentiAlarm 0.5s ease-in-out infinite; }
@keyframes sentiAlarm { 0%,100% { opacity: 1; } 50% { opacity: 0.3; } }
.senti-alert .senti-pupil { transform: scale(1.35); transform-origin: center; }
.senti-alert .senti-bot { animation: sentiShiver 0.35s ease-in-out 4; }
@keyframes sentiShiver { 0%,100% { transform: translateX(0); } 25% { transform: translateX(-2px); } 75% { transform: translateX(2px); } }

/* Reduced motion: belt and braces even if sm-on slipped through */
@media (prefers-reduced-motion: reduce) {
    .sm-reveal { opacity: 1 !important; transform: none !important; }
    .nav-inner { animation: none !important; }
    .mascot-footer img { animation: none !important; }
    .senti, .sm-ping, .sm-confetti, .sm-human, .sm-progress { display: none !important; }
    .sm-waving .sm-ch { animation: none !important; }
}

/* ── Vibrancy: the nav as material, not a painted bar ─────────────────────
   The console topbar already does this (blur(16px) over 0.88 white) and it is
   the single most recognisable macOS trait: chrome is translucent, and content
   blurs beneath it as you scroll. The marketing nav was rgba(255,255,255,0.97)
   with no blur — effectively opaque, so it read as a painted strip sitting on
   the page rather than a layer above it.

   Specificity note: 42 pages define .nav-inner in their own inline <style>,
   and the load order of this file relative to those blocks varies per page.
   `nav .nav-inner` (element + class) outranks a bare `.nav-inner` everywhere,
   so this does not depend on which block happens to come last — the exact
   trap CLAUDE.md warns about.

   Guarded: without backdrop-filter support, 0.72 white over scrolling content
   is unreadable, so those browsers keep the opaque background. */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
    nav .nav-inner {
        background: rgba(255, 255, 255, 0.72);
        -webkit-backdrop-filter: saturate(180%) blur(20px);
        backdrop-filter: saturate(180%) blur(20px);
    }
}

/* ── Header must span the viewport, even inside a flex body ───────────────
   blog.html and blog-post.css use the sticky-footer pattern
   (body { display:flex; flex-direction:column }). That makes the header a
   FLEX ITEM, and the header carries `margin: 14px auto 0` — on a flex item an
   auto cross-axis margin overrides align-items:stretch, so instead of filling
   the width the nav shrank to fit its contents.

   On a 393px phone that measured 248px wide at x=72 on /blog and 227px at
   x=83 on an article: the header rendered as a small pill floating in the
   middle of the screen with the page starting under it. Desktop never showed
   it because at >=1140px the max-width was doing the constraining anyway.

   width:100% restores the fill; max-width and the auto margins still centre
   and cap it exactly as before on large screens. */
body > nav { width: 100%; }
