<header class="site-header">
    <div class="fieldset-wrapper">
      <fieldset>
        <input checked type="radio" id="zoom-scroll-effect" name="effect" value="zoom-scroll" class="sr-only">
        <label for="zoom-scroll-effect">Zoom scroll</label>
      </fieldset>
    </div>
  </header>
    <nav>
      <ul class="indicator">
        <li><a href="#microsoft"><span class="sr-only">Microsoft</span></a></li>
        <li><a href="#facebook"><span class="sr-only">Facebook</span></a></li>
        <li><a href="#nordstrom"><span class="sr-only">Nordstrom</span></a></li>
        <li><a href="#sonosite"><span class="sr-only">SonoSite</span></a></li>
        <li><a href="#zillow"><span class="sr-only">Zillow</span></a></li>
      </ul>
    </nav>
  <main>
    <section id="microsoft" class="section">
      <div class="content">
        <h2>
          <strong>Microsoft</strong>
          Personnel & 
          <strong>Azure</strong> <em>Sovereign</em> Clouds
        </h2>
        <div class="text">
          <img src="https://assets.codepen.io/136395/microsoft.png"
               alt="Microsoft Personnel and Sovereign Clouds UX UI" />
          <p>As Personnel's design quality gatekeeper, I prototyped stateful UI live on Teams for PM-design collaboration using a custom framework rolled in-house (React/TS, CSS Modules, Msal.js, and GraphAPI); safeguarding against third-party telemetry during <strong>JEDI</strong>.</p>
          <p>Later, I evolved my skills on Azure's Sovereign Clouds prototyping and delivering end-to-end UI solutions for Shadow Control, Secure Sovereign Manager, Video Escort Monitoring, Real-time Insights, and DRI Portals.</p>
      <button disabled href="/case-studies/microsoft">Read Case Study</button>
        </div>
      </div>
    </section>
    <section id="facebook" class="section">
      <div class="content">
        <h2>
          <strong>Meta</strong><br />
          (<em><sub>fb</sub></em>)IDE
          codename:
           <em>Lyric</em> 
        </h2>

        <div class="text">
          <img src="https://assets.codepen.io/136395/facebook.png"
               alt="Facebook, Meta, FBIDE codename Lyric. Zero-install, cloud-based IDE
                    integrated into Facebook Platform." />
          <p>The mission was clear: Prepare the UX/UI for open-sourcing Facebook's <em>zero-install, cloud-based IDE</em>, tailored for PHP5 (Hack) and HipHop (VM), integrating directly with the Facebook platform, providing comprehensive tools for building workflows and software. From a low-fi engineering proof of concept, our team transformed (fb)IDE into <strong>Lyric</strong>—a formidable product for more than just Facebook code. Lyric was re-branded Nuclide and shipped as a set of extensions for Atom and VSCode.</p>
            <button disabled href="/case-studies/facebook">Read Case Study</button>
<!--           <img src="https://davidpuerto-com.azurewebsites.net/images/case-studies/facebook/lyric-swag.jpg" alt="Facebook's FBIDE codename Lyric Tshirt. Hottest swag in the company 2014-2017" /> -->
        </div>
      </div>
    </section>
    
    <section id="starbucks" class="section hidden">
      <div class="content">
        <h2>
          <strong>Starbucks</strong>
          <em>Mobile</em> Order & Pay
        </h2>

        <div class="text">
          <img src="https://assets.codepen.io/136395/starbucks.png" alt="">
          <p>Our product team created an experience that allows customers to place a Starbucks order from their phone and pick up from a barista in a café.</p>

<p>The Starbucks App now has over 35 million active users, accounting for +31% of sales. Starbucks has the second most used mobile payment app for POS transactions of any app on the planet.&nbsp;🌎</p>

<p>Oh yeah, and we invented the <a href="https://www.starbucks.com/developer/pattern-library/components/frap" target="_blank">FRAP</a></p>
          <p><a href="https://apps.apple.com/us/app/starbucks/id331177714" target="_blank">Download Starbucks on the AppStore</a></p>
          <p><a href="https://play.google.com/store/apps/details?id=com.starbucks.mobilecard&hl=en_US&pli=1" target="_blank">Download Starbucks from GooglePlay</a></p>
        </div>
      </div>
    </section>
    <section id="nordstrom" class="section">
      <div class="content">
        
        <h2>
          <strong>Nordstrom</strong>
          <em>Enterprise Price Suite</em><br />AI/ML &<br /> 
          CompIntel
          
        </h2>
        <div class="text">
            <img src="https://assets.codepen.io/136395/nordstrom.png"
               alt="Nordstrom. CompIntel. Errors and Warnings Console. Daily Assignment super admin tools. CommonUI." />
            <p>
              Our engineering team developed a 0→1 application (<strong>CompIntel</strong>), delivering an experience that gave rise to the PRICE organization’s unified enterprise application and Nordstrom's CommonUI design system. Our team made the verification and validation process more efficient, boosting productivity, eliminating the need to manually traverse multiple spreadsheets, and surpassing execution targets while providing human-in-the-loop tools that continue to train algorithms for better price matching.
          </p>
          <button disabled href="/case-studies/nordstrom">Read Case Study</button>
        </div>
      </div>
    </section>
    <section id="sonosite" class="section">
      <div class="content">
        <h2><strong>SonoSite</strong><br />
          iViz think
             StarTrek's <em>Tricorder</em>
          </h2>

        <div class="text">
          <img src="https://assets.codepen.io/136395/iviz.png" alt="Prototyping the first handheld ultrasoud device." />
          <p>Joining a team of industrial designers and hardware engineers, I was challenged to prototype an innovative gesture-based UI for the first handheld ultrasound device—not <a href="https://www.unakin.com/" target="_blank">unakin</a> to <strong>Star Trek's tricorder.<strong></p>
          <ul>

          <li>
            <a href="https://youtu.be/emJUu9OrdJc" target="_blank">
See how iViz is assisting global health in Gambia.</a></li>
          <li>
            <a href="https://youtu.be/XHgTSYLgOVI" target="_blank">See iViz in action at the race track.</a>
            </li>
            <li><a href="https://youtu.be/qPcUkbd7izs" target="_blank">Watch iViz Promo Video</a></li>
          </ul>
          <button disabled href="/case-studies/sonosite">Read Case Study</button>
        </div>
      </div>
    </section>
    <section id="zillow" class="section">
      <div class="content">
        <h2><strong>Zillow</strong><br />& <em>then there <br /> was that one time...</em></h2>

        <div class="text">
          <img src="https://assets.codepen.io/136395/zillow.png" alt="Delivered a mobile-first PWA built on Zillow platform and drawing data from Data.gov and various federal and state databases to compile a list of ways to make a smart move
 and buy a house without having to splurge on the down payment through grants. AWARDED First Place, David Puerto and Spacelabforever Feburary 2015 and publicized on the front page of GeekWire and multiple other media outlets." />
          <p>
            <strong>Awarded 1<sup>st</sup> Place</strong> at <em>Seattle’s largest hackathon</em> (#hackHousing) to date, our team of three designed SmartMove—an innovative, data-driven application streamlining the home-buying process and unearthing dozens of hidden programs that exist to assist people with substantially lowering the cost of homeownership.</p>
          <ul style="margin-left: 30px;"><li><a href="https://www.geekwire.com/2015/hacking-housing-market-tech-teams-use-open-data-help-people-find-affordable-homes/" target="_blank">See us on the front page of GeekWire</a></li><li><a href="https://www.huduser.gov/portal/pdredge/pdr_edge_frm_asst_sec_022315.html" target="_blank">Learn about SmartMove on HUD</a></li><li><a href="https://zillow.mediaroom.com/2015-01-23-Zillow-and-University-of-Washington-to-Host-Hack-Housing-Empowering-Smarter-Decisions-A-Weekend-Hackathon" target="_blank">Learn about SmartMove on Zillow</a></li></ul>
          <button disabled href="/case-studies/zillow">Read Case Study</button>
        </div>
      </div>
    </section>

  </main>
<div id="simpleToast" hidden>
  🚨&nbsp;<span>Optimizing images... Please, stay tuned!</span>
</div> 
  <footer>
    <p>nada más <span class="emoji">✌️</span></p>
  </footer>
@layer base, rhythm, layout, components, default, overwrites;

/* hide page scrollbar */
html { scrollbar-width: none; } /* Firefox */
body { -ms-overflow-style: none; } /* IE and Edge */
body::-webkit-scrollbar, body::-webkit-scrollbar-button { display: none; } /* Chrome */
/* end hide page scrollbar */

html {
  /* Create a snapping rule on the html element */
  scroll-snap-type: y mandatory;
  overscroll-behavior: none;
  /* Create a timeline scope, so we can target any element on the page */
  timeline-scope: --section, --main, --site-header;
}

/* We'll want to match these colors for the best melty effect */
/* But play around with them (and add a color to section) to see happens */
body,
.content {
  background-color: var(--color-background, black);
}

main {
  view-timeline: --main;
}

.site-header {
  display: none;
}

.section {
  /* Creating a snapping rule on the section element */
  scroll-snap-align: start;
  scroll-snap-stop: always;

  /* Attach the timeline to the section element*/
  view-timeline: --section;

  /* Set each section to the full dynamic height of the viewport */
  height: 100dvh;
}

.hidden {
  display: none;
}

.content {
  /* Fix the content, so it doesn't scroll with the section */
  overflow: hidden;
  position: fixed;
  inset: 0;

  /* Animate the content based on the section scrolling */
  --contrast: 4;
  --blur: 0.5rem;

  animation: blink ease-in-out both;
  animation-timeline: --section;
}

@keyframes blink {
  0%,
  100% {
    filter: blur(var(--blur)) contrast(var(--contrast));
    opacity: 0;
    visibility: hidden;
  }

  50% {
    filter: blur(0) contrast(1);
    opacity: 1;
    visibility: visible;
  }
}

/* 
  This is a bit of a hack to get the indicator to work because I'm lazy.
  We're translating the dot from the top to the bottom of its parent,
  using the browser scroll position as the animation timeline.
  It's not really matched up to the scrolling sections, only appears to be.
*/
.indicator::before {
  animation: indicate linear both;
  animation-timeline: --main;
  animation-range: contain;
}

/* And we're manually setting the colors because see: lazy comment above */
@keyframes indicate {
  0% {
    --color-indicator: var(--color-primary);
    transform: translateY(0);
  }

  25% {
    --color-indicator: var(--color-yellow);
  }

  50% {
    --color-indicator: var(--color-purple);
  }

  75% {
    --color-indicator: var(--color-secondary);
  }

  100% {
    --color-indicator: var(--color-zillow);
    transform: translateY(calc(var(--indicator-total-height) - var(--indicator-size)));
  }
}

/* Remove gradient indicator on scroll-to-end (visible on small screens */
.site-header label:last-of-type {
  view-timeline: --site-header inline;
}

.site-header::after {
  animation: fade-scroll ease-in-out both;
  animation-timeline: --site-header;
  animation-range: entry-crossing;
}

@keyframes fade-scroll {
  0% {
    opacity: 1;
  }

  100% {
    opacity: 0;
  }
}

/* Change animation based on radio checked */
body:has([value="horizontal-scroll"]:checked) .content {
  /* 
    The only reason we're repeat these two properties instead of simply 
    setting `animation-name` is so the polyfill will pick them up 
    They're flaky though and tend to get stuck. You might need to
    refresh the page and select an option before scrolling
  */
  animation: horizontal-scroll ease-in-out both;
  animation-timeline: --section;
}

body:has([value="backwards-scroll"]:checked) .content {
  animation: backwards-scroll ease-in-out both;
  animation-timeline: --section;
}

body:has([value="zoom-scroll"]:checked) .content {
  animation: zoom-scroll ease-in-out both;
  animation-timeline: --section;
  will-change: filter, transform;
}

/* Alternative animations */
/* Very cool, try it */
@keyframes horizontal-scroll {
  0% {
    transform: translate3d(100%, 0%, 0);
  }

  50% {
    transform: none;
  }

  100% {
    transform: translate3d(-100%, 0%, 0);
  }
}

/* Befuddling, try it */
@keyframes backwards-scroll {
  0% {
    transform: translate3d(0%, -100%, 0);
  }

  50% {
    transform: none;
  }

  100% {
    transform: translate3d(0%, 100%, 0);
  }
}

/* WIP */
@keyframes zoom-scroll {
  0% {
    filter: blur(5rem);
    transform: scale(0);
    opacity: 0;
    visibility: hidden;
  }

  50% {
    filter: blur(0);
    transform: none;
    opacity: 1;
    visibility: visible;
  }

  100% {
    filter: blur(3rem);
    transform: scale(1.5);
    opacity: 0;
    visibility: hidden;
  }
}

#microsoft .text img {
  margin-top: 10dvi;
}

#facebook .text img {
  margin-top: 10dvi;
}

#nordstrom .text img {
    margin-top: 10dvi;
}

#sonosite .text img {
    margin-top: 5dvi !important;
}

#zillow .text img {
    margin-top: 10dvi;
}

.image__zillow {
    padding-top: 20dvi;
}

#simpleToast {
  place-content: center;
  display: flex;
  visibility: hidden;
  min-width: 250px;
  background-color: rgba(251, 151, 109, 0.15);
  border-radius: 4px;
  color: #fff;
  text-align: center;
  padding: 16px;
  position: fixed;
  bottom: 0;
  z-index: 1;
  left: 50%;
  transform: translateX(-50%) translateY(100%); /* Start off-screen */
  text-shadow: 1px 1px 2px black;
  backdrop-filter: blur(5px);
  will-change: transform, opacity;
  transition: visibility 0.3s ease;
}

#simpleToast.show {
  visibility: visible;
  animation: slideUpThenDown 3s ease-in-out both; /* Combined animation */
}

@keyframes slideUpThenDown {
  0% {
    transform: translateX(-50%) translateY(100%); /* Start off-screen */
    opacity: 0;
  }
  10% {
    transform: translateX(-50%) translateY(0); /* Slide into view */
    opacity: 1;
  }
  90% {
    transform: translateX(-50%) translateY(0); /* Stay visible */
    opacity: 1;
  }
  100% {
    transform: translateX(-50%) translateY(100%); /* Slide out of view */
    opacity: 0;
  }
}

@keyframes fadeout {
  from {
    transform: translateY(60px);
    opacity: 1;
  }
  to {
    transform: translateY(-30px);
    opacity: 0;
  }
}

.text button {
  cursor: pointer;
  background: 0;
  color: #fff;
  font-size: 1rem;
  padding: .5rem 1rem;
  &:disabled {
    display: none;
    color: #555;
    pointer-events: none;
    cursor: not-allowed;
    opacity: .35;
  }
}

/* Base indicator styling */
.indicator::before {
  content: '';
  display: block;
  width: var(--indicator-size);
  height: var(--indicator-size);
  background-color: var(--color-indicator, #333);
  border-radius: 50%;
  position: absolute;
  transition: transform 0.3s ease;
}

/* Vertical indicator (default) */
@keyframes vertical-indicate {
  0% { transform: translateY(0); }
  100% { transform: translateY(calc(var(--indicator-step, 100%) * (var(--indicator-number) - 1))); }
}

/* Mobile-specific adjustments */
@media (max-width: 600px) {
  
  #sonosite.section .content img { 
    padding-top: 50px !important;
  }
  
  .section .content {
    padding-top: 120px !important;
  }
  
  .section .content .text img {
    margin-top: 150px !important;
  }

  h2, .text {
    padding-inline-end: 0;
  }
  
  .text {
    line-height: 1.5rem;
  }
}
/*
@keyframes fadeInExplosive {
  0% {
    opacity: 0;
    filter: blur(20px);
    transform: scale(0.9);
  }
  50% {
    opacity: 0.5;
    filter: blur(10px);
    transform: scale(1.05);
  }
  100% {
    opacity: 1;
    filter: blur(0);
    transform: scale(1);
  }
}

h2,
p {
  opacity: 0;
  animation: fadeInExplosive 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
  animation-delay: 0.25s;
}

.section h2,
.section p {
  opacity: 0;
  animation: fadeInExplosive 1s cubic-bezier(0.25, 0.46, 0.45, 0.94) forwards;
  animation-delay: 0.25s;
}

.section h2 {
  animation-delay: 0.25s;
}

.section p:nth-child(1) {
  animation-delay: 0.5s;
}

.section p:nth-child(2) {
  animation-delay: 0.75s;
}*/

External CSS

  1. https://codepen.io/dapinitial/pen/mdNaGKp/a8da07dbfb9b2d642bd3452d59740401.css

External JavaScript

  1. https://flackr.github.io/scroll-timeline/dist/scroll-timeline.js