/* ========== SECTIONS ========== */
.section {
  padding: var(--section-padding-base) 0;
}

.section-alt {
  background-color: var(--light-bg);
}

.section-compact {
  padding: var(--section-compact-padding-base) 0;
}

/* ========== QUICK REQUEST ========== */
.quick-request {
  background-color: var(--white);
}

/* ========== ABOUT ========== */
.about-content {
  max-width: 850px;
  margin: 0 auto;
  text-align: center;
}

.about-content p {
  margin-bottom: var(--space-xl);
  text-align: left;
}

.about-content .btn {
  margin-top: var(--space-lg);
}

/* ========== PARTIAL LOADING STATE ========== */
/* Each #include-* container starts as a literal empty <div> in index.html.
   While empty, show a centered spinner and reserve roughly the space that
   section will occupy once its partial loads, so the page doesn't collapse
   to ~0 height and then jump to full height as each section arrives. Once
   js/includes.js sets el.innerHTML to the real partial markup, the div is no
   longer :empty, so the spinner and this flex centering both stop applying
   automatically — no JS toggle needed. */
[id^="include-"]:empty {
  display: flex;
  align-items: center;
  justify-content: center;
}

[id^="include-"]:empty::before {
  content: "";
  width: 32px;
  height: 32px;
  border: var(--border-width-thick) solid var(--light-bg);
  border-top-color: var(--accent-color);
  border-radius: var(--radius-full);
  animation: partial-spin 0.8s linear infinite;
}

@keyframes partial-spin {
  to { transform: rotate(360deg); }
}

/* Estimated final heights — a floor, not an exact match. Real content simply
   grows past these once it lands, which is far less jarring than starting
   from 0. #include-navbar intentionally has none: navbar.css makes .navbar
   position:fixed, so once loaded it contributes 0 height to this wrapper's
   normal flow anyway — reserving space here would itself cause a shift.
   These are per-section content estimates, not reusable sizing primitives,
   so they're intentionally left as local numbers rather than tokenized. */
#include-hero { min-height: 100vh; }
#include-quick-request { min-height: 460px; }
#include-about { min-height: 480px; }
#include-services { min-height: 640px; }
#include-why-us { min-height: 380px; }
#include-gallery { min-height: 820px; }
#include-testimonials { min-height: 460px; }
#include-quote { min-height: 560px; }
#include-footer { min-height: 420px; }

/* ========== DISABLED SECTIONS ========== */
/* Applied by js/includes.js when a section's APP.SITE_DATA.activeSections
   entry is false. display:none removes the element from the render tree
   entirely, so the reserved min-height above (and the ":empty" spinner
   state's "display: flex") both become moot — a non-rendered box doesn't
   occupy space regardless of what min-height/display it would otherwise
   compute to. !important makes that win unconditional rather than relying on
   this rule simply being declared after the ":empty" rule (equal (0,0,2,0)
   specificity, tie-broken by source order) — a "hidden" utility class should
   never be one stylesheet reorder away from silently losing that tie. */
[id^="include-"].section-hidden {
  display: none !important;
}

/* ========== PARTIAL LOAD ERROR ========== */
.partial-error {
  padding: var(--space-5xl) var(--space-2xl);
  text-align: center;
}

.partial-error p {
  color: var(--error-color);
  font-weight: 600;
  margin-bottom: var(--space-lg);
}

/* ========== GRIDS ========== */
.grid {
  display: grid;
  gap: var(--space-2xl);
}

.services-grid,
.why-grid {
  grid-template-columns: 1fr;
}

.testimonials-grid {
  grid-template-columns: 1fr;
}

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