    /* `overflow-x: clip` on html+body prevents horizontal scrolling when
       any absolutely-positioned element (like the iPhone mockup pinned
       to the bottom-right of the hero, or a section background glow
       that bleeds past the viewport) extends beyond the viewport width.
       `clip` is the modern equivalent of `hidden` but doesn't create a
       new scroll container — it just clips overflow. */
    html, body { overflow-x: clip; max-width: 100%; }
    body { background: #080A12; }

    /* Scroll-triggered animations */
    .reveal { opacity: 0; transform: translateY(30px); transition: opacity 0.8s cubic-bezier(0.16, 1, 0.3, 1), transform 0.8s cubic-bezier(0.16, 1, 0.3, 1); }
    .reveal.visible { opacity: 1; transform: translateY(0); }
    .reveal-delay-1 { transition-delay: 0.1s; }
    .reveal-delay-2 { transition-delay: 0.2s; }
    .reveal-delay-3 { transition-delay: 0.3s; }
    .reveal-delay-4 { transition-delay: 0.4s; }

    /* Hero ambient glow */
    .hero-glow { position: relative; overflow: hidden; }
    .hero-glow::before {
      content: '';
      position: absolute;
      width: 900px; height: 900px;
      top: -250px; left: 50%;
      transform: translateX(-50%);
      background: radial-gradient(circle, rgba(0,220,200,0.10) 0%, rgba(0,220,200,0.04) 40%, transparent 70%);
      animation: hero-pulse 8s ease-in-out infinite alternate;
      pointer-events: none;
    }
    @keyframes hero-pulse {
      0% { opacity: 0.6; transform: translateX(-50%) scale(1); }
      100% { opacity: 1; transform: translateX(-50%) scale(1.15); }
    }

    /* Glass */
    .glass { background: rgba(255,255,255,0.03); backdrop-filter: blur(24px); -webkit-backdrop-filter: blur(24px); border: 1px solid rgba(255,255,255,0.06); }
    .glass-elevated { background: rgba(255,255,255,0.05); backdrop-filter: blur(40px); -webkit-backdrop-filter: blur(40px); border: 1px solid rgba(255,255,255,0.08); }

    /* Gradient text */
    .gradient-text { background: linear-gradient(135deg, #00DCC8 0%, #00C4B4 50%, #2dd4bf 100%); -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent; }

    /* Feature card hover */
    .feature-card { transition: all 0.4s cubic-bezier(0.16, 1, 0.3, 1); }
    .feature-card:hover { transform: translateY(-4px); background: rgba(255,255,255,0.05); border-color: rgba(255,255,255,0.1); }

    /* Pricing glow */
    .pricing-popular {
      border-color: rgba(0,220,200,0.25);
      box-shadow: 0 0 60px -15px rgba(0,220,200,0.15);
    }

    /* Device frames — legacy `.iphone-frame` kept for any non-hero
       usages; the hero switched to the frameless `.iphone-mock` below
       so the screenshot's own rounded corners + status bar render at
       1:1 without being wrapped in a fake bezel. */
    .iphone-frame {
      background: linear-gradient(165deg, #2a2a35 0%, #1a1a24 50%, #141420 100%);
      border: 2.5px solid rgba(255,255,255,0.22);
      box-shadow: 0 50px 100px -20px rgba(0,0,0,0.7), 0 30px 60px -15px rgba(0,0,0,0.5), inset 0 1px 0 rgba(255,255,255,0.1);
    }

    /* Frameless iPhone mockup. Rounds the screenshot corners to match
       iPhone 17 Pro Max's 55pt display curve (≈11.5% of screen width).
       Switched from `filter: drop-shadow()` to `box-shadow` because the
       former was rendering as a big soft halo that read as a visible
       fake-bezel rim around the phone. `box-shadow` with a sharper
       profile + a hairline ring on the inside gives a clean "floating
       glass" look instead of a mushy halo. */
    /* iPhone 17 Pro Max mockup — uses the real Apple device frame
       (exported from the iOS/iPadOS 26 Figma Community kit,
       re-rasterised at 1470x3000 with the display region fully
       transparent). Structure:

         .iphone-mock     = positioning wrapper, carries the floating
                            drop-shadow
         .iphone-screen   = absolutely-positioned behind the frame, at
                            exactly the display cutout coords
         .iphone-frame-img = the PNG overlay with its transparent
                            display hole

       The screenshot sits *behind* the PNG, clipped to the display
       cutout bounds by percentage positioning. Those percentages
       come from a flood-scan of the PNG's alpha channel at an
       off-center probe point (the Dynamic Island is opaque in the
       middle of the frame, so a center probe would mistake the
       island's top edge for the display edge — probing 200px left
       of center stays within the real display area):
         left:    5.102%   (bezel width)
         right:   5.102%   (symmetric with left)
         top:     2.200%   (matches bottom — modern iPhone has
                            symmetric top/bottom bezels)
         bottom:  2.200%
       Resulting cutout: 1320×2868 — exactly iPhone 17 Pro Max
       physical resolution. Aspect 0.4603. The screenshot fills it
       edge-to-edge; the Dynamic Island pill in the frame overlays
       the screenshot's own status-bar area. */
    .iphone-mock {
      position: relative;
      aspect-ratio: 1470/3000;
      /* `isolation: isolate` forces a clean stacking context here so
         the frame-img's `z-index: 10` is unambiguously above the
         slides, even while a slide is mid-transition. Without it, the
         fading slide's implicit opacity-driven stacking context could
         occasionally render on top of the frame. */
      isolation: isolate;
      filter: drop-shadow(0 30px 60px rgba(0,0,0,0.55))
              drop-shadow(0 12px 24px rgba(0,0,0,0.40));
    }
    .iphone-screen {
      /* Position at (approximately) the display cutout — this way the
         container's aspect ratio matches the screenshot's aspect and
         `object-cover` doesn't crop any of the image. A *very* small
         outward nudge from the measured cutout (5.102%, 2.200%) makes
         the screenshot bleed 1-2 pixels under the bezel's anti-aliased
         rim, which eliminates the thin dark fringe that was visible
         when the screen sat exactly on the cutout coords. */
      position: absolute;
      left: 4.6%;
      top: 1.7%;
      right: 4.6%;
      bottom: 1.7%;
      overflow: hidden;
      /* Match the display's own corner curve — 8% reads as the
         actual iPhone 17 Pro Max display radius, not the body radius
         (which is larger). */
      border-radius: 8%;
      background: #000;
      z-index: 1;
    }
    .iphone-frame-img {
      position: absolute;
      inset: 0;
      width: 100%;
      height: 100%;
      pointer-events: none;
      z-index: 10;
    }
    .iphone-mock .iphone-slide {
      border-radius: 0;
      /* Guarantee every slide stays at a lower z-index than the frame
         overlay, regardless of opacity-transition stacking. */
      z-index: 0;
    }

    /* Force-press showcase ripple. Two concentric pulse rings expand
       outward from a fingertip circle, simulating the iOS force-press
       gesture. `translate(-50%, -50%)` centers the pulse on whatever
       top/left coordinate the HTML sets it to, so we can target a
       specific element on the screenshot (e.g. a project header row).
       Two animations share the same keyframes but are phase-shifted
       with `animation-delay` so one ring is always active. */
    .force-ripple {
      position: absolute;
      width: 38px;
      height: 38px;
      border-radius: 50%;
      background: radial-gradient(circle, rgba(0, 220, 200, 0.55) 0%, rgba(0, 220, 200, 0.15) 60%, transparent 100%);
      transform: translate(-50%, -50%);
      pointer-events: none;
      z-index: 5;
    }
    .force-ripple::before,
    .force-ripple::after {
      content: '';
      position: absolute;
      inset: 0;
      border-radius: 50%;
      border: 1.5px solid rgba(0, 220, 200, 0.7);
      animation: force-pulse 2.2s cubic-bezier(0.16, 0.8, 0.3, 1) infinite;
    }
    .force-ripple::after {
      animation-delay: 1.1s;
    }
    @keyframes force-pulse {
      0%   { transform: scale(0.5); opacity: 0.9; }
      70%  { opacity: 0.15; }
      100% { transform: scale(2.4); opacity: 0; }
    }
    /* Caption that floats underneath the ripple, nudged on/off by the
       same cadence. Tiny, uppercase, tracked — reads as a callout
       rather than body copy. */
    .force-tap-label {
      position: absolute;
      left: 50%;
      transform: translateX(-50%);
      font-size: 9px;
      font-weight: 700;
      letter-spacing: 0.12em;
      text-transform: uppercase;
      color: #00DCC8;
      background: rgba(0, 0, 0, 0.75);
      padding: 4px 8px;
      border-radius: 12px;
      white-space: nowrap;
      border: 1px solid rgba(0, 220, 200, 0.3);
      z-index: 6;
      pointer-events: none;
      animation: force-label-bob 2.2s ease-in-out infinite;
    }
    @keyframes force-label-bob {
      0%, 100% { opacity: 0.7; transform: translate(-50%, 0); }
      50%      { opacity: 1.0; transform: translate(-50%, 2px); }
    }

    /* Screenshot slideshows */
    .mac-slide { opacity: 0; transition: opacity 1s ease-in-out; }
    .mac-slide.active { opacity: 1; }
    .iphone-slide { opacity: 0; transition: opacity 0.8s ease-in-out; }
    .iphone-slide.active { opacity: 1; }

    /* Code block */
    .code-block { background: rgba(0,0,0,0.4); border: 1px solid rgba(255,255,255,0.06); font-family: 'SF Mono', 'Fira Code', monospace; }

    /* Section divider */
    .section-fade { background: linear-gradient(to bottom, transparent, rgba(0,220,200,0.02) 50%, transparent); }

    /* Scrollbar */
    ::-webkit-scrollbar { width: 6px; }
    ::-webkit-scrollbar-track { background: #080A12; }
    ::-webkit-scrollbar-thumb { background: #2a2a3e; border-radius: 3px; }

    /* Clam logo with spinning pearl shine.
       The clam image is a flat PNG, so we can't rotate the pearl alone.
       We overlay a conic-gradient highlight CENTERED on the pearl's
       on-image position and rotate IT. The element is positioned by its
       CENTER (left/top mark the pearl's center, then translate(-50%,-50%)
       pulls the element back by half its own size) so width/height changes
       don't drift the shine off the pearl. */
    .clam-logo { position: relative; display: inline-block; line-height: 0; }
    .clam-logo img { display: block; width: 100%; height: auto; filter: drop-shadow(0 8px 30px rgba(0,220,200,0.25)); }
    .clam-logo .pearl-shine {
      position: absolute;
      /* Pearl in carapace-logo.png is centered ~50% x, ~50% y, diameter ~28% */
      left: 50%; top: 50%;
      width: 28%; height: 28%;
      margin: 0;
      border-radius: 50%;
      background: conic-gradient(
        from 0deg,
        rgba(255,255,255,0)    0deg,
        rgba(255,255,255,0.85) 60deg,
        rgba(255,255,255,0)   120deg,
        rgba(255,255,255,0.55) 240deg,
        rgba(255,255,255,0)   300deg
      );
      mix-blend-mode: screen;
      filter: blur(4px);
      pointer-events: none;
      transform-origin: center;
      animation: pearl-spin 3.5s linear infinite;
      will-change: transform;
    }
    /* Both keyframes carry the translate(-50%,-50%) so the element stays
       centered on its (left, top) anchor while it rotates. */
    @keyframes pearl-spin {
      from { transform: translate(-50%, -50%) rotate(0deg);   }
      to   { transform: translate(-50%, -50%) rotate(360deg); }
    }
    @media (prefers-reduced-motion: reduce) {
      .clam-logo .pearl-shine {
        animation: none;
        transform: translate(-50%, -50%);
      }
    }

    /* Hero wordmark — sits above the clam. Premium feel via wide
       letter-spacing + light weight + soft teal underglow. */
    .carapace-wordmark {
      font-weight: 300;
      letter-spacing: 0.4em;
      text-indent: 0.4em; /* compensate for trailing letter-spacing so it visually centers */
      color: rgba(255,255,255,0.95);
      text-shadow: 0 0 24px rgba(0, 220, 200, 0.18);
    }
