/*
 * This is a manifest file that'll be compiled into application.css, which will include all the files
 * listed below.
 *
 * Any CSS (and SCSS, if configured) file within this directory, lib/assets/stylesheets, or any plugin's
 * vendor/assets/stylesheets directory can be referenced here using a relative path.
 *
 * You're free to add application-wide styles to this file and they'll appear at the bottom of the
 * compiled file so the styles you add here take precedence over styles defined in any other CSS
 * files in this directory. Styles in this file should be added after the last require_* statement.
 * It is generally better to create a new file per style scope.
 *
 *= require_tree .
 *= require_self
 */

/* Smooth scrolling for anchor links */
html {
  scroll-behavior: smooth;
}

/* Styling for anchor target sections */
:target {
  animation: highlight 2s ease-in-out;
  scroll-margin-top: 100px; /* Account for fixed navbar */
}

@keyframes highlight {
  0% {
    background-color: rgba(220, 38, 38, 0.1);
    border-left: 4px solid var(--rubydev-primary);
    padding-left: 1rem;
  }
  100% {
    background-color: transparent;
    border-left: none;
    padding-left: 0;
  }
}

/* RubyDev Platform - Ruby Red Design Theme */
/* Design tokens live in tokens.css — the single source of truth for colour.
 * See docs/engineering/design-system.md. Do not reintroduce a :root block here. */

* {
  box-sizing: border-box;
}

/* The page never scrolls sideways.
   `clip` rather than `hidden` on purpose: `overflow-x: hidden` turns the element
   into a scroll container, which silently breaks `position: sticky` on the navbar.
   `clip` does not. Wide content is still readable - tables and code blocks scroll
   inside their own box (see the overflow safety net at the end of this file).
   This is also what finally stops the closed off-canvas drawer, a fixed element
   parked outside the viewport, from widening the document on a phone. */
html,
body {
  overflow-x: clip;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  line-height: 1.6;
  color: var(--text-primary);
  background-color: var(--gray-50);
  margin: 0;
  padding: 0;
  font-weight: 400;
}

/* Enhanced Typography from Ruby Overview */
h1 {
  font-weight: 300;
  letter-spacing: -0.02em;
  line-height: 1.1;
}

h2 {
  font-weight: 300;
  letter-spacing: -0.01em;
  line-height: 1.2;
}

h3 {
  font-weight: 500;
  line-height: 1.3;
}

h4 {
  font-weight: 500;
  line-height: 1.4;
}

p {
  font-weight: 300;
  line-height: 1.6;
}

/* Clean button typography */
button, .btn, .cta-btn {
  font-weight: 500;
}

/* Navigation typography */
.nav-link {
  font-weight: 400;
}

/* Card content typography */
.card-title {
  font-weight: 500;
}

.card-text {
  font-weight: 300;
  line-height: 1.6;
}

.navbar {
  background: rgba(0, 0, 0, 0.95);
  backdrop-filter: blur(10px);
  box-shadow: 0 1px 3px rgba(0,0,0,0.3);
  padding: 0;
  position: sticky;
  top: 0;
  z-index: 999;
}

.navbar-brand {
  color: white !important;
  text-decoration: none;
  transition: transform 0.2s;
}

.navbar-brand:hover {
  transform: scale(1.05);
}

.nav-link {
  color: rgba(255, 255, 255, 0.8) !important;
  white-space: nowrap;
  padding: 0.5rem 1rem;
  border-radius: 0.375rem;
  transition: all 0.2s;
  text-decoration: none;
  font-weight: 400;
}

.nav-link:hover {
  color: white !important;
  background-color: rgba(255, 255, 255, 0.1);
}

.cta-btn {
  background: var(--rubydev-primary);
  color: white;
  padding: 0.75rem 1.5rem;
  border: none;
  border-radius: 0.5rem;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s;
  box-shadow: 0 4px 12px rgba(220, 38, 38, 0.3);
}

.cta-btn:hover {
  background: #991B1B;
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(220, 38, 38, 0.4);
}

/* Enhanced Animations and Effects */
@keyframes float {
  0%, 100% { transform: translateY(0px); }
  50% { transform: translateY(-10px); }
}

@keyframes pulse-ruby {
  0%, 100% { box-shadow: 0 4px 12px rgba(220, 38, 38, 0.3); }
  50% { box-shadow: 0 8px 20px rgba(220, 38, 38, 0.5); }
}

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

@keyframes fadeInScale {
  from { 
    opacity: 0; 
    transform: scale(0.95); 
  }
  to { 
    opacity: 1; 
    transform: scale(1); 
  }
}

.ruby-gem-float {
  animation: float 3s ease-in-out infinite;
}

.card-hover {
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  cursor: pointer;
}

.card-hover:hover {
  transform: translateY(-8px) scale(1.02);
  box-shadow: var(--shadow-xl);
}

.search-input {
  transition: all 0.3s ease;
}

.search-input:focus {
  border-color: var(--rubydev-primary);
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.1);
  outline: none;
}

.learning-badge {
  animation: slideInUp 0.6s ease-out;
}

.hero-title {
  animation: fadeInScale 0.8s ease-out 0.2s both;
}

.dashboard-cards {
  animation: slideInUp 0.8s ease-out 0.4s both;
}

.ecosystem-icon {
  transition: all 0.3s ease;
}

.ecosystem-icon:hover {
  transform: scale(1.1) rotate(10deg);
  animation: pulse-ruby 2s infinite;
}

/* Button hover effects */
.ruby-btn-hover:hover {
  background: rgba(220, 38, 38, 0.2) !important;
  transform: translateY(-2px);
}

.rails-btn-hover:hover {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(220, 38, 38, 0.4);
}

.docker-btn-hover:hover {
  background: rgba(37, 99, 235, 0.1) !important;
  transform: translateY(-2px);
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 1rem;
}

/* Remove container constraints for full-width sections */
.full-width {
  width: 100%;
  max-width: none;
}

.flex { display: flex; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.py-4 { padding-top: 1rem; padding-bottom: 1rem; }
.min-h-screen { min-height: 100vh; }
.text-center { text-align: center; }
.mb-4 { margin-bottom: 1rem; }
.mb-8 { margin-bottom: 2rem; }
.text-4xl { font-size: 2.25rem; font-weight: 300; letter-spacing: -0.01em; }
.text-xl { font-size: 1.25rem; font-weight: 300; }
.font-bold { font-weight: 500; }
.font-light { font-weight: 300; }
.font-medium { font-weight: 500; }

.notice, .alert {
  margin: 0;
  padding: 0.75rem 1rem;
  border-radius: 0.375rem;
  margin-bottom: 1rem;
}

.notice {
  background-color: #D1FAE5;
  color: #047857;
  border: 1px solid #A7F3D0;
}

.alert {
  background-color: #FEE2E2;
  color: #DC2626;
  border: 1px solid #FECACA;
}

.btn-explore {
  display: inline-block;
  width: 100%;
  background: transparent;
  color: var(--rubydev-primary);
  border: 1px solid var(--rubydev-primary);
  padding: 0.75rem 1rem;
  border-radius: 0.375rem;
  text-align: center;
  text-decoration: none;
  font-weight: 400;
  transition: all 0.2s;
}

.cta-btn:hover {
  background: var(--rubydev-dark);
  transform: translateY(-1px);
}

.btn-explore:hover {
  background: var(--rubydev-primary);
  color: white;
}

/* Navigation Dropdown Styles */
.nav-dropdown {
  position: relative;
  display: inline-block;
}

.dropdown-toggle {
  cursor: pointer;
  position: relative;
  /* The arrow is an ::after pseudo-element. As an inline box it wrapped onto its own line
     once the navbar got crowded — eleven dropdowns plus the auth links. inline-flex keeps
     the label and its arrow together as one unit. */
  display: inline-flex;
  align-items: center;
  white-space: nowrap;
}

.dropdown-toggle::after {
  content: '';
  display: inline-block;
  width: 12px;
  height: 12px;
  margin-left: 0.5rem;
  background-image: url("data:image/svg+xml,%3Csvg width='12' height='12' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6 9L12 15L18 9' stroke='rgba(255,255,255,0.8)' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
  transition: transform 0.2s;
  flex-shrink: 0;
}

.nav-dropdown:hover .dropdown-toggle::after {
  transform: rotate(180deg);
}

.dropdown-menu {
  position: absolute;
  top: 100%;
  left: 0;
  background: white;
  min-width: 220px;
  max-width: 900px;
  max-height: 80vh;
  border-radius: 1rem;
  box-shadow: 0 20px 40px rgba(0,0,0,0.15);
  border: 1px solid var(--gray-200);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-15px) scale(0.95);
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  z-index: 1000;
  padding: 0;
  overflow-y: auto;
  overflow-x: hidden;
}

/* Custom scrollbar for dropdown */
.dropdown-menu::-webkit-scrollbar {
  width: 6px;
}

.dropdown-menu::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 3px;
}

.dropdown-menu::-webkit-scrollbar-thumb {
  background: var(--rubydev-primary);
  border-radius: 3px;
}

.dropdown-menu::-webkit-scrollbar-thumb:hover {
  background: var(--rubydev-dark);
}

.nav-dropdown:hover .dropdown-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0) scale(1);
}

.dropdown-item {
  display: block;
  padding: 0.75rem 1rem;
  color: var(--text-secondary) !important;
  text-decoration: none;
  font-weight: 400;
  font-size: 0.9rem;
  transition: all 0.2s;
  border-left: 3px solid transparent;
  white-space: nowrap;
}

/* Dropdown sections */
.dropdown-section {
  padding: 0.75rem 1rem;
}

.dropdown-section:not(:last-child) {
  border-bottom: 1px solid var(--gray-100);
}

.dropdown-section-header {
  padding: 0.5rem 1rem;
  background: var(--gray-50);
  border-bottom: 1px solid var(--gray-100);
}

.dropdown-item:hover {
  background-color: var(--rubydev-pale);
  color: var(--rubydev-primary) !important;
  border-left-color: var(--rubydev-primary);
  padding-left: 1.25rem;
}

/* Mega Menu Styles */
.mega-menu {
  min-width: 800px !important;
  padding: 2rem;
}

.mega-menu-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2rem;
}

.mega-menu-section {
  background: var(--gray-50);
  border-radius: 0.75rem;
  padding: 1.5rem;
  border: 1px solid var(--gray-100);
  transition: all 0.2s ease;
}

.mega-menu-section:hover {
  background: var(--rubydev-pale);
  border-color: var(--rubydev-primary);
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(220, 38, 38, 0.1);
}

.mega-menu-header {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 1rem;
  padding-bottom: 0.75rem;
  border-bottom: 1px solid var(--gray-200);
}

.mega-menu-title {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--rubydev-primary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin: 0;
}

.mega-menu-description {
  font-size: 0.75rem;
  color: var(--text-secondary);
  margin: 0.25rem 0 0 0;
  line-height: 1.4;
}

.mega-menu-links {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.mega-menu-link {
  padding: 0.5rem 0.75rem;
  color: var(--text-secondary) !important;
  text-decoration: none;
  font-size: 0.875rem;
  font-weight: 400;
  border-radius: 0.375rem;
  transition: all 0.2s ease;
  border-left: 2px solid transparent;
}

.mega-menu-link:hover {
  background: white;
  color: var(--rubydev-primary) !important;
  border-left-color: var(--rubydev-primary);
  transform: translateX(4px);
}

.mega-menu-cta {
  grid-column: 1 / -1;
  background: linear-gradient(135deg, var(--rubydev-primary), var(--rubydev-dark));
  color: white;
  border-radius: 0.75rem;
  padding: 1.5rem;
  text-align: center;
  margin-top: 1rem;
}

.mega-menu-cta h4 {
  color: white;
  margin: 0 0 0.5rem 0;
  font-size: 1rem;
  font-weight: 600;
}

.mega-menu-cta p {
  color: rgba(255, 255, 255, 0.8);
  margin: 0 0 1rem 0;
  font-size: 0.875rem;
}

.mega-menu-cta-btn {
  background: white;
  color: var(--rubydev-primary);
  padding: 0.75rem 1.5rem;
  border-radius: 0.5rem;
  text-decoration: none;
  font-weight: 500;
  font-size: 0.875rem;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  transition: all 0.2s ease;
}

.mega-menu-cta-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 16px rgba(255, 255, 255, 0.3);
}

/* Compact Menu Styles for smaller dropdowns */
.compact-menu {
  min-width: 280px !important;
  padding: 1rem;
}

.compact-menu-header {
  padding: 0.75rem 1rem;
  background: var(--gray-50);
  margin: -1rem -1rem 1rem -1rem;
  border-bottom: 1px solid var(--gray-200);
  border-radius: 1rem 1rem 0 0;
}

.compact-menu-main-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem 1.5rem;
  background: var(--rubydev-primary);
  color: white !important;
  text-decoration: none;
  font-weight: 500;
  font-size: 0.9rem;
  border-radius: 0.5rem;
  margin: 0 1rem 1rem 1rem;
  transition: all 0.2s ease;
  border: 2px solid var(--rubydev-primary);
  box-shadow: 0 2px 4px rgba(220, 38, 38, 0.2);
  cursor: pointer;
}

.compact-menu-main-link:hover {
  background: var(--rubydev-dark);
  border-color: var(--rubydev-dark);
  transform: translateY(-1px);
  box-shadow: 0 4px 8px rgba(220, 38, 38, 0.3);
}

.compact-menu-main-link:active {
  transform: translateY(0);
  box-shadow: 0 2px 4px rgba(220, 38, 38, 0.2);
}

.compact-menu-title {
  font-weight: 600;
  color: var(--rubydev-primary);
  font-size: 0.875rem;
  margin: 0;
}

.compact-menu-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.5rem;
}

.compact-menu-grid.single-column {
  grid-template-columns: 1fr;
}

.compact-menu-grid.two-column {
  grid-template-columns: repeat(2, 1fr);
}

.compact-menu-grid.three-column {
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
}

.compact-menu-item {
  padding: 0.75rem;
  background: var(--gray-50);
  border-radius: 0.5rem;
  border: 1px solid var(--gray-100);
  transition: all 0.2s ease;
  text-decoration: none !important;
  color: var(--text-secondary) !important;
  font-size: 0.875rem;
  font-weight: 400;
}

.compact-menu-item:hover {
  background: var(--rubydev-pale);
  border-color: var(--rubydev-primary);
  color: var(--rubydev-primary) !important;
  transform: translateY(-2px);
}

/* Authentication Links */
.auth-link {
  color: rgba(255, 255, 255, 0.8) !important;
  /* "Sign Up" was rendering on two lines inside its bordered pill. */
  white-space: nowrap;
  text-decoration: none;
  font-weight: 400;
  padding: 0.5rem 1rem;
  border-radius: 0.375rem;
  transition: all 0.2s;
}

.auth-link:hover {
  color: white !important;
  background-color: rgba(255, 255, 255, 0.1);
}

.auth-link.signup {
  background: transparent;
  border: 1px solid var(--rubydev-primary);
  color: var(--rubydev-primary) !important;
}

.auth-link.signup:hover {
  background: var(--rubydev-primary);
  color: white !important;
}

/* Update container to use more width */
.container {
  max-width: 95%;
  margin: 0 auto;
  padding: 0 2rem;
}

/* Footer Styles */
footer a:hover {
  color: var(--rubydev-primary) !important;
}

footer .social-icon:hover {
  background: var(--rubydev-primary) !important;
  border-color: var(--rubydev-primary) !important;
  color: white !important;
  transform: translateY(-2px);
}

/* Mobile Menu Button */
.mobile-menu-button {
  display: none;
  cursor: pointer;
  padding: 0.5rem;
  z-index: 1002;
  position: relative;
  background: transparent;
  border: none;
  outline: none;
  touch-action: manipulation;
}



.hamburger {
  display: flex;
  flex-direction: column;
  width: 24px;
  height: 18px;
  justify-content: space-between;
}

.hamburger span {
  width: 100%;
  height: 2px;
  background-color: white;
  transition: all 0.3s ease;
  transform-origin: center;
}

.hamburger-active span:nth-child(1) {
  transform: rotate(45deg) translate(6px, 6px);
}

.hamburger-active span:nth-child(2) {
  opacity: 0;
  transform: scale(0);
}

.hamburger-active span:nth-child(3) {
  transform: rotate(-45deg) translate(6px, -6px);
}

/* Mobile Navigation Menu */
.mobile-nav {
  position: fixed;
  top: 0;
  /* Parked off-screen with a transform, not `right: -100%`.
     A fixed element positioned outside the viewport still counts toward the
     document's scrollable width, so the closed drawer was making every page
     scroll sideways by a full viewport on a phone - 371px of content in a 757px
     scroll area. Transforms do not contribute to scroll overflow, and animating
     one is cheaper than animating `right` because it never triggers layout. */
  right: 0;
  transform: translateX(100%);
  width: 320px;
  max-width: 85vw;
  height: 100vh;
  background: white;
  box-shadow: -5px 0 15px rgba(0,0,0,0.1);
  z-index: 1001;
  transition: transform 0.3s ease;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding-top: 80px;
}

@media (max-width: 1024px) {
  .mobile-nav {
    display: block;
  }
}

@media (min-width: 1025px) {
  .mobile-nav {
    display: none !important;
  }
}

.mobile-nav-active {
  transform: translateX(0) !important;
}

.mobile-nav-content {
  padding: 1rem;
}

.mobile-nav-section {
  margin-bottom: 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--gray-200);
}

.mobile-nav-section:last-child {
  border-bottom: none;
}

.mobile-nav-title {
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--rubydev-primary);
  text-transform: uppercase;
  letter-spacing: 0.5px;
  margin: 0 0 1rem 0;
}


.mobile-auth {
  margin-top: 2rem;
  padding-top: 2rem;
  border-top: 2px solid var(--rubydev-pale);
}

/* Mobile Navigation Dropdowns */
.mobile-nav-dropdown {
  margin-bottom: 1rem;
  border-bottom: 1px solid var(--gray-200);
}

.mobile-nav-dropdown:last-of-type {
  border-bottom: none;
}

.mobile-nav-dropdown-toggle {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 0.5rem;
  cursor: pointer;
  font-weight: 500;
  color: var(--rubydev-primary);
  font-size: 1.1rem;
  transition: all 0.2s;
}

.mobile-nav-dropdown-toggle:hover {
  background-color: var(--rubydev-pale);
  padding-left: 1rem;
}

.mobile-dropdown-arrow {
  font-size: 0.8rem;
  transition: transform 0.3s ease;
}

.mobile-nav-dropdown-content {
  max-height: 0;
  overflow: hidden;
  transition: max-height 0.3s ease;
  padding-left: 1rem;
}

.mobile-nav-dropdown-content.active {
  max-height: 1000px;
  padding-bottom: 0.5rem;
  overflow: visible;
}

.mobile-nav-dropdown.active .mobile-dropdown-arrow {
  transform: rotate(180deg);
}

.mobile-nav-dropdown .mobile-nav-link {
  font-size: 0.9rem;
  padding: 0.5rem 0;
  border-left: 2px solid transparent;
  pointer-events: auto;
  z-index: 1;
  position: relative;
}

.mobile-nav-link {
  display: block;
  padding: 0.75rem 0;
  color: var(--text-secondary) !important;
  text-decoration: none;
  font-weight: 400;
  transition: all 0.2s;
  border-left: 3px solid transparent;
  padding-left: 0.5rem;
}

.mobile-nav-link:hover {
  color: var(--rubydev-primary) !important;
  border-left-color: var(--rubydev-primary);
  padding-left: 1rem;
}

.mobile-nav-link.primary {
  background: var(--rubydev-primary);
  color: white !important;
  padding: 0.75rem 1rem;
  border-radius: 0.5rem;
  border-left: none;
  margin-bottom: 0.5rem;
}

.mobile-nav-link.primary:hover {
  background: var(--rubydev-dark);
  padding-left: 1rem;
}

/* Desktop/Mobile Navigation Toggle */
.desktop-nav {
  display: flex;
}

/* Responsive Navigation */
@media (max-width: 1024px) {
  .mobile-menu-button {
    display: block !important;
  }
  
  .desktop-nav {
    display: none !important;
  }
  
  .navbar {
    padding: 0;
  }
  
  .navbar > div {
    padding: 0 1rem;
  }
  
  .container {
    max-width: 100%;
    padding: 0 1rem;
  }
  
  /* Mobile dropdown adjustments */
  .mega-menu {
    min-width: 90vw !important;
    max-width: 95vw !important;
    left: -200px;
    padding: 1.5rem;
  }
  
  .mega-menu-grid {
    grid-template-columns: 1fr;
    gap: 1.5rem;
  }
  
  .compact-menu {
    min-width: 85vw !important;
    left: -100px;
  }
  
  .compact-menu-grid,
  .compact-menu-grid.two-column,
  .compact-menu-grid.three-column {
    grid-template-columns: 1fr;
  }
}

/* Tablet Responsive */
@media (max-width: 768px) {
  .mobile-nav {
    width: 280px;
  }
  
  .navbar-brand div:first-child {
    font-size: 1.25rem !important;
  }
  
  .navbar-brand div:last-child {
    font-size: 0.55rem !important;
  }
}

/* Mobile Phone Responsive */
@media (max-width: 480px) {
  .mobile-nav {
    width: 100vw;
    /* No `right` override here: the drawer is parked with translateX(100%) so that
       the closed panel does not widen the document. See the base rule. */
    max-width: 100vw;
  }
  
  .mobile-nav-active {
    transform: translateX(0);
  }
  
  .navbar > div {
    padding: 0 0.75rem;
  }
  
  .navbar-brand div:first-child {
    font-size: 1.1rem !important;
  }
  
  .navbar-brand div:last-child {
    display: none;
  }
}

/* Mobile Menu Overlay */
.mobile-nav-overlay {
  position: fixed;
  top: 0;
  left: 0;
  width: 100vw;
  height: 100vh;
  background: rgba(0,0,0,0.5);
  z-index: 999;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0.3s ease;
}

.mobile-nav-overlay.active {
  opacity: 1;
  visibility: visible;
}

@media (max-width: 1024px) {
  .mobile-nav-overlay {
    display: block;
  }
}

@media (min-width: 1025px) {
  .mobile-nav-overlay {
    display: none;
  }
}

/* Button Text Responsive */
.btn-text-mobile {
  display: none;
}

.btn-text-desktop {
  display: inline;
}

/* Home Page Responsive Styles */
@media (max-width: 768px) {
  /* Button Text Mobile */
  .btn-text-mobile {
    display: inline;
  }

  .btn-text-desktop {
    display: none;
  }

  /* Hero Section Mobile */
  .hero-title {
    font-size: 2.5rem !important;
  }

  /* Search Bar Mobile */
  .search-bar-mobile {
    flex-direction: column;
    gap: 0.75rem;
  }

  .search-bar-mobile input {
    padding: 0.875rem 1.25rem !important;
  }

  .search-bar-mobile button {
    width: 100%;
    padding: 1rem !important;
  }

  /* Quick Access Buttons Mobile */
  .quick-access-mobile {
    grid-template-columns: 1fr;
    gap: 0.75rem;
  }

  /* Dashboard Cards Mobile */
  .dashboard-cards-mobile {
    grid-template-columns: 1fr;
    gap: 1rem;
  }

  /* Ecosystem Icons Mobile - maintain single column */
  .ecosystem-mobile {
    grid-template-columns: 1fr !important;
    gap: 1rem;
  }

  /* Hero Section Responsive */
  .hero-section {
    margin: 1rem !important;
    padding: 2rem 0 !important;
    border-radius: 1rem !important;
  }

  .hero-badge {
    font-size: 0.75rem !important;
    padding: 0.5rem 1rem !important;
    margin-bottom: 1rem !important;
  }

  .hero-patterns .pattern {
    display: none !important;
  }

  /* Learning Dashboard Responsive */
  .learning-dashboard-grid {
    grid-template-columns: 1fr !important;
    gap: 1rem !important;
  }

  .learning-card {
    padding: 1rem !important;
  }

  /* Container padding mobile */
  .container-mobile {
    padding: 0 1rem !important;
  }
}

/* Mobile devices - ensure single column is maintained */
@media (max-width: 767px) {
  .course-grid {
    grid-template-columns: 1fr !important;
  }

  .ecosystem-mobile {
    grid-template-columns: 1fr !important;
    text-align: center;
  }

  /* Keep 2 columns only for quick access buttons */
  .quick-access-mobile {
    grid-template-columns: repeat(2, 1fr) !important;
  }
}

@media (max-width: 480px) {
  /* Hero Section Mobile Phone */
  .hero-title {
    font-size: 1.75rem !important;
    line-height: 1.2 !important;
  }

  /* Hero Badge Mobile */
  .hero-badge-mobile {
    font-size: 0.7rem !important;
    padding: 0.4rem 1rem !important;
  }

  /* Search Bar Mobile Phone */
  .search-input-mobile {
    font-size: 1rem !important;
    padding: 0.75rem 1rem !important;
  }

  /* Responsive spacing adjustments for mobile - single column */
  .ecosystem-mobile {
    grid-template-columns: 1fr !important;
    gap: 0.75rem !important;
    text-align: center;
  }

  /* Footer Mobile */
  .footer-mobile {
    grid-template-columns: 1fr !important;
    gap: 2rem !important;
    text-align: center;
  }

  .footer-bottom-mobile {
    flex-direction: column !important;
    gap: 1rem !important;
    text-align: center !important;
  }

  /* Course Grid Mobile Responsive */
  .course-grid {
    grid-template-columns: 1fr !important;
    gap: 1.5rem !important;
  }

  /* Hero Section Extra Small */
  .hero-section {
    margin: 0.5rem !important;
    padding: 1.5rem 0 !important;
  }

  /* Navigation adjustments */
  .navbar > div {
    padding: 0 0.5rem !important;
  }

  /* Logo adjustments */
  .navbar-brand div:first-child {
    font-size: 1rem !important;
  }

  /* Card adjustments */
  .card-mobile {
    padding: 1rem !important;
    margin: 0.5rem !important;
  }

  /* Text size adjustments */
  .text-responsive {
    font-size: 0.875rem !important;
  }

  /* Spacing adjustments */
  .spacing-mobile {
    margin: 0.5rem 0 !important;
    padding: 0.5rem !important;
  }
}

/* Tablet Responsive Styles */
@media (min-width: 481px) and (max-width: 768px) {
  /* Hero section tablet */
  .hero-title {
    font-size: 2.25rem !important;
  }

  .quick-access-mobile {
    grid-template-columns: repeat(2, 1fr);
    gap: 1rem;
  }

  /* Dashboard grid tablet */
  .learning-dashboard-grid {
    grid-template-columns: repeat(2, 1fr) !important;
    gap: 1.5rem !important;
  }

  /* Navigation tablet */
  .compact-menu-grid.three-column {
    grid-template-columns: repeat(2, 1fr) !important;
  }
}

/* Course Grid Responsive Breakpoints */

/* Default: Single column for all mobile devices */
.course-grid {
  grid-template-columns: 1fr !important;
}

.ecosystem-mobile {
  grid-template-columns: 1fr !important;
}

/* Tablets: 3 columns from 768px and up */
@media (min-width: 768px) {
  .course-grid {
    grid-template-columns: repeat(3, 1fr) !important;
  }

  .ecosystem-mobile {
    grid-template-columns: repeat(3, 1fr) !important;
  }

  /* Reset button text for desktop */
  .btn-text-mobile {
    display: none;
  }

  .btn-text-desktop {
    display: inline;
  }

  /* Hero section desktop */
  .hero-title {
    font-size: 3rem !important;
  }

  .quick-access-mobile {
    grid-template-columns: repeat(2, 1fr);
  }

  /* Dashboard grid desktop */
  .learning-dashboard-grid {
    grid-template-columns: 1fr 350px !important;
  }
}

/* Large Tablets/Small Desktop: 4 columns from 1024px */
@media (min-width: 1024px) {
  .course-grid {
    grid-template-columns: repeat(4, 1fr) !important;
  }

  .ecosystem-mobile {
    grid-template-columns: repeat(4, 1fr) !important;
  }

  /* Large screen hero */
  .hero-title {
    font-size: 3.5rem !important;
  }

  .hero-section {
    margin: 2rem !important;
    padding: 4rem 0 !important;
    border-radius: 2rem !important;
  }
}

/* Large Desktop: 5 columns from 1280px */
@media (min-width: 1280px) {
  .course-grid {
    grid-template-columns: repeat(5, 1fr) !important;
  }

  .ecosystem-mobile {
    grid-template-columns: repeat(5, 1fr) !important;
  }

  /* Extra large screens */
  .container {
    max-width: 1200px;
    padding: 0 2rem;
  }
}

/* General Responsive Utilities */
@media (max-width: 1024px) {
  /* Hide desktop-only elements */
  .desktop-only {
    display: none !important;
  }

  /* Show mobile-only elements */
  .mobile-only {
    display: block !important;
  }

  /* Adjust margins and padding for smaller screens */
  .spacing-responsive {
    margin: 1rem !important;
    padding: 1rem !important;
  }

  /* Make images responsive */
  img {
    max-width: 100% !important;
    height: auto !important;
  }

  /* Table responsiveness */
  table {
    font-size: 0.875rem !important;
  }

  /* Form elements */
  input, textarea, select {
    font-size: 16px !important; /* Prevent zoom on iOS */
  }
}

/* Touch target improvements */
@media (max-width: 768px) {
  /* Tap targets of at least 44px (WCAG 2.5.5).
     This deliberately does NOT set `display`. The previous version forced
     `display: flex !important` onto every <a> on mobile, which turned any link
     wrapping a card into a horizontal row: on the home page the Ruby Mastery and
     Rails Mastery cards laid their icon, title and subtitle out side by side,
     while the visually identical System Design card beside them — a <div>, not a
     link — stacked correctly. An !important display rule also overrides the
     element's own inline style, so the markup could not opt out.
     Sizing a tap target is not the same as dictating its layout. */
  button,
  [role="button"],
  input[type="submit"],
  input[type="button"],
  .clickable,
  .btn,
  .cta-btn {
    min-height: 44px;
    min-width: 44px;
  }

  /* Links that are a tap target in their own right, rather than a container for
     a laid-out card. :has() lets us tell those apart. */
  a:not(:has(div, section, article, ul, table)) {
    min-height: 44px;
  }

  /* Improve text readability */
  body {
    font-size: 1rem !important;
    line-height: 1.5 !important;
  }

  /* Better spacing for content */
  .content-responsive {
    padding: 1rem !important;
    margin: 0.5rem 0 !important;
  }
}

/* Ultra-wide screen adjustments */
@media (min-width: 1600px) {
  .container {
    max-width: 1400px;
  }

  .hero-title {
    font-size: 4rem !important;
  }
}

/* Learning Modalities Responsive Grid */
.learning-modalities-grid {
  grid-template-columns: 1fr 1fr !important;
}

@media (max-width: 480px) {
  .learning-modalities-grid {
    grid-template-columns: 1fr !important;
    gap: 0.75rem !important;
  }

  .learning-modalities-grid span {
    font-size: 0.8rem !important;
  }
}

/* ============================================================================
   Desktop navigation: fitting eleven dropdowns between 1025px and wide screens

   The mobile drawer takes over below 1025px, so the desktop bar carries the whole
   menu from 1025px up - eleven dropdowns plus AI Chat, Login and Sign Up. It did
   not fit, and because nothing stopped wrapping, labels broke away from their
   arrows, "Sign Up" split across two lines, and the brand tagline dropped
   "Deploy" onto a second row. white-space: nowrap (above) stops the wrapping;
   this block makes the bar genuinely fit rather than merely refuse to wrap.

   This applies at every desktop width, not just narrow ones: the bar was already
   wrapping at 1800px. Spacing tightens further as the viewport narrows.
   ============================================================================ */

.navbar-brand {
  /* The brand is fixed-size; only the menu should absorb the squeeze. */
  flex-shrink: 0;
}

.desktop-nav {
  /* min-width: 0 lets a flex child shrink below its content size, which is what
     allows the menu to compress instead of pushing the auth buttons off-screen. */
  min-width: 0;
  flex-wrap: nowrap;
}

@media (min-width: 1025px) {
  .navbar > div {
    padding: 0 1rem !important;
  }

  .desktop-nav {
    gap: 0.125rem !important;
  }

  .nav-link {
    padding: 0.5rem 0.55rem;
    font-size: 0.875rem;
  }

  .dropdown-toggle::after {
    margin-left: 0.3rem;
    width: 10px;
    height: 10px;
  }

  .auth-link {
    padding: 0.5rem 0.75rem;
    font-size: 0.875rem;
  }
}

/* The tightest band the desktop bar has to survive. */
@media (min-width: 1025px) and (max-width: 1365px) {
  .desktop-nav {
    gap: 0 !important;
  }

  .nav-link {
    padding: 0.5rem 0.4rem;
    font-size: 0.8125rem;
  }

  .dropdown-toggle::after {
    margin-left: 0.2rem;
  }

  .auth-link {
    padding: 0.45rem 0.6rem;
    font-size: 0.8125rem;
  }
}

/* ============================================================================
   Responsive grids for the legacy inline styles

   120 grids in the views already use repeat(auto-fit, minmax(...)) and reflow on
   their own. Another 63 hardcode a column count inline — repeat(2, 1fr) and up —
   plus two lesson layouts with a fixed-width sidebar. Those cannot reflow, so on
   a phone they force horizontal scrolling.

   They are inline styles, so overriding them needs !important and an attribute
   selector. This is deliberately targeted rather than a blanket rule: each
   selector names an exact declaration that exists in the markup today, and each
   one disappears as its lesson is converted to Markdown (Phase 6), where the
   layout comes from Content::* components instead.
   ============================================================================ */

/* Tablet: the widest grids give up some columns; the lesson sidebar drops below
   the content rather than squeezing it. */
@media (max-width: 1024px) {
  [style*="grid-template-columns: 1fr 350px"],
  [style*="grid-template-columns: 1fr 320px"] {
    grid-template-columns: 1fr !important;
  }

  [style*="repeat(7, 1fr)"] {
    grid-template-columns: repeat(3, 1fr) !important;
  }

  [style*="repeat(4, 1fr)"] {
    grid-template-columns: repeat(2, 1fr) !important;
  }
}

/* Small tablet / large phone. */
@media (max-width: 768px) {
  [style*="repeat(7, 1fr)"],
  [style*="repeat(3, 1fr)"] {
    grid-template-columns: repeat(2, 1fr) !important;
  }

  /* Anything that still declares a pixel width wider than a phone. */
  [style*="width: 600px"],
  [style*="width: 650px"],
  [style*="width: 800px"],
  [style*="width: 300px"] {
    max-width: 100% !important;
  }
}

/* Phone: one column, everything. Two columns of cards at 390px is unreadable. */
@media (max-width: 560px) {
  [style*="repeat(2, 1fr)"],
  [style*="repeat(3, 1fr)"],
  [style*="repeat(4, 1fr)"],
  [style*="repeat(7, 1fr)"] {
    grid-template-columns: 1fr !important;
  }
}

/* ----------------------------------------------------------------------------
   Overflow safety net

   Lessons are full of code samples in fixed-font divs with long lines. On a phone
   those are the single biggest cause of the whole page scrolling sideways. Let
   them scroll inside their own box instead, which is the rule in
   docs/engineering/design-system.md: wide content scrolls itself, the page never
   scrolls horizontally.
   ---------------------------------------------------------------------------- */
img,
svg,
video,
iframe {
  max-width: 100%;
  height: auto;
}

pre,
code[style*="monospace"],
div[style*="monospace"],
[style*="font-family: 'Monaco'"],
[style*="font-family: Monaco"] {
  max-width: 100%;
  overflow-x: auto;
}

table {
  max-width: 100%;
  display: block;
  overflow-x: auto;
}

@media (max-width: 768px) {
  /* Generous desktop padding becomes wasted space on a phone. */
  [style*="padding: 3rem 2rem"] {
    padding: 2rem 1rem !important;
  }

  [style*="padding: 0 2rem"] {
    padding: 0 1rem !important;
  }
}

/* ============================================================================
   Course cards on mobile: five, not ten

   The ecosystem section is two rows of five compact cards. Stacked one per row
   on a phone that is ten full-width cards of scrolling for very little
   information per screen.

   Squeezing them two-across was worse: at 97px a column, "Metaprogramming"
   truncated and the subtitles wrapped to three lines. The cards are designed to
   be read at full width.

   So on a phone the first five are shown at full width, exactly as designed, and
   the second row is hidden. Those five are illustrative - not one of them is a
   link - so no navigation and no crawlable URL is lost.
   ============================================================================ */
@media (max-width: 767px) {
  .course-grid--secondary {
    display: none !important;
  }
}

/* ============================================================================
   Hover effects belong to pointers, not fingers

   Fourteen rules move an element on :hover - scale, rotate, translate. On a
   touch screen there is no hover: the browser fires it on tap and then leaves it
   applied until you tap elsewhere. So tapping a course card left it sitting
   rotated 10 degrees, which reads as a rendering bug rather than an effect.

   `@media (hover: none)` matches devices whose primary input cannot hover. The
   colour and shadow changes are kept - they are harmless and give useful tap
   feedback - and only the movement is cancelled.
   ============================================================================ */
@media (hover: none) {
  .navbar-brand:hover,
  .cta-btn:hover,
  .card-hover:hover,
  .ecosystem-icon:hover,
  .ruby-btn-hover:hover,
  .rails-btn-hover:hover,
  .docker-btn-hover:hover,
  .mega-menu-section:hover,
  .mega-menu-link:hover,
  .mega-menu-cta-btn:hover,
  .compact-menu-main-link:hover,
  .compact-menu-item:hover,
  footer .social-icon:hover {
    transform: none !important;
    animation: none !important;
  }
}

/* ============================================================================
   MOBILE-FIRST SHRINK GUARDS
   ----------------------------------------------------------------------------
   Grid and flex items are `min-width: auto` by default, which means they refuse to
   shrink below the min-content width of what is inside them. One long code line or a
   wide table then forces the whole column open. On /ruby/installation that laid out an
   868px column inside a 340px grid; `overflow-x: clip` on <html> hid the overflow
   rather than fixing it, so the page looked squeezed and cut off instead of scrolling.

   `min-width: auto` computes to 0 for a normal block box, so declaring 0 on content
   elements changes nothing outside a flex or grid container and fixes every item inside
   one. :where() keeps specificity at zero, so any component can still opt out.

   Remove this block when the content partials no longer carry inline layout
   (Phase 6) — it is a guard over 85,000 lines of inline-styled prose, not a design.
   ============================================================================ */
main :where(div, section, article, aside, ul, ol, dl, dd, figure, p, pre, table,
            span, a, label, button, li,
            h1, h2, h3, h4, h5, h6) {
  min-width: 0;
}

/* Long words, URLs and inline code must wrap rather than widen their column. */
main :where(p, li, dd, h1, h2, h3, h4, h5, h6, td, th) {
  overflow-wrap: break-word;
}

/* A dark code block is a scroller, never a strut: it may scroll itself sideways but it
   must not make the page do so. 269 of these already declare overflow-x: auto; this
   makes sure the box can actually reach a narrower width first. */
main :where(pre) {
  max-width: 100%;
  overflow-x: auto;
}

/* Tables are the one thing that genuinely cannot reflow, so they get their own
   scroll region instead of stretching the page. */
main :where(table) {
  display: block;
  max-width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}

/* Media never exceeds its column. */
main :where(img, svg, video, iframe, canvas) {
  max-width: 100%;
}

/* The lesson chrome is a content column plus a sidebar. `1fr` would carry the same
   min-content minimum described above, so the content track is explicitly allowed to
   shrink, and the sidebar drops below the content on anything narrower than a laptop. */
.topic-layout {
  display: grid;
  grid-template-columns: minmax(0, 1fr) 320px;
  gap: 3rem;
  align-items: start;
}

@media (max-width: 1024px) {
  .topic-layout {
    grid-template-columns: minmax(0, 1fr);
    gap: 2rem;
  }

  /* The sidebar is reference material; once it is stacked it should not be sticky, and
     its 300px floor is what used to push the page sideways. */
  .topic-layout > :last-child {
    position: static !important;
    min-width: 0 !important;
  }
}

/* A content column beside a narrower aside. The ratio is what the page was designed
   with, so it is kept on a laptop and collapses to a single column on a phone — the
   inline `2fr 1fr` it replaces had no breakpoint and no way to get one. */
.rd-split {
  display: grid;
  grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
  gap: 3rem;
  align-items: start;
}

.rd-split--narrow-first {
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
}

.rd-split--wide-second {
  grid-template-columns: minmax(0, 1fr) minmax(0, 3fr);
}

@media (max-width: 900px) {
  .rd-split,
  .rd-split--narrow-first,
  .rd-split--wide-second {
    grid-template-columns: minmax(0, 1fr);
    gap: 1.5rem;
  }
}

/* ============================================================================
   TRACK OVERVIEW PAGES  (/ruby, /rails)
   ----------------------------------------------------------------------------
   app/views/ruby_topics/overview.html.erb and app/views/rails_topics/overview.html.erb
   are inline-styled end to end, and an inline `style=` attribute cannot be
   overridden by any stylesheet - which is why the hero stat row could not be made
   to stack and the hover lifts could not be cancelled. The handful of rules that
   genuinely need a breakpoint, a hover state or a reduced-motion escape hatch live
   here instead, and the templates carry a class.

   Every value is the value those templates already computed on a desktop; the only
   new behaviour is below the breakpoints.
   ============================================================================ */

/* The decorative layers - gem/track pattern, soft orbs, depth sheen - sit behind
   the hero copy and must never intercept a tap or be announced. */
.rd-track-deco {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.rd-hero-sheen {
  background: linear-gradient(45deg, rgba(0, 0, 0, 0.02) 0%, transparent 50%, rgba(255, 255, 255, 0.02) 100%);
}

/* Soft brand-red orbs. The diameters are the desktop values (80 / 120 / 60px) with
   a floor at half each, so they cannot crowd the headline in a 390px hero. */
.rd-hero-orb {
  position: absolute;
  aspect-ratio: 1;
  border-radius: 50%;
  pointer-events: none;
}

.rd-hero-orb--a {
  top: 10%;
  left: 5%;
  width: clamp(2.5rem, 14vw, 5rem);
  background: color-mix(in srgb, var(--rubydev-primary) 10%, transparent);
  opacity: 0.6;
}

.rd-hero-orb--b {
  top: 60%;
  right: 10%;
  width: clamp(3.75rem, 20vw, 7.5rem);
  background: color-mix(in srgb, var(--rubydev-primary) 15%, transparent);
  opacity: 0.4;
}

.rd-hero-orb--c {
  bottom: 20%;
  left: 15%;
  width: clamp(1.875rem, 10vw, 3.75rem);
  background: color-mix(in srgb, var(--rubydev-primary) 20%, transparent);
  opacity: 0.5;
}

/* Four stat cards: one column on a phone, two up on a large phone, four across from
   a tablet up - the width they have always had. `auto-fit` cannot express "stop at
   two", which is why this is a breakpoint and not an intrinsic track list. */
.rd-hero-stats {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: clamp(1rem, 3vw, 3rem);
  margin-top: clamp(2rem, 5vw, 4rem);
}

@media (min-width: 400px) {
  .rd-hero-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 860px) {
  .rd-hero-stats {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

.rd-hero-stat-link {
  display: block;
  color: inherit;
  text-decoration: none;
  border-radius: 1rem;
}

.rd-hero-stat-link:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 3px;
}

.rd-hero-stat {
  padding: 1.5rem;
  text-align: center;
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 1rem;
  backdrop-filter: blur(10px);
  transition: all 0.3s ease;
}

.rd-hero-stat-link:hover .rd-hero-stat,
.rd-hero-stat-link:focus-visible .rd-hero-stat {
  background: rgba(255, 255, 255, 0.15);
  border-color: rgba(255, 255, 255, 0.3);
  transform: translateY(-4px);
}

/* A touch device fires :hover on tap and leaves it applied; the colour change is
   useful tap feedback, the movement reads as a glitch. */
@media (hover: none) {
  .rd-hero-stat-link:hover .rd-hero-stat {
    transform: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .rd-hero-stat {
    transition: none;
  }

  .rd-hero-stat-link:hover .rd-hero-stat,
  .rd-hero-stat-link:focus-visible .rd-hero-stat {
    transform: none;
  }
}

/* The two call-to-action buttons sit side by side wherever there is room and become
   a full-width stack on a phone, where 1rem + 2.5rem of horizontal padding each left
   them fighting for the same line. */
.rd-cta-row {
  display: flex;
  flex-wrap: wrap;
  gap: 1.5rem;
  justify-content: center;
}

.rd-cta-row > a {
  justify-content: center;
}

@media (max-width: 480px) {
  .rd-cta-row {
    flex-direction: column;
    align-items: stretch;
    gap: 1rem;
  }

  .rd-cta-row > a {
    text-align: center;
  }
}

/* ============================================================================
   LEARNING PATH SHELL (/learn)
   ----------------------------------------------------------------------------
   /learn is a 280px chapter sidebar beside the lesson content. It was built as
   `display: flex` with the sidebar at a hard `width: 280px`, and nothing in that
   row could wrap — so at a 390px viewport the sidebar still claimed 280px and the
   content column was left ~110px wide. The inline check-list rows inside it
   (icon + <span>) cannot shrink below their min-content width, so seven of them
   ran to 426px, 36px past the viewport. That was the last horizontal overflow in
   the app.

   This is the one place a breakpoint is genuinely needed: a track that is
   `280px + rest` on a laptop and a single column on a phone cannot be expressed
   with auto-fit, because the sidebar is a fixed rail rather than a flexible card.
   It lives here rather than inline because an inline `style=` attribute cannot be
   overridden by a media query.

   Mobile-first: one column, sidebar above the content. From 1024px up it is the
   original two-track layout, pixel for pixel — the grid has no gap, so the tracks
   land exactly where `width: 280px` + `flex: 1` put them. Row stretching is left
   at its default so the sidebar still paints the full page height.
   ============================================================================ */
.learn-shell {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.learn-shell__sidebar,
.learn-shell__main {
  min-width: 0;
}

/* Stacked, the divider reads as a rule under the sidebar; side by side it is the
   rail's right edge. Same hairline either way. */
.learn-shell__sidebar {
  border-bottom: 1px solid var(--gray-200);
}

/* The chapter list is a bounded scroller on a laptop. On a phone it is the page:
   a nested 70vh scroll region there traps the swipe and hides most of the
   curriculum, so it is released to its full height and the page scrolls instead. */
@media (min-width: 1024px) {
  .learn-shell {
    grid-template-columns: 280px minmax(0, 1fr);
  }

  .learn-shell__sidebar {
    border-bottom: 0;
    border-right: 1px solid var(--gray-200);
    overflow-y: auto;
  }

  .learn-chapters {
    max-height: 70vh;
    overflow-y: auto;
  }
}

/* ============================================================================
   LESSON & TRACK CHROME
   ----------------------------------------------------------------------------
   The frame around a lesson: hero, breadcrumbs, content column, sidebar, prev/next.
   Written mobile-first — the base rules are the phone layout and the breakpoints add
   to them, rather than the other way round. New markup carries classes, not inline
   styles, so that a stylesheet can actually reach it (docs/engineering/design-system.md).
   ============================================================================ */

.lesson-hero {
  background: linear-gradient(135deg, #DC2626 0%, #B91C1C 100%);
  color: #fff;
  padding: 2rem 0 1.75rem;
}

.lesson-hero__inner,
.lesson-main__inner {
  max-width: 1200px;
  margin: 0 auto;
  padding-inline: clamp(1rem, 4vw, 2rem);
}

.lesson-hero__identity {
  display: flex;
  align-items: flex-start;
  gap: 0.875rem;
}

/* The track logo must never be squeezed by a long lesson title. */
.lesson-hero__logo {
  flex-shrink: 0;
  line-height: 0;
  padding-top: 0.2rem;
}

.lesson-hero__title {
  font-size: clamp(1.5rem, 6vw, 2.5rem);
  font-weight: 300;
  letter-spacing: -0.02em;
  margin: 0;
  line-height: 1.15;
}

.lesson-hero__summary {
  font-size: clamp(0.9375rem, 2.5vw, 1.125rem);
  opacity: 0.92;
  margin: 0.5rem 0 0;
  line-height: 1.55;
  font-weight: 300;
}

.lesson-hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.125rem;
}

.lesson-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  background: rgba(255, 255, 255, 0.14);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 999px;
  padding: 0.25rem 0.625rem;
  font-size: 0.75rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
}

/* Breadcrumbs scroll sideways on a phone instead of wrapping into a ragged stack. */
.lesson-crumbs {
  display: flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 1.125rem;
  font-size: 0.8125rem;
  opacity: 0.88;
  overflow-x: auto;
  scrollbar-width: none;
  padding-bottom: 0.125rem;
}

.lesson-crumbs::-webkit-scrollbar { display: none; }

.lesson-crumbs a,
.lesson-crumbs span {
  color: inherit;
  text-decoration: none;
  white-space: nowrap;
}

.lesson-crumbs a:hover { text-decoration: underline; }

.lesson-crumbs__sep { opacity: 0.55; }

.lesson-main {
  background: #fff;
  padding-block: clamp(1.5rem, 5vw, 3rem);
}

/* The prose card. On a phone it loses its border and padding so the content gets the
   full width of the screen rather than sitting in a 1rem-inset box. */
.lesson-body {
  background: #fff;
  border-radius: 1rem;
}

.lesson-aside {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.lesson-card {
  background: #FAFAFA;
  border: 1px solid #E5E7EB;
  border-radius: 0.875rem;
  padding: 1.25rem;
}

.lesson-card__title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  color: #1F2937;
  font-size: 0.875rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  margin: 0 0 0.875rem;
}

.lesson-card__list {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.lesson-card__link {
  display: block;
  color: #4B5563;
  text-decoration: none;
  font-size: 0.8125rem;
  line-height: 1.45;
  padding: 0.5rem 0.625rem;
  border-radius: 0.375rem;
  transition: background-color 0.15s, color 0.15s;
}

.lesson-card__link:hover {
  background: #fff;
  color: #DC2626;
}

.lesson-card__link--current {
  background: #fff;
  color: #DC2626;
  font-weight: 600;
  box-shadow: inset 2px 0 0 #DC2626;
}

/* Prev / next. One column on a phone, two on anything wider, with "next" always on the
   right so the reading direction is obvious. */
.lesson-pager {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0.75rem;
  margin-top: 2rem;
}

.lesson-pager__link {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  background: #fff;
  border: 1px solid #E5E7EB;
  border-radius: 0.625rem;
  padding: 0.875rem 1rem;
  text-decoration: none;
  color: #1F2937;
  min-height: 44px;
  transition: border-color 0.15s, box-shadow 0.15s;
}

.lesson-pager__link:hover {
  border-color: #DC2626;
  box-shadow: 0 1px 3px rgba(220, 38, 38, 0.12);
}

.lesson-pager__link--next {
  justify-content: flex-end;
  text-align: right;
}

.lesson-pager__dir {
  display: block;
  font-size: 0.6875rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: #9CA3AF;
  margin-bottom: 0.125rem;
}

.lesson-pager__label {
  display: block;
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.3;
}

.lesson-pager__arrow {
  flex-shrink: 0;
  color: #9CA3AF;
}

@media (min-width: 560px) {
  .lesson-pager {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* Keep "next" in the right-hand cell even when there is no previous lesson. */
  .lesson-pager__link--next:only-child {
    grid-column: 2;
  }
}

@media (min-width: 768px) {
  .lesson-hero {
    padding: 3rem 0 2.5rem;
  }

  .lesson-body {
    border: 1px solid #E5E7EB;
    padding: clamp(1.25rem, 3vw, 2rem);
  }
}

/* The "being written" page for a lesson that exists in the curriculum but has no prose
   yet. Deliberately plain: it is noindex and its only job is to point onward. */
.lesson-draft {
  background: #FAFAFA;
  border: 1px solid #E5E7EB;
  border-radius: 1rem;
  padding: clamp(1.25rem, 4vw, 2.5rem);
  text-align: center;
}

.lesson-draft__title {
  color: #1F2937;
  font-size: clamp(1.25rem, 5vw, 1.75rem);
  font-weight: 300;
  margin: 0 0 0.5rem;
}

.lesson-draft__body {
  color: #6B7280;
  font-size: 0.9375rem;
  line-height: 1.6;
  margin: 0 auto;
  max-width: 48ch;
}

/* Generic track pages, used by any track without a hand-designed landing page. */
.track-index {
  max-width: 1200px;
  margin: 0 auto;
  padding: clamp(1.5rem, 5vw, 3rem) clamp(1rem, 4vw, 2rem);
}

.track-module {
  border: 1px solid #E5E7EB;
  border-radius: 0.875rem;
  padding: clamp(1rem, 3vw, 1.5rem);
  margin-bottom: 1rem;
  background: #fff;
}

.track-module__title {
  color: #1F2937;
  font-size: 1.0625rem;
  font-weight: 600;
  margin: 0 0 0.25rem;
}

.track-module__summary {
  color: #6B7280;
  font-size: 0.875rem;
  margin: 0 0 1rem;
  line-height: 1.55;
}

.track-module__lessons {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
  gap: 0.375rem;
}

/* ============================================================================
   Documentation shell: a fixed-width aside beside the article

   topics/show.html.erb and topics/normal_topic_view.html.erb both open with an
   inline `display: flex` wrapper around an aside that declares `width: 300px`.
   A phone is 390px wide, so that left 90px for the article and the page scrolled
   sideways. Inline declarations cannot be overridden from here, so the layout
   moves into these classes and the markup keeps only its own colours.

   The 300px track and the gapless, flush-border look are exactly what the pages
   render on a laptop today; the only new behaviour is the single-column stack
   below 1024px, where the aside's right border becomes a bottom border so the
   hairline still separates nav from content.
   ============================================================================ */
.rd-docs-shell {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  align-items: start;
  min-height: calc(100vh - 80px);
}

/* normal_topic_view measures its shell against the whole viewport, show.html.erb
   against the viewport minus the navbar. Both are "fill the screen when the page
   is short", so the difference is kept rather than normalised. */
.rd-docs-shell--viewport {
  min-height: 100vh;
}

.rd-docs-shell__aside {
  border-right: 1px solid var(--gray-200);
  min-width: 0;
}

.rd-docs-shell__main {
  min-width: 0;
}

@media (max-width: 1024px) {
  .rd-docs-shell {
    grid-template-columns: minmax(0, 1fr);
  }

  .rd-docs-shell__aside {
    border-right: 0;
    border-bottom: 1px solid var(--gray-200);
  }
}

/* ============================================================================
   RUBY LEARNING HUB  —  /ruby-home
   ----------------------------------------------------------------------------
   app/views/ruby_topics/home.html.erb used to be a `display: flex` row of a
   fixed 300px sidebar and a `flex: 1` content column, with no breakpoint. At
   390px that left the lesson text roughly 90px wide, and the 1074-line
   curriculum tree sat permanently expanded above it, so a reader had to scroll
   the whole syllabus before reaching a word of content.

   The layout is a class rather than an inline style for one reason: an inline
   `style=` attribute cannot be beaten by a stylesheet, so a media query can
   only exist if the declaration it overrides is not inline. Every value below
   is the value the page already computed on a laptop — only the small-screen
   behaviour is new.
   ============================================================================ */
.rd-hub {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  min-height: 100vh;
  background: var(--white);
}

.rd-hub__aside {
  background: var(--gray-50);
  border-bottom: 1px solid var(--gray-200);
  padding: clamp(1.1rem, 4vw, 2rem) clamp(1rem, 4vw, 1.5rem);
}

.rd-hub__main {
  padding: clamp(1.25rem, 5vw, 4rem);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
               Ubuntu, Cantarell, sans-serif;
}

/* The laptop view: the original 300px rail, hairline on the right, no bottom rule. */
@media (min-width: 1024px) {
  .rd-hub {
    grid-template-columns: 300px minmax(0, 1fr);
  }

  .rd-hub__aside {
    border-bottom: 0;
    border-right: 1px solid var(--gray-200);
  }
}

/* ----------------------------------------------------------------------------
   The curriculum disclosure.

   The whole tree lives in a <details open> whose <summary> is the sidebar's own
   "Ruby Home" header — no invented label, and keyboard operable for free. It
   ships open, so with JavaScript unavailable the page renders exactly as it did
   before. On a phone `responsive_nav_controller.js` closes it (and each
   chapter), turning 1074 lines into a two-tap table of contents; at 1024px and
   up the controller re-opens everything and the summary markers are hidden, so
   the laptop view is unchanged.
   -------------------------------------------------------------------------- */
.rd-hub__nav-summary {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  margin-bottom: 2rem;
  cursor: pointer;
  list-style: none;
}

/* Closed, the header is the whole sidebar: its 2rem of breathing room belongs to
   the tree it is hiding, not to a bare grey band. */
details:not([open]) > .rd-hub__nav-summary {
  margin-bottom: 0;
}

.rd-hub__nav-summary::-webkit-details-marker,
.rd-nav-chapter__summary::-webkit-details-marker {
  display: none;
}

.rd-hub__nav-summary:focus-visible,
.rd-nav-chapter__summary:focus-visible {
  outline: 2px solid var(--rubydev-primary);
  outline-offset: 3px;
  border-radius: 0.25rem;
}

.rd-nav-chapter {
  margin-bottom: 2rem;
}

.rd-nav-chapter__summary {
  display: block;
  cursor: pointer;
  list-style: none;
}

/* Unchanged from the inline rule it replaces: 0.875rem/700 uppercase red with a
   2px red rule beneath it. */
.rd-nav-chapter__title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 1rem;
  padding-bottom: 0.5rem;
  font-size: 0.875rem;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--rubydev-primary);
  border-bottom: 2px solid var(--rubydev-primary);
}

/* 28 chapters carried 28 different gradients — teal, lime, pink, indigo, peach.
   Red is the only accent in this brand, so they are one mark now. */
.rd-nav-chapter__badge {
  flex: 0 0 20px;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: linear-gradient(135deg, var(--rubydev-primary) 0%, var(--rubydev-dark) 100%);
  display: flex;
  align-items: center;
  justify-content: center;
}

.rd-nav-chapter__lessons {
  display: grid;
  gap: 0.5rem;
}

/* A collapsed chapter is one row in an index, so the 1rem that separates a heading
   from its lessons goes away with the lessons. The laptop view is always open and
   never sees this rule. */
details:not([open]) > .rd-nav-chapter__summary > .rd-nav-chapter__title {
  margin-bottom: 0;
}

/* Collapse/expand marker. Only drawn where the disclosure is interactive, i.e.
   below the laptop breakpoint; the laptop view has no marker and no summary
   affordance, exactly as before. */
.rd-hub__nav-summary::after,
.rd-nav-chapter__title::after {
  content: "";
  flex: none;
  margin-left: auto;
  width: 0.4rem;
  height: 0.4rem;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
}

details[open] > .rd-hub__nav-summary::after,
details[open] > .rd-nav-chapter__summary > .rd-nav-chapter__title::after {
  transform: rotate(225deg);
}

@media (prefers-reduced-motion: no-preference) {
  .rd-hub__nav-summary::after,
  .rd-nav-chapter__title::after {
    transition: transform 0.2s ease;
  }
}

@media (min-width: 1024px) {
  .rd-hub__nav-summary::after,
  .rd-nav-chapter__title::after {
    display: none;
  }
}

/* ----------------------------------------------------------------------------
   Navigation rows. 123 lesson links and 30 quiz/course chips each carried the
   same inline style string; the values are identical here. Hover and focus
   states could not exist while the base declaration was inline — a stylesheet
   never beats a `style=` attribute — which is why the links had a
   `transition: all 0.2s` that could never fire.
   -------------------------------------------------------------------------- */
.rd-nav-link {
  display: block;
  padding: 0.75rem 1rem;
  border-radius: 0.5rem;
  border-left: 3px solid transparent;
  color: var(--gray-700);
  text-decoration: none;
}

.rd-nav-link__title {
  font-weight: 500;
}

.rd-nav-link__meta {
  display: block;
  margin-top: 0.25rem;
  font-size: 0.75rem;
  color: var(--text-secondary);
}

.rd-nav-chip,
.rd-nav-chip-link {
  text-decoration: none;
}

.rd-nav-chip {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-top: 0.5rem;
  padding: 0.75rem 1rem;
  border-radius: 0.5rem;
  border-left: 3px solid var(--rubydev-primary);
  background: var(--rubydev-pale);
  color: var(--rubydev-primary);
}

.rd-nav-chip > svg {
  flex: none;
}

.rd-nav-chip__label {
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--rubydev-primary);
}

.rd-nav-link:hover {
  background: var(--gray-100);
}

/* Only the chips that are actually links react to a pointer. Several are plain
   <div>s with no destination yet, and those should not pretend otherwise. */
a.rd-nav-chip:hover,
.rd-nav-chip-link:hover > .rd-nav-chip {
  background: var(--rubydev-accent);
}

.rd-nav-link:focus-visible,
a.rd-nav-chip:focus-visible,
.rd-nav-chip-link:focus-visible {
  outline: 2px solid var(--rubydev-primary);
  outline-offset: 2px;
}

/* ============================================================================
   RAILS LEARNING HUB  —  /rails-home
   ----------------------------------------------------------------------------
   The page is a fixed 300px topic index beside the documentation column. On a
   390px phone that left ~90px of content, so the shell, the index and the index
   headings are the one part of this view that genuinely needs a breakpoint;
   everything else on the page is handled with clamp() and auto-fit grids inline.

   These rules live here rather than in a <style> island in the template because
   an island cannot be audited, cannot be reused, and - more practically - the
   hover and focus states have to beat the inline style= attributes the template
   still carries, which is what the !important declarations below are for.
   ============================================================================ */
.rails-home-shell {
  display: grid;
  grid-template-columns: 300px minmax(0, 1fr);
  min-height: 100vh;
  background: #FFFFFF;
}

.rails-home-sidebar {
  min-width: 0;
  background: #F9FAFB;
  border-right: 1px solid #E5E7EB;
  padding: clamp(1.1rem, 4vw, 2rem) 1.5rem;
}

.rails-home-main {
  min-width: 0;
  padding: clamp(1.1rem, 4vw, 2rem) clamp(1.65rem, 4vw, 3rem);
}

/* A topic group. <details open> keeps the desktop rendering byte-identical to the
   22 always-expanded <div> groups it replaces, and gives a phone a collapse
   control that is keyboard operable without a line of JavaScript. */
.rails-nav-group {
  margin-bottom: 2rem;
}

.rails-nav-group__summary {
  display: block; /* suppresses the UA disclosure triangle */
  list-style: none;
}

.rails-nav-group__summary::-webkit-details-marker {
  display: none;
}

.rails-nav-group__summary:focus-visible {
  outline: 2px solid #DC2626;
  outline-offset: 2px;
  border-radius: 0.25rem;
}

.rails-nav-group__title {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin: 0 0 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 2px solid #DC2626;
  color: #1F2937;
  font-size: 0.875rem;
  font-weight: 700;
  text-transform: uppercase;
}

.rails-nav-group__icon {
  display: flex;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: linear-gradient(135deg, #DC2626 0%, #B91C1C 100%);
}

.rails-nav-group__items {
  display: grid;
  gap: 0.5rem;
}

/* The index links keep their inline style= for now; only the interactive states
   are here, so they need to outrank that attribute. */
.rails-nav-link:hover {
  background: #F3F4F6 !important;
  border-left-color: #DC2626 !important;
}

.rails-nav-link:focus-visible {
  outline: 2px solid #DC2626;
  outline-offset: 2px;
}

.rails-nav-link.active {
  background: #FEF2F2 !important;
  border-left-color: #DC2626 !important;
  color: #DC2626 !important;
}

/* The external resource cards used to carry onmouseover/onmouseout attributes
   that repainted them in JavaScript, which meant keyboard users never saw the
   state at all. */
.rails-resource-link:hover,
.rails-resource-link:focus-visible {
  background: #FAFAFA !important;
  border-color: #DC2626 !important;
}

.rails-home-shell code {
  background: #F3F4F6 !important;
  padding: 0.25rem 0.5rem !important;
  border-radius: 0.25rem !important;
  font-family: "Monaco", "Menlo", monospace !important;
  font-size: 0.875rem !important;
}

@media (min-width: 1025px) {
  /* Desktop has no disclosure affordance, so it must not be possible to collapse
     a group by clicking its heading. Keyboard toggling still works. */
  .rails-nav-group__summary {
    pointer-events: none;
  }

  .rails-nav-group__summary a,
  .rails-nav-group__summary button {
    pointer-events: auto;
  }
}

@media (max-width: 1024px) {
  /* The index stacks above the documentation. Capped so 22 groups are a browsable
     panel rather than several screens of scrolling before the first paragraph. */
  .rails-home-shell {
    grid-template-columns: minmax(0, 1fr);
    min-height: 0;
  }

  .rails-home-sidebar {
    border-right: 0;
    border-bottom: 1px solid #E5E7EB;
    padding: 1.25rem 1rem;
    max-height: 60vh;
    overflow-y: auto;
  }

  .rails-home-main {
    padding: 1.5rem 1rem;
  }

  .rails-nav-group {
    margin-bottom: 1.25rem;
  }

  .rails-nav-group__summary {
    cursor: pointer;
  }

  /* A chevron, drawn in CSS so the markup carries no extra icon. */
  .rails-nav-group__title::after {
    content: "";
    flex: 0 0 auto;
    width: 0.4rem;
    height: 0.4rem;
    margin-left: auto;
    border-right: 2px solid #9CA3AF;
    border-bottom: 2px solid #9CA3AF;
    transform: rotate(45deg);
  }

  .rails-nav-group[open] .rails-nav-group__title::after {
    transform: rotate(-135deg);
  }
}

/* ----------------------------------------------------------------------------
   DOCUMENTATION SHELL (app/views/learning/documentation.html.erb)
   The same fixed-rail pattern as .learn-shell, but the rail is `position: fixed`
   and the content clears it with `margin-left: 300px`. On a phone that parks a
   300px panel over the article. Below 1024px the rail is a normal block that the
   page scrolls past; from 1024px up it is the original fixed rail, unchanged.
   (This template has no route today — see the report — but the defect is the one
   that broke /learn, so it is fixed in the same place.)
   ---------------------------------------------------------------------------- */
.learn-docs-shell {
  display: block;
}

.learn-docs-shell__rail {
  width: 100%;
}

.learn-docs-shell__main {
  margin-left: 0;
}

@media (min-width: 1024px) {
  .learn-docs-shell {
    display: flex;
  }

  .learn-docs-shell__rail {
    position: fixed;
    width: 300px;
    height: 100vh;
    overflow-y: auto;
  }

  .learn-docs-shell__main {
    margin-left: 300px;
  }
}
