/* ============================================
   5 Starr Pressure Washing — Global Styles
   ============================================ */

/* --- Reset & Base --- */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

:root {
  --primary: #0d6efd;
  --primary-dark: #0850b8;
  --accent: #ffc107;
  --dark: #111827;
  --dark-light: #1f2937;
  --gray: #6b7280;
  --gray-light: #f3f4f6;
  --white: #ffffff;
  --radius: 12px;
  --shadow: 0 4px 24px rgba(0,0,0,.08);
  --shadow-lg: 0 12px 40px rgba(0,0,0,.12);
  --transition: .3s ease;
}

/*
  The `hidden` attribute has to actually hide.

  `[hidden] { display: none }` comes from the BROWSER's own stylesheet, and any
  author rule beats a user-agent rule no matter how weak its selector. So a
  class that sets `display` — `.book-review > div { display: grid }`,
  `.book-chosen-row { display: flex }` — leaves the element on screen while the
  script that set `hidden` believes it has taken it away. On the booking page
  that would show empty "Service" and "Notes" rows in the summary a customer is
  being asked to check before sending.

  Declared once, here, rather than as a per-component `.thing[hidden]` rule that
  the next component to use `hidden` would have to remember to add.
*/
[hidden] { display: none !important; }

html { scroll-behavior: smooth; }

body {
  font-family: 'Segoe UI', system-ui, -apple-system, sans-serif;
  color: var(--dark);
  line-height: 1.6;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a { text-decoration: none; color: inherit; }
ul { list-style: none; }

/* --- Utility --- */
.container { width: 90%; max-width: 1200px; margin: 0 auto; }
.section { padding: 80px 0; }
.section-dark { background: var(--dark); color: var(--white); }
.section-light { background: var(--gray-light); }
.text-center { text-align: center; }
.text-accent { color: var(--accent); }
.text-primary { color: var(--primary); }

.section-header { margin-bottom: 50px; text-align: center; }
.section-header h2 {
  font-size: 2.4rem;
  font-weight: 800;
  margin-bottom: 12px;
}
.section-header p {
  font-size: 1.1rem;
  color: var(--gray);
  max-width: 600px;
  margin: 0 auto;
}
.section-dark .section-header p { color: #9ca3af; }

/* --- Buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 32px;
  border-radius: 50px;
  font-size: 1rem;
  font-weight: 700;
  border: none;
  cursor: pointer;
  transition: var(--transition);
  text-transform: uppercase;
  letter-spacing: .5px;
}
.btn-primary {
  background: var(--primary);
  color: var(--white);
}
.btn-primary:hover {
  background: var(--primary-dark);
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(13,110,253,.35);
}
.btn-accent {
  background: var(--accent);
  color: var(--dark);
}
.btn-accent:hover {
  background: #e0a800;
  transform: translateY(-2px);
  box-shadow: 0 8px 25px rgba(255,193,7,.35);
}
.btn-outline {
  background: transparent;
  color: var(--white);
  border: 2px solid var(--white);
}
.btn-outline:hover {
  background: var(--white);
  color: var(--dark);
}
.btn-dark {
  background: var(--dark);
  color: var(--white);
}
.btn-dark:hover {
  background: var(--dark-light);
  transform: translateY(-2px);
}

/* --- Navbar --- */
.navbar {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 1000;
  padding: 16px 0;
  transition: var(--transition);
}
.navbar.scrolled {
  background: rgba(255,255,255,.97);
  backdrop-filter: blur(12px);
  box-shadow: 0 2px 20px rgba(0,0,0,.08);
  padding: 10px 0;
}
.navbar .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.logo {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 1.35rem;
  font-weight: 800;
  color: var(--white);
  transition: var(--transition);
}
.navbar.scrolled .logo { color: var(--dark); }
.logo-icon {
  width: 42px;
  height: 42px;
  background: var(--primary);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  color: var(--white);
}
.logo .stars { color: var(--accent); font-size: .9rem; letter-spacing: 2px; display: block; line-height: 1; }

.nav-links {
  display: flex;
  align-items: center;
  gap: 32px;
}
.nav-links a {
  color: rgba(255,255,255,.85);
  font-weight: 600;
  font-size: .95rem;
  transition: var(--transition);
  position: relative;
}
.nav-links a::after {
  content: '';
  position: absolute;
  bottom: -4px; left: 0;
  width: 0;
  height: 2px;
  background: var(--accent);
  transition: var(--transition);
}
.nav-links a:hover::after,
.nav-links a.active::after { width: 100%; }
.nav-links a:hover { color: var(--white); }
.navbar.scrolled .nav-links a { color: var(--gray); }
.navbar.scrolled .nav-links a:hover { color: var(--dark); }

.nav-phone {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--accent);
  font-weight: 700;
  font-size: .95rem;
}
.navbar.scrolled .nav-phone { color: var(--primary); }

/* Hamburger */
.hamburger {
  display: none;
  flex-direction: column;
  gap: 5px;
  cursor: pointer;
  z-index: 1001;
}
.hamburger span {
  width: 28px; height: 3px;
  background: var(--white);
  border-radius: 2px;
  transition: var(--transition);
}
.navbar.scrolled .hamburger span { background: var(--dark); }

/* --- Hero --- */
.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  background: linear-gradient(135deg, #0f172a 0%, #1e3a5f 50%, #0d6efd 100%);
  overflow: hidden;
}
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.03'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
.hero-content {
  position: relative;
  z-index: 2;
  color: var(--white);
  max-width: 650px;
}
.hero-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: rgba(255,255,255,.1);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.15);
  padding: 8px 20px;
  border-radius: 50px;
  font-size: .9rem;
  font-weight: 600;
  margin-bottom: 24px;
  color: var(--accent);
}
.hero h1 {
  font-size: 3.6rem;
  font-weight: 900;
  line-height: 1.1;
  margin-bottom: 20px;
}
.hero h1 span { color: var(--accent); }
.hero p {
  font-size: 1.2rem;
  color: rgba(255,255,255,.8);
  margin-bottom: 36px;
  max-width: 520px;
}
.hero-buttons { display: flex; gap: 16px; flex-wrap: wrap; }

/* Water drops animation */
.water-drops {
  position: absolute;
  inset: 0;
  pointer-events: none;
  overflow: hidden;
}
.water-drops .drop {
  position: absolute;
  width: 8px; height: 8px;
  background: rgba(96,165,250,.3);
  border-radius: 50%;
  animation: dropFall linear infinite;
}
@keyframes dropFall {
  0% { transform: translateY(-10vh) scale(1); opacity: 0; }
  10% { opacity: 1; }
  90% { opacity: 1; }
  100% { transform: translateY(110vh) scale(.5); opacity: 0; }
}

/* Stats bar */
.stats-bar {
  position: absolute;
  bottom: 0; left: 0; right: 0;
  background: rgba(255,255,255,.08);
  backdrop-filter: blur(12px);
  border-top: 1px solid rgba(255,255,255,.1);
  z-index: 3;
}
.stats-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
}
.stat-item {
  text-align: center;
  padding: 28px 20px;
  border-right: 1px solid rgba(255,255,255,.08);
}
.stat-item:last-child { border-right: none; }
.stat-number {
  font-size: 2rem;
  font-weight: 900;
  color: var(--accent);
  display: block;
}
.stat-label {
  font-size: .85rem;
  color: rgba(255,255,255,.6);
  text-transform: uppercase;
  letter-spacing: 1px;
}

/* --- Cards --- */
.card {
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 36px;
  transition: var(--transition);
}
.card:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-lg);
}
.card-icon {
  width: 64px; height: 64px;
  background: linear-gradient(135deg, var(--primary), #3b82f6);
  border-radius: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.6rem;
  color: var(--white);
  margin-bottom: 20px;
}
.card h3 {
  font-size: 1.25rem;
  font-weight: 700;
  margin-bottom: 10px;
}
.card p {
  color: var(--gray);
  font-size: .95rem;
}

.grid-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 30px;
}
.grid-2 {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 30px;
}

/* --- Service Cards (services page) --- */
.service-card {
  background: var(--white);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  transition: var(--transition);
}
.service-card:hover {
  transform: translateY(-8px);
  box-shadow: var(--shadow-lg);
}
.service-card-img {
  height: 220px;
  background-size: cover;
  background-position: center;
  position: relative;
}
.service-card-img::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.4), transparent);
}
.service-card-body { padding: 28px; }
.service-card-body h3 {
  font-size: 1.3rem;
  font-weight: 700;
  margin-bottom: 10px;
}
.service-card-body p {
  color: var(--gray);
  margin-bottom: 16px;
}
.service-card-body ul { margin-bottom: 16px; }
.service-card-body ul li {
  padding: 4px 0;
  color: var(--gray);
  font-size: .93rem;
}
.service-card-body ul li::before {
  content: '✓';
  color: var(--primary);
  font-weight: 700;
  margin-right: 8px;
}

/* --- Before / After Gallery --- */
.gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(350px, 1fr));
  gap: 24px;
}
.gallery-item {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  cursor: pointer;
  aspect-ratio: 16/10;
}
.gallery-item .before,
.gallery-item .after {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--white);
  transition: var(--transition);
}
.gallery-item .before {
  background: linear-gradient(135deg, #78350f, #92400e);
  opacity: 1;
}
.gallery-item .after {
  background: linear-gradient(135deg, #065f46, #047857);
  opacity: 0;
}
.gallery-item:hover .before { opacity: 0; }
.gallery-item:hover .after { opacity: 1; }
.gallery-label {
  position: absolute;
  top: 12px;
  padding: 4px 14px;
  border-radius: 50px;
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
}
.label-before { left: 12px; background: rgba(0,0,0,.6); color: #fbbf24; }
.label-after { right: 12px; background: rgba(0,0,0,.6); color: #34d399; }

/* --- Testimonials --- */
.testimonial-card {
  background: var(--white);
  border-radius: var(--radius);
  padding: 32px;
  box-shadow: var(--shadow);
  position: relative;
}
.testimonial-card::before {
  content: '"';
  position: absolute;
  top: 16px; left: 24px;
  font-size: 4rem;
  color: var(--primary);
  opacity: .15;
  font-family: Georgia, serif;
  line-height: 1;
}
.testimonial-stars { color: var(--accent); font-size: 1.1rem; margin-bottom: 12px; }
.testimonial-text {
  color: var(--gray);
  font-style: italic;
  margin-bottom: 16px;
  font-size: .95rem;
}
.testimonial-author {
  font-weight: 700;
  font-size: .9rem;
}

/* --- CTA Banner --- */
.cta-banner {
  background: linear-gradient(135deg, var(--primary), #2563eb);
  padding: 64px 0;
  text-align: center;
  color: var(--white);
}
.cta-banner h2 {
  font-size: 2.2rem;
  font-weight: 800;
  margin-bottom: 12px;
}
.cta-banner p {
  font-size: 1.1rem;
  opacity: .85;
  margin-bottom: 28px;
}
.cta-banner .btn { font-size: 1.05rem; }

/* --- About Page --- */
.about-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 60px;
  align-items: center;
}
.about-img {
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  aspect-ratio: 4/3;
  background: linear-gradient(135deg, #1e3a5f, #0d6efd);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--white);
  font-size: 4rem;
}
.about-text h2 {
  font-size: 2.2rem;
  font-weight: 800;
  margin-bottom: 16px;
}
.about-text p {
  color: var(--gray);
  margin-bottom: 16px;
}
.values-list { margin-top: 24px; }
.values-list li {
  display: flex;
  align-items: flex-start;
  gap: 14px;
  margin-bottom: 18px;
}
.values-list .icon {
  width: 42px; height: 42px;
  min-width: 42px;
  background: rgba(13,110,253,.1);
  border-radius: 10px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--primary);
  font-size: 1.1rem;
}
.values-list strong { display: block; margin-bottom: 2px; }
.values-list span { color: var(--gray); font-size: .9rem; }

/* --- Contact --- */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1.2fr;
  gap: 50px;
}
.contact-info-card {
  background: var(--dark);
  color: var(--white);
  border-radius: var(--radius);
  padding: 40px;
}
.contact-info-card h3 {
  font-size: 1.5rem;
  margin-bottom: 8px;
}
.contact-info-card > p {
  color: #9ca3af;
  margin-bottom: 30px;
}
.contact-detail {
  display: flex;
  align-items: center;
  gap: 16px;
  margin-bottom: 24px;
}
.contact-detail .icon {
  width: 48px; height: 48px;
  min-width: 48px;
  background: rgba(13,110,253,.2);
  border-radius: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  color: var(--primary);
}
.contact-detail strong { display: block; font-size: .85rem; color: #9ca3af; text-transform: uppercase; letter-spacing: .5px; }
.contact-detail span { font-size: 1.05rem; }
.contact-detail a { color: var(--white); transition: var(--transition); }
.contact-detail a:hover { color: var(--accent); }

.contact-form {
  background: var(--white);
  border-radius: var(--radius);
  padding: 40px;
  box-shadow: var(--shadow);
}
.contact-form h3 { font-size: 1.4rem; margin-bottom: 24px; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.form-group { margin-bottom: 18px; }
.form-group label {
  display: block;
  font-size: .9rem;
  font-weight: 600;
  margin-bottom: 6px;
  color: var(--dark);
}
.form-group input,
.form-group select,
.form-group textarea {
  width: 100%;
  padding: 12px 16px;
  border: 2px solid #e5e7eb;
  border-radius: 10px;
  font-size: 1rem;
  font-family: inherit;
  transition: var(--transition);
  background: var(--white);
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--primary);
  box-shadow: 0 0 0 4px rgba(13,110,253,.1);
}
.form-group textarea { resize: vertical; min-height: 120px; }

/* --- Footer --- */
.footer {
  background: var(--dark);
  color: var(--white);
  padding: 60px 0 0;
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1fr;
  gap: 40px;
  margin-bottom: 40px;
}
.footer-brand p {
  color: #9ca3af;
  margin-top: 12px;
  font-size: .93rem;
}
.footer h4 {
  font-size: 1rem;
  font-weight: 700;
  margin-bottom: 16px;
  text-transform: uppercase;
  letter-spacing: .5px;
}
.footer ul li { margin-bottom: 10px; }
.footer ul li a {
  color: #9ca3af;
  transition: var(--transition);
  font-size: .93rem;
}
.footer ul li a:hover { color: var(--accent); }
.footer-bottom {
  border-top: 1px solid rgba(255,255,255,.08);
  padding: 20px 0;
  text-align: center;
  font-size: .85rem;
  color: #6b7280;
}

/* --- Animations --- */
.fade-up {
  opacity: 0;
  transform: translateY(30px);
  transition: opacity .6s ease, transform .6s ease;
}
.fade-up.visible {
  opacity: 1;
  transform: translateY(0);
}

/* --- Page Hero (inner pages) --- */
.page-hero {
  padding: 160px 0 80px;
  background: linear-gradient(135deg, #0f172a, #1e3a5f);
  text-align: center;
  color: var(--white);
  position: relative;
  overflow: hidden;
}
.page-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.03'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
}
.page-hero h1 {
  font-size: 3rem;
  font-weight: 900;
  margin-bottom: 12px;
  position: relative;
}
.page-hero p {
  font-size: 1.15rem;
  color: rgba(255,255,255,.7);
  position: relative;
}

/* --- Process Steps --- */
.process-steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 30px;
  counter-reset: step;
}
.process-step {
  text-align: center;
  position: relative;
}
.process-step::before {
  counter-increment: step;
  content: counter(step);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px; height: 56px;
  background: var(--primary);
  color: var(--white);
  font-size: 1.3rem;
  font-weight: 800;
  border-radius: 50%;
  margin: 0 auto 16px;
}
.process-step h4 { font-size: 1.05rem; margin-bottom: 6px; }
.process-step p { color: var(--gray); font-size: .9rem; }

/* --- Responsive --- */
@media (max-width: 1024px) {
  .grid-3 { grid-template-columns: repeat(2, 1fr); }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 30px; }
  .stats-grid { grid-template-columns: repeat(2, 1fr); }
  .process-steps { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 768px) {
  .hero h1 { font-size: 2.4rem; }
  .section { padding: 60px 0; }
  .section-header h2 { font-size: 1.8rem; }
  .grid-3, .grid-2 { grid-template-columns: 1fr; }
  .about-grid { grid-template-columns: 1fr; gap: 30px; }
  .contact-grid { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr; }
  .form-row { grid-template-columns: 1fr; }
  .gallery-grid { grid-template-columns: 1fr; }
  .process-steps { grid-template-columns: 1fr 1fr; }

  .nav-links {
    position: fixed;
    top: 0; right: -100%;
    width: 280px;
    height: 100vh;
    background: var(--dark);
    flex-direction: column;
    justify-content: center;
    padding: 40px;
    gap: 24px;
    transition: var(--transition);
    box-shadow: -5px 0 30px rgba(0,0,0,.3);
  }
  .nav-links.open { right: 0; }
  /* Tap targets, not text.

     Measured in a real browser at 320, 360 and 390px: every item in the open
     drawer was 28px tall — the height of the words and nothing else. The
     guideline is 44px, and on a business where nearly every visitor is on a
     phone, a menu you have to aim at is a menu people give up on. `gap: 24px`
     above put the SPACE between the links rather than inside them, so the space
     was there but was not tappable.

     Padding rather than a fixed height, so a label that wraps to two lines grows
     instead of being clipped. `display:block` is what makes the padded box the
     full width of the drawer — an inline <a> would only take the width of its
     text and the rest of the row would stay dead. */
  .nav-links a {
    color: var(--white) !important;
    font-size: 1.1rem;
    display: block;
    padding: 10px 4px;
  }
  .hamburger { display: flex; }
  .nav-phone { display: none; }
  .hero-buttons { flex-direction: column; align-items: flex-start; }
  .page-hero h1 { font-size: 2.2rem; }
}

@media (max-width: 480px) {
  .hero h1 { font-size: 2rem; }
  .stats-grid { grid-template-columns: 1fr 1fr; }
  .stat-item { padding: 18px 10px; }
  .stat-number { font-size: 1.5rem; }
  .process-steps { grid-template-columns: 1fr; }
}

/* ============================================================
   Moved from gallery.html <style> — verbatim, no value changes.
   These pages now load only /style.css, so the rules live here.
   ============================================================ */

/* Gallery-specific styles */
.gallery-filter {
  display: flex;
  justify-content: center;
  gap: 12px;
  margin-bottom: 40px;
  flex-wrap: wrap;
}
.filter-btn {
  padding: 10px 24px;
  border-radius: 50px;
  border: 2px solid #e5e7eb;
  background: var(--white);
  font-weight: 600;
  font-size: .9rem;
  cursor: pointer;
  transition: var(--transition);
  font-family: inherit;
}
.filter-btn:hover,
.filter-btn.active {
  background: var(--primary);
  color: var(--white);
  border-color: var(--primary);
}

.gallery-card {
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  transition: var(--transition);
  background: var(--white);
}
.gallery-card:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-lg);
}
.gallery-comparison {
  position: relative;
  aspect-ratio: 16/10;
  overflow: hidden;
  cursor: pointer;
}
.gallery-side {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  transition: opacity .4s ease;
  padding: 20px;
  text-align: center;
}
.gallery-side.before-side {
  background: linear-gradient(135deg, #78350f, #a16207);
}
.gallery-side.after-side {
  background: linear-gradient(135deg, #065f46, #059669);
  opacity: 0;
}
.gallery-card:hover .before-side { opacity: 0; }
.gallery-card:hover .after-side { opacity: 1; }
.gallery-side .emoji { font-size: 3rem; margin-bottom: 8px; }
.gallery-side .side-label {
  display: inline-block;
  padding: 4px 16px;
  border-radius: 50px;
  font-size: .75rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: var(--white);
  margin-bottom: 8px;
}
.before-side .side-label { background: rgba(0,0,0,.3); }
.after-side .side-label { background: rgba(0,0,0,.3); }
.gallery-side .description {
  color: rgba(255,255,255,.85);
  font-size: .9rem;
}
.gallery-card-body {
  padding: 20px;
}
.gallery-card-body h3 { font-size: 1.1rem; margin-bottom: 4px; }
.gallery-card-body p { color: var(--gray); font-size: .88rem; }
.gallery-card-body .tag {
  display: inline-block;
  background: rgba(13,110,253,.1);
  color: var(--primary);
  padding: 3px 12px;
  border-radius: 50px;
  font-size: .75rem;
  font-weight: 600;
  margin-top: 8px;
}
.hover-hint {
  text-align: center;
  color: var(--gray);
  font-size: .9rem;
  margin-bottom: 30px;
}

/* ============================================================
   Moved from contact.html <style> — verbatim, no value changes.
   ============================================================ */

.success-message {
  display: none;
  background: #ecfdf5;
  border: 2px solid #10b981;
  border-radius: var(--radius);
  padding: 24px;
  text-align: center;
  margin-top: 16px;
}
.success-message h3 { color: #065f46; margin-bottom: 8px; }
.success-message p { color: #047857; }
.faq-item {
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  margin-bottom: 16px;
  overflow: hidden;
}
.faq-question {
  padding: 20px 24px;
  font-weight: 700;
  cursor: pointer;
  display: flex;
  justify-content: space-between;
  align-items: center;
  transition: var(--transition);
}
.faq-question:hover { background: var(--gray-light); }
.faq-question .arrow {
  transition: transform .3s ease;
  font-size: 1.2rem;
  color: var(--primary);
}
.faq-item.open .faq-question .arrow { transform: rotate(180deg); }
.faq-answer {
  max-height: 0;
  overflow: hidden;
  transition: max-height .3s ease, padding .3s ease;
  padding: 0 24px;
  color: var(--gray);
  font-size: .95rem;
  line-height: 1.7;
}
.faq-item.open .faq-answer {
  max-height: 300px;
  padding: 0 24px 20px;
}

/* ============================================================
   Service areas / city landing pages

   Markup contract used below:
     ul.areas-grid > li > a.area-card
         h3                 city name
         p.area-county      county line   (a bare <p> is styled too)
         span.area-link     "View details" affordance
         span.area-badge    optional, e.g. the primary city
   ============================================================ */

.areas-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
  gap: 24px;
}
.area-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--white);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 28px;
  color: var(--dark);
  transition: var(--transition);
}
.area-card:hover {
  transform: translateY(-6px);
  box-shadow: var(--shadow-lg);
}
.area-card h3 {
  font-size: 1.2rem;
  font-weight: 700;
  margin-bottom: 4px;
}
.area-card p,
.area-card .area-county {
  color: var(--gray);
  font-size: .92rem;
}
.area-card .area-badge {
  display: inline-block;
  align-self: flex-start;
  background: rgba(255,193,7,.18);
  color: #92400e;
  padding: 3px 12px;
  border-radius: 50px;
  font-size: .7rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 1px;
  margin-bottom: 10px;
}
.area-card .area-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-top: auto;
  padding-top: 18px;
  color: var(--primary);
  font-weight: 700;
  font-size: .88rem;
}
.area-card .area-link::after {
  content: '\2192';
  transition: var(--transition);
}
.area-card:hover .area-link { color: var(--primary-dark); }
.area-card:hover .area-link::after { transform: translateX(4px); }

.local-note {
  background: rgba(13,110,253,.06);
  border-left: 4px solid var(--primary);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 24px 28px;
  margin: 28px 0;
}
.local-note h3,
.local-note h4 {
  font-size: 1.05rem;
  font-weight: 700;
  margin-bottom: 8px;
  color: var(--dark);
}
.local-note p {
  color: var(--gray);
  font-size: .96rem;
}
.local-note p + p { margin-top: 12px; }
.section-dark .local-note {
  background: rgba(255,255,255,.05);
  border-left-color: var(--accent);
}
.section-dark .local-note h3,
.section-dark .local-note h4 { color: var(--white); }
.section-dark .local-note p { color: #9ca3af; }

.neighborhood-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 16px;
}
.neighborhood-list li {
  display: inline-block;
  background: rgba(13,110,253,.1);
  color: var(--primary);
  padding: 4px 14px;
  border-radius: 50px;
  font-size: .8rem;
  font-weight: 600;
}
.section-dark .neighborhood-list li {
  background: rgba(255,255,255,.1);
  color: var(--white);
}

/* ============================================================
   Breadcrumbs (inner pages, sits directly under .page-hero)
   ============================================================ */

.breadcrumbs {
  font-size: .85rem;
  color: var(--gray);
  padding: 18px 0;
}
.breadcrumbs ol,
.breadcrumbs ul {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
}
.breadcrumbs li {
  display: flex;
  align-items: center;
  gap: 8px;
}
.breadcrumbs li + li::before {
  content: '/';
  color: #d1d5db;
}
.breadcrumbs a {
  color: var(--gray);
  transition: var(--transition);
}
.breadcrumbs a:hover { color: var(--primary); }
.breadcrumbs [aria-current="page"],
.breadcrumbs .current {
  color: var(--dark);
  font-weight: 600;
}
/* On a dark hero the muted greys disappear — flip to light. */
.page-hero .breadcrumbs,
.section-dark .breadcrumbs {
  position: relative;
  color: rgba(255,255,255,.6);
}
.page-hero .breadcrumbs a,
.section-dark .breadcrumbs a { color: rgba(255,255,255,.6); }
.page-hero .breadcrumbs a:hover,
.section-dark .breadcrumbs a:hover { color: var(--accent); }
.page-hero .breadcrumbs li + li::before,
.section-dark .breadcrumbs li + li::before { color: rgba(255,255,255,.3); }
.page-hero .breadcrumbs [aria-current="page"],
.page-hero .breadcrumbs .current,
.section-dark .breadcrumbs [aria-current="page"],
.section-dark .breadcrumbs .current { color: var(--white); }

/* ============================================================
   Gallery real photos

   A .gallery-side carries a photo via class .has-photo and/or an
   inline background-image — either one alone triggers these rules.
   A dark gradient scrim keeps the label and caption legible over any
   photo; the hover-to-reveal-after behaviour above is untouched
   (the scrim lives inside the side, so it fades with it).
   ============================================================ */

.gallery-side.has-photo,
.gallery-side[style*="background-image"] {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  justify-content: flex-end;
}
.gallery-side.has-photo::before,
.gallery-side[style*="background-image"]::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,.8) 0%, rgba(0,0,0,.5) 45%, rgba(0,0,0,.05) 100%);
  pointer-events: none;
}
.gallery-side.has-photo > *,
.gallery-side[style*="background-image"] > * {
  position: relative;
  z-index: 1;
}
.gallery-side.has-photo .emoji,
.gallery-side[style*="background-image"] .emoji { display: none; }
.gallery-side.has-photo .side-label,
.gallery-side[style*="background-image"] .side-label {
  background: rgba(0,0,0,.6);
  backdrop-filter: blur(4px);
}
.gallery-side.has-photo .description,
.gallery-side[style*="background-image"] .description {
  color: rgba(255,255,255,.95);
  text-shadow: 0 1px 3px rgba(0,0,0,.7);
}
/* If the photo is a real <img> (better for SEO/alt text) it sits
   under the scrim rather than replacing the background. */
.gallery-side .gallery-photo {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}

/* ============================================================
   Form status states
   ============================================================ */

/* Mirror of .success-message above, in the red family. */
.form-error {
  display: none;
  background: #fef2f2;
  border: 2px solid #ef4444;
  border-radius: var(--radius);
  padding: 24px;
  text-align: center;
  margin-top: 16px;
}
.form-error h3 { color: #7f1d1d; margin-bottom: 8px; }
.form-error p { color: #b91c1c; }

.btn[disabled],
.btn:disabled,
.btn[aria-disabled="true"] {
  opacity: .6;
  cursor: not-allowed;
  box-shadow: none;
  transform: none;
}
.btn[disabled]:hover,
.btn:disabled:hover,
.btn[aria-disabled="true"]:hover {
  transform: none;
  box-shadow: none;
}
.btn-primary[disabled]:hover,
.btn-primary:disabled:hover { background: var(--primary); }
.btn-accent[disabled]:hover,
.btn-accent:disabled:hover { background: var(--accent); }
.btn-dark[disabled]:hover,
.btn-dark:disabled:hover { background: var(--dark); }
.btn-outline[disabled]:hover,
.btn-outline:disabled:hover { background: transparent; color: var(--white); }

.btn.is-submitting {
  pointer-events: none;
  opacity: .75;
  cursor: progress;
  transform: none;
  box-shadow: none;
}
.btn.is-submitting::before {
  content: '';
  flex: none;
  width: 16px;
  height: 16px;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  animation: btnSpin .7s linear infinite;
}
@keyframes btnSpin {
  to { transform: rotate(360deg); }
}

/* ============================================================
   Accessibility utilities
   ============================================================ */

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 2000;
  transform: translateY(-120%);
  background: var(--dark);
  color: var(--white);
  padding: 14px 24px;
  border-radius: 0 0 var(--radius) 0;
  font-weight: 700;
  font-size: .95rem;
  transition: transform .2s ease;
}
.skip-link:focus,
.skip-link:focus-visible {
  transform: translateY(0);
}

/* --- Visible keyboard focus (there was none anywhere) ---
   Yellow ring with a dark halo behind it, so it stays high-contrast
   on the white sections, the navy hero, and the dark footer alike. */
:where(a, button, input, select, textarea, summary, [tabindex], [role="button"]):focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  box-shadow: 0 0 0 6px rgba(17,24,39,.45);
}
/* Form fields keep the existing blue focus family, but gain a real
   ring — .form-group input:focus sets outline:none and would win. */
.form-group input:focus-visible,
.form-group select:focus-visible,
.form-group textarea:focus-visible {
  outline: 3px solid var(--primary);
  outline-offset: 2px;
  border-color: var(--primary);
  box-shadow: 0 0 0 4px rgba(13,110,253,.15);
}
/* Make the halo follow each element's own shape. */
.btn:focus-visible,
.filter-btn:focus-visible,
.hero-badge:focus-visible { border-radius: 50px; }
.card:focus-visible,
.service-card:focus-visible,
.gallery-card:focus-visible,
.area-card:focus-visible,
.faq-question:focus-visible { border-radius: var(--radius); }
.logo:focus-visible { border-radius: 10px; }

/* ============================================================
   Reduced motion

   The homepage animates 30 falling water drops with no in-page
   opt-out, which is a genuine vestibular trigger. Honour the OS
   setting: kill the drops, the reveal transform, and the hover lifts.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  /* Water drops: removed entirely, not merely slowed. */
  .water-drops { display: none; }
  .water-drops .drop { animation: none; }

  /* Scroll reveal: content visible immediately, no translate. */
  .fade-up,
  .fade-up.visible {
    opacity: 1;
    transform: none;
    transition: none;
  }

  /* Hover lifts. */
  .card:hover,
  .service-card:hover,
  .gallery-card:hover,
  .area-card:hover,
  .btn-primary:hover,
  .btn-accent:hover,
  .btn-dark:hover,
  .area-card:hover .area-link::after {
    transform: none;
  }

  /* Everything else: instant, but still functional (the FAQ
     accordion and the mobile nav still open, just without easing). */
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ============================================================
   Template integration

   The templates use semantic <button> and heading levels where the
   original hand-written HTML used <div> and skipped levels. Native
   buttons bring their own background, border, font and width, so the
   rules above would otherwise render them as grey system buttons.
   ============================================================ */

/* Hamburger and FAQ toggles are real <button>s (keyboard-operable,
   announced correctly) — strip the UA chrome so they look identical
   to the divs they replaced. */
.hamburger {
  background: none;
  border: 0;
  padding: 0;
  -webkit-appearance: none;
  appearance: none;
}

.faq-question {
  width: 100%;
  background: transparent;
  border: 0;
  /* NOT the `font` shorthand — it would reset the font-weight:700 set on
     .faq-question above and silently un-bold every question. */
  font-family: inherit;
  font-size: inherit;
  line-height: inherit;
  color: inherit;
  text-align: left;
  -webkit-appearance: none;
  appearance: none;
}

/* Section headings inside the contact cards are <h2> (the page <h1> is
   the page title, so these are top-level sections) but carry the sizing
   the original <h3> rules defined. */
.contact-info-card h2 {
  font-size: 1.5rem;
  margin-bottom: 8px;
}
.contact-form h2 {
  font-size: 1.4rem;
  margin-bottom: 24px;
}

/* Footer contact row — phone, email, address, hours. Sits between the
   link columns and the copyright line. */
.footer-contact {
  border-top: 1px solid rgba(255,255,255,.08);
  padding-top: 24px;
}
.footer-contact ul {
  display: flex;
  flex-wrap: wrap;
  gap: 12px 32px;
}
.footer-contact li,
.footer-contact a,
.footer-contact address {
  color: #9ca3af;
  font-size: .93rem;
  font-style: normal;
  transition: var(--transition);
}
.footer-contact a:hover { color: var(--accent); }

/* Service and area cards are links wrapping block content. */
a.card { display: block; }

/* Gallery photos: stacking order.
   The scrim is a ::before with no z-index, so against an <img> at z-index 0 it
   would lose on DOM order and the photo would paint OVER it — leaving white
   label/caption text sitting directly on a bright driveway photo. Order it
   explicitly: photo (0) < scrim (1) < text (2). */
.gallery-side.has-photo .gallery-photo { z-index: 0; }
.gallery-side.has-photo::before { z-index: 1; }
.gallery-side.has-photo > *:not(.gallery-photo) { z-index: 2; }

/* ============================================================
   Audit fixes
   ============================================================ */

/* THE HERO CTAs WERE UNTAPPABLE ON PHONES.

   .stats-bar was position:absolute;bottom:0;z-index:3 inside a
   .hero{min-height:100vh} whose content is vertically centred at z-index:2.
   Being out of flow it added no height, so it painted over the bottom of the
   hero and swallowed the taps: at 375x667 and 360x640 NEITHER "Get a Free
   Estimate" nor the click-to-call button worked, and .nav-phone is display:none
   below 768px — so the homepage had no working call to action at all on the
   most common phone sizes. For a business that lives on phone calls that is the
   most expensive bug on the site.

   Putting the bar back in flow keeps the desktop look (a bar across the bottom
   of a full-height hero) and makes the overlap structurally impossible at every
   width, rather than patching it per breakpoint. */
.hero {
  flex-direction: column;
  align-items: stretch;
}
.hero > .container {
  margin: auto;          /* centres the copy in the space above the bar */
  position: relative;
  z-index: 2;
}
.stats-bar {
  position: static;
  z-index: 2;
}

/* The fixed navbar overlapped the hero badge — and at 320px the H1 — because
   the logo wraps to two lines on narrow screens. Shrink the logo and reserve
   the navbar's height at the top of the hero. */
@media (max-width: 768px) {
  .hero { padding-top: 92px; padding-bottom: 8px; }
}
@media (max-width: 480px) {
  .hero { padding-top: 104px; }
  .logo { font-size: 1.05rem; gap: 8px; }
  .logo-icon { width: 36px; height: 36px; font-size: 1rem; }
  .logo .stars { font-size: .75rem; letter-spacing: 1px; }
}

/* The city-page callout heading is an <h2>; the component rule only covered
   h3/h4, so it rendered at the UA default with no margin. */
.local-note h2 {
  font-size: 1.05rem;
  font-weight: 700;
  margin-bottom: 8px;
  color: var(--dark);
}
.section-dark .local-note h2 { color: var(--white); }

/* Owner-uploaded photos in a service card or the About story are <img>
   elements dropped into boxes sized for a background-image. Without object-fit
   the default `fill` stretches them out of proportion. */
.service-card-img,
.about-img {
  object-fit: cover;
}
img.service-card-img,
img.about-img {
  width: 100%;
  display: block;
}

/* Contrast: these four pairs missed WCAG AA (4.5:1 for normal text). */
.footer-bottom { color: #9ca3af; }
.cta-banner p { opacity: 1; color: rgba(255,255,255,.92); }
.gallery-card-body .tag { color: var(--primary-dark); }
.section-light .section-header p { color: #4b5563; }

/* ============================================================
   Sticky mobile call bar

   Below 768px .nav-phone is display:none, so a visitor who scrolled past the
   hero had no way to call without hunting for a CTA block. This site's whole
   business is inbound phone calls, so that gap costs jobs.

   Desktop keeps the navbar number and never renders this.
   ============================================================ */
.call-bar { display: none; }

@media (max-width: 768px) {
  .call-bar {
    display: flex;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 1200;              /* above the nav drawer's backdrop, below the drawer */
    gap: 10px;
    padding: 10px 12px calc(10px + env(safe-area-inset-bottom, 0px));
    background: rgba(17,24,39,.97);
    backdrop-filter: blur(10px);
    border-top: 1px solid rgba(255,255,255,.12);
    transform: translateY(110%);
    transition: transform .25s ease;
  }
  .call-bar.visible { transform: translateY(0); }

  .call-bar a {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;           /* comfortably above the 44px touch minimum */
    border-radius: 50px;
    font-weight: 700;
    font-size: .95rem;
    letter-spacing: .3px;
    padding: 0 14px;
  }
  .call-bar-phone { background: var(--accent); color: var(--dark); flex: 1.4; }
  .call-bar-quote { background: transparent; color: var(--white); border: 2px solid rgba(255,255,255,.35); }

  /* Stop the bar covering the last of the footer. */
  body { padding-bottom: 76px; }
}

@media (prefers-reduced-motion: reduce) {
  .call-bar { transition: none; }
}

/* ============================================================
   Gallery reveal — tappable, not hover-only

   The before/after swap was `.gallery-card:hover .after-side`. On a phone
   there is no hover, the card was a non-focusable <article>, and nothing
   listened for a tap — so the "after" photo, which is the entire point of a
   before/after gallery, was unreachable on Android and flaky on iOS while the
   page text said "hover or tap". It is now a <button> toggling .revealed.
   ============================================================ */
button.gallery-comparison {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  color: inherit;
  text-align: inherit;
  -webkit-appearance: none;
  appearance: none;
}

/* Tap / keyboard state, mirroring the existing hover rules. */
.gallery-card.revealed .before-side { opacity: 0; }
.gallery-card.revealed .after-side  { opacity: 1; }

/* On touch screens hover is unreliable or sticky, so let the class alone drive
   it there and keep hover purely as a desktop nicety. */
@media (hover: none) {
  .gallery-card:hover .before-side { opacity: 1; }
  .gallery-card:hover .after-side  { opacity: 0; }
  .gallery-card.revealed .before-side { opacity: 0; }
  .gallery-card.revealed .after-side  { opacity: 1; }
}

/* Post-submit actions — the only acknowledgement the customer gets, shown at
   the point of highest intent. Netlify Forms has no autoresponder, so if it is
   not on this screen it does not happen. */
.success-actions {
  display: flex;
  gap: 12px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 20px;
}
.success-actions .btn { min-height: 48px; }
.success-note {
  margin-top: 14px;
  font-size: .9rem;
  color: #047857;
}

/* ============================================================
   BOOKING — /book/, and the status vocabulary it shares with /admin

   Ported from the worry-free-saas admin calendar's design language, not its
   code: that one is React + Tailwind, this site has no build step, so what
   crosses over is the LOOK — a status colour carried as a 3px left border over
   a ~10% tint of itself, rounded cards, small pill badges, a day strip.

   The status colours are custom properties rather than literals because two
   surfaces have to agree on them: this page (a request shows as "pending") and
   the owner's calendar. A booking that reads amber here and blue there is a
   booking two people describe differently.

     pending   amber   — needs somebody to act. Worded as "Needs Action", never
                         "Pending": it says what to DO rather than naming a
                         state, which is the part of that calendar's vocabulary
                         most worth stealing.
     confirmed blue    — agreed and in the diary.
     completed emerald — done.
     cancelled slate   — cancelled or declined; present but inert.
     problem   red     — no-show, or something wrong.
   ============================================================ */

:root {
  --status-pending: #d97706;
  --status-pending-edge: #f59e0b;
  --status-pending-tint: #fef6e7;

  --status-confirmed: #1d4ed8;
  --status-confirmed-edge: #3b82f6;
  --status-confirmed-tint: #eaf1fe;

  --status-completed: #047857;
  --status-completed-edge: #10b981;
  --status-completed-tint: #e7f6f0;

  --status-cancelled: #64748b;
  --status-cancelled-edge: #cbd5e1;
  --status-cancelled-tint: #f1f5f9;

  --status-problem: #b91c1c;
  --status-problem-edge: #ef4444;
  --status-problem-tint: #fdecec;

  /* One hour of calendar. 64px is the admin grid's row height; the day strip
     and the window cards here are sized off the same scale so the two screens
     feel like one product. */
  --hour-height: 64px;
}

/* --- Layout ------------------------------------------------------------- */

.book-layout {
  display: grid;
  grid-template-columns: 1.6fr 1fr;
  gap: 40px;
  align-items: start;
}

.book-card {
  background: var(--white);
  border: 1px solid #e5e7eb;
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: var(--shadow);
  margin-bottom: 24px;
}

/* --- The honesty notice -------------------------------------------------- */

.book-notice {
  border: 1px solid var(--status-pending-edge);
  border-left: 4px solid var(--status-pending-edge);
  background: var(--status-pending-tint);
  border-radius: var(--radius);
  padding: 24px;
  margin-bottom: 32px;
}
.book-notice h2 {
  font-size: 1.25rem;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 8px;
}
.book-notice p { color: #4b5563; }

.book-pill {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 50px;
  font-size: .72rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .6px;
  white-space: nowrap;
}
.book-pill-pending { background: var(--status-pending-edge); color: #3b2600; }

.book-how {
  list-style: none;
  counter-reset: bookstep;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-top: 20px;
}
.book-how li {
  counter-increment: bookstep;
  background: rgba(255,255,255,.7);
  border-radius: 10px;
  padding: 14px 16px;
}
.book-how li::before {
  content: counter(bookstep);
  display: flex;
  align-items: center;
  justify-content: center;
  width: 26px; height: 26px;
  border-radius: 50%;
  background: var(--status-pending-edge);
  color: #3b2600;
  font-weight: 800;
  font-size: .8rem;
  margin-bottom: 8px;
}
.book-how strong { display: block; font-size: .98rem; }
.book-how span { display: block; font-size: .88rem; color: #4b5563; }

/* --- Fallback (the default state, not the error state) ------------------- */

.book-fallback {
  background: var(--dark);
  color: var(--white);
  border-radius: var(--radius);
  padding: 28px;
}
.book-fallback h2 { font-size: 1.3rem; margin-bottom: 8px; }
.book-fallback p { color: #9ca3af; }
.book-fallback-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
  margin-top: 18px;
}
.book-fallback-actions .btn { min-height: 48px; }
.book-fallback-form { margin-top: 14px; font-size: .93rem; }
.book-fallback-form a { color: var(--accent); text-decoration: underline; }

/* --- Widget shell -------------------------------------------------------- */

.book-widget {
  background: var(--white);
  border: 1px solid #e5e7eb;
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: var(--shadow);
}
.book-widget[hidden] { display: none; }

.book-status {
  font-size: .95rem;
  color: var(--gray);
  padding: 10px 0;
}

.book-alert {
  border: 1px solid var(--status-problem-edge);
  border-left: 4px solid var(--status-problem-edge);
  background: var(--status-problem-tint);
  border-radius: 10px;
  padding: 16px 18px;
  margin-bottom: 20px;
}
.book-alert-text { color: #7f1d1d; font-weight: 600; }
.book-alert-actions { margin-top: 12px; }

.book-chosen {
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  padding: 10px 14px;
  margin-bottom: 20px;
  background: var(--gray-light);
}
.book-chosen-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 4px 0;
}
.book-chosen-value { font-weight: 700; font-size: .95rem; }

.book-link {
  background: none;
  border: 0;
  padding: 4px 2px;
  font: inherit;
  font-size: .88rem;
  font-weight: 700;
  color: var(--primary);
  text-decoration: underline;
  cursor: pointer;
}

/* --- Steps --------------------------------------------------------------- */

.book-step[hidden] { display: none; }
.book-step-title {
  display: flex;
  align-items: center;
  gap: 12px;
  flex-wrap: wrap;
  font-size: 1.2rem;
  margin-bottom: 16px;
}
.book-step-num {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 30px; height: 30px;
  min-width: 30px;
  border-radius: 50%;
  background: var(--primary);
  color: var(--white);
  font-size: .9rem;
  font-weight: 800;
}

.book-choices { display: grid; gap: 14px; }
.book-choice {
  text-align: left;
  border: 1px solid #e5e7eb;
  border-left: 3px solid var(--status-confirmed-edge);
  background: var(--status-confirmed-tint);
  border-radius: 10px;
  padding: 18px 20px;
  font: inherit;
  cursor: pointer;
  transition: var(--transition);
  min-height: 64px;
}
.book-choice:hover { box-shadow: var(--shadow); transform: translateY(-1px); }
.book-choice.is-selected {
  border-color: var(--primary);
  border-left-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(13,110,253,.15);
}
.book-choice-label { display: block; font-weight: 800; font-size: 1.05rem; }
.book-choice-help { display: block; margin-top: 4px; font-size: .9rem; color: #4b5563; }

/* Day strip — the phone-first shape. One chip per day, scrolled sideways;
   never a 7-column week grid, which is unusable at 375px. */
.book-days {
  display: flex;
  gap: 10px;
  overflow-x: auto;
  padding: 4px 2px 12px;
  scroll-snap-type: x proximity;
  -webkit-overflow-scrolling: touch;
}
.book-day {
  flex: 0 0 auto;
  scroll-snap-align: start;
  width: 76px;
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  background: var(--white);
  padding: 10px 6px;
  text-align: center;
  font: inherit;
  cursor: pointer;
  transition: var(--transition);
}
.book-day:hover { border-color: var(--primary); }
.book-day.is-selected {
  border-color: var(--primary);
  background: rgba(13,110,253,.08);
  box-shadow: 0 0 0 3px rgba(13,110,253,.15);
}
.book-day.is-full {
  background: var(--status-cancelled-tint);
  color: var(--status-cancelled);
  cursor: not-allowed;
}
.book-day-dow {
  display: block;
  font-size: .68rem;
  text-transform: uppercase;
  letter-spacing: .8px;
  color: var(--gray);
}
.book-day-num { display: block; font-size: 1.4rem; font-weight: 800; line-height: 1.1; }
.book-day-mon { display: block; font-size: .7rem; color: var(--gray); }
.book-day-free { display: block; margin-top: 4px; font-size: .68rem; font-weight: 700; }
.book-day.is-full .book-day-free { color: var(--status-cancelled); }

/* Arrival windows — the calendar's booking-card idiom: rounded, a 3px left
   border in the status colour over a tint of the same colour. */
.book-windows { display: grid; gap: 12px; }
.book-window {
  text-align: left;
  border: 1px solid #e5e7eb;
  border-left: 3px solid var(--status-confirmed-edge);
  background: var(--status-confirmed-tint);
  border-radius: 10px;
  padding: 14px 18px;
  font: inherit;
  cursor: pointer;
  transition: var(--transition);
  min-height: 56px;
}
.book-window:hover { box-shadow: var(--shadow); }
.book-window.is-selected {
  border-color: var(--primary);
  border-left-color: var(--primary);
  box-shadow: 0 0 0 3px rgba(13,110,253,.15);
}
.book-window.is-full {
  border-left-color: var(--status-cancelled-edge);
  background: var(--status-cancelled-tint);
  color: var(--status-cancelled);
  cursor: not-allowed;
}
.book-window-label { display: block; font-weight: 800; }
.book-window-time { display: block; font-size: .95rem; }
.book-window-state {
  display: inline-block;
  margin-top: 6px;
  padding: 2px 9px;
  border-radius: 50px;
  background: var(--status-cancelled-edge);
  color: #334155;
  font-size: .7rem;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: .5px;
}

.book-empty {
  border: 1px dashed #d1d5db;
  border-radius: 10px;
  padding: 20px;
  text-align: center;
  color: var(--gray);
}
.book-window-note {
  margin-top: 16px;
  font-size: .9rem;
  color: var(--gray);
  border-left: 3px solid #e5e7eb;
  padding-left: 12px;
}

/* --- Form and review ----------------------------------------------------- */

.form-help { font-size: .82rem; color: var(--gray); margin-top: 5px; }
.form-group input.is-invalid,
.form-group select.is-invalid,
.form-group textarea.is-invalid { border-color: var(--status-problem-edge); }

.book-field-error {
  color: var(--status-problem);
  font-weight: 600;
  font-size: .93rem;
  margin-bottom: 12px;
}
.book-submit { width: 100%; justify-content: center; min-height: 52px; }

.book-review {
  border: 1px solid #e5e7eb;
  border-radius: 10px;
  overflow: hidden;
}
.book-review > div {
  display: grid;
  grid-template-columns: 40% 60%;
  gap: 12px;
  padding: 11px 16px;
  border-bottom: 1px solid #f1f5f9;
}
.book-review > div:last-child { border-bottom: 0; }
.book-review dt { color: var(--gray); font-size: .88rem; }
.book-review dd { font-weight: 600; overflow-wrap: anywhere; }
.book-review-note { margin-top: 14px; font-size: .9rem; color: var(--gray); }
.book-review-actions {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
  margin-top: 20px;
}
.book-review-actions .btn { min-height: 52px; }

.book-done {
  border: 1px solid var(--status-pending-edge);
  border-left: 4px solid var(--status-pending-edge);
  background: var(--status-pending-tint);
  border-radius: 10px;
  padding: 22px;
}
.book-done-note { margin-top: 14px; font-size: .92rem; color: #4b5563; }

/* --- Service-area check -------------------------------------------------- */

.book-zip-row { display: flex; gap: 10px; }
.book-zip-row input { flex: 1; }
.book-zip-row .btn { padding: 12px 22px; }

.book-zip-answer {
  border-radius: 10px;
  padding: 14px 16px;
  margin-top: 4px;
  border-left: 3px solid var(--status-cancelled-edge);
  background: var(--status-cancelled-tint);
}
.book-zip-answer.is-covered {
  border-left-color: var(--status-completed-edge);
  background: var(--status-completed-tint);
}
.book-zip-answer.is-unknown {
  border-left-color: var(--status-pending-edge);
  background: var(--status-pending-tint);
}
.book-zip-heading { font-weight: 800; }
.book-zip-body { font-size: .92rem; color: #4b5563; margin-top: 4px; }
.book-zip-actions { margin-top: 12px; }
.book-zip-actions .btn { min-height: 48px; }

.book-zip-towns-label {
  margin-top: 18px;
  font-size: .85rem;
  color: var(--gray);
  text-transform: uppercase;
  letter-spacing: .5px;
  font-weight: 700;
}
.book-zip-towns {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 10px;
}
.book-zip-towns a {
  display: inline-block;
  padding: 5px 12px;
  border-radius: 50px;
  background: var(--gray-light);
  font-size: .85rem;
  font-weight: 600;
}
.book-zip-towns a:hover { background: #e5e7eb; }

.book-contact-card { background: var(--dark); color: var(--white); border-color: transparent; }
.book-contact-card .contact-detail:last-child { margin-bottom: 0; }

/* --- Phone first --------------------------------------------------------- */

@media (max-width: 1024px) {
  /* Six menu items plus the logo and the phone number stopped fitting at
     tablet widths with a 32px gap. */
  .nav-links { gap: 20px; }
  .book-layout { grid-template-columns: 1fr; gap: 28px; }
  .book-how { grid-template-columns: 1fr; }
}

@media (max-width: 768px) {
  .book-widget { padding: 18px 16px; }
  .book-notice { padding: 18px; }
  .book-fallback { padding: 22px 18px; }
  .book-card { padding: 18px; }
  .book-review > div { grid-template-columns: 1fr; gap: 2px; }
  .book-step-title { font-size: 1.08rem; }
  /* Full-width targets: this gets used one-handed, standing in a driveway. */
  .book-fallback-actions .btn,
  .book-review-actions .btn { width: 100%; justify-content: center; }
  .book-days { margin: 0 -16px; padding-left: 16px; padding-right: 16px; }
}

@media (prefers-reduced-motion: reduce) {
  .book-choice, .book-day, .book-window { transition: none; }
  .book-choice:hover { transform: none; }
}

/* ============================================================
   Site-wide booking entry points

   The booking page was reachable from exactly two places: the sticky mobile
   call bar, and one button on the contact page. On a desktop there was no way
   to book at all. These rules dress the menu and footer links that fix that
   (templates/partials/nav.njk, templates/partials/footer.njk).

   Every selector here is on markup that only exists when `bookingEnabled` is
   true — .nav-book, .nav-drawer-call, .footer-book and the .has-book class on
   #navLinks. With booking switched off none of them match anything, so a
   build with it off renders exactly as it did before any of this existed.
   Nothing below changes a rule that an existing element already uses.

   No new button style is invented: the pill is the .btn/.call-bar shape
   (border-radius:50px, weight 700, the accent and primary tokens) and the
   phone/booking pairing repeats the call bar's own hierarchy — the phone
   filled in accent and first, booking outlined and second.
   ============================================================ */

/* --- Menu: the Book pill --------------------------------------------------
   Selectors are written `.nav-links a.nav-book` rather than `.nav-book`
   because `.nav-links a` already sets colour and would otherwise win on
   specificity and paint the pill the same grey as the page links. */
.nav-links a.nav-book {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: 44px;              /* the touch minimum, met on every width */
  padding: 0 18px;
  border: 2px solid rgba(255,255,255,.5);
  border-radius: 50px;
  color: rgba(255,255,255,.95);
  font-weight: 700;
  font-size: .95rem;
  letter-spacing: .3px;
  white-space: nowrap;
}
/* The sweep-in underline is for text links; on a pill it draws a line under
   the border. `content: none` removes the pseudo-element outright rather than
   leaving a zero-width one that :hover would grow. */
.nav-links a.nav-book::after { content: none; }
.nav-links a.nav-book:hover {
  background: rgba(255,255,255,.16);
  color: var(--white);
  border-color: var(--white);
}
/* Current page. `.active` on a text link means the accent underline, which
   the pill has just removed — so it says so with the accent border instead. */
.nav-links a.nav-book.active {
  border-color: var(--accent);
  color: var(--accent);
}

/* Scrolled navbar: white background, so the white-on-transparent values above
   would leave a nearly invisible pill. */
.navbar.scrolled .nav-links a.nav-book {
  color: var(--primary);
  border-color: rgba(13,110,253,.45);
}
.navbar.scrolled .nav-links a.nav-book:hover {
  background: rgba(13,110,253,.08);
  color: var(--primary-dark);
  border-color: var(--primary);
}
.navbar.scrolled .nav-links a.nav-book.active {
  border-color: var(--primary);
  color: var(--primary-dark);
}

/* --- Menu: the drawer-only phone -----------------------------------------
   Hidden by default; the desktop bar already has .nav-phone and two phone
   links in one bar would be a duplicate, not emphasis. */
.nav-drawer-call { display: none; }

/* Tablet: six text links, a pill, the logo and the phone number in one bar.
   The gap was already cut to 20px here for six links; the pill needs a little
   more back. Scoped to .has-book so a build without the pill is untouched. */
@media (max-width: 1024px) {
  .nav-links.has-book { gap: 16px; }
  .nav-links.has-book a.nav-book { padding: 0 14px; }
}

@media (max-width: 768px) {
  /* The drawer is the one surface where the phone number was missing
     altogether: .nav-phone is display:none below 768px and the sticky call
     bar stays hidden until 400px of scroll. Putting Book in the drawer
     without it would have made booking the only action a visitor could take
     from an open menu at the top of a page. Phone first, filled, accent —
     the same order and weight the call bar uses. */
  .nav-links a.nav-drawer-call {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 48px;
    padding: 0 16px;
    border-radius: 50px;
    background: var(--accent);
    /* `.nav-links a` sets `color: var(--white) !important` for the drawer, so
       matching that weight at a higher specificity is the only way for the
       dark-on-accent text to survive. */
    color: var(--dark) !important;
    font-weight: 700;
    font-size: 1rem;
    white-space: nowrap;
  }
  .nav-links a.nav-book {
    min-height: 48px;
    width: 100%;
    font-size: 1rem;
  }
  /* The drawer is dark on EVERY page, but an inner page's navbar also carries
     .scrolled — which is a white bar, and paints the pill in translucent blue.
     In the drawer that reads as an almost invisible outline round white text.
     Both selectors are listed so this matches the specificity of the scrolled
     rule above (0,4,1) and wins on order, whichever state the bar is in. */
  .navbar .nav-links a.nav-book,
  .navbar.scrolled .nav-links a.nav-book {
    color: var(--white);
    border-color: rgba(255,255,255,.55);
    background: transparent;
  }
  .navbar .nav-links a.nav-book.active,
  .navbar.scrolled .nav-links a.nav-book.active {
    border-color: var(--accent);
  }
  /* Two pills are taller than the two text links they replace; buy the height
     back out of the gaps so the column still fits a 375x667 screen. */
  .nav-links.has-book { gap: 16px; }
}

/* Short screens — a phone held sideways. A centred flex column that overflows
   is unscrollable at the TOP (the overflow escapes the padding box), which
   would hide "Home" with no way to reach it. Above that height the column
   fits, so this only ever applies where it is needed. */
@media (max-width: 768px) and (max-height: 560px) {
  .nav-links.has-book {
    justify-content: flex-start;
    padding-top: 84px;           /* clear of the navbar and hamburger */
    /* 40px of the drawer's own padding, plus the height the sticky call bar
       occupies (the same 76px body already reserves for it). Without this the
       last item scrolls to a resting place UNDERNEATH the call bar, which
       paints above the drawer, and cannot be tapped. */
    padding-bottom: 116px;
    overflow-y: auto;
    overscroll-behavior: contain;
  }
}

/* --- Footer quick links --------------------------------------------------
   One action at the end of a list of pages. Accent + emoji is how the footer
   already marks its phone, email and address rows, so it reads as part of the
   footer rather than as a button dropped into it. */
.footer ul li a.footer-book {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 44px;              /* the rest of the list is ~24px; this is the
                                    one link here that is a call to action */
  color: var(--accent);
  font-weight: 700;
}
.footer ul li a.footer-book:hover { color: var(--white); }

/* ==================================================================
   PRICE LIST  (templates/partials/pricing.njk)

   Rows, not a table. A <table> is the obvious markup and the wrong one on a
   360px phone, which is most of this traffic: two columns either scroll
   sideways or squeeze the service name down to three words a line. These rows
   let the price drop underneath the name when there is no room beside it, and
   the name is never truncated — a customer has to be able to read what they
   are being charged for.
   ================================================================== */

.price-groups {
  display: grid;
  gap: 40px;
  margin-bottom: 40px;
}
@media (min-width: 900px) {
  /* Two columns on a desktop so forty prices are not one endless scroll.
     Groups stay whole — a group never splits across the columns, because a
     heading in one column and half its prices in the other is unreadable. */
  .price-groups {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 40px 48px;
    align-items: start;
  }
}

.price-group-title {
  font-size: 1.25rem;
  margin-bottom: 6px;
  color: var(--dark);
}
.price-group-intro {
  color: var(--gray);
  font-size: .95rem;
  margin-bottom: 16px;
}

.price-rows {
  list-style: none;
  margin: 0;
  padding: 0;
  border-top: 1px solid var(--gray-light);
}
.price-row {
  padding: 14px 0;
  border-bottom: 1px solid var(--gray-light);
}
.price-row-main {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  flex-wrap: wrap;
}
.price-name {
  font-weight: 600;
  color: var(--dark);
  /* Takes the room it needs and wraps; the price is what gives way. */
  flex: 1 1 60%;
  min-width: 0;
}
.price-value {
  /* Never wraps mid-figure — "$1" on one line and "95" on the next is a
     different number. */
  white-space: nowrap;
  flex: 0 0 auto;
}
.price-amount {
  font-weight: 800;
  font-size: 1.1rem;
  color: var(--primary);
}
.price-unit {
  font-weight: 600;
  font-size: .85rem;
  color: var(--gray);
}
.price-call {
  /* An unpriced row is a sentence, not a gap. Smaller and grey so it does not
     read as a headline number. */
  font-size: .95rem;
  font-weight: 700;
  color: var(--gray);
}
.price-note {
  margin: 6px 0 0;
  color: var(--gray);
  font-size: .9rem;
  max-width: 62ch;
}

/* The pointer from /services/ to the fleet page. Deliberately styled as a card
   and not as another price group: it is a door, not a list of numbers. */
.price-crosslink {
  background: var(--gray-light);
  border-radius: var(--radius);
  padding: 28px;
  margin-bottom: 40px;
  text-align: center;
}
.price-crosslink h3 { font-size: 1.4rem; margin-bottom: 8px; }
.price-crosslink p {
  color: var(--gray);
  max-width: 60ch;
  margin: 0 auto 18px;
}

/* The two conditional charges. Set apart and quieter than the services, because
   they are not something anybody is buying — they are things a customer is
   entitled to know before the van turns up. */
.price-fees {
  margin-top: 40px;
  padding: 24px;
  border: 1px solid var(--gray-light);
  border-radius: var(--radius);
}
.price-fees h3 { font-size: 1.1rem; margin-bottom: 6px; }
.price-fees > p { color: var(--gray); font-size: .95rem; margin-bottom: 12px; }
.price-fees .price-amount { color: var(--dark); font-size: 1rem; }

.price-footnote {
  margin-top: 28px;
  color: var(--gray);
  font-size: .9rem;
  max-width: 78ch;
}

/* ==================================================================
   FLEET & TRUCK WASHING PAGE  (templates/pages/fleet.njk)
   ================================================================== */

.page-hero-eyebrow {
  text-transform: uppercase;
  letter-spacing: .08em;
  font-size: .8rem;
  font-weight: 700;
  color: var(--accent);
  margin-bottom: 10px;
}
.page-hero-actions {
  display: flex;
  gap: 14px;
  justify-content: center;
  flex-wrap: wrap;
  margin-top: 24px;
}

.fleet-points {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 14px;
}
@media (min-width: 760px) {
  .fleet-points { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px 32px; }
}
.fleet-points li {
  position: relative;
  padding-left: 30px;
  color: var(--dark);
  font-weight: 600;
}
.fleet-points li::before {
  content: "✓";
  position: absolute;
  left: 0;
  top: 0;
  color: var(--primary);
  font-weight: 800;
}

.fleet-steps {
  list-style: none;
  counter-reset: fleetstep;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 24px;
}
@media (min-width: 900px) {
  .fleet-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 32px; }
}
.fleet-steps li {
  counter-increment: fleetstep;
  background: var(--white);
  border-radius: var(--radius);
  padding: 28px 24px 24px;
  box-shadow: var(--shadow);
  position: relative;
}
.fleet-steps li::before {
  content: counter(fleetstep);
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--primary);
  color: var(--white);
  font-weight: 800;
  margin-bottom: 14px;
}
.fleet-steps li h3 { font-size: 1.1rem; margin-bottom: 8px; }
.fleet-steps li p { color: var(--gray); font-size: .95rem; margin: 0; }
