/* ==========================================================================
   custom.css  —  hand-written styles that are NOT part of the Tailwind build.

   WHY THIS IS A SEPARATE FILE
   ---------------------------
   styles.css is generated output from the Tailwind v4 CLI. Anything appended to
   it is destroyed the moment someone runs the build again. Everything below used
   to live at the bottom of styles.css, which meant a single `tailwindcss -o
   styles.css` at the dev machine would have silently deleted the WhatsApp button
   styling site-wide — green buttons rendering as unstyled text, with no error.

   So: styles.css is disposable and regenerable. THIS file is source. Keep it.

   Load order matters — every page links styles.css first, then custom.css:
       <link rel="stylesheet" href="styles.css">
       <link rel="stylesheet" href="custom.css">

   Cascade note: `@layer utilities` blocks below join the same named layer that
   styles.css declares, and land after it in document order — so these behave
   exactly as they did when appended. The unlayered rules (.btn-wa, .wa-fab and
   the :root variables) intentionally sit outside any layer, so they win over
   every layered utility.

   If you ever rebuild Tailwind, see _build/src/input.css and _build/REBUILD.md —
   the theme and the component layer are reproduced there so the regenerated
   styles.css comes out identical.
   ========================================================================== */


/* WhatsApp green, deepened for legibility.
   ----------------------------------------
   WhatsApp's brand green is #25d366, but white text on it measures 1.98:1 — far
   under the 4.5:1 WCAG AA needs, and under the 3:1 that the icon alone would need.
   Used as-is it makes the site's most important mobile CTA hard to read in
   sunlight, which is exactly where a builder's customer will be standing.

   #0b7a45 is the lightest green that clears AA in both directions:
       white text on it .............. 5.41:1
       it as text on #ffffff ......... 5.41:1
       it as text on #f8f9fa ......... 5.13:1
       it as text on #eef4fb ......... 4.88:1
   The WhatsApp logo mark carries the brand recognition; the exact hue does not
   need to, and a deeper green also sits better beside the blue primary buttons.

   The alternative — keeping #25d366 and switching to dark text (8.96:1) — also
   passes, but reads oddly next to the site's white-on-blue button system. */
:root {
  --color-wa: #0b7a45;        /* filled buttons + outline text */
  --color-wa-dark: #095f35;   /* hover / pressed */
}

/* --- WhatsApp buttons ---------------------------------------------------- */

/* Filled green pill. Pair with the layout utilities already in the sheet
   (flex, items-center, rounded-full, px-*, py-*, font-display …). */
.btn-wa {
  background-color: var(--color-wa);
  color: #ffffff;
  transition: background-color 150ms var(--default-transition-timing-function),
              box-shadow 150ms var(--default-transition-timing-function);
}
.btn-wa:hover { background-color: var(--color-wa-dark); }

/* Same shape, but outlined — for use on the dark ink sections where a second
   solid green block would fight the blue primary CTA. */
.btn-wa-outline {
  border: 2px solid var(--color-wa);
  color: var(--color-wa);
  background-color: transparent;
  transition: background-color 150ms var(--default-transition-timing-function),
              color 150ms var(--default-transition-timing-function);
}
.btn-wa-outline:hover { background-color: var(--color-wa); color: #ffffff; }

.text-wa { color: var(--color-wa); }

/* --- Desktop floating WhatsApp button ------------------------------------
   Mobile is deliberately excluded: the sticky bottom CTA bar already carries a
   full-width WhatsApp button there, and stacking a FAB on top of it would cover
   page content and double up the same action. */
.wa-fab {
  position: fixed;
  right: 1.5rem;
  bottom: 1.5rem;
  z-index: 30;
  display: none;
  align-items: center;
  gap: 0.75rem;
  padding: 0.875rem;
  border-radius: 9999px;
  background-color: var(--color-wa);
  color: #ffffff;
  box-shadow: 0 10px 25px -5px rgb(11 122 69 / 0.45), 0 8px 10px -6px rgb(0 0 0 / 0.3);
  transition: background-color 200ms var(--ease-soft), transform 200ms var(--ease-soft);
}
@media (min-width: 1024px) { .wa-fab { display: inline-flex; } }
.wa-fab:hover { background-color: var(--color-wa-dark); transform: translateY(-2px); }
.wa-fab:focus-visible { outline: 2px solid #ffffff; outline-offset: 3px; }
.wa-fab i { font-size: 1.75rem; line-height: 1; }

/* Label slides open on hover. max-width (not display) so the transition works;
   it starts collapsed so the resting state is a clean circle. */
.wa-fab-label {
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  opacity: 0;
  font-family: var(--font-display);
  font-weight: 600;
  transition: max-width 250ms var(--ease-soft), opacity 200ms var(--ease-soft),
              padding-right 250ms var(--ease-soft);
}
.wa-fab:hover .wa-fab-label,
.wa-fab:focus-visible .wa-fab-label {
  max-width: 12rem;
  opacity: 1;
  padding-right: 0.375rem;
}

@media (prefers-reduced-motion: reduce) {
  .wa-fab, .wa-fab-label { transition: none; }
  .wa-fab:hover { transform: none; }
}

/* --- Utilities the compiled sheet is missing -----------------------------
   Two standard Tailwind utilities used by the generated shell partials that were
   not in the original build (nothing in the old markup referenced them). Copied
   verbatim from Tailwind v4's own output — same selectors, same custom properties
   — so they behave identically to the generated utilities above, including the
   :where() zero-specificity wrapper on space-y that lets later margins override.

   These carry no responsive variants and nothing else in the sheet competes for
   the same properties, so appending them here is cascade-safe. */

@layer utilities {
  .border-b {
    border-bottom-style: var(--tw-border-style);
    border-bottom-width: 1px;
  }
  :where(.space-y-3 > :not(:last-child)) {
    --tw-space-y-reverse: 0;
    margin-block-start: calc(calc(var(--spacing) * 3) * var(--tw-space-y-reverse));
    margin-block-end: calc(calc(var(--spacing) * 3) * calc(1 - var(--tw-space-y-reverse)));
  }
}

/* --- More utilities the compiled sheet is missing -------------------------
   Needed by the pages added after the original Tailwind build. Copied verbatim
   from Tailwind v4's own output shapes so they behave identically.

   ORDERING INVARIANT - do not reorder these blocks.
   Within a cascade layer, later rules beat earlier ones at equal specificity, so
   responsive variants must appear base -> sm -> md -> lg, exactly as Tailwind emits
   them. Putting `md:grid-cols-3` after `lg:grid-cols-2` would make the md rule win
   at large widths and silently break the layout.

   Checked at the time of writing: no page combines md:grid-cols-* with
   lg:grid-cols-* on the same element, so these additions are conflict-free.
   Re-check with _build/verify.ps1 before adding more. */

@layer utilities {
  /* base */
  .grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .h-8  { height: calc(var(--spacing) * 8); }
  .w-8  { width: calc(var(--spacing) * 8); }
  .ml-5 { margin-left: calc(var(--spacing) * 5); }
  .pt-32 { padding-top: calc(var(--spacing) * 32); }
  .pb-16 { padding-bottom: calc(var(--spacing) * 16); }
  .pb-20 { padding-bottom: calc(var(--spacing) * 20); }
  .list-disc { list-style-type: disc; }
  :where(.space-y-10 > :not(:last-child)) {
    --tw-space-y-reverse: 0;
    margin-block-start: calc(calc(var(--spacing) * 10) * var(--tw-space-y-reverse));
    margin-block-end: calc(calc(var(--spacing) * 10) * calc(1 - var(--tw-space-y-reverse)));
  }

  /* sm */
  @media (min-width: 640px) {
    .sm\:pt-36 { padding-top: calc(var(--spacing) * 36); }
    .sm\:pb-20 { padding-bottom: calc(var(--spacing) * 20); }
    .sm\:pb-28 { padding-bottom: calc(var(--spacing) * 28); }
  }

  /* md */
  @media (min-width: 768px) {
    .md\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  }

  /* lg */
  @media (min-width: 1024px) {
    .lg\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  }
}

/* --- Primary-button hover contrast ---------------------------------------
   Every primary CTA is `bg-blue text-white ... hover:bg-blue-bright`. The resting
   state is fine (white on #085dae = 6.59:1) but the hover was not: white on
   #2f8fe0 measures 3.43:1, under the 4.5:1 AA needs. WCAG applies to every state,
   so the buttons failed for the whole time the pointer was over them.

   The token itself can't just be darkened: --color-blue-bright is also used as
   TEXT on the dark ink sections, where #2f8fe0 scores 5.08:1 and a darker value
   would fail instead. One token, two conflicting jobs — so the fix decouples them
   and only changes the button-background use.

   #0d6fc9 keeps the "brightens on hover" feel against #085dae while giving white
   text 5.08:1. Checked: all 70 occurrences of hover:bg-blue-bright in the markup
   are white-text buttons, so nothing else is affected.

   Unlayered on purpose, so it beats the layered Tailwind utility. */
.hover\:bg-blue-bright:hover {
  background-color: #0d6fc9;
}


/* --- Footer clearance for the desktop WhatsApp FAB -----------------------
   The floating WhatsApp button is fixed bottom-right and only exists at lg and
   up. At the very bottom of any page it was sitting directly on top of the
   "Website by Major Visibility" credit line, which is bottom-right too.

   .pb-safe gives the footer 3.5rem below 768px-and-up, which is enough to clear
   the mobile sticky CTA bar but not the 68px FAB plus its offset. Bumped to 7rem
   from 1024px, the width at which the FAB actually appears, so tablet spacing is
   left alone. Verified: FAB and credit no longer intersect. */
@media (min-width: 1024px) {
  footer.pb-safe {
    padding-bottom: calc(7rem + env(safe-area-inset-bottom, 0px));
  }
}

/* --- Hero trust strip ----------------------------------------------------
   The three hero trust points (Google rating, years, next-month bookings) in
   one bordered container instead of loose items scattered under the buttons.
   Replaced a layout that needed two separate blocks: a 2-up grid plus a
   mobile-only full-width bookings box, with a third stat shown only at sm+.

   Mobile: stacked rows separated by hairlines.
   sm and up: three equal columns with vertical hairlines instead.

   Done here rather than with utilities because the compiled Tailwind build has
   no border-l or divide-x, and an inline style cannot carry a media query. */
.hero-stats > * + * {
  border-top: 1px solid rgba(255, 255, 255, 0.09);
}
@media (min-width: 1024px) {
  .hero-stats {
    display: grid;
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
  .hero-stats > * + * {
    border-top: 0;
    border-left: 1px solid rgba(255, 255, 255, 0.09);
    padding-left: 1.25rem;
  }
}

/* --- Secondary buttons on dark backgrounds -------------------------------
   "See our work", the sticky bar's "Get a quote" and friends were drawn with
   border-ink-line (#3a3a3a) on a near-black background. Measured:

       See our work      border vs hero  1.62:1
       Get a quote       border vs bar   1.85:1

   WCAG 2.2 SC 1.4.11 (Non-text Contrast) wants 3:1 for the visual boundary of
   a UI component. Both failed, which is why they read as flat text rather than
   buttons. The white label inside was always fine; it was the outline that
   vanished.

   rgba(255,255,255,0.45) composites to about #7e7e7e on the ink background,
   which measures 4.6:1. Applies only to buttons -- card and accordion borders
   are decorative containers and are deliberately left alone.

   Unlayered so it beats the layered Tailwind border-color utility. */
.btn-outline-light {
  border-color: rgba(255, 255, 255, 0.45);
}
.btn-outline-light:hover {
  border-color: rgba(255, 255, 255, 0.85);
  background-color: rgba(255, 255, 255, 0.08);
}