diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 839bf6f8..7cae48c4 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -10,6 +10,7 @@ jobs: runs-on: ubuntu-latest env: SITE_HOST: ${{ vars.SITE_HOST }} + THOR_SILENCE_DEPRECATION: 1 steps: - uses: actions/checkout@v1 @@ -19,7 +20,7 @@ jobs: - name: Install Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 3.4.3 + ruby-version: 4.0.0 - name: Ruby Version run: | ruby -v diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 2802c762..cc1eaf84 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -17,6 +17,7 @@ jobs: runs-on: ubuntu-latest env: SITE_HOST: ${{ vars.SITE_HOST }} + THOR_SILENCE_DEPRECATION: 1 steps: - uses: actions/checkout@v1 @@ -27,7 +28,7 @@ jobs: - name: Install Ruby uses: ruby/setup-ruby@v1 with: - ruby-version: 3.4.3 + ruby-version: 4.0.0 if: github.event.pull_request.merged == true - name: Ruby Version diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml new file mode 100644 index 00000000..9a1861b5 --- /dev/null +++ b/.github/workflows/security.yml @@ -0,0 +1,30 @@ +name: Security + +# gitleaks detect \ +# --source=. \ +# --redact \ +# --verbose > tmp/gitleaks-output.txt 2>&1 + +on: + pull_request: + +jobs: + security_leaks: + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Install Gitleaks + run: | + curl -sSL https://github.com/gitleaks/gitleaks/releases/download/v8.24.3/gitleaks_8.24.3_linux_x64.tar.gz | tar -xz + sudo mv gitleaks /usr/local/bin/ + + - name: Run Gitleaks Scan + run: | + gitleaks detect \ + --source=. \ + --redact \ + --exit-code=1 diff --git a/.gitignore b/.gitignore index 4f474fdf..b42f4129 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ backup webpack.config.js .vscode .idea +.playwright-mcp ############################################################################################### # Environment variables diff --git a/.ruby-version b/.ruby-version index 6cb9d3dd..fcdb2e10 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -3.4.3 +4.0.0 diff --git a/CHANGELOG.md b/CHANGELOG.md index bb5f7a23..b8f048b4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ This changelog documents the evolution of a personal branding website from a sim - **v2.x (2020)**: Multi-page application with Webpack integration, Bootstrap framework - **v3.x (2021-2025)**: Complete redesign with custom design system, single-page focus, modern tooling - **v4.x (2025)**: Infrastructure modernization, environment-based configuration, dependency stabilization +- **v5.x (2026)**: Complete visual redesign with blueprint/schematic aesthetic, animated SVG schematics ### Key Architectural Patterns @@ -32,6 +33,75 @@ No unreleased changes at this time. --- +## [5.0.0] - 2026-02-03 - RELEASED + +### MAJOR RELEASE - Complete Visual Redesign with Blueprint Aesthetic & Ruby 4.0.0 Upgrade + +This version represents a complete visual redesign with a cohesive technical blueprint/schematic aesthetic across all sections, along with a major Ruby runtime upgrade. + +### Added +- **Blueprint Design System**: + - Technical schematic visual language across all sections + - Animated SVG schematics with industrial/robotic theme + - Blueprint grid overlays and coordinate markers + - Frame corners and technical labels +- **New Section Schematics**: + - About section: Robot arm schematic with animated joints and motion arcs + - Products/Workshop section: Forge assembly with furnace, anvil, hammer, and conveyor + - Contact section: Communication beacon with signal waves and data packets +- **Enhanced Animations**: + - Flame flicker effects in forge schematic + - Hammer strike and spark burst animations + - Signal wave expansion for communication beacon + - Temperature gauge swing and LED status indicators + - Conveyor belt movement and QC scanner beam +- **Stacked Category Tiles**: Workshop section redesigned with vertical tile stack +- **Ruby 4.0.0 Compatibility**: + - Added `cgi` gem (removed from Ruby 4.0.0 stdlib, required by Rack) + - Added `tsort` gem (removed from Ruby 4.0.0 stdlib, required by RuboCop) + - Added `rdoc` gem (removed from Ruby 4.0.0 stdlib, required by various tools) + +### Changed +- **Ruby Version**: Upgraded from Ruby 3.4.3 to Ruby 4.0.0 +- **Section Layouts**: All content sections now use consistent two-column layout (content + schematic) +- **Visual Consistency**: Unified technical/industrial aesthetic replacing previous design +- **Navigation Logic**: Fixed Connect nav dot highlighting when scrolling to bottom of page +- **GitHub Actions**: Added `THOR_SILENCE_DEPRECATION: 1` environment variable to silence Thor deprecation warnings about boolean default values + +### Fixed +- **Nav Highlighting Bug**: Connect section nav dot now properly highlights when user scrolls to page bottom +- **70 Stylelint Errors**: Fixed all CSS linting errors in `_home.scss`: + - Expanded 17 single-line keyframes to multi-line format (`declaration-block-single-line-max-declarations`) + - Added URL quotes for all `url()` functions (`function-url-quotes`) + - Added `stylelint-disable` comments for intentional selector specificity patterns (`.frame-corner`, `.terminal-marker`, `svg`, `span:last-child`) +- **Ruby 4.0.0 LoadError**: Resolved `cannot load such file -- cgi/cookie` by adding stdlib gems removed in Ruby 4.0.0 + +### Developer Notes + +**Architecture Decision - Blueprint Aesthetic**: The move to a technical blueprint/schematic visual language creates unique brand identity distinct from typical portfolio sites. SVG-based animations provide smooth performance and consistent visual vocabulary across all sections reinforces brand. + +**Design Philosophy**: +1. **Robot Arm (About)**: Represents the engineering/technical foundation +2. **Forge Assembly (Workshop)**: Industrial metaphor for building products +3. **Communication Beacon (Contact)**: Signal transmission for connection/outreach + +**Animation Strategy**: Each schematic uses CSS keyframe animations with careful timing. Products section includes 11 coordinated animations: `flame-flicker`, `shimmer-rise`, `gauge-swing`, `led-heat-blink`, `led-ready-blink`, `led-cycle-blink`, `hammer-strike`, `spark-burst`, `conveyor-move`, `scan-sweep`, `scan-indicator-blink`. About section features: `joint-pulse`, `gripper-open`, `grip-pulse`, `value-update`, `ghost-fade`. Contact section includes: `beacon-grid-breathe`, `packet-north/east/south/west/northeast/southwest`, `core-ring-pulse`, `beacon-core-glow`, `focus-pulse`, `beacon-led-blink`, `beacon-led-steady`, `beam-rotate`, `dish-scan`. + +**Navigation Fix**: The scroll highlighting issue was fixed by adding a "near bottom" check that prioritizes the last section (contact) when within 100px of the page bottom. + +**Ruby 4.0.0 Migration Notes**: +- Ruby 4.0.0 removed several gems from the standard library that were previously bundled +- The `cgi` gem is required by Rack for cookie handling +- The `tsort` gem is required by RuboCop for dependency sorting +- The `rdoc` gem is required by various documentation tools +- Thor deprecation warnings about boolean default values can be silenced with `THOR_SILENCE_DEPRECATION=1` + +**Code Quality Achievement**: All linters passing (RuboCop, ESLint, Stylelint) after fixing 70 stylelint errors in the new animation keyframes. + +**Reference**: Feature branch `feature/version_five_o` + +--- + ## [4.0.0] - 2025-12-01 - RELEASED ### MAJOR RELEASE - Infrastructure Modernization & Build System Overhaul @@ -688,6 +758,7 @@ The first tagged release of the personal branding website. | Version | Date | Type | Key Changes | LOC Impact | |---------|------|------|-------------|------------| +| 5.0.0 | 2026-02-03 | Major | Visual redesign, blueprint aesthetic, SVG schematics, Ruby 4.0.0 | New design system, +3 gems | | 4.0.0 | 2025-12-01 | Major | Infrastructure modernization, dependency restoration, environment config | +6 packages, 100% linter compliance | | 3.5.1 | 2025-02-01 | Patch | Contact email update | Minimal | | 3.5.0 | 2024-11-28 | Minor | Feature parity, asset cleanup | +1,278 / -1,963 | @@ -717,6 +788,7 @@ This changelog demonstrates real-world semantic versioning: - v2.0.0: Multi-page app with Webpack - v3.0.0: Single-page app with custom design system - v4.0.0: Infrastructure modernization with breaking environment variable requirements + - v5.0.0: Blueprint/schematic redesign with Ruby 4.0.0 upgrade - **Minor versions (x.y.0)**: New features, non-breaking enhancements - New pages (2.1.0, 2.2.0) @@ -787,11 +859,11 @@ This project had two major redesigns (v2.0.0, v3.0.0): This project is proprietary software. All Rights Reserved. -Copyright (c) 2017-2025 RobotsBuildingRobots, LLC +Copyright (c) 2017-2026 RobotsBuildingRobots, LLC See the LICENSE file for details. --- -**Generated**: 2025-12-01 using git tag analysis and commit history +**Generated**: 2026-02-03 using git tag analysis and commit history **Maintainer**: RobotsBuildingRobots, LLC diff --git a/CLAUDE.md b/CLAUDE.md index 3057f275..6b75a2d7 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,7 +8,7 @@ This is a personal branding/portfolio website built with Middleman static site g ## Technology Stack -- **Ruby 3.4.3** with Middleman 4.5+ +- **Ruby 4.0.0** with Middleman 4.5+ - **Webpack 5.94.0** for asset bundling - **Slim** templating engine - **SCSS** with custom design system (no longer using Bootstrap) @@ -19,7 +19,7 @@ This is a personal branding/portfolio website built with Middleman static site g ### Development Server ```bash -rake server:development # Start server on http://localhost:4567 +rbe rake server:development # Start server on http://localhost:4567 ``` ### Building @@ -97,7 +97,7 @@ source/ ### Ruby - Follow `.rubocop.yml` configuration - Max line length: 180 characters -- Target Ruby 3.4.3 syntax +- Target Ruby 4.0.0 syntax ### JavaScript - ESLint with Airbnb base configuration @@ -118,3 +118,40 @@ source/ 5. **Data**: Site configuration in `data/settings.yml` 6. **Images**: Store in `source/assets/images/`, use Middleman image helpers 7. **Videos**: Place in `source/assets/images/videos/` for proper asset pipeline handling + +## Design System Maintenance + +**IMPORTANT**: When making any design changes, always update the design system documentation. + +The design system page is located at: `source/design-system.html.slim` + +When modifying: +- **Fonts** (`_settings.scss`) → Update typography section in design-system.html.slim +- **Colors** (`_settings.scss`) → Update color palette section in design-system.html.slim +- **Spacing** → Update spacing scale section +- **Components** → Update component examples + +The design system page must always reflect the actual implementation. Never change fonts, colors, or core design tokens without updating the design system documentation. + +## Session Cleanup + +**IMPORTANT**: Always kill background processes when finishing a task or ending a session. + +### Development Server Rules +- Always start with: `rbe rake server:development` +- Only run ONE instance at a time +- Always kill the server when done with the task + +### Cleanup Commands +```bash +# Kill Middleman server +pkill -f "middleman" 2>/dev/null +lsof -ti:4567 | xargs kill -9 2>/dev/null + +# Kill any other background processes started during the session +``` + +### Before Ending Any Session +1. Kill all background dev servers you started +2. Verify no orphaned processes on development ports (4567, 3000, etc.) +3. Never leave background tasks running diff --git a/Gemfile b/Gemfile index 520eab71..a2b81d81 100644 --- a/Gemfile +++ b/Gemfile @@ -1,6 +1,6 @@ source 'https://rubygems.org' -ruby '3.4.3' +ruby '4.0.0' if Gem::Version.new( Bundler::VERSION ) < Gem::Version.new( '2.0.0' ) abort 'Bundler version >= 2.X.X is required' @@ -33,6 +33,12 @@ gem 'bigdecimal' gem 'mutex_m' gem 'csv' +# Ruby 4.0.0 removed these gems from the standard library +# Required by Middleman, Rack, RuboCop, and Tilt +gem 'cgi' +gem 'tsort' +gem 'rdoc' + group :development do gem 'pry' gem 'pry-nav' diff --git a/Gemfile.lock b/Gemfile.lock index 84511d4c..0cf39dc9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -2,17 +2,27 @@ GEM remote: https://rubygems.org/ specs: abbrev (0.1.2) - activesupport (7.0.8.4) + activesupport (7.0.10) + base64 + benchmark (>= 0.3) + bigdecimal concurrent-ruby (~> 1.0, >= 1.0.2) + drb i18n (>= 1.6, < 2) + logger (>= 1.4.2) minitest (>= 5.1) + mutex_m + securerandom (>= 0.3) tzinfo (~> 2.0) addressable (2.8.7) public_suffix (>= 2.0.2, < 7.0) ast (2.4.2) backports (3.25.0) + base64 (0.3.0) + benchmark (0.5.0) bigdecimal (3.1.5) builder (3.3.0) + cgi (0.5.1) coderay (1.1.3) coffee-script (2.4.1) coffee-script-source @@ -23,6 +33,8 @@ GEM csv (3.2.8) date (3.4.0) dotenv (3.1.2) + drb (2.2.3) + erb (6.0.1) erubis (2.7.0) execjs (2.9.1) fast_blank (1.0.1) @@ -48,6 +60,7 @@ GEM listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) + logger (1.7.0) memoist (0.16.2) method_source (1.1.0) middleman (4.5.1) @@ -90,7 +103,8 @@ GEM middleman-minify-html (3.4.1) htmlcompressor (~> 0.2.0) middleman-core (>= 3.2) - minitest (5.24.1) + minitest (6.0.1) + prism (~> 1.5) mutex_m (0.2.0) net-ftp (0.1.4) net-protocol @@ -111,11 +125,15 @@ GEM ast (~> 2.4.1) racc parslet (2.0.0) + prism (1.8.0) pry (0.14.2) coderay (~> 1.1) method_source (~> 1.0) pry-nav (1.0.0) pry (>= 0.9.10, < 0.15) + psych (5.3.1) + date + stringio ptools (1.5.0) public_suffix (6.0.1) racc (1.8.1) @@ -125,6 +143,10 @@ GEM rb-fsevent (0.11.2) rb-inotify (0.11.1) ffi (~> 1.0) + rdoc (7.1.0) + erb + psych (>= 4.0.0) + tsort redcarpet (3.6.0) regexp_parser (2.9.2) reline (0.5.9) @@ -153,10 +175,12 @@ GEM ruby-progressbar (1.13.0) sassc (2.4.0) ffi (~> 1.9) + securerandom (0.4.1) servolux (0.13.0) slim (4.1.0) temple (>= 0.7.6, < 0.9) tilt (>= 2.0.6, < 2.1) + stringio (3.2.0) strscan (3.1.0) temple (0.8.2) thor (1.2.2) @@ -167,6 +191,7 @@ GEM titleize (1.4.1) toml (0.3.0) parslet (>= 1.8.0, < 3.0.0) + tsort (0.2.0) tzinfo (2.0.6) concurrent-ruby (~> 1.0) uglifier (3.2.0) @@ -181,6 +206,7 @@ DEPENDENCIES abbrev bigdecimal builder + cgi csv dotenv highline @@ -193,6 +219,7 @@ DEPENDENCIES pry pry-nav rake + rdoc redcarpet require_all rubocop @@ -200,9 +227,10 @@ DEPENDENCIES rubocop-rake (~> 0.6.0) slim (~> 4.0) titleize + tsort RUBY VERSION - ruby 3.4.3p32 + ruby 4.0.0p0 BUNDLED WITH - 2.5.17 + 2.7.2 diff --git a/_data_last_version/about.yml b/_data_last_version/about.yml new file mode 100644 index 00000000..9a76551a --- /dev/null +++ b/_data_last_version/about.yml @@ -0,0 +1,22 @@ +copyright: 2016 - Present / + +cta: It has been said there are two ways to build a business. You can either focus on building the tallest building or spend your time and energy tearing other buildings around you down. Let's work together to build, create, invent, not destroy. + +description: Founded in Boulder, Colorado in 2016 we've had successful engagements in Chicago, Boulder, Manhattan, and Portland, Oregon. We are remote-first and can help you establish the same culture. If you are interested in learning more about working together, our process, and how we can help, please reach out. A quiet warning though, we are very selective of who we work with and are always happy to refer out if we are not the right fit. + +locations: + - + id: 1 + location: Chicago + - + id: 2 + location: Boulder + - + id: 3 + location: Manhattan + - + id: 4 + location: Portland + - + id: 5 + location: Las Vegas diff --git a/_data_last_version/components.yml b/_data_last_version/components.yml new file mode 100644 index 00000000..90d80bac --- /dev/null +++ b/_data_last_version/components.yml @@ -0,0 +1,14 @@ +url: https://robotsbuildingrobots.com + +social: + email: salesteam@robotsbuildingrobots.com + shortname: RobotsBuildingRobots + formalname: RobotsBuildingRobots, LLC + founder: Chris Hough + focus: How can we help you? + +meta: + description: ROBOTSBUILDINGROBOTS, LLC was founded in Boulder Colorado in 2016. Through successful engagements across Chicago, Manhattan, and Portland, Oregon we focus on delivering quality measured ROI through the products we engineer in-house, and the services we provide to our clients. Being brutally honest, and highly selective are part of our core values. We are picky about the clients and projects we attach our name to, and you could say we are more focused on bringing impact, than merely collecting fees. Ultimately we derive success through win-win partnerships. + +preloader: + text: Reticulating Splines diff --git a/data/contact.yml b/_data_last_version/contact.yml similarity index 100% rename from data/contact.yml rename to _data_last_version/contact.yml diff --git a/data/cta.yml b/_data_last_version/cta.yml similarity index 100% rename from data/cta.yml rename to _data_last_version/cta.yml diff --git a/_data_last_version/engagements.yml b/_data_last_version/engagements.yml new file mode 100644 index 00000000..e5c2e6fa --- /dev/null +++ b/_data_last_version/engagements.yml @@ -0,0 +1,51 @@ +process: With engagements helping small startups to large enterprises, we bring both technical knowledge and industry-leading processes to help you achieve your vision. We are not a cookie-cutter service provider. Through effective collaboration and tailoring the project to the needs of the business, we achieve project success. + +projects: + - + id: 1 + company: Gathrly + logo: gathrly.png + collaboration: >- + Partnered with company founders to create a technical product roadmap and setup agile processes. Designed, engineered, and maintained a lead management application utilized by top tier brewers. Coached and mentored a team of junior engineers to meet productivity goals and ensure high-performance. + - + id: 2 + company: USA Today + logo: usatoday.png + collaboration: >- + Developed and architected a backend CMS with frontend content creation interfaces & features. Optimized user flows & improved the customer experience by designing an updated responsive layout. + - + id: 3 + company: W. W. Norton + logo: wwnorton.png + collaboration: >- + Designed and architected an interactive delivery platform to serve over 300+ interactives for a global publisher. Setup the GitFlow Process, code reviews, quality guidelines, & workflow management. Coached & mentored junior engineers on best practices to increase their productivity & contributions to the code base. + - + id: 4 + company: Crowd OX + logo: crowdox.png + collaboration: >- + Built out platform features across three ruby-on-rails engines. Rewrote the Partner application testing suite porting it from Minitest to the latest version of RSpec while maintaining testing coverage metrics. Expanded testing coverage from 0% to over 60% in a legacy code base with 100% model testing coverage. + - + id: 5 + company: Eggplant + logo: eggplant.png + collaboration: >- + Expanded the authorization capability of the testing manager application to include Microsoft Active Directory (LDAP). Coordinated daily pair programming sessions to mentor junior engineers, improve team collaboration, and increase overall team performance. + - + id: 6 + company: Advanced Building Technology + logo: advancedbd.svg + collaboration: >- + Utilized responsive web design construction techniques to rearchitect version two of this corporation's website. While version one was not mobile or tablet friendly, iPhones, iPads, and desktops are all now supported. It was successfully launched on time in preparation for new product kickoffs. + - + id: 7 + company: Sidebench + logo: sidebench.svg + collaboration: >- + Serving as a Technical Architect for the Momints NFT Marketplace by researching architecture, selecting components based on scalability needs and risk mitigation, developing the MVP, and compiling marketing materials. Provide high-level documentation on recommendations for system architecture diagrams, server infrastructure, tech stack selection, 3rd Party dependencies, data models and database schema, and API specifications to drive development. + - + id: 8 + company: Arthur Maxwell Experience Builder + logo: arthur-maxwell.gif + collaboration: >- + Transforming a corporate eLearning management application with 200+ users from an experience-driven offline solution via iPads to online learning in classrooms using Hotwire, Stimulus, and Ruby on Rails. diff --git a/_data_last_version/services.yml b/_data_last_version/services.yml new file mode 100644 index 00000000..5b8a7f13 --- /dev/null +++ b/_data_last_version/services.yml @@ -0,0 +1,5 @@ +process: Whether augmented bolt-on resources or individual projects, we utilize Kanban or Scrum for our agile workflows. We are not interested in waterfall or pure chaos. All engagements are tracked hourly, invoiced weekly, and require NET-7. A successful engagement with us occurs when product and engineering work together with a shared vision and goals to completion. + +metrics: At a foundational level, we believe automated tests are critical to the success of writing software. We advocate for community-driven, coding style approaches utilizing code linters and we grade our code with testing coverage metrics and style evaluation tools. If you are wanting to cut this corner, don’t worry, you can find many cheaper options out there. + +values: First and foremost, we are craftsmen. We intrinsically value the work we accomplish, the meticulous attention to detail, and the quality of our work. We understand that we are not perfect; software processes are not perfect; bugs are inevitable. With over 15 years of experience in technology from startups to enterprises, we understand every business presents a unique set of challenges, and we tailor our approach accordingly. diff --git a/data/settings.yml b/_data_last_version/settings.yml similarity index 100% rename from data/settings.yml rename to _data_last_version/settings.yml diff --git a/source/assets/images/avatar/20241101.png b/_source_last_version/assets/images/avatar/20241101.png similarity index 100% rename from source/assets/images/avatar/20241101.png rename to _source_last_version/assets/images/avatar/20241101.png diff --git a/source/assets/images/favicons/android-icon-144x144.png b/_source_last_version/assets/images/favicons/android-icon-144x144.png similarity index 100% rename from source/assets/images/favicons/android-icon-144x144.png rename to _source_last_version/assets/images/favicons/android-icon-144x144.png diff --git a/source/assets/images/favicons/android-icon-192x192.png b/_source_last_version/assets/images/favicons/android-icon-192x192.png similarity index 100% rename from source/assets/images/favicons/android-icon-192x192.png rename to _source_last_version/assets/images/favicons/android-icon-192x192.png diff --git a/source/assets/images/favicons/android-icon-36x36.png b/_source_last_version/assets/images/favicons/android-icon-36x36.png similarity index 100% rename from source/assets/images/favicons/android-icon-36x36.png rename to _source_last_version/assets/images/favicons/android-icon-36x36.png diff --git a/source/assets/images/favicons/android-icon-48x48.png b/_source_last_version/assets/images/favicons/android-icon-48x48.png similarity index 100% rename from source/assets/images/favicons/android-icon-48x48.png rename to _source_last_version/assets/images/favicons/android-icon-48x48.png diff --git a/source/assets/images/favicons/android-icon-72x72.png b/_source_last_version/assets/images/favicons/android-icon-72x72.png similarity index 100% rename from source/assets/images/favicons/android-icon-72x72.png rename to _source_last_version/assets/images/favicons/android-icon-72x72.png diff --git a/source/assets/images/favicons/android-icon-96x96.png b/_source_last_version/assets/images/favicons/android-icon-96x96.png similarity index 100% rename from source/assets/images/favicons/android-icon-96x96.png rename to _source_last_version/assets/images/favicons/android-icon-96x96.png diff --git a/source/assets/images/favicons/apple-icon-114x114.png b/_source_last_version/assets/images/favicons/apple-icon-114x114.png similarity index 100% rename from source/assets/images/favicons/apple-icon-114x114.png rename to _source_last_version/assets/images/favicons/apple-icon-114x114.png diff --git a/source/assets/images/favicons/apple-icon-120x120.png b/_source_last_version/assets/images/favicons/apple-icon-120x120.png similarity index 100% rename from source/assets/images/favicons/apple-icon-120x120.png rename to _source_last_version/assets/images/favicons/apple-icon-120x120.png diff --git a/source/assets/images/favicons/apple-icon-144x144.png b/_source_last_version/assets/images/favicons/apple-icon-144x144.png similarity index 100% rename from source/assets/images/favicons/apple-icon-144x144.png rename to _source_last_version/assets/images/favicons/apple-icon-144x144.png diff --git a/source/assets/images/favicons/apple-icon-152x152.png b/_source_last_version/assets/images/favicons/apple-icon-152x152.png similarity index 100% rename from source/assets/images/favicons/apple-icon-152x152.png rename to _source_last_version/assets/images/favicons/apple-icon-152x152.png diff --git a/source/assets/images/favicons/apple-icon-180x180.png b/_source_last_version/assets/images/favicons/apple-icon-180x180.png similarity index 100% rename from source/assets/images/favicons/apple-icon-180x180.png rename to _source_last_version/assets/images/favicons/apple-icon-180x180.png diff --git a/source/assets/images/favicons/apple-icon-57x57.png b/_source_last_version/assets/images/favicons/apple-icon-57x57.png similarity index 100% rename from source/assets/images/favicons/apple-icon-57x57.png rename to _source_last_version/assets/images/favicons/apple-icon-57x57.png diff --git a/source/assets/images/favicons/apple-icon-60x60.png b/_source_last_version/assets/images/favicons/apple-icon-60x60.png similarity index 100% rename from source/assets/images/favicons/apple-icon-60x60.png rename to _source_last_version/assets/images/favicons/apple-icon-60x60.png diff --git a/source/assets/images/favicons/apple-icon-72x72.png b/_source_last_version/assets/images/favicons/apple-icon-72x72.png similarity index 100% rename from source/assets/images/favicons/apple-icon-72x72.png rename to _source_last_version/assets/images/favicons/apple-icon-72x72.png diff --git a/source/assets/images/favicons/apple-icon-76x76.png b/_source_last_version/assets/images/favicons/apple-icon-76x76.png similarity index 100% rename from source/assets/images/favicons/apple-icon-76x76.png rename to _source_last_version/assets/images/favicons/apple-icon-76x76.png diff --git a/source/assets/images/favicons/apple-icon-precomposed.png b/_source_last_version/assets/images/favicons/apple-icon-precomposed.png similarity index 100% rename from source/assets/images/favicons/apple-icon-precomposed.png rename to _source_last_version/assets/images/favicons/apple-icon-precomposed.png diff --git a/source/assets/images/favicons/apple-icon.png b/_source_last_version/assets/images/favicons/apple-icon.png similarity index 100% rename from source/assets/images/favicons/apple-icon.png rename to _source_last_version/assets/images/favicons/apple-icon.png diff --git a/source/assets/images/favicons/favicon-16x16.png b/_source_last_version/assets/images/favicons/favicon-16x16.png similarity index 100% rename from source/assets/images/favicons/favicon-16x16.png rename to _source_last_version/assets/images/favicons/favicon-16x16.png diff --git a/source/assets/images/favicons/favicon-32x32.png b/_source_last_version/assets/images/favicons/favicon-32x32.png similarity index 100% rename from source/assets/images/favicons/favicon-32x32.png rename to _source_last_version/assets/images/favicons/favicon-32x32.png diff --git a/source/assets/images/favicons/favicon-96x96.png b/_source_last_version/assets/images/favicons/favicon-96x96.png similarity index 100% rename from source/assets/images/favicons/favicon-96x96.png rename to _source_last_version/assets/images/favicons/favicon-96x96.png diff --git a/source/assets/images/favicons/favicon.ico b/_source_last_version/assets/images/favicons/favicon.ico similarity index 100% rename from source/assets/images/favicons/favicon.ico rename to _source_last_version/assets/images/favicons/favicon.ico diff --git a/source/assets/images/favicons/ms-icon-144x144.png b/_source_last_version/assets/images/favicons/ms-icon-144x144.png similarity index 100% rename from source/assets/images/favicons/ms-icon-144x144.png rename to _source_last_version/assets/images/favicons/ms-icon-144x144.png diff --git a/source/assets/images/favicons/ms-icon-150x150.png b/_source_last_version/assets/images/favicons/ms-icon-150x150.png similarity index 100% rename from source/assets/images/favicons/ms-icon-150x150.png rename to _source_last_version/assets/images/favicons/ms-icon-150x150.png diff --git a/source/assets/images/favicons/ms-icon-310x310.png b/_source_last_version/assets/images/favicons/ms-icon-310x310.png similarity index 100% rename from source/assets/images/favicons/ms-icon-310x310.png rename to _source_last_version/assets/images/favicons/ms-icon-310x310.png diff --git a/source/assets/images/favicons/ms-icon-70x70.png b/_source_last_version/assets/images/favicons/ms-icon-70x70.png similarity index 100% rename from source/assets/images/favicons/ms-icon-70x70.png rename to _source_last_version/assets/images/favicons/ms-icon-70x70.png diff --git a/source/assets/images/logos/blue.svg b/_source_last_version/assets/images/logos/blue.svg similarity index 100% rename from source/assets/images/logos/blue.svg rename to _source_last_version/assets/images/logos/blue.svg diff --git a/source/assets/images/logos/meta.png b/_source_last_version/assets/images/logos/meta.png similarity index 100% rename from source/assets/images/logos/meta.png rename to _source_last_version/assets/images/logos/meta.png diff --git a/source/assets/images/logos/white.svg b/_source_last_version/assets/images/logos/white.svg similarity index 100% rename from source/assets/images/logos/white.svg rename to _source_last_version/assets/images/logos/white.svg diff --git a/source/assets/images/logos/yellow.svg b/_source_last_version/assets/images/logos/yellow.svg similarity index 100% rename from source/assets/images/logos/yellow.svg rename to _source_last_version/assets/images/logos/yellow.svg diff --git a/source/assets/images/pages/contact/background.jpg b/_source_last_version/assets/images/pages/contact/background.jpg similarity index 100% rename from source/assets/images/pages/contact/background.jpg rename to _source_last_version/assets/images/pages/contact/background.jpg diff --git a/_source_last_version/assets/images/pages/four-o-four/background.jpg b/_source_last_version/assets/images/pages/four-o-four/background.jpg new file mode 100644 index 00000000..2686b6c3 Binary files /dev/null and b/_source_last_version/assets/images/pages/four-o-four/background.jpg differ diff --git a/source/assets/images/pages/index/always-grey.png b/_source_last_version/assets/images/pages/index/always-grey.png similarity index 100% rename from source/assets/images/pages/index/always-grey.png rename to _source_last_version/assets/images/pages/index/always-grey.png diff --git a/source/assets/images/pages/index/buildings.png b/_source_last_version/assets/images/pages/index/buildings.png similarity index 100% rename from source/assets/images/pages/index/buildings.png rename to _source_last_version/assets/images/pages/index/buildings.png diff --git a/source/assets/images/pages/index/cta-background.jpg b/_source_last_version/assets/images/pages/index/cta-background.jpg similarity index 100% rename from source/assets/images/pages/index/cta-background.jpg rename to _source_last_version/assets/images/pages/index/cta-background.jpg diff --git a/source/assets/images/pages/index/dark-sharp-edges.png b/_source_last_version/assets/images/pages/index/dark-sharp-edges.png similarity index 100% rename from source/assets/images/pages/index/dark-sharp-edges.png rename to _source_last_version/assets/images/pages/index/dark-sharp-edges.png diff --git a/source/assets/images/pages/index/engagements-background.jpg b/_source_last_version/assets/images/pages/index/engagements-background.jpg similarity index 100% rename from source/assets/images/pages/index/engagements-background.jpg rename to _source_last_version/assets/images/pages/index/engagements-background.jpg diff --git a/source/assets/images/pages/index/engagements/advancedbd.svg b/_source_last_version/assets/images/pages/index/engagements/advancedbd.svg similarity index 100% rename from source/assets/images/pages/index/engagements/advancedbd.svg rename to _source_last_version/assets/images/pages/index/engagements/advancedbd.svg diff --git a/source/assets/images/pages/index/engagements/arthur-maxwell.gif b/_source_last_version/assets/images/pages/index/engagements/arthur-maxwell.gif similarity index 100% rename from source/assets/images/pages/index/engagements/arthur-maxwell.gif rename to _source_last_version/assets/images/pages/index/engagements/arthur-maxwell.gif diff --git a/source/assets/images/pages/index/engagements/crowdox.png b/_source_last_version/assets/images/pages/index/engagements/crowdox.png similarity index 100% rename from source/assets/images/pages/index/engagements/crowdox.png rename to _source_last_version/assets/images/pages/index/engagements/crowdox.png diff --git a/source/assets/images/pages/index/engagements/eggplant.png b/_source_last_version/assets/images/pages/index/engagements/eggplant.png similarity index 100% rename from source/assets/images/pages/index/engagements/eggplant.png rename to _source_last_version/assets/images/pages/index/engagements/eggplant.png diff --git a/source/assets/images/pages/index/engagements/gathrly.png b/_source_last_version/assets/images/pages/index/engagements/gathrly.png similarity index 100% rename from source/assets/images/pages/index/engagements/gathrly.png rename to _source_last_version/assets/images/pages/index/engagements/gathrly.png diff --git a/source/assets/images/pages/index/engagements/sidebench.svg b/_source_last_version/assets/images/pages/index/engagements/sidebench.svg similarity index 100% rename from source/assets/images/pages/index/engagements/sidebench.svg rename to _source_last_version/assets/images/pages/index/engagements/sidebench.svg diff --git a/source/assets/images/pages/index/engagements/usatoday.png b/_source_last_version/assets/images/pages/index/engagements/usatoday.png similarity index 100% rename from source/assets/images/pages/index/engagements/usatoday.png rename to _source_last_version/assets/images/pages/index/engagements/usatoday.png diff --git a/source/assets/images/pages/index/engagements/wwnorton.png b/_source_last_version/assets/images/pages/index/engagements/wwnorton.png similarity index 100% rename from source/assets/images/pages/index/engagements/wwnorton.png rename to _source_last_version/assets/images/pages/index/engagements/wwnorton.png diff --git a/source/assets/images/pages/index/financial-management.json b/_source_last_version/assets/images/pages/index/financial-management.json similarity index 100% rename from source/assets/images/pages/index/financial-management.json rename to _source_last_version/assets/images/pages/index/financial-management.json diff --git a/source/assets/images/pages/index/right-setup.svg b/_source_last_version/assets/images/pages/index/right-setup.svg similarity index 100% rename from source/assets/images/pages/index/right-setup.svg rename to _source_last_version/assets/images/pages/index/right-setup.svg diff --git a/source/assets/images/pages/index/startup-project.json b/_source_last_version/assets/images/pages/index/startup-project.json similarity index 100% rename from source/assets/images/pages/index/startup-project.json rename to _source_last_version/assets/images/pages/index/startup-project.json diff --git a/source/assets/images/signatures/full-name.svg b/_source_last_version/assets/images/signatures/full-name.svg similarity index 100% rename from source/assets/images/signatures/full-name.svg rename to _source_last_version/assets/images/signatures/full-name.svg diff --git a/source/assets/javascripts/components/navigation.js b/_source_last_version/assets/javascripts/components/navigation.js similarity index 100% rename from source/assets/javascripts/components/navigation.js rename to _source_last_version/assets/javascripts/components/navigation.js diff --git a/source/assets/javascripts/pages/contact.js b/_source_last_version/assets/javascripts/pages/contact.js similarity index 100% rename from source/assets/javascripts/pages/contact.js rename to _source_last_version/assets/javascripts/pages/contact.js diff --git a/source/assets/javascripts/pages/index.js b/_source_last_version/assets/javascripts/pages/index.js similarity index 100% rename from source/assets/javascripts/pages/index.js rename to _source_last_version/assets/javascripts/pages/index.js diff --git a/_source_last_version/assets/javascripts/site.js b/_source_last_version/assets/javascripts/site.js new file mode 100644 index 00000000..2efe5b38 --- /dev/null +++ b/_source_last_version/assets/javascripts/site.js @@ -0,0 +1,45 @@ +import breakpoints from './vendor/breakpoints'; +import navigation from './components/navigation'; +import index from './pages/index'; +import contact from './pages/contact'; + +const hidePreloader = () => { + $('#preloader').fadeOut(1000, () => { + $('#cover').remove(); + }); +}; + +const resizeContent = () => { + const vh = window.innerHeight * 0.01; + + document.documentElement.style.setProperty('--vh', `${vh}px`); +}; + +$(document).ready(() => { + const $body = $('body'); + const $bodyId = $body.attr('id'); + + breakpoints(); + navigation(); + + switch ($bodyId) { + case 'index': + index(); + break; + case 'contact': + contact(); + break; + default: + break; + } + + resizeContent(); +}); + +window.addEventListener('load', () => { + hidePreloader(); +}, false); + +window.addEventListener('resize', () => { + resizeContent(); +}); diff --git a/_source_last_version/assets/javascripts/vendor.js b/_source_last_version/assets/javascripts/vendor.js new file mode 100644 index 00000000..7bbf9e4d --- /dev/null +++ b/_source_last_version/assets/javascripts/vendor.js @@ -0,0 +1,11 @@ +window.jQuery = require('jquery'); + +// eslint-disable-next-line no-multi-assign +window.jQuery = window.$ = $; + +window.Popper = require('popper.js'); + +require('bootstrap'); +require('breakpoints'); +require('validation'); +require('fontawesome'); diff --git a/source/assets/javascripts/vendor/breakpoints.js b/_source_last_version/assets/javascripts/vendor/breakpoints.js similarity index 100% rename from source/assets/javascripts/vendor/breakpoints.js rename to _source_last_version/assets/javascripts/vendor/breakpoints.js diff --git a/source/assets/javascripts/vendor/fontawesome.js b/_source_last_version/assets/javascripts/vendor/fontawesome.js similarity index 100% rename from source/assets/javascripts/vendor/fontawesome.js rename to _source_last_version/assets/javascripts/vendor/fontawesome.js diff --git a/_source_last_version/assets/stylesheets/_settings.scss b/_source_last_version/assets/stylesheets/_settings.scss new file mode 100644 index 00000000..1e1bb49b --- /dev/null +++ b/_source_last_version/assets/stylesheets/_settings.scss @@ -0,0 +1,44 @@ +$image-path: '../../assets/images/'; + +$color-white: #fff; +$color-black: #000; +$color-one: #C99383; +$color-two: #1e2022; +$color-three: #d8b2a7; +$color-four: #ba745f; +$color-five: #36393d; +$color-six: #060607; + +@mixin font-color-light { color: $color-white; } + +@mixin font-highlight-color { color: $highlight-color; } + +$darkest-color: $color-one; +$highlight-color: $color-five; +$border-color: $color-two; +$link-color: $color-five; + +$backdrop-opacity: 0.8; +$backdrop-opacity-dark: 0.9; +$backdrop-opacity-light: 0.7; +$backdrop-opacity-medium-light: 0.5; +$backdrop-opacity-super-light: 0.2; + +$radius: 1rem; + +$minimum-height: 700px; +$grid-breakpoints: ( + xs: 0, + minimium: 375px, + transition: 450px, + sm: 576px, + md: 768px, + lg: 992px, + maximum: 1000px, + xl: 1200px, + xxl: 1400px, + xxxl: 1800px, + xxxxl: 2450px +); + +$zindex-cover: 10000 !default; diff --git a/source/assets/stylesheets/components/_footer.scss b/_source_last_version/assets/stylesheets/components/_footer.scss similarity index 100% rename from source/assets/stylesheets/components/_footer.scss rename to _source_last_version/assets/stylesheets/components/_footer.scss diff --git a/_source_last_version/assets/stylesheets/components/_html-body.scss b/_source_last_version/assets/stylesheets/components/_html-body.scss new file mode 100644 index 00000000..8b4051f1 --- /dev/null +++ b/_source_last_version/assets/stylesheets/components/_html-body.scss @@ -0,0 +1,17 @@ +html { + overflow: hidden scroll; +} + +html, +body { + padding: 0 !important; + margin: 0 !important; + height: 100% !important; + min-width: map-get($grid-breakpoints, 'minimium') !important; + min-height: 100% !important; + background-color: $darkest-color; + font-size: 1rem; + + @include primary-font(); + @include font-color-light(); +} diff --git a/source/assets/stylesheets/components/_navigation.scss b/_source_last_version/assets/stylesheets/components/_navigation.scss similarity index 100% rename from source/assets/stylesheets/components/_navigation.scss rename to _source_last_version/assets/stylesheets/components/_navigation.scss diff --git a/source/assets/stylesheets/components/_preloader.scss b/_source_last_version/assets/stylesheets/components/_preloader.scss similarity index 100% rename from source/assets/stylesheets/components/_preloader.scss rename to _source_last_version/assets/stylesheets/components/_preloader.scss diff --git a/source/assets/stylesheets/mixins/_utilities.scss b/_source_last_version/assets/stylesheets/mixins/_utilities.scss similarity index 100% rename from source/assets/stylesheets/mixins/_utilities.scss rename to _source_last_version/assets/stylesheets/mixins/_utilities.scss diff --git a/source/assets/stylesheets/pages/contact/_contact-form.scss b/_source_last_version/assets/stylesheets/pages/contact/_contact-form.scss similarity index 100% rename from source/assets/stylesheets/pages/contact/_contact-form.scss rename to _source_last_version/assets/stylesheets/pages/contact/_contact-form.scss diff --git a/source/assets/stylesheets/pages/contact/_contact-wrapper-inner.scss b/_source_last_version/assets/stylesheets/pages/contact/_contact-wrapper-inner.scss similarity index 100% rename from source/assets/stylesheets/pages/contact/_contact-wrapper-inner.scss rename to _source_last_version/assets/stylesheets/pages/contact/_contact-wrapper-inner.scss diff --git a/source/assets/stylesheets/pages/contact/_index.scss b/_source_last_version/assets/stylesheets/pages/contact/_index.scss similarity index 100% rename from source/assets/stylesheets/pages/contact/_index.scss rename to _source_last_version/assets/stylesheets/pages/contact/_index.scss diff --git a/source/assets/stylesheets/pages/four-o-four/_index.scss b/_source_last_version/assets/stylesheets/pages/four-o-four/_index.scss similarity index 100% rename from source/assets/stylesheets/pages/four-o-four/_index.scss rename to _source_last_version/assets/stylesheets/pages/four-o-four/_index.scss diff --git a/source/assets/stylesheets/pages/index/_about.scss b/_source_last_version/assets/stylesheets/pages/index/_about.scss similarity index 100% rename from source/assets/stylesheets/pages/index/_about.scss rename to _source_last_version/assets/stylesheets/pages/index/_about.scss diff --git a/source/assets/stylesheets/pages/index/_call-to-action.scss b/_source_last_version/assets/stylesheets/pages/index/_call-to-action.scss similarity index 100% rename from source/assets/stylesheets/pages/index/_call-to-action.scss rename to _source_last_version/assets/stylesheets/pages/index/_call-to-action.scss diff --git a/source/assets/stylesheets/pages/index/_cta-banner-wrapper.scss b/_source_last_version/assets/stylesheets/pages/index/_cta-banner-wrapper.scss similarity index 100% rename from source/assets/stylesheets/pages/index/_cta-banner-wrapper.scss rename to _source_last_version/assets/stylesheets/pages/index/_cta-banner-wrapper.scss diff --git a/source/assets/stylesheets/pages/index/_engagements.scss b/_source_last_version/assets/stylesheets/pages/index/_engagements.scss similarity index 100% rename from source/assets/stylesheets/pages/index/_engagements.scss rename to _source_last_version/assets/stylesheets/pages/index/_engagements.scss diff --git a/source/assets/stylesheets/pages/index/_include.scss b/_source_last_version/assets/stylesheets/pages/index/_include.scss similarity index 100% rename from source/assets/stylesheets/pages/index/_include.scss rename to _source_last_version/assets/stylesheets/pages/index/_include.scss diff --git a/source/assets/stylesheets/pages/index/_index.scss b/_source_last_version/assets/stylesheets/pages/index/_index.scss similarity index 100% rename from source/assets/stylesheets/pages/index/_index.scss rename to _source_last_version/assets/stylesheets/pages/index/_index.scss diff --git a/source/assets/stylesheets/pages/index/_services-banner.scss b/_source_last_version/assets/stylesheets/pages/index/_services-banner.scss similarity index 100% rename from source/assets/stylesheets/pages/index/_services-banner.scss rename to _source_last_version/assets/stylesheets/pages/index/_services-banner.scss diff --git a/_source_last_version/assets/stylesheets/site.scss b/_source_last_version/assets/stylesheets/site.scss new file mode 100644 index 00000000..18ae33e0 --- /dev/null +++ b/_source_last_version/assets/stylesheets/site.scss @@ -0,0 +1,14 @@ +@charset "utf-8"; + +@import "~normalize-scss/sass/normalize/import-now"; +@import "settings"; +@import "vendor/bootstrap"; +@import "vendor/google_fonts"; +@import "mixins/*"; +@import "components/html-body"; +@import "components/preloader"; +@import "components/navigation"; +@import "components/footer"; +@import "pages/index/index"; +@import "pages/contact/index"; +@import "pages/four-o-four/index"; diff --git a/source/assets/stylesheets/vendor/_bootstrap.scss b/_source_last_version/assets/stylesheets/vendor/_bootstrap.scss similarity index 100% rename from source/assets/stylesheets/vendor/_bootstrap.scss rename to _source_last_version/assets/stylesheets/vendor/_bootstrap.scss diff --git a/source/assets/stylesheets/vendor/_flexslider.scss b/_source_last_version/assets/stylesheets/vendor/_flexslider.scss similarity index 100% rename from source/assets/stylesheets/vendor/_flexslider.scss rename to _source_last_version/assets/stylesheets/vendor/_flexslider.scss diff --git a/source/assets/stylesheets/vendor/_google_fonts.scss b/_source_last_version/assets/stylesheets/vendor/_google_fonts.scss similarity index 100% rename from source/assets/stylesheets/vendor/_google_fonts.scss rename to _source_last_version/assets/stylesheets/vendor/_google_fonts.scss diff --git a/source/assets/stylesheets/vendor/flexslider/_base.scss b/_source_last_version/assets/stylesheets/vendor/flexslider/_base.scss similarity index 100% rename from source/assets/stylesheets/vendor/flexslider/_base.scss rename to _source_last_version/assets/stylesheets/vendor/flexslider/_base.scss diff --git a/source/assets/stylesheets/vendor/flexslider/_mixins.scss b/_source_last_version/assets/stylesheets/vendor/flexslider/_mixins.scss similarity index 100% rename from source/assets/stylesheets/vendor/flexslider/_mixins.scss rename to _source_last_version/assets/stylesheets/vendor/flexslider/_mixins.scss diff --git a/source/assets/stylesheets/vendor/flexslider/_resets.scss b/_source_last_version/assets/stylesheets/vendor/flexslider/_resets.scss similarity index 100% rename from source/assets/stylesheets/vendor/flexslider/_resets.scss rename to _source_last_version/assets/stylesheets/vendor/flexslider/_resets.scss diff --git a/source/assets/stylesheets/vendor/flexslider/_responsive.scss b/_source_last_version/assets/stylesheets/vendor/flexslider/_responsive.scss similarity index 100% rename from source/assets/stylesheets/vendor/flexslider/_responsive.scss rename to _source_last_version/assets/stylesheets/vendor/flexslider/_responsive.scss diff --git a/source/assets/stylesheets/vendor/flexslider/_theme.scss b/_source_last_version/assets/stylesheets/vendor/flexslider/_theme.scss similarity index 100% rename from source/assets/stylesheets/vendor/flexslider/_theme.scss rename to _source_last_version/assets/stylesheets/vendor/flexslider/_theme.scss diff --git a/source/assets/stylesheets/vendor/flexslider/_variables.scss b/_source_last_version/assets/stylesheets/vendor/flexslider/_variables.scss similarity index 100% rename from source/assets/stylesheets/vendor/flexslider/_variables.scss rename to _source_last_version/assets/stylesheets/vendor/flexslider/_variables.scss diff --git a/source/contact.html.slim b/_source_last_version/contact.html.slim similarity index 100% rename from source/contact.html.slim rename to _source_last_version/contact.html.slim diff --git a/source/four-o-four.html.slim b/_source_last_version/four-o-four.html.slim similarity index 100% rename from source/four-o-four.html.slim rename to _source_last_version/four-o-four.html.slim diff --git a/_source_last_version/index.html.slim b/_source_last_version/index.html.slim new file mode 100644 index 00000000..2a8c14c9 --- /dev/null +++ b/_source_last_version/index.html.slim @@ -0,0 +1,24 @@ +--- +id: index +layout: index +--- + +section[class="row call-to-action"] + div[class="col-12 mx-auto section-wrapper"] + = partial "partials/pages/index/call-to-action" +section[class="row d-block d-md-none services-banner"] + a[name="services"] + div[class="col-12 mx-auto section-wrapper"] + = partial "partials/pages/index/services-banner" +section[class="row engagements"] + a[name="engagements"] + div[class="col-12 mx-auto section-wrapper"] + = partial "partials/pages/index/engagements" +section[class="row about"] + a[name="about"] + div[class="col-12 mx-auto section-wrapper"] + = partial "partials/pages/index/about" +section[class="row footer"] + div[class="col-12 mx-auto section-wrapper"] + div[class="row"] + = partial "partials/components/footer" diff --git a/source/layouts/four-o-four.html.slim b/_source_last_version/layouts/four-o-four.html.slim similarity index 100% rename from source/layouts/four-o-four.html.slim rename to _source_last_version/layouts/four-o-four.html.slim diff --git a/_source_last_version/layouts/index.html.slim b/_source_last_version/layouts/index.html.slim new file mode 100644 index 00000000..8e2ce6b2 --- /dev/null +++ b/_source_last_version/layouts/index.html.slim @@ -0,0 +1,9 @@ += partial "partials/components/document" do + = partial "partials/components/header", locals: { include_lottie: true } + = partial "partials/components/body" do + = partial "partials/components/navigation" + + main[class="container-fluid"] + == yield + + = partial "partials/components/javascript" diff --git a/source/layouts/page.html.slim b/_source_last_version/layouts/page.html.slim similarity index 100% rename from source/layouts/page.html.slim rename to _source_last_version/layouts/page.html.slim diff --git a/_source_last_version/partials/components/_body.html.slim b/_source_last_version/partials/components/_body.html.slim new file mode 100644 index 00000000..2c757ec9 --- /dev/null +++ b/_source_last_version/partials/components/_body.html.slim @@ -0,0 +1,3 @@ +body[id="#{current_page.data.id}"] + = partial "partials/components/pre-loader" + == yield diff --git a/_source_last_version/partials/components/_document.html.slim b/_source_last_version/partials/components/_document.html.slim new file mode 100644 index 00000000..fe3b5823 --- /dev/null +++ b/_source_last_version/partials/components/_document.html.slim @@ -0,0 +1,3 @@ +doctype html +html[lang="en-US"] + == yield diff --git a/source/partials/components/_favicons.html.slim b/_source_last_version/partials/components/_favicons.html.slim similarity index 100% rename from source/partials/components/_favicons.html.slim rename to _source_last_version/partials/components/_favicons.html.slim diff --git a/_source_last_version/partials/components/_footer.html.slim b/_source_last_version/partials/components/_footer.html.slim new file mode 100644 index 00000000..aa9a2cdd --- /dev/null +++ b/_source_last_version/partials/components/_footer.html.slim @@ -0,0 +1,14 @@ +div[class="col-12 locations"] + - data.about.locations.sort_by { |k| k["id"] }.each_with_index do |l, index| + span + = l.location + span[class="divider"] + - if index < data.about.locations.count - 1 + |❙ + +div[class="col-12 company"] + |© + => + = data.about.copyright + => + = data.components.social.formalname diff --git a/_source_last_version/partials/components/_header.html.slim b/_source_last_version/partials/components/_header.html.slim new file mode 100644 index 00000000..18590a11 --- /dev/null +++ b/_source_last_version/partials/components/_header.html.slim @@ -0,0 +1,16 @@ +head + | + + javascript: + window.dataLayer = window.dataLayer || []; + function gtag(){dataLayer.push(arguments);} + gtag('js', new Date()); + gtag('config', 'G-YMVZTN6RSB'); + + = partial "partials/components/meta" + = partial "partials/components/favicons" + = partial "partials/components/title" + = stylesheet_link_tag(webpack_asset_path("site.scss", "site")) + + - if locals[:include_lottie].present? + | diff --git a/_source_last_version/partials/components/_javascript.html.slim b/_source_last_version/partials/components/_javascript.html.slim new file mode 100644 index 00000000..115bbbcc --- /dev/null +++ b/_source_last_version/partials/components/_javascript.html.slim @@ -0,0 +1,12 @@ += javascript_include_tag(webpack_asset_path("vendor.js", "site")) += javascript_include_tag(webpack_asset_path("site.js", "site")) + +| + +- if app.development? + javascript: + $(document).ready(() => { + console.log("------------------------------------------------------------"); + console.log("Site Mode: Development"); + console.log("------------------------------------------------------------"); + }); diff --git a/source/partials/components/_meta.html.slim b/_source_last_version/partials/components/_meta.html.slim similarity index 100% rename from source/partials/components/_meta.html.slim rename to _source_last_version/partials/components/_meta.html.slim diff --git a/_source_last_version/partials/components/_navigation.html.slim b/_source_last_version/partials/components/_navigation.html.slim new file mode 100644 index 00000000..552e5c3e --- /dev/null +++ b/_source_last_version/partials/components/_navigation.html.slim @@ -0,0 +1,46 @@ +nav[class="navbar navbar-expand-sm sticky-top navbar-dark"] + div[class="row flex-fill mx-auto navbar-wrapper"] + div[class="col-12 col-lg-7 my-auto navbar-toggler-wrapper"] + div[class="row"] + div[class="col-10 col-sm-12 d-flex my-auto"] + = link_to("/", class: "logo-link-logo") do + embed[id="company-logo" src="#{image_path('logos/yellow.svg')}"] + = link_to("/", class: "logo-link-text") do + = data.components.social.shortname + div[class="col-2 my-auto d-md-none navbar-button"] + button[class="navbar-toggler" type="button" data-toggle="collapse" + data-target="#navbarCollapse" + aria-controls="navbarCollapse" + aria-expanded="false" + aria-label="Toggle navigation"] + i[id="nav-button" class="fas fa-bars"] + + div[class="col-12 col-lg-5 navbar-nav-item-wrapper"] + div[class="collapse navbar-collapse" id="navbarCollapse"] + ul[class="navbar-nav flex-fill"] + ruby: + redirection = current_page.data.id == "index" ? false : true + li[class="nav-item flex-fill d-md-none"] + = link_to("/", id: "services", class: "nav-link", data: { reference: "home", redirection: redirection }) do + span[class="nav-button d-lg-none"] + i[class="fas fa-hammer nav-icon"] + span[class="nav-description"] + |Services + li[class="nav-item flex-fill"] + = link_to("/", id: "engagements", class: "nav-link", data: { reference: "home", redirection: redirection }) do + span[class="nav-button d-lg-none"] + i[class="fas fa-project-diagram nav-icon"] + span[class="nav-description"] + |Engagements + li[class="nav-item flex-fill"] + = link_to("/", id: "about", class: "nav-link", data: { reference: "home", redirection: redirection }) do + span[class="nav-button d-lg-none"] + i[class="fas fa-brain nav-icon"] + span[class="nav-description"] + |About + li[class="nav-item flex-fill"] + = link_to("/", id: "contact", class: "nav-link", data: { reference: "page", redirection: true }) do + span[class="nav-button"] + i[class="far fa-envelope nav-icon"] + span[class="nav-description d-lg-none"] + |Contact diff --git a/source/partials/components/_pre-loader.html.slim b/_source_last_version/partials/components/_pre-loader.html.slim similarity index 100% rename from source/partials/components/_pre-loader.html.slim rename to _source_last_version/partials/components/_pre-loader.html.slim diff --git a/_source_last_version/partials/components/_title.html.slim b/_source_last_version/partials/components/_title.html.slim new file mode 100644 index 00000000..01223067 --- /dev/null +++ b/_source_last_version/partials/components/_title.html.slim @@ -0,0 +1,5 @@ +title + - if current_page.data.title + = "#{data.components.social.formalname} | #{data.components.social.focus} | #{current_page.data.title}" + - else + = "#{data.components.social.formalname} | #{data.components.social.focus}" diff --git a/source/partials/pages/contact/_contact_form.html.slim b/_source_last_version/partials/pages/contact/_contact_form.html.slim similarity index 100% rename from source/partials/pages/contact/_contact_form.html.slim rename to _source_last_version/partials/pages/contact/_contact_form.html.slim diff --git a/source/partials/pages/index/_about.html.slim b/_source_last_version/partials/pages/index/_about.html.slim similarity index 100% rename from source/partials/pages/index/_about.html.slim rename to _source_last_version/partials/pages/index/_about.html.slim diff --git a/source/partials/pages/index/_call-to-action.html.slim b/_source_last_version/partials/pages/index/_call-to-action.html.slim similarity index 100% rename from source/partials/pages/index/_call-to-action.html.slim rename to _source_last_version/partials/pages/index/_call-to-action.html.slim diff --git a/source/partials/pages/index/_engagements.html.slim b/_source_last_version/partials/pages/index/_engagements.html.slim similarity index 100% rename from source/partials/pages/index/_engagements.html.slim rename to _source_last_version/partials/pages/index/_engagements.html.slim diff --git a/source/partials/pages/index/_services-banner.html.slim b/_source_last_version/partials/pages/index/_services-banner.html.slim similarity index 100% rename from source/partials/pages/index/_services-banner.html.slim rename to _source_last_version/partials/pages/index/_services-banner.html.slim diff --git a/source/partials/view_source_footer.txt b/_source_last_version/partials/view_source_footer.txt similarity index 100% rename from source/partials/view_source_footer.txt rename to _source_last_version/partials/view_source_footer.txt diff --git a/source/partials/view_source_header.txt b/_source_last_version/partials/view_source_header.txt similarity index 100% rename from source/partials/view_source_header.txt rename to _source_last_version/partials/view_source_header.txt diff --git a/_source_last_version/sitemap.xml.builder b/_source_last_version/sitemap.xml.builder new file mode 100644 index 00000000..23a329a4 --- /dev/null +++ b/_source_last_version/sitemap.xml.builder @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +xml.instruct! +xml.urlset 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9' do + sitemap.resources.select { |page| page.path.include?('.html') }.each do |page| + next unless page.data.seo != false + + location = if page.url == '/' + "#{data.components.url}/index.html" + else + "#{data.components.url}#{page.url}index.html" + end + + xml.url do + xml.loc location + xml.lastmod Date.today.to_time.iso8601 + xml.changefreq page.data.changefreq || 'monthly' + xml.priority page.data.priority || '0.5' + end + end +end diff --git a/config.rb b/config.rb index e0663b03..dc58dd38 100644 --- a/config.rb +++ b/config.rb @@ -30,6 +30,9 @@ activate :directory_indexes +# 404 page must be at root level for GitHub Pages +page '/404.html', directory_index: false + activate :deploy do |deploy| deploy.build_before = true deploy.deploy_method = :git diff --git a/data/.keep b/data/.keep new file mode 100644 index 00000000..e69de29b diff --git a/data/about.yml b/data/about.yml index 9a76551a..f37acf7b 100644 --- a/data/about.yml +++ b/data/about.yml @@ -2,7 +2,7 @@ copyright: 2016 - Present / cta: It has been said there are two ways to build a business. You can either focus on building the tallest building or spend your time and energy tearing other buildings around you down. Let's work together to build, create, invent, not destroy. -description: Founded in Boulder, Colorado in 2016 we've had successful engagements in Chicago, Boulder, Manhattan, and Portland, Oregon. We are remote-first and can help you establish the same culture. If you are interested in learning more about working together, our process, and how we can help, please reach out. A quiet warning though, we are very selective of who we work with and are always happy to refer out if we are not the right fit. +description: Founded in Boulder, Colorado in 2016 we've had successful engagements in Chicago, Boulder, Manhattan, Portland, Oregon, and Las Vegas. We are remote-first and can help you establish the same culture. If you are interested in learning more about working together, our process, and how we can help, please reach out. A quiet warning though, we are very selective of who we work with and are always happy to refer out if we are not the right fit. locations: - diff --git a/data/components.yml b/data/components.yml index 90d80bac..c475e7bb 100644 --- a/data/components.yml +++ b/data/components.yml @@ -6,6 +6,7 @@ social: formalname: RobotsBuildingRobots, LLC founder: Chris Hough focus: How can we help you? + linkedin: https://www.linkedin.com/company/robots-building-robots/ meta: description: ROBOTSBUILDINGROBOTS, LLC was founded in Boulder Colorado in 2016. Through successful engagements across Chicago, Manhattan, and Portland, Oregon we focus on delivering quality measured ROI through the products we engineer in-house, and the services we provide to our clients. Being brutally honest, and highly selective are part of our core values. We are picky about the clients and projects we attach our name to, and you could say we are more focused on bringing impact, than merely collecting fees. Ultimately we derive success through win-win partnerships. diff --git a/data/engagements.yml b/data/engagements.yml index e5c2e6fa..2882f292 100644 --- a/data/engagements.yml +++ b/data/engagements.yml @@ -4,48 +4,46 @@ projects: - id: 1 company: Gathrly - logo: gathrly.png collaboration: >- - Partnered with company founders to create a technical product roadmap and setup agile processes. Designed, engineered, and maintained a lead management application utilized by top tier brewers. Coached and mentored a team of junior engineers to meet productivity goals and ensure high-performance. + Partnered with founders to define the technical roadmap and implement agile workflows from the ground up. Architected and delivered a lead management platform adopted by top-tier craft breweries. Mentored junior engineers, accelerating their growth while building a high-performance engineering culture. - id: 2 company: USA Today - logo: usatoday.png collaboration: >- - Developed and architected a backend CMS with frontend content creation interfaces & features. Optimized user flows & improved the customer experience by designing an updated responsive layout. + Architected a robust backend CMS with intuitive content creation tools for editorial teams. Redesigned the responsive frontend experience, streamlining user flows and elevating engagement across devices. - id: 3 company: W. W. Norton - logo: wwnorton.png collaboration: >- - Designed and architected an interactive delivery platform to serve over 300+ interactives for a global publisher. Setup the GitFlow Process, code reviews, quality guidelines, & workflow management. Coached & mentored junior engineers on best practices to increase their productivity & contributions to the code base. + Architected an interactive content delivery platform serving 300+ educational experiences for a leading global publisher. Established GitFlow workflows, code review standards, and quality guidelines. Elevated team capabilities through hands-on mentorship, driving measurable gains in productivity and code quality. - id: 4 company: Crowd OX - logo: crowdox.png collaboration: >- - Built out platform features across three ruby-on-rails engines. Rewrote the Partner application testing suite porting it from Minitest to the latest version of RSpec while maintaining testing coverage metrics. Expanded testing coverage from 0% to over 60% in a legacy code base with 100% model testing coverage. + Extended platform capabilities across three interconnected Rails engines. Modernized the testing infrastructure by migrating from Minitest to RSpec, increasing coverage from 0% to 60% overall with complete model-layer coverage—transforming a legacy codebase into a maintainable foundation. - id: 5 company: Eggplant - logo: eggplant.png collaboration: >- - Expanded the authorization capability of the testing manager application to include Microsoft Active Directory (LDAP). Coordinated daily pair programming sessions to mentor junior engineers, improve team collaboration, and increase overall team performance. + Integrated Microsoft Active Directory (LDAP) authentication into the testing management platform, enabling enterprise-grade access control. Led daily pair programming sessions that strengthened team collaboration and accelerated junior engineer development. - id: 6 company: Advanced Building Technology - logo: advancedbd.svg collaboration: >- - Utilized responsive web design construction techniques to rearchitect version two of this corporation's website. While version one was not mobile or tablet friendly, iPhones, iPads, and desktops are all now supported. It was successfully launched on time in preparation for new product kickoffs. + Rebuilt the corporate website from the ground up with a mobile-first responsive architecture. Delivered on schedule to support new product launches, transforming a desktop-only experience into a seamless presence across all devices. - id: 7 company: Sidebench - logo: sidebench.svg collaboration: >- - Serving as a Technical Architect for the Momints NFT Marketplace by researching architecture, selecting components based on scalability needs and risk mitigation, developing the MVP, and compiling marketing materials. Provide high-level documentation on recommendations for system architecture diagrams, server infrastructure, tech stack selection, 3rd Party dependencies, data models and database schema, and API specifications to drive development. + Served as Technical Architect for the Momints NFT Marketplace, guiding technology decisions from concept through MVP delivery. Defined system architecture, infrastructure strategy, and API specifications—balancing scalability requirements with risk mitigation to establish a solid foundation for growth. - id: 8 company: Arthur Maxwell Experience Builder - logo: arthur-maxwell.gif collaboration: >- - Transforming a corporate eLearning management application with 200+ users from an experience-driven offline solution via iPads to online learning in classrooms using Hotwire, Stimulus, and Ruby on Rails. + Modernized a corporate eLearning platform serving 200+ users, transitioning from offline iPad-based delivery to a real-time classroom experience. Built with Rails, Hotwire, and Stimulus for responsive, interactive learning at scale. + - + id: 9 + company: Serenity + status: on-going + collaboration: >- + Pioneering ongoing AI-assisted development methodology using Claude to build and enhance a production-ready Rails 8 application featuring Rodauth authentication, Hotwire (Turbo + Stimulus) for reactive interfaces, Solid Suite integration (Queue, Cache, Cable), and service-oriented design patterns. Collaborating with AI to implement custom UI components, establish comprehensive testing infrastructure, and ensure strict code quality standards, reducing traditional development time by 10x while maintaining professional-grade architecture and deployment practices on Heroku with full monitoring and error tracking capabilities. diff --git a/data/products.yml b/data/products.yml new file mode 100644 index 00000000..f8d6ce20 --- /dev/null +++ b/data/products.yml @@ -0,0 +1,13 @@ +headline: Products in the Fire +description: We're forging tools to solve real problems. + +categories: + - name: SAAS TOOLS + icon: cloud + description: Subscription software that scales. + - name: E-COMMERCE + icon: cart + description: Products you can buy and use. + - name: OPEN SOURCE + icon: code + description: Free tools for the community. diff --git a/data/services.yml b/data/services.yml index 5b8a7f13..aeadcef8 100644 --- a/data/services.yml +++ b/data/services.yml @@ -1,5 +1,9 @@ -process: Whether augmented bolt-on resources or individual projects, we utilize Kanban or Scrum for our agile workflows. We are not interested in waterfall or pure chaos. All engagements are tracked hourly, invoiced weekly, and require NET-7. A successful engagement with us occurs when product and engineering work together with a shared vision and goals to completion. +obsession: We are craftsmen who architect systems worth defending. Every function, every test, every deployment receives obsessive attention to detail—because mediocrity ships bugs and technical debt compounds. With fifteen years building production systems for startups and enterprises alike, we've learned that excellence isn't an accident. It's a discipline we practice daily, tailoring our approach to each unique challenge. -metrics: At a foundational level, we believe automated tests are critical to the success of writing software. We advocate for community-driven, coding style approaches utilizing code linters and we grade our code with testing coverage metrics and style evaluation tools. If you are wanting to cut this corner, don’t worry, you can find many cheaper options out there. +discipline: Whether augmenting your team or delivering standalone projects, we run on structured agile workflows—Kanban or Scrum, never waterfall, never chaos. When embedded with your engineers, we mentor and elevate—running pair programming sessions, conducting code reviews, and transferring knowledge that outlasts the engagement. All work is tracked hourly, invoiced weekly, on NET-7 terms. Product and engineering move as one unit toward shared milestones. -values: First and foremost, we are craftsmen. We intrinsically value the work we accomplish, the meticulous attention to detail, and the quality of our work. We understand that we are not perfect; software processes are not perfect; bugs are inevitable. With over 15 years of experience in technology from startups to enterprises, we understand every business presents a unique set of challenges, and we tailor our approach accordingly. +innovation: We leverage cutting-edge tools and modern frameworks to build solutions that scale and last. From AI integration to cloud-native architecture, we deploy tomorrow's tooling today—because yesterday's stack becomes tomorrow's technical debt. Our automated testing and CI/CD pipelines ensure rapid, reliable deployments while maintaining the production stability your business depends on. + +results: We build partnerships around measurable outcomes, not feature bloat or vanity metrics. Every engagement we take on must move the needle and deliver clear value to your business. We focus on cost-effective solutions that drive real results, not gold-plated features nobody asked for. Your long-term success is the only KPI that matters. + +evidence: At our foundation, we believe automated tests are critical to shipping quality software. We advocate for community-driven coding standards, enforce style guides with linters, and grade our work with coverage metrics. We prove quality with data, not promises. If you're looking to cut corners on testing and quality, we're happy to refer you elsewhere. diff --git a/readme.md b/readme.md index 12e69d9b..37cb0477 100644 --- a/readme.md +++ b/readme.md @@ -1,22 +1,22 @@ # RobotsBuildingRobots.com -A modern, responsive portfolio and business presence website built with Middleman, featuring a custom design system with space/galaxy theming and responsive "easter eggs" at various viewport sizes. +A modern, responsive portfolio and business presence website built with Middleman, featuring a custom blueprint/schematic design system with animated SVG graphics and responsive "easter eggs" at various viewport sizes. ## Overview -This is a professional portfolio and business website showcasing services, engagements, and expertise. The site features a single-page application design with smooth scrolling, modern animations, and a unique custom design system. +This is a professional portfolio and business website showcasing services, engagements, and expertise. The site features a single-page application design with smooth scrolling, animated technical schematics, and a unique industrial/blueprint visual language. ## Technology Stack ### Core Framework - **Middleman 4.5+** - Ruby-based static site generator -- **Ruby 3.4.3** - Server-side language +- **Ruby 4.0.0** - Server-side language - **Slim** - Template engine for clean, semantic markup ### Asset Pipeline - **Webpack 5.94.0** - Modern JavaScript bundling and asset compilation - **Babel** - ES6+ JavaScript transpilation -- **SCSS/Sass** - Custom design system (no Bootstrap framework) +- **SCSS/Sass** - Custom design system with blueprint aesthetic ### JavaScript Libraries - **jQuery 3.7.1** - DOM manipulation and interactions @@ -63,7 +63,7 @@ This is a professional portfolio and business website showcasing services, engag ## Development Setup ### Prerequisites -- Ruby 3.4.3 (use `.ruby-version`) +- Ruby 4.0.0 (use `.ruby-version`) - Node.js (use `.nvmrc` for version) - Yarn package manager - Bundler gem @@ -138,10 +138,14 @@ rake deploy:github ## Features ### Custom Design System -- Galaxy/space-themed custom CSS (no Bootstrap CSS) +- Blueprint/schematic visual language with industrial aesthetic +- Animated SVG schematics in each section: + - **Robot Arm** (About): Articulated arm with animated joints and motion arcs + - **Forge Assembly** (Workshop): Furnace, anvil, hammer with flame and spark effects + - **Communication Beacon** (Contact): Signal waves and data packet animations - Responsive design with breakpoints from xs to xxxl (2500px) - "Easter egg" content reveals at different viewport sizes -- Modern animations and transitions +- 20+ coordinated CSS keyframe animations - Custom CSS variables and design tokens ### Content Management @@ -187,9 +191,10 @@ Content managed through YAML files in `data/`: See [CHANGELOG.md](CHANGELOG.md) for detailed version history and architectural decisions. -**Current Version**: 4.0.0 +**Current Version**: 5.0.0 Major releases: +- **v5.x (2026)**: Complete visual redesign with blueprint/schematic aesthetic, animated SVG schematics, Ruby 4.0.0 upgrade - **v4.x (2025)**: Infrastructure modernization, environment-based configuration - **v3.x (2021-2025)**: Complete redesign with custom design system - **v2.x (2020)**: Multi-page application with Webpack integration @@ -201,7 +206,7 @@ This is a proprietary business website. Contributions are not accepted. ## License -Copyright (c) 2017-2025 RobotsBuildingRobots, LLC +Copyright (c) 2017-2026 RobotsBuildingRobots, LLC All Rights Reserved. See [LICENSE](LICENSE) for details. diff --git a/source/404.html.slim b/source/404.html.slim new file mode 100644 index 00000000..0c7af759 --- /dev/null +++ b/source/404.html.slim @@ -0,0 +1,23 @@ +--- +id: "404" +layout: "404" +seo: false +title: Page Not Found +--- + +.four-o-four-page + .blueprint-grid + .four-o-four-content + .four-o-four-logo + = image_tag 'logos/logo.png', alt: 'RBR Logo', class: 'four-o-four-logo-img' + + h1.four-o-four-code 404 + + .four-o-four-message + p.message-primary Looks like our robots wandered off. + p.message-secondary Even AI needs a coffee break. + + a.four-o-four-btn[href="/"] + span Take Me Home + svg[viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"] + path[d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"] diff --git a/source/assets/images/favicons/favicon.png b/source/assets/images/favicons/favicon.png new file mode 100644 index 00000000..f51b7982 Binary files /dev/null and b/source/assets/images/favicons/favicon.png differ diff --git a/source/assets/images/logos/logo.png b/source/assets/images/logos/logo.png new file mode 100644 index 00000000..f4a3d7c6 Binary files /dev/null and b/source/assets/images/logos/logo.png differ diff --git a/source/assets/javascripts/site.js b/source/assets/javascripts/site.js index 2efe5b38..e356fe44 100644 --- a/source/assets/javascripts/site.js +++ b/source/assets/javascripts/site.js @@ -1,45 +1,269 @@ -import breakpoints from './vendor/breakpoints'; -import navigation from './components/navigation'; -import index from './pages/index'; -import contact from './pages/contact'; - -const hidePreloader = () => { - $('#preloader').fadeOut(1000, () => { - $('#cover').remove(); +// ============================================================================= +// RobotsBuildingRobots - Site JavaScript +// ============================================================================= + +// ============================================================================= +// PAGE LOADER +// ============================================================================= + +function initPageLoader() { + const loader = document.querySelector('[data-loader]'); + if (!loader) return; + + // Wait for page load, then hide loader + window.addEventListener('load', () => { + setTimeout(() => { + loader.classList.add('loaded'); + }, 2000); // Show loader for at least 2 seconds }); -}; -const resizeContent = () => { - const vh = window.innerHeight * 0.01; + // Fallback: hide loader after 5 seconds max + setTimeout(() => { + if (loader && !loader.classList.contains('loaded')) { + loader.classList.add('loaded'); + } + }, 5000); +} - document.documentElement.style.setProperty('--vh', `${vh}px`); -}; +// ============================================================================= +// SCROLL ANIMATIONS +// ============================================================================= -$(document).ready(() => { - const $body = $('body'); - const $bodyId = $body.attr('id'); - - breakpoints(); - navigation(); - - switch ($bodyId) { - case 'index': - index(); - break; - case 'contact': - contact(); - break; - default: - break; +function initScrollAnimations() { + const animatedElements = document.querySelectorAll('.scroll-animate, .scroll-animate-left, .scroll-animate-right, .scroll-animate-scale'); + + if (!animatedElements.length) return; + + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + entry.target.classList.add('in-view'); + observer.unobserve(entry.target); + } + }); + }, + { + threshold: 0.1, + rootMargin: '0px 0px -50px 0px', + }, + ); + + animatedElements.forEach((el) => observer.observe(el)); +} + +// ============================================================================= +// FLOATING NAVIGATION +// ============================================================================= + +function initFloatingNav() { + const nav = document.querySelector('[data-floating-nav]'); + if (!nav) return; + + const progressBar = nav.querySelector('.scroll-progress-bar'); + const navDots = nav.querySelectorAll('.nav-dot'); + const sections = document.querySelectorAll('section[id]'); + + // Update scroll progress + function updateScrollProgress() { + const scrollTop = window.scrollY; + const docHeight = document.documentElement.scrollHeight - window.innerHeight; + const scrollPercent = (scrollTop / docHeight) * 100; + + if (progressBar) { + progressBar.style.width = `${scrollPercent}%`; + } } - resizeContent(); -}); + // Update active nav dot + function updateActiveSection() { + const scrollPosition = window.scrollY + window.innerHeight / 3; + const scrollTop = window.scrollY; + const docHeight = document.documentElement.scrollHeight; + const windowHeight = window.innerHeight; + + // Check if we're near the bottom of the page (within 100px) + const nearBottom = scrollTop + windowHeight >= docHeight - 100; + + // If near bottom, always highlight the last section (contact) + if (nearBottom) { + const lastSection = sections[sections.length - 1]; + if (lastSection) { + const lastSectionId = lastSection.getAttribute('id'); + navDots.forEach((dot) => { + dot.classList.remove('active'); + if (dot.getAttribute('data-section') === lastSectionId) { + dot.classList.add('active'); + } + }); + } + return; + } + + // Otherwise, use normal section detection + sections.forEach((section) => { + const sectionTop = section.offsetTop; + const sectionHeight = section.offsetHeight; + const sectionId = section.getAttribute('id'); + + if (scrollPosition >= sectionTop && scrollPosition < sectionTop + sectionHeight) { + navDots.forEach((dot) => { + dot.classList.remove('active'); + if (dot.getAttribute('data-section') === sectionId) { + dot.classList.add('active'); + } + }); + } + }); + } + + // Throttled scroll handler + let ticking = false; + window.addEventListener('scroll', () => { + if (!ticking) { + window.requestAnimationFrame(() => { + updateScrollProgress(); + updateActiveSection(); + ticking = false; + }); + ticking = true; + } + }); + + // Initial state + updateScrollProgress(); + updateActiveSection(); +} + +// ============================================================================= +// BACK TO TOP BUTTON +// ============================================================================= + +function initBackToTop() { + const button = document.querySelector('[data-back-to-top]'); + if (!button) return; + + // Show/hide button based on scroll position + function toggleButton() { + if (window.scrollY > 500) { + button.classList.add('visible'); + } else { + button.classList.remove('visible'); + } + } + + // Scroll to top on click + button.addEventListener('click', () => { + window.scrollTo({ + top: 0, + behavior: 'smooth', + }); + }); + + // Throttled scroll handler + let ticking = false; + window.addEventListener('scroll', () => { + if (!ticking) { + window.requestAnimationFrame(() => { + toggleButton(); + ticking = false; + }); + ticking = true; + } + }); + + // Initial state + toggleButton(); +} + +// ============================================================================= +// SMOOTH SCROLL FOR ANCHOR LINKS +// ============================================================================= + +function initSmoothScroll() { + const anchorLinks = document.querySelectorAll('a[href^="#"]'); + + anchorLinks.forEach((link) => { + link.addEventListener('click', (e) => { + const href = link.getAttribute('href'); + if (href === '#') return; + + const target = document.querySelector(href); + if (!target) return; + + e.preventDefault(); + + const headerOffset = 80; + const elementPosition = target.getBoundingClientRect().top; + const offsetPosition = elementPosition + window.scrollY - headerOffset; -window.addEventListener('load', () => { - hidePreloader(); -}, false); + window.scrollTo({ + top: offsetPosition, + behavior: 'smooth', + }); + }); + }); +} + +// ============================================================================= +// TEXT SCRAMBLE EFFECT +// ============================================================================= + +function scrambleText(el, finalText) { + const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@#$%'; + let iteration = 0; + const maxIterations = finalText.length; + const targetEl = el; + + const interval = setInterval(() => { + targetEl.textContent = finalText + .split('') + .map((char, index) => { + if (index < iteration) { + return finalText[index]; + } + return chars[Math.floor(Math.random() * chars.length)]; + }) + .join(''); + + iteration += 1 / 3; + + if (iteration >= maxIterations) { + clearInterval(interval); + targetEl.textContent = finalText; + } + }, 30); +} -window.addEventListener('resize', () => { - resizeContent(); +function initTextScramble() { + document.querySelectorAll('[data-scramble]').forEach((el) => { + const text = el.textContent; + + const observer = new IntersectionObserver( + (entries) => { + entries.forEach((entry) => { + if (entry.isIntersecting) { + scrambleText(el, text); + observer.unobserve(el); + } + }); + }, + { threshold: 0.5 }, + ); + + observer.observe(el); + }); +} + +// ============================================================================= +// INITIALIZE ALL COMPONENTS +// ============================================================================= + +$(document).ready(() => { + initPageLoader(); + initScrollAnimations(); + initFloatingNav(); + initBackToTop(); + initSmoothScroll(); + initTextScramble(); }); diff --git a/source/assets/javascripts/vendor.js b/source/assets/javascripts/vendor.js index 7bbf9e4d..1327592b 100644 --- a/source/assets/javascripts/vendor.js +++ b/source/assets/javascripts/vendor.js @@ -1,11 +1 @@ -window.jQuery = require('jquery'); - -// eslint-disable-next-line no-multi-assign -window.jQuery = window.$ = $; - -window.Popper = require('popper.js'); - -require('bootstrap'); -require('breakpoints'); -require('validation'); -require('fontawesome'); +// Vendor dependencies - add as needed during redesign diff --git a/source/assets/stylesheets/_settings.scss b/source/assets/stylesheets/_settings.scss index 87a64dc9..12f6c5af 100644 --- a/source/assets/stylesheets/_settings.scss +++ b/source/assets/stylesheets/_settings.scss @@ -1,31 +1,155 @@ +// ============================================================================= +// FORGE Design System - Settings & Tokens +// ============================================================================= +// "Where precision meets partnership" - Premium craftsmanship meets innovation +// ============================================================================= + $image-path: '../../assets/images/'; +// ============================================================================= +// TYPOGRAPHY +// ============================================================================= + +// Font Families +$font-display: 'Playfair Display', 'Georgia', serif; // Hero headlines, impact statements +$font-heading: 'Inter', 'Arial', sans-serif; // Section headers, navigation +$font-body: 'Libre Franklin', 'Helvetica Neue', sans-serif; // Body text, UI elements +$font-mono: 'JetBrains Mono', 'SF Mono', 'Monaco', 'Inconsolata', monospace; // Code, technical + +// Font Weights +$font-weight-light: 300; +$font-weight-regular: 400; +$font-weight-medium: 500; +$font-weight-semibold: 600; +$font-weight-bold: 700; +$font-weight-extrabold: 800; + +// Type Scale (Major Third - 1.25) +$type-scale-xs: 0.75rem; // 12px +$type-scale-sm: 0.875rem; // 14px +$type-scale-base: 1rem; // 16px +$type-scale-lg: 1.125rem; // 18px +$type-scale-xl: 1.25rem; // 20px +$type-scale-2xl: 1.5rem; // 24px +$type-scale-3xl: 1.875rem; // 30px +$type-scale-4xl: 2.25rem; // 36px +$type-scale-5xl: 3rem; // 48px +$type-scale-6xl: 3.75rem; // 60px +$type-scale-7xl: 4.5rem; // 72px +$type-scale-8xl: 6rem; // 96px + +// Line Heights +$leading-none: 1; +$leading-tight: 1.15; +$leading-snug: 1.3; +$leading-normal: 1.5; +$leading-relaxed: 1.625; +$leading-loose: 2; + +// Letter Spacing +$tracking-tighter: -0.05em; +$tracking-tight: -0.025em; +$tracking-normal: 0; +$tracking-wide: 0.025em; +$tracking-wider: 0.05em; +$tracking-widest: 0.1em; + +// ============================================================================= +// COLORS - FORGE Palette +// ============================================================================= + +// Core Palette - The Forge +$forge-black: #0C0A09; // Foundation - rich, warm black +$warm-stone: #1C1917; // Surface - cards, elevated sections +$charred: #292524; // Elevated - tertiary surfaces, hover states +$ash: #44403C; // Border - subtle borders, dividers +$stone-gray: #A8A29E; // Text Secondary - body text, captions +$warm-white: #FAFAF9; // Text Primary - headlines, primary text + +// Accent Palette - The Fire +$ember: #DC6B4A; // Primary accent - CTAs, links, key highlights +$copper-glow: #F4A261; // Secondary accent - hover states, warmth +$teal-spark: #2DD4BF; // Tertiary accent - innovation moments, special highlights + +// Extended Palette +$ember-dark: #B5543A; // Darker ember for active states +$ember-light: #E8917A; // Lighter ember for subtle accents +$teal-dark: #14B8A6; // Darker teal +$teal-light: #5EEAD4; // Lighter teal + +// Legacy colors (keeping for backwards compat during transition) $color-white: #fff; $color-black: #000; -$color-one: #46496b; -$color-two: #5f64a2; -$color-three: #e6e9f2; -$color-four: #f09d37; -$color-five: #f6c96d; +$color-one: $ember; +$color-two: $warm-stone; +$color-three: $stone-gray; +$color-four: $copper-glow; +$color-five: $ash; +$color-six: $forge-black; + +// ============================================================================= +// SEMANTIC MAPPINGS +// ============================================================================= + +// Backgrounds +$bg-primary: $forge-black; // Page backgrounds, dark sections +$bg-secondary: $warm-stone; // Cards, containers, elevated surfaces +$bg-tertiary: $charred; // Subtle backgrounds, hover states +$bg-elevated: $charred; // Modal, dropdown backgrounds -@mixin font-color-light { color: $color-white; } +// Text +$text-primary: $warm-white; // Headlines, primary content +$text-secondary: $stone-gray; // Body text, descriptions +$text-muted: $ash; // Subtle text, placeholders +$text-accent: $ember; // Links, emphasized text -@mixin font-highlight-color { color: $highlight-color; } +// Interactive +$accent-primary: $ember; // Primary buttons, links, CTAs +$accent-hover: $copper-glow; // Hover states for accent elements +$accent-active: $ember-dark; // Active/pressed states +$accent-soft: $stone-gray; // Secondary buttons, tags -$darkest-color: $color-one; -$highlight-color: $color-five; -$border-color: $color-two; -$link-color: $color-five; +// Innovation/Special +$accent-spark: $teal-spark; // Special highlights, innovation moments +$accent-spark-hover: $teal-light; -$backdrop-opacity: 0.8; -$backdrop-opacity-dark: 0.9; -$backdrop-opacity-light: 0.7; -$backdrop-opacity-medium-light: 0.5; -$backdrop-opacity-super-light: 0.2; +// Borders & Dividers +$border-color: $ash; // Default borders +$border-subtle: $charred; // Subtle dividers +$border-strong: $stone-gray; // Emphasized borders -$radius: 1rem; +// ============================================================================= +// SPACING +// ============================================================================= + +$space-0: 0; +$space-1: 0.25rem; // 4px +$space-2: 0.5rem; // 8px +$space-3: 0.75rem; // 12px +$space-4: 1rem; // 16px +$space-5: 1.25rem; // 20px +$space-6: 1.5rem; // 24px +$space-8: 2rem; // 32px +$space-10: 2.5rem; // 40px +$space-12: 3rem; // 48px +$space-16: 4rem; // 64px +$space-20: 5rem; // 80px +$space-24: 6rem; // 96px +$space-32: 8rem; // 128px + +// ============================================================================= +// LAYOUT +// ============================================================================= + +$radius-sm: 0.25rem; +$radius: 0.5rem; +$radius-md: 0.75rem; +$radius-lg: 1rem; +$radius-xl: 1.5rem; +$radius-full: 9999px; $minimum-height: 700px; + $grid-breakpoints: ( xs: 0, minimium: 375px, @@ -40,4 +164,52 @@ $grid-breakpoints: ( xxxxl: 2450px ); +$container-max-width: 1200px; +$container-padding: $space-6; + +// ============================================================================= +// SHADOWS & EFFECTS +// ============================================================================= + +$shadow-sm: 0 1px 2px 0 rgba($forge-black, 0.3); +$shadow: 0 4px 6px -1px rgba($forge-black, 0.4), 0 2px 4px -2px rgba($forge-black, 0.3); +$shadow-md: 0 10px 15px -3px rgba($forge-black, 0.4), 0 4px 6px -4px rgba($forge-black, 0.3); +$shadow-lg: 0 25px 50px -12px rgba($forge-black, 0.5); +$shadow-inner: inset 0 2px 4px 0 rgba($forge-black, 0.3); + +// Glow effects for accents +$glow-ember: 0 0 20px rgba($ember, 0.3); +$glow-teal: 0 0 20px rgba($teal-spark, 0.3); + +// ============================================================================= +// TRANSITIONS +// ============================================================================= + +$transition-fast: 150ms ease; +$transition-base: 250ms ease; +$transition-slow: 350ms ease; +$transition-slower: 500ms ease; + +// ============================================================================= +// Z-INDEX +// ============================================================================= + +$z-base: 0; +$z-dropdown: 100; +$z-sticky: 200; +$z-fixed: 300; +$z-modal-backdrop: 400; +$z-modal: 500; +$z-popover: 600; +$z-tooltip: 700; $zindex-cover: 10000 !default; + +// ============================================================================= +// BACKDROP OPACITY (for layered backgrounds) +// ============================================================================= + +$backdrop-dark: 0.9; +$backdrop-regular: 0.8; +$backdrop-light: 0.7; +$backdrop-medium-light: 0.5; +$backdrop-super-light: 0.2; diff --git a/source/assets/stylesheets/components/_animations.scss b/source/assets/stylesheets/components/_animations.scss new file mode 100644 index 00000000..35b7e494 --- /dev/null +++ b/source/assets/stylesheets/components/_animations.scss @@ -0,0 +1,215 @@ +// ============================================================================= +// Shared Animations +// ============================================================================= + +// Fade In Up Animation +@keyframes fade-in-up { + from { + opacity: 0; + transform: translateY(30px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +// Fade In Animation +@keyframes fade-in { + from { + opacity: 0; + } + + to { + opacity: 1; + } +} + +// Scale In Animation +@keyframes scale-in { + from { + opacity: 0; + transform: scale(0.9); + } + + to { + opacity: 1; + transform: scale(1); + } +} + +// Slide In From Left +@keyframes slide-in-left { + from { + opacity: 0; + transform: translateX(-50px); + } + + to { + opacity: 1; + transform: translateX(0); + } +} + +// Slide In From Right +@keyframes slide-in-right { + from { + opacity: 0; + transform: translateX(50px); + } + + to { + opacity: 1; + transform: translateX(0); + } +} + +// Pulse Glow +@keyframes pulse-glow { + 0%, + 100% { + box-shadow: 0 0 20px rgba($ember, 0.3); + } + + 50% { + box-shadow: 0 0 40px rgba($ember, 0.5); + } +} + +// Float Animation +@keyframes float { + 0%, + 100% { + transform: translateY(0); + } + + 50% { + transform: translateY(-10px); + } +} + +// Shimmer Effect +@keyframes shimmer { + 0% { + background-position: -200% center; + } + + 100% { + background-position: 200% center; + } +} + +// Rotate +@keyframes rotate { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +// Text Scramble (for use with JS) +@keyframes text-flicker { + 0%, + 100% { + opacity: 1; + } + + 50% { + opacity: 0.8; + } +} + +// ============================================================================= +// Scroll Animation Classes +// ============================================================================= + +.scroll-animate { + opacity: 0; + transform: translateY(30px); + transition: opacity 0.6s ease, transform 0.6s ease; + + &.in-view { + opacity: 1; + transform: translateY(0); + } + + &.delay-1 { + transition-delay: 0.1s; + } + + &.delay-2 { + transition-delay: 0.2s; + } + + &.delay-3 { + transition-delay: 0.3s; + } + + &.delay-4 { + transition-delay: 0.4s; + } + + &.delay-5 { + transition-delay: 0.5s; + } +} + +.scroll-animate-left { + opacity: 0; + transform: translateX(-50px); + transition: opacity 0.6s ease, transform 0.6s ease; + + &.in-view { + opacity: 1; + transform: translateX(0); + } +} + +.scroll-animate-right { + opacity: 0; + transform: translateX(50px); + transition: opacity 0.6s ease, transform 0.6s ease; + + &.in-view { + opacity: 1; + transform: translateX(0); + } +} + +.scroll-animate-scale { + opacity: 0; + transform: scale(0.9); + transition: opacity 0.6s ease, transform 0.6s ease; + + &.in-view { + opacity: 1; + transform: scale(1); + } +} + +// ============================================================================= +// Reduced Motion Support +// ============================================================================= + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + } + + .scroll-animate, + .scroll-animate-left, + .scroll-animate-right, + .scroll-animate-scale { + opacity: 1; + transform: none; + transition: none; + } +} diff --git a/source/assets/stylesheets/components/_floating-nav.scss b/source/assets/stylesheets/components/_floating-nav.scss new file mode 100644 index 00000000..2544cc25 --- /dev/null +++ b/source/assets/stylesheets/components/_floating-nav.scss @@ -0,0 +1,185 @@ +// ============================================================================= +// Floating Navigation Component +// ============================================================================= + +.floating-nav { + position: fixed; + left: $space-4; + top: 50%; + transform: translateY(-50%); + z-index: $z-fixed; + display: none; + + @media (min-width: map-get($grid-breakpoints, lg)) { + display: block; + } + + // Scroll Progress Bar (top of screen) + .scroll-progress { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 3px; + background: transparent; + z-index: $z-fixed + 1; + + .scroll-progress-bar { + height: 100%; + width: 0%; + background: linear-gradient(90deg, $ember, $copper-glow, $teal-spark); + transition: width 0.1s linear; + border-radius: 0 $radius-full $radius-full 0; + } + } + + // Navigation Dots + .nav-dots { + display: flex; + flex-direction: column; + gap: $space-3; + padding: $space-4; + background: rgba($bg-secondary, 0.9); + backdrop-filter: blur(10px); + border: 1px solid $border-subtle; + + .nav-dot { + display: flex; + align-items: center; + gap: $space-3; + text-decoration: none; + color: $text-secondary; + transition: all $transition-fast; + cursor: pointer; + + .dot-indicator { + width: 10px; + height: 10px; + border-radius: $radius-full; + background: $ash; + transition: all $transition-fast; + flex-shrink: 0; + } + + .dot-label { + font-family: $font-body; + font-size: $type-scale-xs; + font-weight: $font-weight-medium; + text-transform: uppercase; + letter-spacing: $tracking-wide; + opacity: 1; + transform: translateX(0); + transition: all $transition-fast; + white-space: nowrap; + } + + &:hover, + &.active { + color: $text-primary; + + .dot-indicator { + background: $ember; + box-shadow: $glow-ember; + transform: scale(1.2); + } + + .dot-label { + opacity: 1; + transform: translateX(0); + } + } + + &.active { + .dot-indicator { + background: $ember; + } + } + } + } + +} + +// ============================================================================= +// Back to Top Button (independent component) +// ============================================================================= + +.back-to-top { + position: fixed; + bottom: $space-6; + right: $space-6; + width: 48px; + height: 48px; + border-radius: $radius-full; + background: $bg-secondary; + border: 1px solid $border-subtle; + color: $text-secondary; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + opacity: 0; + visibility: hidden; + transform: translateY(20px); + transition: all $transition-base; + z-index: $z-fixed; + + &:hover { + background: $bg-tertiary; + color: $ember; + border-color: $ember; + box-shadow: $glow-ember; + } + + &.visible { + opacity: 1; + visibility: visible; + transform: translateY(0); + } + + svg { + width: 20px; + height: 20px; + } +} + +// Mobile Navigation (bottom bar) +.mobile-nav { + position: fixed; + bottom: 0; + left: 0; + right: 0; + background: rgba($bg-secondary, 0.95); + backdrop-filter: blur(10px); + border-top: 1px solid $border-subtle; + padding: $space-2 $space-4; + z-index: $z-fixed; + display: flex; + justify-content: space-around; + align-items: center; + + @media (min-width: map-get($grid-breakpoints, lg)) { + display: none; + } + + .mobile-nav-item { + display: flex; + flex-direction: column; + align-items: center; + gap: $space-1; + text-decoration: none; + color: $text-secondary; + font-size: $type-scale-xs; + padding: $space-2; + transition: color $transition-fast; + + &.active, + &:hover { + color: $ember; + } + + .nav-icon { + width: 20px; + height: 20px; + } + } +} diff --git a/source/assets/stylesheets/components/_html-body.scss b/source/assets/stylesheets/components/_html-body.scss index 8b4051f1..50ae03f0 100644 --- a/source/assets/stylesheets/components/_html-body.scss +++ b/source/assets/stylesheets/components/_html-body.scss @@ -1,17 +1,847 @@ -html { - overflow: hidden scroll; -} +// ============================================================================= +// Base HTML/Body Styles - FORGE Design System +// ============================================================================= html, body { - padding: 0 !important; - margin: 0 !important; - height: 100% !important; - min-width: map-get($grid-breakpoints, 'minimium') !important; - min-height: 100% !important; - background-color: $darkest-color; - font-size: 1rem; - - @include primary-font(); - @include font-color-light(); + background-color: $bg-primary; + color: $text-secondary; + min-height: 100vh; + margin: 0; + padding: 0; + font-family: $font-body; + font-size: $type-scale-base; + font-weight: $font-weight-regular; + line-height: $leading-normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +// Code elements +code, +pre, +kbd, +samp { + font-family: $font-mono; +} + +// Links +a { + color: $accent-primary; + text-decoration: none; + transition: color $transition-fast; + + &:hover { + color: $accent-hover; + } +} + +// ============================================================================= +// Minimal Page (RBR Landing) +// ============================================================================= + +.minimal-page { + background-color: $warm-white; + min-height: 100vh; + margin: 0; + padding: 0; +} + +.minimal-container { + display: flex; + align-items: center; + justify-content: center; + min-height: 100vh; + padding: $space-4; +} + +.rbr-title { + font-family: $font-heading; + font-size: clamp(4rem, 15vw, 12rem); + font-weight: $font-weight-bold; + color: $forge-black; + margin: 0; + letter-spacing: $tracking-tight; + line-height: 1; +} + +// ============================================================================= +// FORGE Design System Preview Page +// ============================================================================= + +.design-system { + max-width: $container-max-width; + margin: 0 auto; + padding: $space-12 $space-6; + + // Page Header + .page-header { + margin-bottom: $space-16; + text-align: center; + + .badge { + display: inline-block; + font-family: $font-mono; + font-size: $type-scale-xs; + font-weight: $font-weight-medium; + color: $teal-spark; + background: rgba($teal-spark, 0.1); + padding: $space-2 $space-4; + border-radius: $radius-full; + letter-spacing: $tracking-wider; + text-transform: uppercase; + margin-bottom: $space-4; + } + + .page-title { + font-family: $font-display; + font-size: $type-scale-6xl; + font-weight: $font-weight-regular; + color: $text-primary; + margin: 0 0 $space-4; + line-height: $leading-tight; + letter-spacing: $tracking-tight; + + @media (width <= 768px) { + font-size: $type-scale-4xl; + } + } + + .page-tagline { + font-family: $font-heading; + font-size: $type-scale-xl; + font-weight: $font-weight-regular; + color: $text-secondary; + margin: 0; + } + } + + // Section styling + .section { + margin-bottom: $space-16; + } + + .section-title { + font-family: $font-heading; + font-size: $type-scale-sm; + font-weight: $font-weight-semibold; + color: $ember; + margin-bottom: $space-6; + text-transform: uppercase; + letter-spacing: $tracking-widest; + } + + .section-subtitle { + font-family: $font-body; + font-size: $type-scale-lg; + color: $text-secondary; + margin-bottom: $space-8; + max-width: 600px; + } + + // ============================================================================= + // Color Palette Section + // ============================================================================= + + .color-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: $space-4; + } + + .color-swatch { + background: $bg-secondary; + border-radius: $radius-lg; + overflow: hidden; + transition: transform $transition-base, box-shadow $transition-base; + + &:hover { + transform: translateY(-2px); + box-shadow: $shadow-md; + } + + .swatch-preview { + height: 100px; + position: relative; + + &::after { + content: ''; + position: absolute; + bottom: 0; + left: 0; + right: 0; + height: 1px; + background: rgba($forge-black, 0.2); + } + } + + .swatch-info { + padding: $space-4; + + .color-name { + font-family: $font-heading; + font-size: $type-scale-base; + font-weight: $font-weight-semibold; + color: $text-primary; + margin: 0 0 $space-1; + } + + .var-name { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $ember; + margin: 0 0 $space-2; + } + + .hex-value { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $text-muted; + margin: 0; + } + + .description { + font-family: $font-body; + font-size: $type-scale-sm; + color: $text-secondary; + margin: $space-2 0 0 0; + } + } + } + + // Core palette colors + .forge-black .swatch-preview { + background-color: $forge-black; + border: 1px solid $ash; + } + .warm-stone .swatch-preview { background-color: $warm-stone; } + .charred .swatch-preview { background-color: $charred; } + .ash .swatch-preview { background-color: $ash; } + .stone-gray .swatch-preview { background-color: $stone-gray; } + .warm-white .swatch-preview { background-color: $warm-white; } + + // Accent colors + .ember .swatch-preview { background-color: $ember; } + .copper-glow .swatch-preview { background-color: $copper-glow; } + .teal-spark .swatch-preview { background-color: $teal-spark; } + + // ============================================================================= + // Typography Section + // ============================================================================= + + .typography-grid { + display: grid; + gap: $space-6; + } + + .font-card { + background: $bg-secondary; + border-radius: $radius-lg; + padding: $space-8; + border: 1px solid $border-subtle; + + .font-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: $space-6; + flex-wrap: wrap; + gap: $space-4; + } + + .font-meta { + .font-name { + font-size: $type-scale-xl; + font-weight: $font-weight-semibold; + color: $text-primary; + margin: 0 0 $space-1; + } + + .font-role { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $ember; + text-transform: uppercase; + letter-spacing: $tracking-wide; + } + } + + .font-weights { + display: flex; + gap: $space-2; + flex-wrap: wrap; + } + + .weight-pill { + font-family: $font-mono; + font-size: $type-scale-xs; + padding: $space-1 $space-3; + background: $bg-tertiary; + border-radius: $radius-full; + color: $text-secondary; + } + + .font-samples { + display: flex; + flex-direction: column; + gap: $space-4; + } + + .sample-row { + display: flex; + align-items: baseline; + gap: $space-4; + padding-bottom: $space-4; + border-bottom: 1px solid $border-subtle; + + &:last-child { + border-bottom: none; + padding-bottom: 0; + } + + .sample-size { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $text-muted; + min-width: 60px; + flex-shrink: 0; + } + + .sample-text { + color: $text-primary; + margin: 0; + } + } + + // Font-specific styling + &.display { + .font-name, + .sample-text { + font-family: $font-display; + } + } + + &.heading { + .font-name, + .sample-text { + font-family: $font-heading; + } + } + + &.body { + .font-name, + .sample-text { + font-family: $font-body; + } + } + + &.mono { + .font-name, + .sample-text { + font-family: $font-mono; + } + + .sample-text { + background: $bg-tertiary; + padding: $space-3 $space-4; + border-radius: $radius; + } + } + } + + // ============================================================================= + // Type Scale Section + // ============================================================================= + + .type-scale-list { + display: flex; + flex-direction: column; + gap: $space-4; + } + + .type-scale-item { + display: flex; + align-items: baseline; + gap: $space-6; + padding: $space-4 0; + border-bottom: 1px solid $border-subtle; + + &:last-child { + border-bottom: none; + } + + .scale-meta { + min-width: 100px; + flex-shrink: 0; + + .scale-name { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $ember; + } + + .scale-size { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $text-muted; + } + } + + .scale-sample { + font-family: $font-display; + color: $text-primary; + margin: 0; + line-height: $leading-tight; + } + + &.xs .scale-sample { font-size: $type-scale-xs; } + &.sm .scale-sample { font-size: $type-scale-sm; } + &.base .scale-sample { font-size: $type-scale-base; } + &.lg .scale-sample { font-size: $type-scale-lg; } + &.xl .scale-sample { font-size: $type-scale-xl; } + &.xxl .scale-sample { font-size: $type-scale-2xl; } + &.xxxl .scale-sample { font-size: $type-scale-3xl; } + &.xxxxl .scale-sample { font-size: $type-scale-4xl; } + &.xxxxxl .scale-sample { font-size: $type-scale-5xl; } + &.xxxxxxl .scale-sample { font-size: $type-scale-6xl; } + } + + // ============================================================================= + // Components Section + // ============================================================================= + + .components-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: $space-6; + } + + .component-card { + background: $bg-secondary; + border-radius: $radius-lg; + padding: $space-6; + border: 1px solid $border-subtle; + + .component-title { + font-family: $font-heading; + font-size: $type-scale-sm; + font-weight: $font-weight-semibold; + color: $text-muted; + text-transform: uppercase; + letter-spacing: $tracking-wide; + margin: 0 0 $space-4; + } + + .component-content { + display: flex; + flex-direction: column; + gap: $space-3; + } + } + + // Buttons + .btn { + display: inline-flex; + align-items: center; + justify-content: center; + font-family: $font-heading; + font-size: $type-scale-sm; + font-weight: $font-weight-semibold; + padding: $space-3 $space-6; + border-radius: $radius; + border: none; + cursor: pointer; + transition: all $transition-fast; + text-decoration: none; + + &.btn-primary { + background: $ember; + color: $warm-white; + + &:hover { + background: $copper-glow; + box-shadow: $glow-ember; + } + } + + &.btn-secondary { + background: transparent; + color: $ember; + border: 1px solid $ember; + + &:hover { + background: rgba($ember, 0.1); + } + } + + &.btn-spark { + background: $teal-spark; + color: $forge-black; + + &:hover { + background: $teal-light; + box-shadow: $glow-teal; + } + } + + &.btn-ghost { + background: transparent; + color: $text-secondary; + + &:hover { + color: $text-primary; + background: $bg-tertiary; + } + } + } + + // Input fields + .input-field { + width: 100%; + font-family: $font-body; + font-size: $type-scale-base; + padding: $space-3 $space-4; + background: $bg-tertiary; + border: 1px solid $border-color; + border-radius: $radius; + color: $text-primary; + transition: border-color $transition-fast, box-shadow $transition-fast; + + &::placeholder { + color: $text-muted; + } + + &:focus { + outline: none; + border-color: $ember; + box-shadow: 0 0 0 3px rgba($ember, 0.1); + } + } + + // Cards + .sample-card { + background: $bg-tertiary; + border-radius: $radius; + padding: $space-4; + + .card-title { + font-family: $font-heading; + font-size: $type-scale-base; + font-weight: $font-weight-semibold; + color: $text-primary; + margin: 0 0 $space-2; + } + + .card-text { + font-size: $type-scale-sm; + color: $text-secondary; + margin: 0; + } + } + + // ============================================================================= + // Hero Preview Section + // ============================================================================= + + .hero-preview { + background: linear-gradient(135deg, $bg-secondary 0%, $bg-tertiary 100%); + border-radius: $radius-xl; + padding: $space-16 $space-8; + text-align: center; + margin-bottom: $space-8; + position: relative; + overflow: hidden; + + &::before { + content: ''; + position: absolute; + inset: 0; + background: radial-gradient(circle at 30% 20%, rgba($ember, 0.1) 0%, transparent 50%), + radial-gradient(circle at 70% 80%, rgba($teal-spark, 0.05) 0%, transparent 50%); + pointer-events: none; + } + + .hero-content { + position: relative; + z-index: 1; + } + + .hero-eyebrow { + font-family: $font-mono; + font-size: $type-scale-xs; + font-weight: $font-weight-medium; + color: $teal-spark; + text-transform: uppercase; + letter-spacing: $tracking-widest; + margin-bottom: $space-4; + } + + .hero-title { + font-family: $font-display; + font-size: $type-scale-7xl; + font-weight: $font-weight-regular; + color: $text-primary; + margin: 0 0 $space-4; + line-height: $leading-none; + letter-spacing: $tracking-tight; + + .accent { + color: $ember; + } + + @media (width <= 768px) { + font-size: $type-scale-5xl; + } + } + + .hero-subtitle { + font-family: $font-heading; + font-size: $type-scale-xl; + font-weight: $font-weight-regular; + color: $text-secondary; + margin: 0 0 $space-8; + max-width: 600px; + margin-left: auto; + margin-right: auto; + } + + .hero-actions { + display: flex; + gap: $space-4; + justify-content: center; + flex-wrap: wrap; + } + } + + // ============================================================================= + // Spacing Preview + // ============================================================================= + + .spacing-grid { + display: flex; + flex-wrap: wrap; + gap: $space-4; + align-items: flex-end; + } + + .spacing-item { + display: flex; + flex-direction: column; + align-items: center; + gap: $space-2; + + .spacing-box { + background: $ember; + border-radius: $radius-sm; + } + + .spacing-label { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $text-muted; + } + } + + // ============================================================================= + // Favicon Grid Section + // ============================================================================= + + .favicon-grid { + display: flex; + gap: $space-6; + flex-wrap: wrap; + } + + .favicon-item { + background: $bg-secondary; + border-radius: $radius-lg; + padding: $space-6; + border: 1px solid $border-subtle; + display: flex; + align-items: center; + gap: $space-4; + } + + .favicon-preview { + display: flex; + align-items: center; + justify-content: center; + padding: $space-3; + background: $forge-black; + border: 1px solid $ash; + border-radius: $radius; + + img { + display: block; + } + } + + .favicon-info { + .favicon-name { + font-family: $font-heading; + font-size: $type-scale-base; + font-weight: $font-weight-semibold; + color: $text-primary; + margin: 0 0 $space-1; + } + + .favicon-file { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $ember; + margin: 0 0 $space-1; + } + + .favicon-dimensions { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $text-muted; + margin: 0; + } + } + + // ============================================================================= + // Logo Showcase Section + // ============================================================================= + + .logo-showcase { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: $space-6; + } + + .logo-preview { + display: flex; + align-items: center; + justify-content: center; + padding: $space-4; + border-radius: $radius; + + &.dark-bg { + background: $forge-black; + border: 1px solid $ash; + } + + &.light-bg { + background: $warm-white; + } + + img { + display: block; + max-width: 100%; + height: auto; + } + } + + .logo-card { + background: $bg-secondary; + border-radius: $radius-lg; + padding: $space-6; + border: 1px solid $border-subtle; + + .variation-title { + font-family: $font-heading; + font-size: $type-scale-sm; + font-weight: $font-weight-semibold; + color: $text-muted; + text-transform: uppercase; + letter-spacing: $tracking-wide; + margin: 0 0 $space-4; + } + + &.full-size { + grid-column: 1 / -1; + display: flex; + gap: $space-6; + align-items: center; + flex-wrap: wrap; + + .logo-preview { + flex-shrink: 0; + + img { + max-width: 200px; + height: auto; + } + } + } + } + + .logo-info { + .logo-name { + font-family: $font-heading; + font-size: $type-scale-lg; + font-weight: $font-weight-semibold; + color: $text-primary; + margin: 0 0 $space-2; + } + + .logo-file { + font-family: $font-mono; + font-size: $type-scale-sm; + color: $ember; + margin: 0 0 $space-1; + } + + .logo-dimensions { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $text-muted; + margin: 0; + } + } + + .size-grid { + display: flex; + gap: $space-6; + flex-wrap: wrap; + align-items: flex-end; + } + + .size-item { + display: flex; + flex-direction: column; + align-items: center; + gap: $space-2; + + .size-label { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $text-muted; + } + } + + .bg-grid { + display: flex; + gap: $space-6; + flex-wrap: wrap; + } + + .bg-item { + display: flex; + flex-direction: column; + align-items: center; + gap: $space-2; + padding: $space-4; + border-radius: $radius; + + &.dark-bg { + background: $forge-black; + border: 1px solid $ash; + } + + &.light-bg { + background: $warm-white; + } + + .bg-label { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $text-muted; + } + + &.light-bg .bg-label { + color: $ash; + } + } } diff --git a/source/assets/stylesheets/components/_loader.scss b/source/assets/stylesheets/components/_loader.scss new file mode 100644 index 00000000..fbcc6109 --- /dev/null +++ b/source/assets/stylesheets/components/_loader.scss @@ -0,0 +1,143 @@ +// ============================================================================= +// Page Loader Component +// ============================================================================= + +.page-loader { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: $bg-primary; + display: flex; + align-items: center; + justify-content: center; + z-index: $zindex-cover; + opacity: 1; + visibility: visible; + transition: opacity 0.6s $transition-slow, visibility 0.6s $transition-slow; + + &.loaded { + opacity: 0; + visibility: hidden; + pointer-events: none; + } + + .loader-content { + display: flex; + flex-direction: column; + align-items: center; + gap: $space-8; + } + + .loader-logo { + position: relative; + width: 120px; + height: 120px; + + @media (min-width: map-get($grid-breakpoints, md)) { + width: 150px; + height: 150px; + } + + .loader-logo-img { + width: 100%; + height: 100%; + object-fit: contain; + animation: loader-spin 8s linear infinite; + } + + &::after { + content: ''; + position: absolute; + inset: -10px; + border-radius: $radius-full; + background: radial-gradient(circle, rgba($ember, 0.2) 0%, transparent 70%); + animation: loader-glow 2s ease-in-out infinite; + } + } + + .loader-text { + font-family: $font-mono; + font-size: $type-scale-sm; + color: $text-secondary; + letter-spacing: $tracking-wider; + text-transform: uppercase; + display: flex; + align-items: center; + gap: $space-1; + + .loader-cursor { + animation: loader-blink 0.8s step-end infinite; + color: $ember; + } + } + + .loader-progress { + width: 200px; + height: 2px; + background: $bg-tertiary; + border-radius: $radius-full; + overflow: hidden; + + @media (min-width: map-get($grid-breakpoints, md)) { + width: 250px; + } + + .loader-progress-bar { + height: 100%; + width: 0%; + background: linear-gradient(90deg, $ember, $copper-glow); + border-radius: $radius-full; + animation: loader-progress 2s ease-out forwards; + box-shadow: $glow-ember; + } + } +} + +// Loader Animations +@keyframes loader-spin { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } +} + +@keyframes loader-glow { + 0%, 100% { + opacity: 0.5; + transform: scale(1); + } + + 50% { + opacity: 1; + transform: scale(1.05); + } +} + +@keyframes loader-blink { + 0%, 100% { + opacity: 1; + } + + 50% { + opacity: 0; + } +} + +@keyframes loader-progress { + 0% { + width: 0%; + } + + 50% { + width: 70%; + } + + 100% { + width: 100%; + } +} diff --git a/source/assets/stylesheets/pages/_four-o-four.scss b/source/assets/stylesheets/pages/_four-o-four.scss new file mode 100644 index 00000000..93062d77 --- /dev/null +++ b/source/assets/stylesheets/pages/_four-o-four.scss @@ -0,0 +1,133 @@ +// ============================================================================= +// 404 Page Styles +// ============================================================================= + +.four-o-four-body { + background: #FFF; + min-height: 100vh; + margin: 0; + padding: 0; +} + +.four-o-four-page { + min-height: 100vh; + display: flex; + align-items: center; + justify-content: center; + padding: $space-6; + background: #FFF; + position: relative; + + .blueprint-grid { + position: absolute; + inset: 0; + background-image: + linear-gradient(#E1E5EA 1px, transparent 1px), + linear-gradient(90deg, #E1E5EA 1px, transparent 1px); + background-size: 40px 40px; + opacity: 0.6; + pointer-events: none; + } + + .four-o-four-content { + text-align: center; + max-width: 500px; + position: relative; + } + + .four-o-four-logo { + margin-bottom: $space-8; + + .four-o-four-logo-img { + width: 180px; + height: 180px; + object-fit: contain; + filter: grayscale(100%) contrast(1.2); + opacity: 0.8; + transition: all $transition-base; + + @media (min-width: map-get($grid-breakpoints, md)) { + width: 220px; + height: 220px; + } + + &:hover { + filter: grayscale(0%); + opacity: 1; + } + } + } + + .four-o-four-code { + // Use system font to prevent layout shift from web font loading + font-family: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif; + font-size: 8rem; + font-weight: $font-weight-bold; + color: $forge-black; + line-height: $leading-none; + margin: 0 0 $space-6; + letter-spacing: $tracking-tight; + + @media (min-width: map-get($grid-breakpoints, md)) { + font-size: 12rem; + } + } + + .four-o-four-message { + margin-bottom: $space-10; + + .message-primary { + // Use system font to prevent layout shift from web font loading + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + font-size: $type-scale-2xl; + font-weight: $font-weight-semibold; + color: $forge-black; + margin: 0 0 $space-2; + white-space: nowrap; // Prevent text wrap during page load + + @media (min-width: map-get($grid-breakpoints, md)) { + font-size: $type-scale-3xl; + } + } + + .message-secondary { + // Use system font to prevent layout shift from web font loading + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + font-size: $type-scale-lg; + font-weight: $font-weight-regular; + color: $stone-gray; + margin: 0; + } + } + + .four-o-four-btn { + display: inline-flex; + align-items: center; + gap: $space-3; + padding: $space-4 $space-8; + background: $forge-black; + color: #FFF; + // Use system font to prevent layout shift from web font loading + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; + font-size: $type-scale-base; + font-weight: $font-weight-semibold; + text-decoration: none; + border-radius: $radius-full; + transition: all $transition-base; + + svg { + width: 20px; + height: 20px; + } + + &:hover { + background: $ember; + transform: translateY(-2px); + box-shadow: 0 10px 30px rgba($ember, 0.3); + } + + &:active { + transform: translateY(0); + } + } +} diff --git a/source/assets/stylesheets/pages/_home.scss b/source/assets/stylesheets/pages/_home.scss new file mode 100644 index 00000000..6f120501 --- /dev/null +++ b/source/assets/stylesheets/pages/_home.scss @@ -0,0 +1,2554 @@ +// ============================================================================= +// BLUEPRINT - Architect/Technical Drawing Theme +// ============================================================================= + +// Blueprint Theme Colors +$blueprint-blue: #1E3A5F; +$blueprint-light: #2A4A72; +$blueprint-dark: #0D1B2A; +$blueprint-bg: #F8F9FA; +$blueprint-grid: #E1E5EA; +$blueprint-accent: $ember; // Technical orange from design system + +// ============================================================================= +// HERO SECTION +// ============================================================================= + +.hero-section { + min-height: 100vh; + display: flex; + align-items: center; + position: relative; + overflow: hidden; + background: $blueprint-bg; + + // Blueprint grid background + .blueprint-grid { + position: absolute; + inset: 0; + background-image: + linear-gradient($blueprint-grid 1px, transparent 1px), + linear-gradient(90deg, $blueprint-grid 1px, transparent 1px); + background-size: 40px 40px; + opacity: 0.6; + pointer-events: none; + } + + .hero-container { + position: relative; + z-index: 2; + width: 100%; + max-width: $container-max-width; + margin: 0 auto; + padding: $space-6; + } + + .hero-content-wrapper { + display: grid; + grid-template-columns: 1fr; + gap: $space-8; + align-items: center; + position: relative; + + @media (min-width: map-get($grid-breakpoints, lg)) { + grid-template-columns: 1.2fr 1fr; + gap: $space-12; + } + } + + // Blueprint annotations + .blueprint-annotation { + display: none; + position: absolute; + left: 0; + right: 0; + align-items: center; + gap: $space-4; + + @media (min-width: map-get($grid-breakpoints, md)) { + display: flex; + } + + &.annotation-top { + top: -$space-8; + } + + &.annotation-bottom { + bottom: -$space-8; + } + + .annotation-line { + flex: 1; + height: 1px; + background: linear-gradient(90deg, transparent, $blueprint-blue, transparent); + } + + .annotation-text { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $blueprint-blue; + letter-spacing: $tracking-wider; + white-space: nowrap; + } + } + + .hero-content { + order: 2; + + @media (min-width: map-get($grid-breakpoints, lg)) { + order: 1; + } + } + + .blueprint-badge { + display: inline-flex; + align-items: center; + gap: $space-2; + padding: $space-2 $space-4; + background: rgba($blueprint-blue, 0.1); + border: 1px solid $blueprint-blue; + border-radius: $radius-sm; + margin-bottom: $space-6; + + .badge-text { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $blueprint-blue; + text-transform: uppercase; + letter-spacing: $tracking-wider; + } + } + + .hero-title { + font-family: $font-display; + font-size: $type-scale-5xl; + font-weight: $font-weight-bold; + line-height: $leading-tight; + margin: 0 0 $space-6; + color: $blueprint-dark; + + @media (min-width: map-get($grid-breakpoints, md)) { + font-size: $type-scale-6xl; + } + + @media (min-width: map-get($grid-breakpoints, lg)) { + font-size: $type-scale-7xl; + } + + .title-main { + display: block; + } + + .title-accent { + color: $blueprint-accent; + } + } + + .hero-subtitle { + font-family: $font-body; + font-size: $type-scale-lg; + color: $blueprint-light; + max-width: 550px; + margin: 0 0 $space-10; + line-height: $leading-relaxed; + + @media (min-width: map-get($grid-breakpoints, md)) { + font-size: $type-scale-xl; + } + } + + .hero-cta { + display: flex; + flex-direction: column; + gap: $space-4; + + @media (min-width: map-get($grid-breakpoints, sm)) { + flex-direction: row; + } + } + + // Logo with blueprint frame + .hero-visual { + display: flex; + justify-content: center; + align-items: center; + order: 1; + + @media (min-width: map-get($grid-breakpoints, lg)) { + order: 2; + } + } + + .blueprint-frame { + position: relative; + width: 250px; + height: 250px; + display: flex; + align-items: center; + justify-content: center; + + @media (min-width: map-get($grid-breakpoints, md)) { + width: 350px; + height: 350px; + } + + .frame-corner { + position: absolute; + width: 30px; + height: 30px; + border-color: $blueprint-blue; + border-style: solid; + border-width: 0; + + &.top-left { + top: 0; + left: 0; + border-top-width: 2px; + border-left-width: 2px; + } + + &.top-right { + top: 0; + right: 0; + border-top-width: 2px; + border-right-width: 2px; + } + + &.bottom-left { + bottom: 0; + left: 0; + border-bottom-width: 2px; + border-left-width: 2px; + } + + &.bottom-right { + bottom: 0; + right: 0; + border-bottom-width: 2px; + border-right-width: 2px; + } + } + + .dimension-marker { + position: absolute; + font-family: $font-mono; + font-size: $type-scale-xs; + color: $blueprint-blue; + + &.horizontal { + bottom: -$space-6; + left: 50%; + transform: translateX(-50%); + + &::before, + &::after { + content: ''; + position: absolute; + top: 50%; + width: $space-8; + height: 1px; + background: $blueprint-blue; + } + + &::before { + right: calc(100% + $space-2); + } + + &::after { + left: calc(100% + $space-2); + } + } + + &.vertical { + right: -$space-10; + top: 50%; + transform: translateY(-50%) rotate(90deg); + + @media (max-width: map-get($grid-breakpoints, md) - 1px) { + display: none; + } + } + } + + .blueprint-logo { + width: 150px; + height: 150px; + object-fit: contain; + + @media (min-width: map-get($grid-breakpoints, md)) { + width: 200px; + height: 200px; + } + } + } +} + +// ============================================================================= +// BLUEPRINT BUTTONS +// ============================================================================= + +.btn-blueprint-primary { + display: inline-flex; + align-items: center; + gap: $space-2; + padding: $space-4 $space-8; + background: $blueprint-blue; + color: $warm-white; + font-family: $font-heading; + font-size: $type-scale-base; + font-weight: $font-weight-semibold; + text-decoration: none; + border: 2px solid $blueprint-blue; + transition: all $transition-base; + + &:hover { + background: $blueprint-dark; + border-color: $blueprint-dark; + transform: translateY(-2px); + } +} + +.btn-blueprint-secondary { + display: inline-flex; + align-items: center; + gap: $space-2; + padding: $space-4 $space-8; + background: transparent; + color: $blueprint-blue; + font-family: $font-heading; + font-size: $type-scale-base; + font-weight: $font-weight-semibold; + text-decoration: none; + border: 2px solid $blueprint-blue; + transition: all $transition-base; + + &:hover { + background: rgba($blueprint-blue, 0.1); + } +} + +// ============================================================================= +//SERVICES SECTION +// ============================================================================= + +.services-section { + padding: $space-24 $space-6; + background: $warm-white; + position: relative; + + .section-container { + max-width: $container-max-width; + margin: 0 auto; + } + + .section-header { + text-align: center; + margin-bottom: $space-16; + } + + .blueprint-label { + display: inline-flex; + align-items: center; + gap: $space-3; + margin-bottom: $space-4; + + .label-marker { + width: 12px; + height: 12px; + background: $blueprint-accent; + transform: rotate(45deg); + } + + span:last-child { + font-family: $font-mono; + font-size: $type-scale-sm; + color: $blueprint-blue; + text-transform: uppercase; + letter-spacing: $tracking-widest; + } + } + + .section-title { + font-family: $font-display; + font-size: $type-scale-4xl; + font-weight: $font-weight-bold; + color: $blueprint-dark; + margin: 0 0 $space-4; + + @media (min-width: map-get($grid-breakpoints, md)) { + font-size: $type-scale-5xl; + } + } + + .section-subtitle { + font-family: $font-body; + font-size: $type-scale-lg; + color: $blueprint-light; + max-width: 600px; + margin: 0 auto; + } + + .services-grid { + display: grid; + grid-template-columns: 1fr; + gap: $space-6; + + @media (min-width: map-get($grid-breakpoints, md)) { + grid-template-columns: repeat(2, 1fr); + } + + @media (min-width: map-get($grid-breakpoints, xl)) { + grid-template-columns: repeat(3, 1fr); + } + } + + .blueprint-card { + position: relative; + background: $blueprint-bg; + border: 1px solid $blueprint-grid; + padding: $space-8; + transition: all $transition-base; + + // Left accent border (hidden by default, appears on hover) + &::before { + content: ''; + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: 4px; + background: $ember; + opacity: 0; + transition: opacity $transition-base; + } + + .card-number { + position: absolute; + top: $space-4; + right: $space-4; + font-family: $font-mono; + font-size: $type-scale-sm; + color: $ember; + font-weight: $font-weight-bold; + + &::before { + content: '//'; + margin-right: $space-1; + color: rgba($blueprint-blue, 0.4); + } + } + + .card-header { + display: flex; + align-items: flex-start; + gap: $space-4; + margin-bottom: $space-4; + } + + .card-icon { + width: 56px; + height: 56px; + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; + background: rgba($blueprint-blue, 0.08); + border: 1px solid rgba($blueprint-blue, 0.3); + transition: all $transition-base; + + svg { + width: 28px; + height: 28px; + color: $blueprint-blue; + transition: color $transition-base; + } + } + + .card-title { + font-family: $font-heading; + font-size: $type-scale-2xl; + font-weight: $font-weight-bold; + color: $blueprint-dark; + margin: $space-2 0 0; + text-transform: uppercase; + letter-spacing: $tracking-wider; + } + + .card-description { + font-family: $font-body; + font-size: $type-scale-base; + color: $blueprint-light; + line-height: $leading-relaxed; + margin: 0; + + // Style for inline emphasis + strong { + color: $blueprint-dark; + font-weight: $font-weight-semibold; + } + + em { + color: $ember; + font-style: normal; + font-weight: $font-weight-medium; + } + } + + .card-corner { + position: absolute; + bottom: 0; + right: 0; + width: 32px; + height: 32px; + opacity: 0; + transition: opacity $transition-base; + + &::before, + &::after { + content: ''; + position: absolute; + background: $ember; + } + + &::before { + bottom: 0; + right: 0; + width: 2px; + height: 20px; + } + + &::after { + bottom: 0; + right: 0; + width: 20px; + height: 2px; + } + } + + &:hover { + border-color: $ember; + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba($blueprint-dark, 0.1); + + &::before { + opacity: 1; + } + + .card-icon { + background: rgba($ember, 0.12); + border-color: $ember; + box-shadow: 0 0 16px rgba($ember, 0.2); + + svg { + color: $ember; + } + } + + .card-corner { + opacity: 1; + } + } + + // Alternating accent colors for even cards (teal) + &:nth-child(even) { + &::before { + background: $teal-spark; + } + + .card-number { + color: $teal-spark; + } + + .card-corner { + &::before, + &::after { + background: $teal-spark; + } + } + + &:hover { + border-color: $teal-spark; + + .card-icon { + background: rgba($teal-spark, 0.12); + border-color: $teal-spark; + box-shadow: 0 0 16px rgba($teal-spark, 0.2); + + svg { + color: $teal-spark; + } + } + } + } + + } +} + +// ============================================================================= +//ENGAGEMENTS SECTION +// ============================================================================= + +.engagements-section { + padding: $space-24 $space-6; + background: $blueprint-bg; + + .section-container { + max-width: $container-max-width; + margin: 0 auto; + } + + .section-header { + text-align: center; + margin-bottom: $space-16; + } + + .blueprint-label { + display: inline-flex; + align-items: center; + gap: $space-3; + margin-bottom: $space-4; + + .label-marker { + width: 12px; + height: 12px; + background: $blueprint-accent; + transform: rotate(45deg); + } + + span:last-child { + font-family: $font-mono; + font-size: $type-scale-sm; + color: $blueprint-blue; + text-transform: uppercase; + letter-spacing: $tracking-widest; + } + } + + .section-title { + font-family: $font-display; + font-size: $type-scale-4xl; + font-weight: $font-weight-bold; + color: $blueprint-dark; + margin: 0 0 $space-4; + + @media (min-width: map-get($grid-breakpoints, md)) { + font-size: $type-scale-5xl; + } + } + + .section-subtitle { + font-family: $font-body; + font-size: $type-scale-lg; + color: $blueprint-light; + max-width: 700px; + margin: 0 auto; + line-height: $leading-relaxed; + } + + .engagements-timeline { + position: relative; + max-width: 900px; + margin: 0 auto; + } + + .timeline-track { + position: absolute; + left: 20px; + top: 0; + bottom: 0; + width: 2px; + + @media (min-width: map-get($grid-breakpoints, md)) { + left: 50%; + transform: translateX(-50%); + } + + .timeline-line { + width: 100%; + height: 100%; + background: linear-gradient(to bottom, $blueprint-blue, transparent); + } + } + + .timeline-items { + position: relative; + } + + .timeline-item { + display: flex; + align-items: flex-start; + gap: $space-6; + margin-bottom: $space-8; + padding-left: $space-12; + + @media (min-width: map-get($grid-breakpoints, md)) { + padding: 0; + + &.item-left { + justify-content: flex-end; + padding-right: calc(50% + $space-8); + + .timeline-marker { + left: auto; + right: calc(50% - 10px); + } + + .timeline-card { + text-align: right; + } + } + + &.item-right { + justify-content: flex-start; + padding-left: calc(50% + $space-8); + + .timeline-marker { + left: calc(50% - 10px); + } + } + } + } + + .timeline-marker { + position: absolute; + left: 10px; + + .marker-dot { + width: 20px; + height: 20px; + background: $blueprint-bg; + border: 3px solid $blueprint-blue; + transform: rotate(45deg); + } + } + + .timeline-card { + background: $warm-white; + border: 1px solid $blueprint-grid; + padding: $space-6; + flex: 1; + max-width: 400px; + transition: all $transition-base; + + .card-header { + display: flex; + align-items: baseline; + gap: $space-3; + margin-bottom: $space-3; + + @media (min-width: map-get($grid-breakpoints, md)) { + .item-left & { + justify-content: flex-end; + } + } + } + + .project-index { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $blueprint-accent; + font-weight: $font-weight-bold; + } + + .project-name { + font-family: $font-heading; + font-size: $type-scale-xl; + font-weight: $font-weight-semibold; + color: $blueprint-dark; + margin: 0; + } + + .project-description { + font-family: $font-body; + font-size: $type-scale-sm; + color: $blueprint-light; + line-height: $leading-relaxed; + margin: 0 0 $space-4; + } + + .card-footer { + @media (min-width: map-get($grid-breakpoints, md)) { + .item-left & { + text-align: right; + } + } + } + + .status-badge { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $blueprint-blue; + text-transform: uppercase; + letter-spacing: $tracking-wider; + padding: $space-1 $space-3; + background: rgba($blueprint-blue, 0.1); + border: 1px solid rgba($blueprint-blue, 0.3); + + &--ongoing { + color: $teal-spark; + background: rgba($teal-spark, 0.15); + border-color: rgba($teal-spark, 0.4); + } + } + + &:hover { + border-color: $blueprint-blue; + transform: translateY(-2px); + box-shadow: 0 4px 16px rgba($blueprint-dark, 0.08); + } + } +} + +// ============================================================================= +// PRODUCTS SECTION - The Workshop +// ============================================================================= + +// ============================================================================= +// PRODUCTS SECTION - The Workshop (Two-Column with Forge Schematic) +// ============================================================================= + +.products-section { + position: relative; + padding: $space-24 $space-6; + background: linear-gradient(180deg, $warm-stone 0%, $charred 100%); + overflow: hidden; + + // Ember-tinted grid background (warm workshop feel) + .blueprint-grid { + position: absolute; + inset: 0; + background-image: + linear-gradient(rgba($ember, 0.05) 1px, transparent 1px), + linear-gradient(90deg, rgba($ember, 0.05) 1px, transparent 1px); + background-size: 40px 40px; + opacity: 0.5; + pointer-events: none; + } + + .section-container { + position: relative; + z-index: 2; + max-width: $container-max-width; + margin: 0 auto; + } + + // === TWO-COLUMN WRAPPER === + .products-wrapper { + display: grid; + grid-template-columns: 1fr; + gap: $space-12; + align-items: center; + + @media (min-width: map-get($grid-breakpoints, lg)) { + grid-template-columns: 1fr 1fr; + gap: $space-16; + } + } + + // === LEFT CONTENT AREA === + .products-content { + .workshop-marker { + display: inline-flex; + align-items: center; + gap: $space-2; + margin-bottom: $space-6; + + .marker-icon { + color: $ember; + font-size: $type-scale-lg; + animation: blink 1.5s ease-in-out infinite; + } + + .marker-text { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $ember; + text-transform: uppercase; + letter-spacing: $tracking-widest; + } + } + + .section-title { + font-family: $font-display; + font-size: $type-scale-4xl; + font-weight: $font-weight-bold; + color: $warm-white; + margin: 0 0 $space-4; + + @media (min-width: map-get($grid-breakpoints, md)) { + font-size: $type-scale-5xl; + } + } + + .section-subtitle { + font-family: $font-body; + font-size: $type-scale-lg; + color: $stone-gray; + max-width: 400px; + margin: 0 0 $space-8; + } + } + + // === STACKED CATEGORY TILES === + .category-stack { + display: flex; + flex-direction: column; + gap: $space-4; + } + + .category-tile { + display: grid; + grid-template-columns: auto auto 1fr auto; + gap: $space-4; + align-items: center; + padding: $space-4 $space-6; + background: rgba($warm-stone, 0.6); + border: 1px solid rgba($ember, 0.2); + transition: all $transition-base; + + &:hover { + border-color: rgba($ember, 0.5); + background: rgba($warm-stone, 0.8); + transform: translateX(8px); + box-shadow: -4px 0 20px rgba($ember, 0.15); + } + + .tile-index { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $ember; + font-weight: $font-weight-bold; + opacity: 0.7; + } + + .tile-icon { + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + background: rgba($ember, 0.1); + border-radius: $radius-sm; + + // stylelint-disable-next-line no-descending-specificity + svg { + width: 20px; + height: 20px; + color: $ember; + } + } + + .tile-content { + min-width: 0; + + .tile-title { + font-family: $font-heading; + font-size: $type-scale-base; + font-weight: $font-weight-semibold; + color: $warm-white; + margin: 0; + text-transform: uppercase; + letter-spacing: $tracking-wide; + } + + .tile-description { + font-family: $font-body; + font-size: $type-scale-sm; + color: $stone-gray; + margin: $space-1 0 0; + } + } + + .tile-indicator { + .status-dot { + display: block; + width: 8px; + height: 8px; + background: $ember; + border-radius: 50%; + animation: status-pulse 2s ease-in-out infinite; + } + } + + // Alternating accent for visual variety + &:nth-child(2) { + .tile-icon { + background: rgba($teal-spark, 0.1); + + // stylelint-disable-next-line no-descending-specificity + svg { + color: $teal-spark; + } + } + + .tile-indicator .status-dot { + background: $teal-spark; + } + + &:hover { + border-color: rgba($teal-spark, 0.5); + box-shadow: -4px 0 20px rgba($teal-spark, 0.15); + } + } + } + + @keyframes status-pulse { + 0%, 100% { + opacity: 1; + transform: scale(1); + } + + 50% { + opacity: 0.5; + transform: scale(0.8); + } + } + + // === RIGHT VISUAL AREA === + .products-visual { + display: none; + + @media (min-width: map-get($grid-breakpoints, lg)) { + display: block; + } + } + + .visual-frame { + position: relative; + aspect-ratio: 1; + max-width: 380px; + margin: 0 auto; + } + + // Frame corners (matching contact section) + // stylelint-disable no-descending-specificity + .frame-corner { + position: absolute; + width: 40px; + height: 40px; + border-color: rgba($ember, 0.6); + border-style: solid; + + &.top-left { + top: 0; + left: 0; + border-width: 2px 0 0 2px; + } + + &.top-right { + top: 0; + right: 0; + border-width: 2px 2px 0 0; + } + + &.bottom-left { + bottom: 0; + left: 0; + border-width: 0 0 2px 2px; + } + + &.bottom-right { + bottom: 0; + right: 0; + border-width: 0 2px 2px 0; + } + } + // stylelint-enable no-descending-specificity + + // Coordinate markers + .coordinate-marker { + position: absolute; + font-family: $font-mono; + font-size: $type-scale-xs; + color: $stone-gray; + letter-spacing: $tracking-wide; + + &.coord-x { + bottom: -$space-6; + left: 50%; + transform: translateX(-50%); + } + + &.coord-y { + right: -$space-16; + top: 50%; + transform: translateY(-50%) rotate(90deg); + } + } + + .visual-content { + position: absolute; + inset: $space-8; + display: flex; + align-items: center; + justify-content: center; + } + + // === FORGE ASSEMBLY SCHEMATIC === + .forge-assembly-schematic { + width: 100%; + height: 100%; + color: rgba($warm-white, 0.8); + + // Grid breathing + .grid-layer { + animation: forge-grid-breathe 8s ease-in-out infinite; + } + + // Flame animations + .flame { + fill: $ember; + filter: url("#forge-glow"); + animation: flame-flicker 0.5s ease-in-out infinite alternate; + + &.flame-1 { + animation-delay: 0s; + } + + &.flame-2 { + animation-delay: 0.15s; + } + + &.flame-3 { + animation-delay: 0.3s; + } + } + + // Heat shimmer + .heat-shimmer { + stroke: rgba($ember, 0.4); + animation: shimmer-rise 2s ease-in-out infinite; + + &.shimmer-1 { + animation-delay: 0s; + } + + &.shimmer-2 { + animation-delay: 0.5s; + } + + &.shimmer-3 { + animation-delay: 1s; + } + } + + // Temperature gauge needle + .temp-needle { + transform-origin: 60px 115px; + animation: gauge-swing 4s ease-in-out infinite; + } + + // Status LEDs + .status-led { + fill: transparent; + stroke: rgba($warm-white, 0.3); + stroke-width: 1; + animation: forge-led-blink 2s ease-in-out infinite; + + &.led-heat { + fill: $ember; + stroke: $ember; + filter: url("#forge-glow"); + animation: none; + } + + &.led-ready { + animation-delay: 0.3s; + } + + &.led-cycle { + animation-delay: 0.6s; + } + } + + // Hammer mechanism + .hammer-arm { + transform-origin: 150px 165px; + animation: hammer-strike 2s ease-in-out infinite; + } + + // Sparks + .spark { + fill: $copper-glow; + filter: url("#forge-glow"); + opacity: 0; + animation: spark-burst 2s ease-out infinite; + + &.spark-1 { + animation-delay: 1s; + + --spark-x: 0px; + --spark-y: -15px; + } + + &.spark-2 { + animation-delay: 1.05s; + + --spark-x: -10px; + --spark-y: -20px; + } + + &.spark-3 { + animation-delay: 1.1s; + + --spark-x: 10px; + --spark-y: -18px; + } + + &.spark-4 { + animation-delay: 1.15s; + + --spark-x: -15px; + --spark-y: -12px; + } + + &.spark-5 { + animation-delay: 1.2s; + + --spark-x: 15px; + --spark-y: -10px; + } + } + + // Conveyor belt items + .product-item { + animation: conveyor-move 4s linear infinite; + + &.item-1 { + animation-delay: 0s; + } + + &.item-2 { + animation-delay: 2s; + } + } + + // Scanner beam + .scan-beam { + stroke: $teal-spark; + animation: scan-sweep 1.5s ease-in-out infinite; + } + + .scan-indicator { + fill: $teal-spark; + filter: url("#forge-glow"); + animation: scan-pulse 1.5s ease-in-out infinite; + } + + // Data readout + .status-val { + fill: $ember; + } + + .temp-val, + .cycle-val, + .yield-val { + animation: forge-value-flicker 4s ease-in-out infinite; + } + + .cycle-val { + animation-delay: 1s; + } + + .yield-val { + animation-delay: 2s; + } + } + + // === FORGE ANIMATIONS === + + @keyframes forge-grid-breathe { + 0%, 100% { + opacity: 0.06; + } + + 50% { + opacity: 0.1; + } + } + + @keyframes flame-flicker { + 0% { + transform: scaleY(1) scaleX(1); + opacity: 0.9; + } + + 100% { + transform: scaleY(1.15) scaleX(0.95); + opacity: 1; + } + } + + @keyframes shimmer-rise { + 0%, 100% { + transform: translateY(0); + opacity: 0.3; + } + + 50% { + transform: translateY(-5px); + opacity: 0.6; + } + } + + @keyframes gauge-swing { + 0%, 100% { + transform: rotate(-15deg); + } + + 50% { + transform: rotate(15deg); + } + } + + @keyframes forge-led-blink { + 0%, 100% { + fill: transparent; + stroke: rgba($warm-white, 0.3); + } + + 40%, 60% { + fill: $ember; + stroke: $ember; + filter: url("#forge-glow"); + } + } + + @keyframes hammer-strike { + 0%, 40%, 100% { + transform: rotate(0deg); + } + + 45% { + transform: rotate(-20deg); + } + + 50% { + transform: rotate(0deg); + } + } + + @keyframes spark-burst { + 0% { + opacity: 0; + transform: translate(0, 0) scale(1); + } + + 10% { + opacity: 1; + } + + 100% { + opacity: 0; + transform: translate(var(--spark-x, 10px), var(--spark-y, -20px)) scale(0); + } + } + + @keyframes conveyor-move { + 0% { + transform: translateX(0); + opacity: 1; + } + + 80% { + transform: translateX(30px); + opacity: 1; + } + + 100% { + transform: translateX(40px); + opacity: 0; + } + } + + @keyframes scan-sweep { + 0%, 100% { + opacity: 0.5; + } + + 50% { + opacity: 1; + } + } + + @keyframes scan-pulse { + 0%, 100% { + r: 2; + opacity: 0.7; + } + + 50% { + r: 3; + opacity: 1; + } + } + + @keyframes forge-value-flicker { + 0%, 85%, 100% { + opacity: 1; + } + + 90% { + opacity: 0.3; + } + + 95% { + opacity: 0.8; + } + } + + // Reduced motion support + @media (prefers-reduced-motion: reduce) { + .forge-assembly-schematic * { + animation: none !important; + } + + .flame { + opacity: 0.8 !important; + } + + .status-led.led-heat { + fill: $ember !important; + opacity: 0.8; + } + } +} + +// ============================================================================= +//ABOUT SECTION +// ============================================================================= + +.about-section { + padding: $space-24 $space-6; + background: #F5F5F4; // Warmer stone-tinted white for visual separation from Principles + + .section-container { + max-width: $container-max-width; + margin: 0 auto; + } + + .about-wrapper { + display: grid; + grid-template-columns: 1fr; + gap: $space-12; + align-items: center; + + @media (min-width: map-get($grid-breakpoints, lg)) { + grid-template-columns: 1.2fr 1fr; + } + } + + .about-content { + .blueprint-label { + display: inline-flex; + align-items: center; + gap: $space-3; + margin-bottom: $space-4; + + .label-marker { + width: 12px; + height: 12px; + background: $blueprint-accent; + transform: rotate(45deg); + } + + span:last-child { + font-family: $font-mono; + font-size: $type-scale-sm; + color: $blueprint-blue; + text-transform: uppercase; + letter-spacing: $tracking-widest; + } + } + + .about-title { + font-family: $font-display; + font-size: $type-scale-4xl; + font-weight: $font-weight-bold; + color: $blueprint-dark; + margin: 0 0 $space-6; + + @media (min-width: map-get($grid-breakpoints, md)) { + font-size: $type-scale-5xl; + } + } + + .about-quote { + position: relative; + margin: 0 0 $space-6; + padding: $space-6; + padding-left: $space-10; + background: $warm-white; + border: 1px solid $blueprint-grid; + border-left: 4px solid $blueprint-blue; + + .quote-mark { + position: absolute; + top: $space-4; + left: $space-3; + width: 24px; + height: 24px; + color: rgba($blueprint-blue, 0.3); + + // stylelint-disable-next-line no-descending-specificity + svg { + width: 100%; + height: 100%; + } + } + + p { + font-family: $font-display; + font-size: $type-scale-lg; + font-style: italic; + color: $blueprint-dark; + line-height: $leading-relaxed; + margin: 0; + } + } + + .about-description { + font-family: $font-body; + font-size: $type-scale-base; + color: $blueprint-light; + line-height: $leading-relaxed; + margin: 0 0 $space-8; + } + + .about-locations { + margin-bottom: $space-8; + + .locations-label { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $blueprint-blue; + text-transform: uppercase; + letter-spacing: $tracking-wider; + display: block; + margin-bottom: $space-3; + } + + .locations-list { + display: flex; + flex-wrap: wrap; + gap: $space-4; + } + + .location-item { + display: inline-flex; + align-items: center; + gap: $space-2; + } + + .location-marker { + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + background: $blueprint-blue; + color: $warm-white; + font-family: $font-mono; + font-size: $type-scale-xs; + font-weight: $font-weight-bold; + + &::before { + content: attr(data-index); + } + } + + .location-name { + font-family: $font-body; + font-size: $type-scale-sm; + color: $blueprint-dark; + } + } + + .about-footer { + display: flex; + flex-wrap: wrap; + gap: $space-8; + } + + .footer-item { + display: flex; + flex-direction: column; + gap: $space-1; + + .label { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $blueprint-light; + text-transform: uppercase; + letter-spacing: $tracking-wider; + } + + .value { + font-family: $font-heading; + font-size: $type-scale-base; + color: $blueprint-dark; + font-weight: $font-weight-medium; + } + } + } + + .about-visual { + display: flex; + justify-content: center; + align-items: center; + + @media (max-width: map-get($grid-breakpoints, lg) - 1px) { + order: -1; + } + } + + .blueprint-schematic { + position: relative; + padding: $space-12; + } + + .schematic-frame { + width: 280px; + height: 280px; + display: flex; + align-items: center; + justify-content: center; + border: 2px solid $blueprint-blue; + background: $warm-white; + position: relative; + + @media (min-width: map-get($grid-breakpoints, md)) { + width: 380px; + height: 380px; + } + + // Corner registration marks + &::before, + &::after { + content: ''; + position: absolute; + width: 20px; + height: 20px; + border: 1px solid rgba($blueprint-blue, 0.3); + } + + &::before { + top: 8px; + left: 8px; + border-right: none; + border-bottom: none; + } + + &::after { + bottom: 8px; + right: 8px; + border-left: none; + border-top: none; + } + } + + .robot-arm-schematic { + width: 240px; + height: 240px; + color: $blueprint-blue; + + @media (min-width: map-get($grid-breakpoints, md)) { + width: 320px; + height: 320px; + } + + // Grid breathing + .grid-layer { + animation: grid-breathe 8s ease-in-out infinite; + } + + // Arc sweep animation + .arc-indicator { + stroke: $ember; + animation: arc-sweep 4s ease-in-out infinite; + } + + // Ghost trail + .ghost-positions { + animation: ghost-fade 5s ease-in-out infinite; + } + + // Joint pulses + .joint-center { + animation: joint-pulse 3s ease-in-out infinite; + } + + .joint-j2 .joint-center { + animation-delay: 0.5s; + } + + .joint-j3 .joint-center { + animation-delay: 1s; + } + + // Status LEDs - ember glow + .status-led { + fill: transparent; + stroke: $blueprint-blue; + stroke-width: 1; + animation: led-pulse 2s ease-in-out infinite; + + &.led-1 { animation-delay: 0s; } + &.led-2 { animation-delay: 0.4s; } + &.led-3 { animation-delay: 0.8s; } + } + + // Gripper micro-motion + .gripper-finger-1 { + animation: gripper-open 4s ease-in-out infinite; + transform-origin: 210px 30px; + } + + .gripper-finger-2 { + animation: gripper-open 4s ease-in-out infinite reverse; + transform-origin: 210px 44px; + } + + // Grip point pulse + .grip-point { + stroke: $ember; + stroke-width: 1; + fill: none; + animation: grip-pulse 2s ease-in-out infinite; + } + + // Data readout flicker + .data-readout { + .status-val { + fill: $ember; + } + + .pos-val, + .cycle-val { + animation: value-update 3s ease-in-out infinite; + } + + .cycle-val { + animation-delay: 1.5s; + } + } + } + + // === ROBOT ARM ANIMATIONS === + + @keyframes grid-breathe { + 0%, 100% { opacity: 0.06; } + 50% { opacity: 0.1; } + } + + @keyframes arc-sweep { + 0%, 100% { + stroke-dasharray: 0 200; + opacity: 0.6; + } + + 50% { + stroke-dasharray: 100 200; + opacity: 1; + } + } + + @keyframes ghost-fade { + 0%, 100% { + opacity: 0.05; + } + + 50% { + opacity: 0.15; + } + } + + @keyframes joint-pulse { + 0%, 100% { + opacity: 0.6; + transform: scale(1); + } + + 50% { + opacity: 1; + transform: scale(1.1); + } + } + + @keyframes led-pulse { + 0%, 100% { + fill: transparent; + stroke: $blueprint-blue; + filter: none; + } + + 50% { + fill: $ember; + stroke: $ember; + filter: url("#ember-glow"); + } + } + + @keyframes gripper-open { + 0%, 100% { + transform: rotate(0deg); + } + + 50% { + transform: rotate(2deg); + } + } + + @keyframes grip-pulse { + 0%, 100% { + r: 4; + opacity: 0.5; + } + + 50% { + r: 6; + opacity: 1; + } + } + + @keyframes value-update { + 0%, 85%, 100% { + opacity: 1; + } + + 90% { + opacity: 0.3; + } + } + + // Reduced motion support + @media (prefers-reduced-motion: reduce) { + .robot-arm-schematic * { + animation: none !important; + } + + .status-led { + fill: $ember !important; + opacity: 0.7; + } + } + + .schematic-labels { + .label-item { + position: absolute; + font-family: $font-mono; + font-size: $type-scale-xs; + color: $blueprint-blue; + letter-spacing: $tracking-wider; + white-space: nowrap; + + &::before { + content: ''; + position: absolute; + background: $blueprint-blue; + } + + &.label-top { + top: 0; + left: 50%; + transform: translateX(-50%); + + &::before { + width: 1px; + height: $space-4; + left: 50%; + top: 100%; + margin-top: $space-1; + } + } + + &.label-right { + right: 0; + top: 50%; + transform: translateY(-50%); + + &::before { + width: $space-2; + height: 1px; + right: 100%; + top: 50%; + margin-right: $space-1; + } + } + + &.label-bottom { + bottom: 0; + left: 50%; + transform: translateX(-50%); + + &::before { + width: 1px; + height: $space-4; + left: 50%; + bottom: 100%; + margin-bottom: $space-1; + } + } + } + } +} + +// ============================================================================= +//CONTACT SECTION - Terminal Connection +// ============================================================================= + +.contact-section { + position: relative; + padding: $space-24 $space-6; + background: $blueprint-dark; + overflow: hidden; + + // Blueprint grid background + .blueprint-grid { + position: absolute; + inset: 0; + background-image: + linear-gradient(rgba($blueprint-blue, 0.1) 1px, transparent 1px), + linear-gradient(90deg, rgba($blueprint-blue, 0.1) 1px, transparent 1px); + background-size: 40px 40px; + opacity: 0.5; + pointer-events: none; + } + + .contact-container { + position: relative; + z-index: 2; + max-width: $container-max-width; + margin: 0 auto; + display: grid; + grid-template-columns: 1fr; + gap: $space-12; + align-items: center; + + @media (min-width: map-get($grid-breakpoints, lg)) { + grid-template-columns: 1.2fr 1fr; + gap: $space-16; + } + } + + // Terminal marker + // stylelint-disable no-descending-specificity + .terminal-marker { + display: inline-flex; + align-items: center; + gap: $space-2; + margin-bottom: $space-6; + + .marker-icon { + color: $ember; + font-size: $type-scale-lg; + animation: blink 1.5s ease-in-out infinite; + } + + .marker-text { + font-family: $font-mono; + font-size: $type-scale-xs; + color: $ember; + text-transform: uppercase; + letter-spacing: $tracking-widest; + } + } + // stylelint-enable no-descending-specificity + + @keyframes blink { + 0%, 50%, 100% { opacity: 1; } + 25%, 75% { opacity: 0.4; } + } + + .contact-title { + font-family: $font-display; + font-size: $type-scale-5xl; + font-weight: $font-weight-bold; + line-height: $leading-tight; + color: $warm-white; + margin: 0 0 $space-6; + + @media (min-width: map-get($grid-breakpoints, md)) { + font-size: $type-scale-6xl; + } + + .title-line { + display: block; + } + + .title-accent { + color: $ember; + } + } + + .contact-description { + font-family: $font-body; + font-size: $type-scale-lg; + color: $stone-gray; + line-height: $leading-relaxed; + max-width: 480px; + margin-bottom: $space-8; + } + + // CTA Button + .contact-cta { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: $space-3; + } + + .btn-terminal { + position: relative; + display: inline-flex; + align-items: center; + gap: $space-3; + padding: $space-4 $space-8; + background: $ember; + color: $warm-white; + font-family: $font-heading; + font-size: $type-scale-base; + font-weight: $font-weight-semibold; + text-decoration: none; + border: none; + transition: all $transition-base; + overflow: hidden; + + .btn-glow { + position: absolute; + inset: 0; + background: linear-gradient(135deg, rgba($copper-glow, 0.3), transparent); + opacity: 0; + transition: opacity $transition-base; + } + + .btn-icon { + width: 20px; + height: 20px; + position: relative; + z-index: 1; + } + + // stylelint-disable-next-line no-descending-specificity + span:last-child { + position: relative; + z-index: 1; + } + + &:hover { + transform: translateY(-2px); + box-shadow: $glow-ember; + + .btn-glow { + opacity: 1; + } + } + } + + .cta-subtext { + font-family: $font-mono; + font-size: $type-scale-xs; + color: rgba($stone-gray, 0.7); + } + + // Visual Element + .contact-visual { + display: none; + + @media (min-width: map-get($grid-breakpoints, lg)) { + display: block; + } + } + + .visual-frame { + position: relative; + aspect-ratio: 1; + max-width: 350px; + margin: 0 auto; + } + + // Corner brackets + // stylelint-disable no-descending-specificity + .frame-corner { + position: absolute; + width: 40px; + height: 40px; + border-color: rgba($ember, 0.6); + border-style: solid; + + &.top-left { + top: 0; + left: 0; + border-width: 2px 0 0 2px; + } + + &.top-right { + top: 0; + right: 0; + border-width: 2px 2px 0 0; + } + + &.bottom-left { + bottom: 0; + left: 0; + border-width: 0 0 2px 2px; + } + + &.bottom-right { + bottom: 0; + right: 0; + border-width: 0 2px 2px 0; + } + } + // stylelint-enable no-descending-specificity + + // Coordinate markers + .coordinate-marker { + position: absolute; + font-family: $font-mono; + font-size: $type-scale-xs; + color: $stone-gray; + letter-spacing: $tracking-wide; + + &.coord-x { + bottom: -$space-6; + left: 50%; + transform: translateX(-50%); + } + + &.coord-y { + right: -$space-12; + top: 50%; + transform: translateY(-50%) rotate(90deg); + } + } + + // Signal animation + .visual-content { + position: absolute; + inset: $space-8; + display: flex; + align-items: center; + justify-content: center; + } + + // === COMMUNICATION BEACON SCHEMATIC === + .comm-beacon-schematic { + width: 100%; + height: 100%; + color: rgba($blueprint-blue, 0.8); + + // Grid breathing + .grid-layer { + animation: beacon-grid-breathe 8s ease-in-out infinite; + } + + // Signal waves - expand outward + .wave { + stroke: rgba($ember, 0.6); + animation: wave-expand 3s ease-out infinite; + transform-origin: center; + + &.wave-1 { animation-delay: 0s; } + &.wave-2 { animation-delay: 0.5s; } + &.wave-3 { animation-delay: 1s; } + &.wave-4 { animation-delay: 1.5s; } + } + + // Data packets - travel outward + .packet { + fill: $ember; + filter: url("#beacon-glow"); + + &.packet-n { animation: packet-north 2.5s ease-in-out infinite; } + &.packet-e { animation: packet-east 2.5s ease-in-out infinite 0.3s; } + &.packet-s { animation: packet-south 2.5s ease-in-out infinite 0.6s; } + &.packet-w { animation: packet-west 2.5s ease-in-out infinite 0.9s; } + &.packet-ne { animation: packet-northeast 3s ease-in-out infinite 0.2s; } + &.packet-sw { animation: packet-southwest 3s ease-in-out infinite 0.8s; } + } + + // Core pulse + .core-active { + stroke: $ember; + animation: core-ring-pulse 2s ease-in-out infinite; + } + + .core-pulse { + fill: $ember; + filter: url("#beacon-glow"); + animation: beacon-core-glow 1.5s ease-in-out infinite; + } + + // Focus point + .focus-point { + fill: $ember; + filter: url("#beacon-glow"); + animation: focus-pulse 2s ease-in-out infinite 0.5s; + } + + // Status LEDs + .status-led { + fill: transparent; + stroke: rgba($blueprint-blue, 0.5); + stroke-width: 1; + animation: beacon-led-blink 2s ease-in-out infinite; + + &.led-tx { animation-delay: 0s; } + &.led-rx { animation-delay: 0.25s; } + &.led-link { animation-delay: 0.5s; } + &.led-pwr { animation: beacon-led-steady 3s ease-in-out infinite; } + } + + // Scanning beam + .beam-sweep { + transform-origin: 150px 150px; + animation: beam-rotate 6s linear infinite; + } + + // Antenna oscillation + .antenna-secondary { + animation: dish-scan 4s ease-in-out infinite; + transform-origin: 150px 150px; + } + + .antenna-tertiary { + animation: dish-scan 4s ease-in-out infinite reverse; + transform-origin: 150px 150px; + } + + // Data readout + .link-val { + fill: $ember; + } + + .freq-val, .signal-val, .uptime-val { + animation: beacon-value-flicker 4s ease-in-out infinite; + } + + .signal-val { animation-delay: 1s; } + .uptime-val { animation-delay: 2s; } + } + + // === BEACON ANIMATIONS === + + @keyframes beacon-grid-breathe { + 0%, 100% { + opacity: 0.06; + } + + 50% { + opacity: 0.1; + } + } + + @keyframes wave-expand { + 0% { + transform: scale(0.6); + opacity: 0.8; + stroke-width: 2; + } + + 100% { + transform: scale(1.2); + opacity: 0; + stroke-width: 0.5; + } + } + + @keyframes packet-north { + 0%, 100% { + transform: translate(0, 0); + opacity: 1; + } + + 45% { + transform: translate(0, -100px); + opacity: 0; + } + + 55% { + transform: translate(0, 0); + opacity: 0; + } + + 65% { + opacity: 1; + } + } + + @keyframes packet-east { + 0%, 100% { + transform: translate(0, 0); + opacity: 1; + } + + 45% { + transform: translate(100px, 0); + opacity: 0; + } + + 55% { + transform: translate(0, 0); + opacity: 0; + } + + 65% { + opacity: 1; + } + } + + @keyframes packet-south { + 0%, 100% { + transform: translate(0, 0); + opacity: 1; + } + + 45% { + transform: translate(0, 80px); + opacity: 0; + } + + 55% { + transform: translate(0, 0); + opacity: 0; + } + + 65% { + opacity: 1; + } + } + + @keyframes packet-west { + 0%, 100% { + transform: translate(0, 0); + opacity: 1; + } + + 45% { + transform: translate(-100px, 0); + opacity: 0; + } + + 55% { + transform: translate(0, 0); + opacity: 0; + } + + 65% { + opacity: 1; + } + } + + @keyframes packet-northeast { + 0%, 100% { + transform: translate(0, 0); + opacity: 1; + } + + 45% { + transform: translate(80px, -80px); + opacity: 0; + } + + 55% { + transform: translate(0, 0); + opacity: 0; + } + + 65% { + opacity: 1; + } + } + + @keyframes packet-southwest { + 0%, 100% { + transform: translate(0, 0); + opacity: 1; + } + + 45% { + transform: translate(-80px, 80px); + opacity: 0; + } + + 55% { + transform: translate(0, 0); + opacity: 0; + } + + 65% { + opacity: 1; + } + } + + @keyframes core-ring-pulse { + 0%, 100% { + stroke-width: 2; + opacity: 0.8; + } + + 50% { + stroke-width: 3; + opacity: 1; + filter: url("#beacon-glow"); + } + } + + @keyframes beacon-core-glow { + 0%, 100% { + r: 5; + opacity: 0.8; + } + + 50% { + r: 7; + opacity: 1; + } + } + + @keyframes focus-pulse { + 0%, 100% { + r: 4; + opacity: 0.7; + } + + 50% { + r: 6; + opacity: 1; + } + } + + @keyframes beacon-led-blink { + 0%, 100% { + fill: transparent; + stroke: rgba($blueprint-blue, 0.5); + } + + 40%, 60% { + fill: $ember; + stroke: $ember; + filter: url("#beacon-glow"); + } + } + + @keyframes beacon-led-steady { + 0%, 100% { + fill: $ember; + stroke: $ember; + filter: url("#beacon-glow"); + opacity: 1; + } + + 50% { + opacity: 0.7; + } + } + + @keyframes beam-rotate { + from { + transform: rotate(0deg); + } + + to { + transform: rotate(360deg); + } + } + + @keyframes dish-scan { + 0%, 100% { + transform: translateX(0); + } + + 50% { + transform: translateX(5px); + } + } + + @keyframes beacon-value-flicker { + 0%, 85%, 100% { opacity: 1; } + 90% { opacity: 0.3; } + 95% { opacity: 0.8; } + } + + // Reduced motion support + @media (prefers-reduced-motion: reduce) { + .comm-beacon-schematic * { + animation: none !important; + } + + .status-led.led-pwr { + fill: $ember !important; + opacity: 0.8; + } + + .core-pulse { + opacity: 1 !important; + } + } +} + +// ============================================================================= +// FOOTER +// ============================================================================= + +.site-footer { + position: relative; + padding: $space-8 $space-6; + background: linear-gradient(180deg, $blueprint-dark 0%, $forge-black 100%); + text-align: center; + overflow: hidden; + + // Glowing ember accent line at top + .footer-accent-line { + position: absolute; + top: 0; + left: 0; + right: 0; + height: 2px; + background: linear-gradient(90deg, transparent, $ember, transparent); + box-shadow: 0 0 20px rgba($ember, 0.5), 0 0 40px rgba($ember, 0.3); + } + + // Subtle blueprint grid + .blueprint-grid { + position: absolute; + inset: 0; + background-image: + linear-gradient(rgba($blueprint-blue, 0.05) 1px, transparent 1px), + linear-gradient(90deg, rgba($blueprint-blue, 0.05) 1px, transparent 1px); + background-size: 40px 40px; + pointer-events: none; + } + + .footer-container { + position: relative; + z-index: 1; + max-width: $container-max-width; + margin: 0 auto; + display: flex; + align-items: center; + justify-content: center; + gap: $space-4; + } + + .footer-marker { + font-family: $font-mono; + font-size: $type-scale-sm; + color: $ember; + letter-spacing: $tracking-wide; + } + + .footer-divider { + font-family: $font-mono; + font-size: $type-scale-sm; + color: rgba($warm-white, 0.5); + } + + .footer-name { + font-family: $font-mono; + font-size: $type-scale-sm; + color: $warm-white; + letter-spacing: $tracking-wide; + } +} diff --git a/source/assets/stylesheets/site.scss b/source/assets/stylesheets/site.scss index 18ae33e0..2703526e 100644 --- a/source/assets/stylesheets/site.scss +++ b/source/assets/stylesheets/site.scss @@ -1,14 +1,21 @@ @charset "utf-8"; +// ============================================================================= +// FORGE Design System - Main Stylesheet +// ============================================================================= + +// Vendor @import "~normalize-scss/sass/normalize/import-now"; + +// Settings & Tokens @import "settings"; -@import "vendor/bootstrap"; -@import "vendor/google_fonts"; -@import "mixins/*"; + +// Base Components @import "components/html-body"; -@import "components/preloader"; -@import "components/navigation"; -@import "components/footer"; -@import "pages/index/index"; -@import "pages/contact/index"; -@import "pages/four-o-four/index"; +@import "components/animations"; +@import "components/loader"; +@import "components/floating-nav"; + +// Pages +@import "pages/four-o-four"; +@import "pages/home"; diff --git a/source/design-system.html.slim b/source/design-system.html.slim new file mode 100644 index 00000000..f39f9ded --- /dev/null +++ b/source/design-system.html.slim @@ -0,0 +1,399 @@ +--- +id: design-system +layout: index +--- + +.design-system + / Page Header + .page-header + .badge FORGE Design System + h1.page-title Design System + p.page-tagline Where precision meets partnership + + / Hero Preview Section + .section + h2.section-title Live Preview + .hero-preview + .hero-content + p.hero-eyebrow Agentic AI Solutions + h1.hero-title + | Robots Building + span.accent Robots + p.hero-subtitle Architecting products and services across emerging technologies. Creating win-win strategic partnerships. + .hero-actions + a.btn.btn-primary[href="#"] Start a Conversation + a.btn.btn-secondary[href="#"] View Our Work + a.btn.btn-spark[href="#"] Innovation Lab + + / Color Palette - Core + .section + h2.section-title Core Palette + p.section-subtitle The foundation of FORGE. Warm blacks evoke the heat of creation; stone grays provide depth and hierarchy. + .color-grid + .color-swatch.forge-black + .swatch-preview + .swatch-info + p.color-name Forge Black + p.var-name $forge-black + p.hex-value #0C0A09 + p.description Primary background + + .color-swatch.warm-stone + .swatch-preview + .swatch-info + p.color-name Warm Stone + p.var-name $warm-stone + p.hex-value #1C1917 + p.description Cards, elevated sections + + .color-swatch.charred + .swatch-preview + .swatch-info + p.color-name Charred + p.var-name $charred + p.hex-value #292524 + p.description Tertiary surfaces + + .color-swatch.ash + .swatch-preview + .swatch-info + p.color-name Ash + p.var-name $ash + p.hex-value #44403C + p.description Borders, dividers + + .color-swatch.stone-gray + .swatch-preview + .swatch-info + p.color-name Stone Gray + p.var-name $stone-gray + p.hex-value #A8A29E + p.description Secondary text + + .color-swatch.warm-white + .swatch-preview + .swatch-info + p.color-name Warm White + p.var-name $warm-white + p.hex-value #FAFAF9 + p.description Primary text + + / Color Palette - Accents + .section + h2.section-title Accent Palette + p.section-subtitle The fire of the forge. Ember for action, copper for warmth, teal for innovation. + .color-grid + .color-swatch.ember + .swatch-preview + .swatch-info + p.color-name Ember + p.var-name $ember + p.hex-value #DC6B4A + p.description Primary accent, CTAs + + .color-swatch.copper-glow + .swatch-preview + .swatch-info + p.color-name Copper Glow + p.var-name $copper-glow + p.hex-value #F4A261 + p.description Hover states, warmth + + .color-swatch.teal-spark + .swatch-preview + .swatch-info + p.color-name Teal Spark + p.var-name $teal-spark + p.hex-value #2DD4BF + p.description Innovation moments + + / Typography + .section + h2.section-title Typography + p.section-subtitle Four fonts, each with a purpose. Editorial gravitas meets innovative spirit. + + .typography-grid + / Playfair Display + .font-card.display + .font-header + .font-meta + h3.font-name Playfair Display + p.font-role Display / Hero Headlines + .font-weights + span.weight-pill 400 + span.weight-pill 500 + span.weight-pill 600 + span.weight-pill 700 + .font-samples + .sample-row + span.sample-size 72px + p.sample-text[style="font-size: 4.5rem;"] Robots Building Robots + .sample-row + span.sample-size 48px + p.sample-text[style="font-size: 3rem;"] Where precision meets partnership + .sample-row + span.sample-size 36px + p.sample-text[style="font-size: 2.25rem;"] Architecting the future of AI + + / Inter + .font-card.heading + .font-header + .font-meta + h3.font-name Inter + p.font-role Headings / Navigation + .font-weights + span.weight-pill 400 + span.weight-pill 500 + span.weight-pill 600 + span.weight-pill 700 + .font-samples + .sample-row + span.sample-size 30px + p.sample-text[style="font-size: 1.875rem; font-family: 'Inter', sans-serif;"] Strategic Technology Consulting + .sample-row + span.sample-size 24px + p.sample-text[style="font-size: 1.5rem; font-family: 'Inter', sans-serif;"] Agentic Workflows & Team Augmentation + .sample-row + span.sample-size 18px + p.sample-text[style="font-size: 1.125rem; font-family: 'Inter', sans-serif;"] Creating win-win partnerships through innovation + + / Libre Franklin + .font-card.body + .font-header + .font-meta + h3.font-name Libre Franklin + p.font-role Body Text / UI Elements + .font-weights + span.weight-pill 300 + span.weight-pill 400 + span.weight-pill 500 + span.weight-pill 600 + span.weight-pill 700 + .font-samples + .sample-row + span.sample-size 18px + p.sample-text[style="font-size: 1.125rem;"] RobotsBuildingRobots focuses on architecting products and services across a variety of existing and emerging technologies. + .sample-row + span.sample-size 16px + p.sample-text[style="font-size: 1rem;"] More than process, lines of code, and innovative design, the goal is to create win-win strategic partnerships. + .sample-row + span.sample-size 14px + p.sample-text[style="font-size: 0.875rem;"] This includes implementing agentic workflows, team augmentation, mentoring on artificial technologies, service-oriented APIs. + + / JetBrains Mono + .font-card.mono + .font-header + .font-meta + h3.font-name JetBrains Mono + p.font-role Code / Technical Content + .font-weights + span.weight-pill 400 + span.weight-pill 500 + span.weight-pill 600 + .font-samples + .sample-row + span.sample-size 16px + p.sample-text const forge = new AgenticWorkflow(); + .sample-row + span.sample-size 14px + p.sample-text async function buildRobot(specs) { return await ai.generate(specs); } + .sample-row + span.sample-size 12px + p.sample-text[style="font-size: 0.75rem;"] + | // Innovation happens here + + / Type Scale + .section + h2.section-title Type Scale + p.section-subtitle Major Third scale (1.25 ratio). From whisper to shout. + + .type-scale-list + .type-scale-item.xxxxxxl + .scale-meta + p.scale-name 6xl + p.scale-size 60px + p.scale-sample Forge + + .type-scale-item.xxxxxl + .scale-meta + p.scale-name 5xl + p.scale-size 48px + p.scale-sample Innovation + + .type-scale-item.xxxxl + .scale-meta + p.scale-name 4xl + p.scale-size 36px + p.scale-sample Partnership + + .type-scale-item.xxxl + .scale-meta + p.scale-name 3xl + p.scale-size 30px + p.scale-sample Precision + + .type-scale-item.xxl + .scale-meta + p.scale-name 2xl + p.scale-size 24px + p.scale-sample Craftsmanship + + .type-scale-item.xl + .scale-meta + p.scale-name xl + p.scale-size 20px + p.scale-sample Architecture + + .type-scale-item.lg + .scale-meta + p.scale-name lg + p.scale-size 18px + p.scale-sample Strategic + + .type-scale-item.base + .scale-meta + p.scale-name base + p.scale-size 16px + p.scale-sample Default body text size + + .type-scale-item.sm + .scale-meta + p.scale-name sm + p.scale-size 14px + p.scale-sample Captions and metadata + + .type-scale-item.xs + .scale-meta + p.scale-name xs + p.scale-size 12px + p.scale-sample Fine print and labels + + / Components + .section + h2.section-title Components + p.section-subtitle Interactive elements that embody the FORGE aesthetic. + + .components-grid + / Buttons + .component-card + h3.component-title Buttons + .component-content + button.btn.btn-primary Primary Action + button.btn.btn-secondary Secondary Action + button.btn.btn-spark Innovation Spark + button.btn.btn-ghost Ghost Button + + / Form Elements + .component-card + h3.component-title Form Elements + .component-content + input.input-field[type="text" placeholder="Enter your email"] + input.input-field[type="text" placeholder="Your message here..."] + + / Cards + .component-card + h3.component-title Cards + .component-content + .sample-card + h4.card-title Agentic Workflows + p.card-text Implementing intelligent automation that adapts and learns. + .sample-card + h4.card-title Team Augmentation + p.card-text Scaling your team with expert technologists. + + / Spacing Scale + .section + h2.section-title Spacing Scale + p.section-subtitle Consistent rhythm creates visual harmony. + + .spacing-grid + .spacing-item + .spacing-box[style="width: 4px; height: 4px;"] + span.spacing-label 1 (4px) + + .spacing-item + .spacing-box[style="width: 8px; height: 8px;"] + span.spacing-label 2 (8px) + + .spacing-item + .spacing-box[style="width: 12px; height: 12px;"] + span.spacing-label 3 (12px) + + .spacing-item + .spacing-box[style="width: 16px; height: 16px;"] + span.spacing-label 4 (16px) + + .spacing-item + .spacing-box[style="width: 24px; height: 24px;"] + span.spacing-label 6 (24px) + + .spacing-item + .spacing-box[style="width: 32px; height: 32px;"] + span.spacing-label 8 (32px) + + .spacing-item + .spacing-box[style="width: 48px; height: 48px;"] + span.spacing-label 12 (48px) + + .spacing-item + .spacing-box[style="width: 64px; height: 64px;"] + span.spacing-label 16 (64px) + + / Brand Assets - Logos + .section + h2.section-title Brand Assets - Logos + p.section-subtitle The FORGE mark. Displayed at multiple sizes across light and dark backgrounds. + + .logo-showcase + / Full size preview + .logo-card.full-size + .logo-preview.dark-bg + = image_tag 'logos/logo.png', alt: 'FORGE Logo' + .logo-info + p.logo-name Primary Logo + p.logo-file logo.png + p.logo-dimensions 500 × 500px + + / Size variations + .logo-card.size-variations + h4.variation-title Size Variations + .size-grid + .size-item + .logo-preview.dark-bg + = image_tag 'logos/logo.png', alt: 'Logo 200px', style: 'width: 200px; height: 200px;' + span.size-label 200px + .size-item + .logo-preview.dark-bg + = image_tag 'logos/logo.png', alt: 'Logo 100px', style: 'width: 100px; height: 100px;' + span.size-label 100px + .size-item + .logo-preview.dark-bg + = image_tag 'logos/logo.png', alt: 'Logo 50px', style: 'width: 50px; height: 50px;' + span.size-label 50px + + / Background variations + .logo-card.bg-variations + h4.variation-title Background Contrast + .bg-grid + .bg-item.dark-bg + = image_tag 'logos/logo.png', alt: 'Logo on dark', style: 'width: 150px; height: 150px;' + span.bg-label Dark Background + .bg-item.light-bg + = image_tag 'logos/logo.png', alt: 'Logo on light', style: 'width: 150px; height: 150px;' + span.bg-label Light Background + + / Brand Assets - Favicons + .section + h2.section-title Brand Assets - Favicons + p.section-subtitle Browser and device icons at their intended display sizes. + + .favicon-grid + .favicon-item + .favicon-preview + = image_tag 'favicons/favicon.png', alt: 'Favicon', style: 'width: 50px; height: 50px;' + .favicon-info + p.favicon-name Favicon + p.favicon-file favicon.png + p.favicon-dimensions 50 × 50px + += partial "partials/components/footer" diff --git a/source/index.html.slim b/source/index.html.slim index 2a8c14c9..b099d1dd 100644 --- a/source/index.html.slim +++ b/source/index.html.slim @@ -1,24 +1,14 @@ --- -id: index -layout: index +id: blueprint +layout: landing +title: RobotsBuildingRobots --- -section[class="row call-to-action"] - div[class="col-12 mx-auto section-wrapper"] - = partial "partials/pages/index/call-to-action" -section[class="row d-block d-md-none services-banner"] - a[name="services"] - div[class="col-12 mx-auto section-wrapper"] - = partial "partials/pages/index/services-banner" -section[class="row engagements"] - a[name="engagements"] - div[class="col-12 mx-auto section-wrapper"] - = partial "partials/pages/index/engagements" -section[class="row about"] - a[name="about"] - div[class="col-12 mx-auto section-wrapper"] - = partial "partials/pages/index/about" -section[class="row footer"] - div[class="col-12 mx-auto section-wrapper"] - div[class="row"] - = partial "partials/components/footer" +/ BLUEPRINT - Engineering Excellence += partial "partials/pages/home/hero" += partial "partials/pages/home/about" += partial "partials/pages/home/services" += partial "partials/pages/home/engagements" += partial "partials/pages/home/products" += partial "partials/pages/home/contact" += partial "partials/components/footer" diff --git a/source/layouts/404.html.slim b/source/layouts/404.html.slim new file mode 100644 index 00000000..d62b9c32 --- /dev/null +++ b/source/layouts/404.html.slim @@ -0,0 +1,19 @@ +doctype html +html[lang="en"] + head + meta[charset="utf-8"] + meta[name="viewport" content="width=device-width, initial-scale=1"] + title 404 - Page Not Found | RobotsBuildingRobots + + / FORGE Design System Fonts + link[rel="preconnect" href="https://fonts.googleapis.com"] + link[rel="preconnect" href="https://fonts.gstatic.com" crossorigin=""] + link[rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Libre+Franklin:wght@300;400;500;600;700&family=Playfair+Display:wght@400;500;600;700&display=swap"] + + / Favicon + link[rel="icon" type="image/png" href="/assets/images/favicons/favicon.png"] + + = stylesheet_link_tag(webpack_asset_path("site.scss", "site")) + + body.four-o-four-body + == yield diff --git a/source/layouts/index.html.slim b/source/layouts/index.html.slim index 8e2ce6b2..e54a7728 100644 --- a/source/layouts/index.html.slim +++ b/source/layouts/index.html.slim @@ -1,9 +1,5 @@ -= partial "partials/components/document" do - = partial "partials/components/header", locals: { include_lottie: true } - = partial "partials/components/body" do - = partial "partials/components/navigation" - - main[class="container-fluid"] - == yield - - = partial "partials/components/javascript" +doctype html +html[lang="en"] + = partial "partials/components/header" + body + == yield diff --git a/source/layouts/landing.html.slim b/source/layouts/landing.html.slim new file mode 100644 index 00000000..09acd361 --- /dev/null +++ b/source/layouts/landing.html.slim @@ -0,0 +1,16 @@ +doctype html +html[lang="en"] + = partial "partials/components/header" + body[id="#{current_page.data.id}" class="landing-page"] + / Page Loader + = partial "partials/components/loader" + + / Floating Navigation + = partial "partials/components/floating-nav" + + / Main Content + main.landing-content + == yield + + / Scripts + = partial "partials/components/javascript" diff --git a/source/partials/components/_body.html.slim b/source/partials/components/_body.html.slim index 2c757ec9..0940020f 100644 --- a/source/partials/components/_body.html.slim +++ b/source/partials/components/_body.html.slim @@ -1,3 +1,2 @@ body[id="#{current_page.data.id}"] - = partial "partials/components/pre-loader" == yield diff --git a/source/partials/components/_floating-nav.html.slim b/source/partials/components/_floating-nav.html.slim new file mode 100644 index 00000000..02f723e7 --- /dev/null +++ b/source/partials/components/_floating-nav.html.slim @@ -0,0 +1,30 @@ +.floating-nav[data-floating-nav=""] + / Navigation Dots + nav.nav-dots[aria-label="Section navigation"] + a.nav-dot[href="#hero" data-section="hero" aria-label="Go to Hero section"] + span.dot-indicator + span.dot-label Home + a.nav-dot[href="#about" data-section="about" aria-label="Go to About section"] + span.dot-indicator + span.dot-label About + a.nav-dot[href="#services" data-section="services" aria-label="Go to Principles section"] + span.dot-indicator + span.dot-label Principles + a.nav-dot[href="#engagements" data-section="engagements" aria-label="Go to Portfolio section"] + span.dot-indicator + span.dot-label Portfolio + a.nav-dot[href="#products" data-section="products" aria-label="Go to Workshop section"] + span.dot-indicator + span.dot-label Workshop + a.nav-dot[href="#contact" data-section="contact" aria-label="Go to Connect section"] + span.dot-indicator + span.dot-label Connect + + / Scroll Progress Bar + .scroll-progress + .scroll-progress-bar + +/ Back to Top Button (independent of floating-nav) +button.back-to-top[aria-label="Back to top" data-back-to-top=""] + svg[viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"] + polyline[points="18 15 12 9 6 15"] diff --git a/source/partials/components/_footer.html.slim b/source/partials/components/_footer.html.slim index aa9a2cdd..db71cbee 100644 --- a/source/partials/components/_footer.html.slim +++ b/source/partials/components/_footer.html.slim @@ -1,14 +1,8 @@ -div[class="col-12 locations"] - - data.about.locations.sort_by { |k| k["id"] }.each_with_index do |l, index| - span - = l.location - span[class="divider"] - - if index < data.about.locations.count - 1 - |❙ - -div[class="col-12 company"] - |© - => - = data.about.copyright - => - = data.components.social.formalname +/ Footer Section +footer.site-footer + .footer-accent-line + .blueprint-grid + .footer-container + span.footer-marker © 2016 - Present + span.footer-divider / + span.footer-name RobotsBuildingRobots, LLC diff --git a/source/partials/components/_header.html.slim b/source/partials/components/_header.html.slim index 18590a11..b40f889e 100644 --- a/source/partials/components/_header.html.slim +++ b/source/partials/components/_header.html.slim @@ -1,16 +1,18 @@ head - | + meta[charset="utf-8"] + meta[name="viewport" content="width=device-width, initial-scale=1"] + = partial "partials/components/title" - javascript: - window.dataLayer = window.dataLayer || []; - function gtag(){dataLayer.push(arguments);} - gtag('js', new Date()); - gtag('config', 'G-YMVZTN6RSB'); + / FORGE Design System Fonts + / - Playfair Display: Hero headlines, editorial gravitas + / - Inter: Section headers, maximum readability + / - Libre Franklin: Body text, clean professionalism + / - JetBrains Mono: Code, technical credibility + link[rel="preconnect" href="https://fonts.googleapis.com"] + link[rel="preconnect" href="https://fonts.gstatic.com" crossorigin=""] + link[rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Libre+Franklin:wght@300;400;500;600;700&family=Playfair+Display:wght@400;500;600;700&display=swap"] - = partial "partials/components/meta" - = partial "partials/components/favicons" - = partial "partials/components/title" - = stylesheet_link_tag(webpack_asset_path("site.scss", "site")) + / Favicon + link[rel="icon" type="image/png" href="/assets/images/favicons/favicon.png"] - - if locals[:include_lottie].present? - | + = stylesheet_link_tag(webpack_asset_path("site.scss", "site")) diff --git a/source/partials/components/_loader.html.slim b/source/partials/components/_loader.html.slim new file mode 100644 index 00000000..0327a3b8 --- /dev/null +++ b/source/partials/components/_loader.html.slim @@ -0,0 +1,9 @@ +.page-loader[data-loader=""] + .loader-content + .loader-logo + = image_tag 'logos/logo.png', alt: 'RBR Logo', class: 'loader-logo-img' + .loader-text + span.loader-text-content Reticulating Splines + span.loader-cursor | + .loader-progress + .loader-progress-bar diff --git a/source/partials/components/_navigation.html.slim b/source/partials/components/_navigation.html.slim index 552e5c3e..d7967895 100644 --- a/source/partials/components/_navigation.html.slim +++ b/source/partials/components/_navigation.html.slim @@ -4,9 +4,9 @@ nav[class="navbar navbar-expand-sm sticky-top navbar-dark"] div[class="row"] div[class="col-10 col-sm-12 d-flex my-auto"] = link_to("/", class: "logo-link-logo") do - embed[id="company-logo" src="#{image_path('logos/yellow.svg')}"] + = image_tag 'logos/logo.png', id: 'company-logo', alt: 'RobotsBuildingRobots Logo' = link_to("/", class: "logo-link-text") do - = data.components.social.shortname + | RobotsBuildingRobots div[class="col-2 my-auto d-md-none navbar-button"] button[class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarCollapse" @@ -38,9 +38,3 @@ nav[class="navbar navbar-expand-sm sticky-top navbar-dark"] i[class="fas fa-brain nav-icon"] span[class="nav-description"] |About - li[class="nav-item flex-fill"] - = link_to("/", id: "contact", class: "nav-link", data: { reference: "page", redirection: true }) do - span[class="nav-button"] - i[class="far fa-envelope nav-icon"] - span[class="nav-description d-lg-none"] - |Contact diff --git a/source/partials/components/_title.html.slim b/source/partials/components/_title.html.slim index 01223067..dd44662c 100644 --- a/source/partials/components/_title.html.slim +++ b/source/partials/components/_title.html.slim @@ -1,5 +1,5 @@ title - if current_page.data.title - = "#{data.components.social.formalname} | #{data.components.social.focus} | #{current_page.data.title}" + = "RobotsBuildingRobots, LLC | How can we help you? | #{current_page.data.title}" - else - = "#{data.components.social.formalname} | #{data.components.social.focus}" + = "RobotsBuildingRobots, LLC | How can we help you?" diff --git a/source/partials/pages/home/_about.html.slim b/source/partials/pages/home/_about.html.slim new file mode 100644 index 00000000..36fed58a --- /dev/null +++ b/source/partials/pages/home/_about.html.slim @@ -0,0 +1,163 @@ +/ About Section - Blueprint Layout +section#about.about-section + .section-container + .about-wrapper + .about-content.scroll-animate + .blueprint-label + span.label-marker + span About + + h2.about-title Company Profile + + blockquote.about-quote + .quote-mark + svg[viewBox="0 0 24 24" fill="currentColor"] + path[d="M4.583 17.321C3.553 16.227 3 15 3 13.011c0-3.5 2.457-6.637 6.03-8.188l.893 1.378c-3.335 1.804-3.987 4.145-4.247 5.621.537-.278 1.24-.375 1.929-.311 1.804.167 3.226 1.648 3.226 3.489a3.5 3.5 0 01-3.5 3.5c-1.073 0-2.099-.49-2.748-1.179zm10 0C13.553 16.227 13 15 13 13.011c0-3.5 2.457-6.637 6.03-8.188l.893 1.378c-3.335 1.804-3.987 4.145-4.247 5.621.537-.278 1.24-.375 1.929-.311 1.804.167 3.226 1.648 3.226 3.489a3.5 3.5 0 01-3.5 3.5c-1.073 0-2.099-.49-2.748-1.179z"] + p = data.about.cta + + p.about-description = data.about.description + + .about-locations + span.locations-label Locations + .locations-list + - data.about.locations.each_with_index do |loc, index| + .location-item + span.location-marker[data-index="#{index + 1}"] + span.location-name = loc.location + + .about-footer + .footer-item + span.label Company + span.value = data.components.social.formalname + .footer-item + span.label Established + span.value = data.about.copyright + + .about-visual.scroll-animate.delay-2 + .blueprint-schematic + .schematic-frame + svg.robot-arm-schematic[viewBox="0 0 300 300" fill="none"] + defs + linearGradient#arm-gradient[x1="0%" y1="0%" x2="100%" y2="0%"] + stop[offset="0%" stop-color="currentColor" stop-opacity="0.2"] + stop[offset="50%" stop-color="currentColor" stop-opacity="0.4"] + stop[offset="100%" stop-color="currentColor" stop-opacity="0.2"] + filter#ember-glow[x="-50%" y="-50%" width="200%" height="200%"] + feGaussianBlur[stdDeviation="3" result="blur"] + feMerge + feMergeNode[in="blur"] + feMergeNode[in="SourceGraphic"] + + / Background grid + g.grid-layer[opacity="0.06"] + - (1..5).each do |i| + line[x1="#{i * 50}" y1="0" x2="#{i * 50}" y2="300" stroke="currentColor" stroke-width="0.5"] + line[x1="0" y1="#{i * 50}" x2="300" y2="#{i * 50}" stroke="currentColor" stroke-width="0.5"] + + / Motion arc indicator (animated ember sweep) + g.motion-arcs + path.arc-range[d="M 100 245 A 50 50 0 0 1 200 245" stroke="currentColor" stroke-width="0.5" stroke-dasharray="3 2" fill="none" opacity="0.2"] + path.arc-indicator[d="M 110 245 A 40 40 0 0 1 190 245" stroke-width="2" fill="none"] + + / Ghost positions (motion trail) + g.ghost-positions[opacity="0.08"] + line[x1="150" y1="200" x2="120" y2="130" stroke="currentColor" stroke-width="2"] + line[x1="120" y1="130" x2="170" y2="75" stroke="currentColor" stroke-width="2"] + + / === MAIN ROBOT ARM === + g.robot-arm-main + + / Base mount plate + g.arm-base + rect[x="110" y="260" width="80" height="15" stroke="currentColor" stroke-width="1.5" fill="none" rx="2"] + circle[cx="125" cy="267" r="3" stroke="currentColor" stroke-width="0.75" fill="none"] + circle[cx="175" cy="267" r="3" stroke="currentColor" stroke-width="0.75" fill="none"] + / Base column + rect[x="130" y="220" width="40" height="40" stroke="currentColor" stroke-width="2" fill="url(#arm-gradient)" rx="4"] + / Servo housing + rect[x="125" y="205" width="50" height="20" stroke="currentColor" stroke-width="1.5" fill="none" rx="3"] + + / Joint 1 - Base rotation + g.joint-j1 + circle.joint-outer[cx="150" cy="195" r="16" stroke="currentColor" stroke-width="2" fill="none"] + circle.joint-inner[cx="150" cy="195" r="10" stroke="currentColor" stroke-width="1" fill="none" opacity="0.5"] + circle.joint-center[cx="150" cy="195" r="4" fill="currentColor"] + circle.status-led.led-1[cx="165" cy="182" r="3"] + + / Lower arm segment + g.arm-lower + path[d="M 142 188 L 92 125 L 88 118 L 95 112 L 158 182 Z" stroke="currentColor" stroke-width="1.5" fill="url(#arm-gradient)"] + line[x1="145" y1="185" x2="95" y2="122" stroke="currentColor" stroke-width="0.5" opacity="0.3"] + + / Joint 2 - Shoulder + g.joint-j2 + rect[x="72" y="100" width="30" height="22" stroke="currentColor" stroke-width="1.5" fill="none" rx="3" transform="rotate(-40, 87, 111)"] + circle.joint-outer[cx="90" cy="118" r="14" stroke="currentColor" stroke-width="2" fill="none"] + circle.joint-inner[cx="90" cy="118" r="8" stroke="currentColor" stroke-width="1" fill="none" opacity="0.5"] + circle.joint-center[cx="90" cy="118" r="4" fill="currentColor"] + circle.status-led.led-2[cx="75" cy="105" r="3"] + + / Upper arm segment + g.arm-upper + path[d="M 95 110 L 162 58 L 170 62 L 168 72 L 102 118 Z" stroke="currentColor" stroke-width="1.5" fill="url(#arm-gradient)"] + line[x1="98" y1="114" x2="165" y2="62" stroke="currentColor" stroke-width="0.5" opacity="0.3"] + + / Joint 3 - Elbow + g.joint-j3 + circle.joint-outer[cx="168" cy="55" r="12" stroke="currentColor" stroke-width="2" fill="none"] + circle.joint-inner[cx="168" cy="55" r="6" stroke="currentColor" stroke-width="1" fill="none" opacity="0.5"] + circle.joint-center[cx="168" cy="55" r="3" fill="currentColor"] + circle.status-led.led-3[cx="180" cy="45" r="3"] + + / Wrist + g.wrist + rect[x="175" y="42" width="22" height="14" stroke="currentColor" stroke-width="1.5" fill="none" rx="2" transform="rotate(20, 186, 49)"] + circle.joint-j4[cx="192" cy="42" r="7" stroke="currentColor" stroke-width="1" fill="none"] + circle[cx="192" cy="42" r="2.5" fill="currentColor"] + + / End effector - Gripper + g.end-effector + rect.gripper-mount[x="198" y="32" width="14" height="10" stroke="currentColor" stroke-width="1" fill="none" rx="1" transform="rotate(10, 205, 37)"] + / Gripper finger 1 + g.gripper-finger-1 + path[d="M 210 30 L 235 18 L 240 24 L 218 34 Z" stroke="currentColor" stroke-width="1" fill="none"] + line[x1="235" y1="18" x2="250" y2="28" stroke="currentColor" stroke-width="1.5"] + / Gripper finger 2 + g.gripper-finger-2 + path[d="M 210 44 L 238 48 L 240 56 L 214 50 Z" stroke="currentColor" stroke-width="1" fill="none"] + line[x1="238" y1="48" x2="252" y2="50" stroke="currentColor" stroke-width="1.5"] + / Grip target + circle.grip-point[cx="245" cy="38" r="4" stroke-dasharray="2 2"] + + / Dimension lines + g.dimensions[opacity="0.3"] + line[x1="50" y1="40" x2="50" y2="260" stroke="currentColor" stroke-width="0.5" stroke-dasharray="4 2"] + line[x1="45" y1="40" x2="55" y2="40" stroke="currentColor" stroke-width="0.75"] + line[x1="45" y1="260" x2="55" y2="260" stroke="currentColor" stroke-width="0.75"] + line[x1="110" y1="285" x2="250" y2="285" stroke="currentColor" stroke-width="0.5" stroke-dasharray="4 2"] + line[x1="110" y1="280" x2="110" y2="290" stroke="currentColor" stroke-width="0.75"] + line[x1="250" y1="280" x2="250" y2="290" stroke="currentColor" stroke-width="0.75"] + + / Technical labels + g.tech-labels[font-size="8" fill="currentColor" opacity="0.5"] + text[x="160" y="200"] J1 + text[x="72" y="135"] J2 + text[x="178" y="68"] J3 + text[x="200" y="38"] J4 + + / Data readout + g.data-readout[opacity="0.4"] + rect[x="8" y="8" width="70" height="50" stroke="currentColor" stroke-width="0.5" fill="none"] + g[font-size="7" fill="currentColor"] + text[x="12" y="20"] STATUS: + text.status-val[x="48" y="20"] READY + text[x="12" y="32"] POS: + text.pos-val[x="32" y="32"] +045.2 + text[x="12" y="44"] CYCLE: + text.cycle-val[x="40" y="44"] 1,247 + text[x="235" y="18" font-size="6" opacity="0.3"] RBR-01 + text[x="235" y="26" font-size="5" opacity="0.3"] REV.5 + + .schematic-labels + .label-item.label-top Founded 2016 + .label-item.label-bottom Remote-First diff --git a/source/partials/pages/home/_contact.html.slim b/source/partials/pages/home/_contact.html.slim new file mode 100644 index 00000000..52545ee3 --- /dev/null +++ b/source/partials/pages/home/_contact.html.slim @@ -0,0 +1,160 @@ +/ Contact Section - Terminal Connection +section#contact.contact-section + .blueprint-grid + + .contact-container + / Left: Content + .contact-content.scroll-animate + .terminal-marker + span.marker-icon ▸ + span.marker-text OPEN CHANNEL + + h2.contact-title + span.title-line Let's Build + span.title-accent Something + + p.contact-description The best partnerships start with a conversation. Whether you're scaling a team, architecting a new system, or exploring AI integration. + + .contact-cta + a.btn-terminal[href=data.components.social.linkedin target="_blank" rel="noopener noreferrer"] + span.btn-glow + svg.btn-icon[viewBox="0 0 24 24" fill="currentColor"] + path[d="M20.5 2h-17A1.5 1.5 0 002 3.5v17A1.5 1.5 0 003.5 22h17a1.5 1.5 0 001.5-1.5v-17A1.5 1.5 0 0020.5 2zM8 19H5v-9h3zM6.5 8.25A1.75 1.75 0 118.3 6.5a1.78 1.78 0 01-1.8 1.75zM19 19h-3v-4.74c0-1.42-.6-1.93-1.38-1.93A1.74 1.74 0 0013 14.19a.66.66 0 000 .14V19h-3v-9h2.9v1.3a3.11 3.11 0 012.7-1.4c1.55 0 3.36.86 3.36 3.66z"] + span Let's Connect + p.cta-subtext Why LinkedIn? Zero spam. Professional context. Real conversations. + + / Right: Enhanced Communication Beacon + .contact-visual.scroll-animate.delay-1 + .visual-frame + .frame-corner.top-left + .frame-corner.top-right + .frame-corner.bottom-left + .frame-corner.bottom-right + .coordinate-marker.coord-x + span X: 2016 + .coordinate-marker.coord-y + span Y: NOW + .visual-content + svg.comm-beacon-schematic[viewBox="0 0 300 300" fill="none"] + defs + filter#beacon-glow[x="-50%" y="-50%" width="200%" height="200%"] + feGaussianBlur[stdDeviation="3" result="blur"] + feMerge + feMergeNode[in="blur"] + feMergeNode[in="SourceGraphic"] + linearGradient#beacon-gradient[x1="0%" y1="0%" x2="100%" y2="100%"] + stop[offset="0%" stop-color="currentColor" stop-opacity="0.1"] + stop[offset="50%" stop-color="currentColor" stop-opacity="0.25"] + stop[offset="100%" stop-color="currentColor" stop-opacity="0.1"] + + / Background grid with radial circles + g.grid-layer[opacity="0.06"] + - (1..5).each do |i| + line[x1="#{i * 50}" y1="0" x2="#{i * 50}" y2="300" stroke="currentColor" stroke-width="0.5"] + line[x1="0" y1="#{i * 50}" x2="300" y2="#{i * 50}" stroke="currentColor" stroke-width="0.5"] + circle[cx="150" cy="150" r="40" stroke="currentColor" stroke-width="0.5" fill="none"] + circle[cx="150" cy="150" r="80" stroke="currentColor" stroke-width="0.5" fill="none"] + + / Signal waves (expanding outward) + g.signal-waves + circle.wave.wave-1[cx="150" cy="150" r="50" stroke-width="1.5" fill="none"] + circle.wave.wave-2[cx="150" cy="150" r="75" stroke-width="1.5" fill="none"] + circle.wave.wave-3[cx="150" cy="150" r="100" stroke-width="1.5" fill="none"] + circle.wave.wave-4[cx="150" cy="150" r="125" stroke-width="1" fill="none"] + + / Data packets (traveling outward) + g.data-packets + circle.packet.packet-n[cx="150" cy="150" r="4"] + circle.packet.packet-e[cx="150" cy="150" r="4"] + circle.packet.packet-s[cx="150" cy="150" r="4"] + circle.packet.packet-w[cx="150" cy="150" r="4"] + circle.packet.packet-ne[cx="150" cy="150" r="3"] + circle.packet.packet-sw[cx="150" cy="150" r="3"] + + / Main beacon structure + g.beacon-main + / Central transmission core + g.transmission-core + circle.core-housing[cx="150" cy="150" r="28" stroke="currentColor" stroke-width="2" fill="url(#beacon-gradient)"] + circle.core-chamber[cx="150" cy="150" r="18" stroke="currentColor" stroke-width="1.5" fill="none"] + line[x1="150" y1="122" x2="150" y2="132" stroke="currentColor" stroke-width="1"] + line[x1="150" y1="168" x2="150" y2="178" stroke="currentColor" stroke-width="1"] + line[x1="122" y1="150" x2="132" y2="150" stroke="currentColor" stroke-width="1"] + line[x1="168" y1="150" x2="178" y2="150" stroke="currentColor" stroke-width="1"] + circle.core-active[cx="150" cy="150" r="10" fill="none" stroke="currentColor" stroke-width="2"] + circle.core-pulse[cx="150" cy="150" r="5"] + + / Primary antenna (top) + g.antenna-primary + rect[x="146" y="70" width="8" height="52" stroke="currentColor" stroke-width="1.5" fill="url(#beacon-gradient)" rx="2"] + ellipse.antenna-dish[cx="150" cy="55" rx="35" ry="12" stroke="currentColor" stroke-width="1.5" fill="none"] + ellipse[cx="150" cy="55" rx="22" ry="8" stroke="currentColor" stroke-width="1" fill="none" opacity="0.5"] + rect[x="145" y="42" width="10" height="18" stroke="currentColor" stroke-width="1" fill="none" rx="1"] + circle.focus-point[cx="150" cy="35" r="4"] + line[x1="120" y1="67" x2="146" y2="95" stroke="currentColor" stroke-width="1" opacity="0.6"] + line[x1="180" y1="67" x2="154" y2="95" stroke="currentColor" stroke-width="1" opacity="0.6"] + + / Secondary antenna (right) + g.antenna-secondary + rect[x="200" y="145" width="40" height="6" stroke="currentColor" stroke-width="1" fill="url(#beacon-gradient)" rx="1"] + ellipse[cx="248" cy="148" rx="18" ry="6" stroke="currentColor" stroke-width="1" fill="none"] + circle[cx="248" cy="148" r="3" stroke="currentColor" stroke-width="0.75" fill="none"] + + / Tertiary antenna (left) + g.antenna-tertiary + rect[x="60" y="145" width="40" height="6" stroke="currentColor" stroke-width="1" fill="url(#beacon-gradient)" rx="1"] + ellipse[cx="52" cy="148" rx="18" ry="6" stroke="currentColor" stroke-width="1" fill="none"] + circle[cx="52" cy="148" r="3" stroke="currentColor" stroke-width="0.75" fill="none"] + + / Base platform + g.platform-base + rect[x="110" y="200" width="80" height="12" stroke="currentColor" stroke-width="1.5" fill="url(#beacon-gradient)" rx="2"] + rect[x="135" y="178" width="30" height="22" stroke="currentColor" stroke-width="1.5" fill="none" rx="2"] + rect[x="100" y="212" width="100" height="8" stroke="currentColor" stroke-width="1" fill="none" rx="1"] + circle[cx="115" cy="216" r="3" stroke="currentColor" stroke-width="0.75" fill="none"] + circle[cx="150" cy="216" r="3" stroke="currentColor" stroke-width="0.75" fill="none"] + circle[cx="185" cy="216" r="3" stroke="currentColor" stroke-width="0.75" fill="none"] + + / Status LEDs + g.status-panel + circle.status-led.led-tx[cx="125" cy="192" r="3"] + circle.status-led.led-rx[cx="140" cy="192" r="3"] + circle.status-led.led-link[cx="155" cy="192" r="3"] + circle.status-led.led-pwr[cx="170" cy="192" r="3"] + g[font-size="5" fill="currentColor" opacity="0.4"] + text[x="122" y="186"] TX + text[x="137" y="186"] RX + text[x="150" y="186"] LNK + text[x="166" y="186"] PWR + + / Scanning beam + g.scan-beam + path.beam-sweep[d="M 150 150 L 250 80 L 255 95 Z" fill="currentColor" opacity="0.15"] + + / Technical labels + g.tech-labels[font-size="7" fill="currentColor" opacity="0.4"] + text[x="158" y="158"] CORE + text[x="155" y="40"] FEED + text[x="30" y="152"] SEC-A + text[x="255" y="152"] SEC-B + + / Data readout + g.data-readout[opacity="0.5"] + rect[x="8" y="8" width="80" height="60" stroke="currentColor" stroke-width="0.5" fill="none"] + g[font-size="7" fill="currentColor"] + text[x="12" y="20"] FREQ: + text.freq-val[x="40" y="20"] 2.4GHz + text[x="12" y="32"] SIGNAL: + text.signal-val[x="48" y="32"] -42dBm + text[x="12" y="44"] LINK: + text.link-val[x="36" y="44"] ACTIVE + text[x="12" y="56"] UPTIME: + text.uptime-val[x="48" y="56"] 99.9% + text[x="220" y="290" font-size="6" opacity="0.3"] RBR-COMM + text[x="220" y="298" font-size="5" opacity="0.3"] v2.0 + + / Dimension lines + g.dimensions[opacity="0.25"] + line[x1="270" y1="35" x2="270" y2="220" stroke="currentColor" stroke-width="0.5" stroke-dasharray="3 2"] + line[x1="265" y1="35" x2="275" y2="35" stroke="currentColor" stroke-width="0.75"] + line[x1="265" y1="220" x2="275" y2="220" stroke="currentColor" stroke-width="0.75"] diff --git a/source/partials/pages/home/_engagements.html.slim b/source/partials/pages/home/_engagements.html.slim new file mode 100644 index 00000000..d417baf0 --- /dev/null +++ b/source/partials/pages/home/_engagements.html.slim @@ -0,0 +1,28 @@ +/ Engagements Section - Blueprint Timeline +section#engagements.engagements-section + .section-container + .section-header.scroll-animate + .blueprint-label + span.label-marker + span Portfolio + h2.section-title Project Archive + p.section-subtitle = data.engagements.process + + .engagements-timeline + .timeline-track + .timeline-line + + .timeline-items + - data.engagements.projects.each_with_index do |project, index| + .timeline-item.scroll-animate[class="delay-#{(index % 4) + 1}" class="#{index.even? ? 'item-left' : 'item-right'}"] + .timeline-marker + .marker-dot + .marker-line + + .timeline-card + .card-header + span.project-index #{'%02d' % (index + 1)} + h3.project-name = project.company + p.project-description = project.collaboration + .card-footer + span.status-badge[class="#{project.status == 'on-going' ? 'status-badge--ongoing' : ''}"] = project.status || 'Completed' diff --git a/source/partials/pages/home/_hero.html.slim b/source/partials/pages/home/_hero.html.slim new file mode 100644 index 00000000..559d2853 --- /dev/null +++ b/source/partials/pages/home/_hero.html.slim @@ -0,0 +1,45 @@ +/ Hero Section - Blueprint/Architect +section#hero.hero-section + / Blueprint Grid Background + .blueprint-grid + + .hero-container + .hero-content-wrapper + / Dimension annotation + .blueprint-annotation.annotation-top + span.annotation-line + span.annotation-text SPEC: RBR-2016 + + .hero-content.scroll-animate + .blueprint-badge + span.badge-text Engineering Excellence + + h1.hero-title + span.title-main Robots Building + span.title-accent Robots + + p.hero-subtitle Strategic software engineering and AI-driven solutions. We architect systems that scale, perform, and deliver measurable results. + + .hero-cta + a.btn-blueprint-primary[href="#contact"] + span Connect With Us + a.btn-blueprint-secondary[href="#engagements"] + span View Projects + + / Logo with dimension markers + .hero-visual.scroll-animate.delay-1 + .blueprint-frame + .frame-corner.top-left + .frame-corner.top-right + .frame-corner.bottom-left + .frame-corner.bottom-right + .dimension-marker.horizontal + span 500px + .dimension-marker.vertical + span 500px + = image_tag 'logos/logo.png', alt: 'RBR Logo', class: 'blueprint-logo' + + / Dimension annotation + .blueprint-annotation.annotation-bottom + span.annotation-line + span.annotation-text REV: 5.0 diff --git a/source/partials/pages/home/_products.html.slim b/source/partials/pages/home/_products.html.slim new file mode 100644 index 00000000..697c7667 --- /dev/null +++ b/source/partials/pages/home/_products.html.slim @@ -0,0 +1,156 @@ +/ Products Section - The Workshop +section#products.products-section + .blueprint-grid + + .section-container + .products-wrapper + / Left: Stacked Category Tiles + .products-content.scroll-animate + .workshop-marker + span.marker-icon ▸ + span.marker-text THE WORKSHOP + + h2.section-title = data.products.headline + p.section-subtitle = data.products.description + + .category-stack + - data.products.categories.each_with_index do |category, index| + .category-tile + .tile-index + span = "%02d" % (index + 1) + .tile-icon + - case category.icon + - when 'cloud' + svg[viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"] + path[d="M2.25 15a4.5 4.5 0 004.5 4.5H18a3.75 3.75 0 001.332-7.257 3 3 0 00-3.758-3.848 5.25 5.25 0 00-10.233 2.33A4.502 4.502 0 002.25 15z"] + - when 'cart' + svg[viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"] + path[d="M2.25 3h1.386c.51 0 .955.343 1.087.835l.383 1.437M7.5 14.25a3 3 0 00-3 3h15.75m-12.75-3h11.218c1.121-2.3 2.1-4.684 2.924-7.138a60.114 60.114 0 00-16.536-1.84M7.5 14.25L5.106 5.272M6 20.25a.75.75 0 11-1.5 0 .75.75 0 011.5 0zm12.75 0a.75.75 0 11-1.5 0 .75.75 0 011.5 0z"] + - when 'code' + svg[viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"] + path[d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5"] + .tile-content + h4.tile-title = category.name + p.tile-description = category.description + .tile-indicator + span.status-dot + + / Right: Forge Assembly Schematic + .products-visual.scroll-animate.delay-1 + .visual-frame + .frame-corner.top-left + .frame-corner.top-right + .frame-corner.bottom-left + .frame-corner.bottom-right + .coordinate-marker.coord-x + span TEMP: 2400K + .coordinate-marker.coord-y + span YIELD: 98.7% + .visual-content + svg.forge-assembly-schematic[viewBox="0 0 300 300" fill="none"] + defs + linearGradient#forge-gradient[x1="0%" y1="0%" x2="100%" y2="100%"] + stop[offset="0%" stop-color="currentColor" stop-opacity="0.1"] + stop[offset="50%" stop-color="currentColor" stop-opacity="0.25"] + stop[offset="100%" stop-color="currentColor" stop-opacity="0.1"] + filter#forge-glow[x="-50%" y="-50%" width="200%" height="200%"] + feGaussianBlur[stdDeviation="3" result="blur"] + feMerge + feMergeNode[in="blur"] + feMergeNode[in="SourceGraphic"] + + / Background grid + g.grid-layer[opacity="0.06"] + - (1..5).each do |i| + line[x1="#{i * 50}" y1="0" x2="#{i * 50}" y2="300" stroke="currentColor" stroke-width="0.5"] + line[x1="0" y1="#{i * 50}" x2="300" y2="#{i * 50}" stroke="currentColor" stroke-width="0.5"] + + / === FORGE FURNACE === + g.forge-furnace + rect.furnace-body[x="90" y="60" width="120" height="140" stroke="currentColor" stroke-width="2" fill="url(#forge-gradient)" rx="4"] + rect.furnace-window[x="110" y="80" width="80" height="60" stroke="currentColor" stroke-width="1.5" fill="none" rx="2"] + g.fire-chamber + rect[x="115" y="85" width="70" height="50" fill="rgba(220, 107, 74, 0.15)"] + path.flame.flame-1[d="M 130 135 Q 135 115 130 100 Q 140 110 145 100 Q 145 120 140 135 Z"] + path.flame.flame-2[d="M 150 135 Q 155 110 150 95 Q 160 105 165 95 Q 165 115 160 135 Z"] + path.flame.flame-3[d="M 170 135 Q 175 118 170 105 Q 180 112 182 105 Q 180 122 175 135 Z"] + g.exhaust-vents + rect[x="105" y="50" width="15" height="15" stroke="currentColor" stroke-width="1" fill="none"] + rect[x="142" y="50" width="15" height="15" stroke="currentColor" stroke-width="1" fill="none"] + rect[x="180" y="50" width="15" height="15" stroke="currentColor" stroke-width="1" fill="none"] + path.heat-shimmer.shimmer-1[d="M 112 45 Q 115 35 112 25" stroke="currentColor" stroke-width="0.75" fill="none"] + path.heat-shimmer.shimmer-2[d="M 150 45 Q 153 32 150 20" stroke="currentColor" stroke-width="0.75" fill="none"] + path.heat-shimmer.shimmer-3[d="M 187 45 Q 190 35 187 25" stroke="currentColor" stroke-width="0.75" fill="none"] + + / === CONTROL PANEL === + g.control-panel + rect[x="40" y="90" width="40" height="80" stroke="currentColor" stroke-width="1.5" fill="url(#forge-gradient)" rx="2"] + circle.temp-gauge[cx="60" cy="115" r="15" stroke="currentColor" stroke-width="1" fill="none"] + line.temp-needle[x1="60" y1="115" x2="60" y2="103" stroke="currentColor" stroke-width="1.5"] + circle[cx="60" cy="115" r="3" fill="currentColor"] + circle.status-led.led-heat[cx="50" cy="145" r="3"] + circle.status-led.led-ready[cx="60" cy="145" r="3"] + circle.status-led.led-cycle[cx="70" cy="145" r="3"] + rect[x="55" y="155" width="10" height="10" stroke="currentColor" stroke-width="1" fill="none"] + line.control-lever[x1="60" y1="160" x2="60" y2="168" stroke="currentColor" stroke-width="2"] + + / === ANVIL ASSEMBLY === + g.anvil-assembly + rect[x="100" y="230" width="100" height="12" stroke="currentColor" stroke-width="1.5" fill="url(#forge-gradient)" rx="2"] + path.anvil-body[d="M 120 230 L 125 215 L 175 215 L 180 230 Z" stroke="currentColor" stroke-width="2" fill="url(#forge-gradient)"] + rect[x="130" y="205" width="40" height="12" stroke="currentColor" stroke-width="1.5" fill="none"] + path.anvil-horn[d="M 120 217 L 100 220 L 100 225 L 125 222 Z" stroke="currentColor" stroke-width="1" fill="none"] + g.hammer-arm + rect[x="145" y="160" width="10" height="35" stroke="currentColor" stroke-width="1.5" fill="url(#forge-gradient)" rx="1"] + rect.hammer-head[x="138" y="195" width="24" height="12" stroke="currentColor" stroke-width="2" fill="none" rx="1"] + circle.pivot-point[cx="150" cy="165" r="5" stroke="currentColor" stroke-width="1" fill="none"] + g.sparks-zone + circle.spark.spark-1[cx="150" cy="207" r="2"] + circle.spark.spark-2[cx="145" cy="205" r="1.5"] + circle.spark.spark-3[cx="155" cy="203" r="1.5"] + circle.spark.spark-4[cx="142" cy="208" r="1"] + circle.spark.spark-5[cx="158" cy="206" r="1"] + + / === OUTPUT CONVEYOR === + g.output-system + rect.conveyor-belt[x="220" y="215" width="60" height="8" stroke="currentColor" stroke-width="1" fill="none" rx="4"] + line[x1="230" y1="215" x2="230" y2="223" stroke="currentColor" stroke-width="0.5" opacity="0.5"] + line[x1="245" y1="215" x2="245" y2="223" stroke="currentColor" stroke-width="0.5" opacity="0.5"] + line[x1="260" y1="215" x2="260" y2="223" stroke="currentColor" stroke-width="0.5" opacity="0.5"] + rect.product-item.item-1[x="225" y="208" width="10" height="7" stroke="currentColor" stroke-width="0.75" fill="none"] + rect.product-item.item-2[x="250" y="208" width="10" height="7" stroke="currentColor" stroke-width="0.75" fill="none"] + rect[x="265" y="195" width="15" height="25" stroke="currentColor" stroke-width="1" fill="none"] + line.scan-beam[x1="270" y1="200" x2="270" y2="215" stroke="currentColor" stroke-width="0.5"] + circle.scan-indicator[cx="272" cy="202" r="2"] + + / Dimension lines + g.dimensions[opacity="0.25"] + line[x1="30" y1="60" x2="30" y2="200" stroke="currentColor" stroke-width="0.5" stroke-dasharray="3 2"] + line[x1="25" y1="60" x2="35" y2="60" stroke="currentColor" stroke-width="0.75"] + line[x1="25" y1="200" x2="35" y2="200" stroke="currentColor" stroke-width="0.75"] + line[x1="90" y1="260" x2="210" y2="260" stroke="currentColor" stroke-width="0.5" stroke-dasharray="3 2"] + line[x1="90" y1="255" x2="90" y2="265" stroke="currentColor" stroke-width="0.75"] + line[x1="210" y1="255" x2="210" y2="265" stroke="currentColor" stroke-width="0.75"] + + / Technical labels + g.tech-labels[font-size="7" fill="currentColor" opacity="0.4"] + text[x="130" y="150"] FURNACE + text[x="42" y="85"] CTRL + text[x="128" y="250"] ANVIL + text[x="230" y="235"] OUTPUT + text[x="265" y="190"] QC + + / Data readout + g.data-readout[opacity="0.5"] + rect[x="8" y="8" width="75" height="55" stroke="currentColor" stroke-width="0.5" fill="none"] + g[font-size="7" fill="currentColor"] + text[x="12" y="20"] TEMP: + text.temp-val[x="40" y="20"] 2400K + text[x="12" y="32"] CYCLE: + text.cycle-val[x="42" y="32"] 1,847 + text[x="12" y="44"] YIELD: + text.yield-val[x="40" y="44"] 98.7% + text[x="12" y="55"] STATUS: + text.status-val[x="48" y="55"] FORGE + text[x="220" y="290" font-size="6" opacity="0.3"] RBR-FORGE + text[x="220" y="298" font-size="5" opacity="0.3"] v1.0 diff --git a/source/partials/pages/home/_services.html.slim b/source/partials/pages/home/_services.html.slim new file mode 100644 index 00000000..fe33873e --- /dev/null +++ b/source/partials/pages/home/_services.html.slim @@ -0,0 +1,66 @@ +/ Services Section - Blueprint Cards +section#services.services-section + .section-container + .section-header.scroll-animate + .blueprint-label + span.label-marker + span How We Work + h2.section-title Engineering Principles + p.section-subtitle Five pillars that define our approach to building software + + .services-grid + / Obsession Card + .blueprint-card.scroll-animate.delay-1 + .card-number 01 + .card-header + .card-icon + svg[viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"] + path[d="M9.813 15.904L9 18.75l-.813-2.846a4.5 4.5 0 00-3.09-3.09L2.25 12l2.846-.813a4.5 4.5 0 003.09-3.09L9 5.25l.813 2.846a4.5 4.5 0 003.09 3.09L15.75 12l-2.846.813a4.5 4.5 0 00-3.09 3.09z"] + h3.card-title Obsession + p.card-description = data.services.obsession + .card-corner + + / Discipline Card + .blueprint-card.scroll-animate.delay-2 + .card-number 02 + .card-header + .card-icon + svg[viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"] + path[d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 011.37.49l1.296 2.247a1.125 1.125 0 01-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 010 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 01-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 01-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 01-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 01-1.369-.49l-1.297-2.247a1.125 1.125 0 01.26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 010-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 01-.26-1.43l1.297-2.247a1.125 1.125 0 011.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281z"] + circle[cx="12" cy="12" r="3"] + h3.card-title Discipline + p.card-description = data.services.discipline + .card-corner + + / Innovation Card + .blueprint-card.scroll-animate.delay-3 + .card-number 03 + .card-header + .card-icon + svg[viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"] + path[d="M17.25 6.75L22.5 12l-5.25 5.25m-10.5 0L1.5 12l5.25-5.25m7.5-3l-4.5 16.5"] + h3.card-title Innovation + p.card-description = data.services.innovation + .card-corner + + / Results Card + .blueprint-card.scroll-animate.delay-4 + .card-number 04 + .card-header + .card-icon + svg[viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"] + path[d="M2.25 18L9 11.25l4.306 4.307a11.95 11.95 0 015.814-5.519l2.74-1.22m0 0l-5.94-2.28m5.94 2.28l-2.28 5.941"] + h3.card-title Results + p.card-description = data.services.results + .card-corner + + / Evidence Card + .blueprint-card.scroll-animate.delay-5 + .card-number 05 + .card-header + .card-icon + svg[viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"] + path[d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 013 19.875v-6.75zM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V8.625zM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 01-1.125-1.125V4.125z"] + h3.card-title Evidence + p.card-description = data.services.evidence + .card-corner diff --git a/source/sitemap.xml.builder b/source/sitemap.xml.builder index 23a329a4..ee323ff5 100644 --- a/source/sitemap.xml.builder +++ b/source/sitemap.xml.builder @@ -5,10 +5,11 @@ xml.urlset 'xmlns' => 'http://www.sitemaps.org/schemas/sitemap/0.9' do sitemap.resources.select { |page| page.path.include?('.html') }.each do |page| next unless page.data.seo != false + site_url = 'https://robotsbuildingrobots.com' location = if page.url == '/' - "#{data.components.url}/index.html" + "#{site_url}/index.html" else - "#{data.components.url}#{page.url}index.html" + "#{site_url}#{page.url}index.html" end xml.url do