/* ==========================================================================
   Tex Painting — Exterior Painting Landing Page
   Custom styles layered on top of Tailwind (CDN).
   Brand palette sourced from the live texpainting.com theme CSS.
   ========================================================================== */

/* The Google Fonts request is issued from a <link> in each page's <head>, not
   an @import here. An @import can only start downloading after styles.css has
   itself downloaded and parsed, which serialised the chain three levels deep
   (html -> styles.css -> fonts.css -> woff2) and stretched the render-blocking
   window. The <link> sits beside the existing preconnects and starts in
   parallel with this file. */

:root {
  /* Dark surfaces — drawn from the charcoal shield in the Tex Painting logo */
  --ink-950: #12161a;
  --ink-900: #1a1f24;
  --ink-800: #232a30;
  --ink-700: #2e373e;

  /* Neutrals — lifted straight from texpainting.com.
     --grey was #808285, which measured 3.85:1 on white and 3.69:1 on --paper.
     It is only ever used for small supporting text, so it needed 4.5:1;
     #676c72 is the same hue at 5.07:1 on --paper. */
  --charcoal: #3a3a3a;
  --grey: #676c72;
  --body: #55606b;
  --line: #dde4e4;
  --mist: #e9f0f0;
  --paper: #fafafa;

  /* Form-field boundary. --line (1.29:1 on the white card) was effectively
     invisible, and the #fafafa fill is only 1.04:1 against that card, so the
     border is the sole thing identifying the control — WCAG 1.4.11 wants 3:1.
     #8a969c measures 3.03:1. */
  --field-border: #8a969c;

  /* Validation red. #d64545 was 4.38:1 on white / 4.12:1 on the invalid-field
     background — both under 4.5:1 for this text size. */
  --error: #b91c1c;

  /* Brand greens — #66a92b and #9dca00 are the two dominant theme colours.
     Both are decorative-only: #66a92b is 2.89:1 on white and #9dca00 is
     1.93:1, so neither may carry text or a focus ring on a light surface.
     --green-text is the darkened version (5.00:1 on white) used wherever the
     green appears AS TYPE — eyebrows, accent words in headings, links, the
     required-field asterisk. Fills, rules and dark-surface text keep the
     original brand values. */
  --green: #66a92b;
  --green-dk: #5a9d1f;
  --green-text: #457d18;
  --lime: #9dca00;
  --lime-dk: #8ab300;

  --shadow-card: 0 24px 56px -10px rgba(18, 22, 26, 0.18);
  --shadow-float: 0 32px 64px -12px rgba(18, 22, 26, 0.35);
}

/* --------------------------------------------------------------------------
   Base
   -------------------------------------------------------------------------- */

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  /* `clip` rather than `hidden`, and on html rather than body. `overflow-x:
     hidden` on body promoted body to the scroll container, which breaks
     scroll-behavior:smooth on anchor jumps and position:sticky in some
     browsers. `clip` suppresses sideways overflow without creating a
     scrollport, so the sticky header and smooth jumps keep working. */
  overflow-x: clip;

  /* The header is sticky and opaque, so an anchor jump or a keyboard focus
     that scrolls an element to y=0 puts it underneath the header. Reserve the
     header's height (plus a little breathing room) on every scroll the browser
     performs — anchors, :target, and focus alike. */
  scroll-padding-top: 5.75rem;
}

@media (min-width: 1024px) {
  html { scroll-padding-top: 6.5rem; }
}

body {
  font-family: 'Inter Tight', 'Inter', system-ui, -apple-system, sans-serif;
  color: var(--body);
  background: #fff;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.font-display {
  font-family: 'Instrument Serif', Georgia, 'Times New Roman', serif;
  font-weight: 400;
  letter-spacing: -0.01em;
}

/* Respect users who ask for less motion */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

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

/* `viewport-fit=cover` lets content run under the sensor housing when a phone
   is held in landscape, so the gutters take the larger of the design padding
   and the safe-area inset. */
.container-narrow {
  width: 100%;
  max-width: 1240px;
  margin-inline: auto;
  padding-left: max(1.25rem, env(safe-area-inset-left));
  padding-right: max(1.25rem, env(safe-area-inset-right));
}

@media (min-width: 1024px) {
  .container-narrow {
    padding-left: max(2.5rem, env(safe-area-inset-left));
    padding-right: max(2.5rem, env(safe-area-inset-right));
  }
}

.section-padding {
  padding-block: 4.5rem;
}

@media (min-width: 768px) {
  .section-padding { padding-block: 6rem; }
}

@media (min-width: 1024px) {
  .section-padding { padding-block: 7.5rem; }
}

/* Hero form privacy line — always one line. Font shrinks with viewport
   below 640px because the offer sticker eats the card's right edge. */
.privacy-line {
  white-space: nowrap;
  font-size: 0.875rem;
  max-width: 100%;
}
.privacy-line svg { flex-shrink: 0; }
@media (max-width: 639.98px) {
  .privacy-line { font-size: clamp(0.55rem, 2.75vw, 0.875rem); }
}

/* --------------------------------------------------------------------------
   Section 2 rating summary strip
   One row at every width: G · 4.9 · stars | divider | serving line. Every
   child is sized in em against the strip's own font-size, so shrinking that
   single value on phones scales the WHOLE unit proportionally — identical
   look on desktop and phone, always centered, never wrapping.
   -------------------------------------------------------------------------- */

.rating-strip {
  display: flex;
  align-items: center;
  justify-content: center;
  column-gap: 2em;
  font-size: 1rem;
}

.rs-left {
  display: flex;
  align-items: center;
  gap: 0.7em;
}

.rs-logo { width: 1.75em; height: 1.75em; flex: 0 0 auto; }

.rs-score { font-size: 1.875em; line-height: 1; }

.rs-stars { display: flex; gap: 0.125em; }

.rs-star { width: 1em; height: 1em; flex: 0 0 auto; }

.rs-divider { width: 1px; height: 2.5em; background: var(--line); flex: 0 0 auto; }

.rs-text { font-size: 0.875em; font-weight: 600; white-space: nowrap; }

/* Phones: scale the strip with the viewport; full size from ~470px up */
@media (max-width: 639.98px) {
  .rating-strip { font-size: clamp(0.6rem, 3.4vw, 1rem); }
}

/* Ranger-style golden rating stars (hero) */
.text-star-gold { color: #fbbf24; }

/* Accent rule that sits under headings, same device Ranger uses */
.accent-rule {
  width: 5rem;
  height: 4px;
  border-radius: 999px;
  background: var(--lime);
}

/* --------------------------------------------------------------------------
   Scroll reveal — driven by IntersectionObserver in script.js
   -------------------------------------------------------------------------- */

/* Only hide content once JS has confirmed it is alive (the inline snippet in
   <head> adds .js to <html>). If script.js ever fails to load, or the visitor
   has JS disabled, every section stays fully visible instead of blank. */
.js .reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity 0.7s cubic-bezier(0.16, 1, 0.3, 1),
              transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
  will-change: opacity, transform;
}

.js .reveal.is-visible {
  opacity: 1;
  transform: none;
  /* Drop the compositor-layer hint once the element has finished animating.
     Left on, ~20 section-sized elements stay promoted to their own GPU layers
     for the whole session for no benefit. */
  will-change: auto;
}

/* --------------------------------------------------------------------------
   Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 0.9rem;
  transition: transform 0.25s ease, box-shadow 0.25s ease, background-color 0.25s ease;
  cursor: pointer;
  border: none;
  text-align: center;
}

/* Two-tone focus ring. A lime-only ring was invisible on the white form card
   (#9dca00 is 1.93:1 against white); a dark-only ring would vanish on the
   charcoal sections. The dark inner outline carries the contrast on light
   backgrounds and the lime halo carries it on dark ones, so the same rule
   reads everywhere on the page. */
.btn:focus-visible {
  outline: 3px solid var(--ink-950);
  outline-offset: 3px;
  box-shadow: 0 0 0 6px rgba(157, 202, 0, 0.85);
}

.btn-primary {
  background: var(--lime);
  color: var(--ink-950);
  padding: 1.05rem 1.75rem;
  font-size: 0.9rem;
  box-shadow: 0 12px 28px -8px rgba(157, 202, 0, 0.55);
}

/* Very narrow phones: the step-2 Back/Submit row is a two-column grid whose
   1fr track cannot shrink below the submit label's min-content width, so the
   default horizontal padding pushed the pair past the form card at 320px. */
@media (max-width: 380px) {
  .btn-primary { padding-inline: 1.05rem; }
  .btn-ghost { padding-inline: 0.9rem; }
}

/* Hover effects are guarded: on a touchscreen there is no pointer to leave, so
   an unguarded :hover sticks to the last tapped button until something else is
   tapped — the CTA sits in its hover state for the rest of the visit. */
@media (hover: hover) {
  .btn-primary:hover {
    background: var(--lime-dk);
    transform: translateY(-2px);
    box-shadow: 0 18px 38px -10px rgba(157, 202, 0, 0.6);
  }

  .btn-ghost:hover {
    border-color: var(--green);
    color: var(--green-text);
  }
}

.btn-primary:active { transform: translateY(0); }

.btn-ghost {
  background: transparent;
  color: var(--ink-900);
  border: 1.5px solid var(--field-border);
  padding: 1.05rem 1.5rem;
  font-size: 0.85rem;
}

/* --------------------------------------------------------------------------
   Hero
   -------------------------------------------------------------------------- */

.hero-bg::after {
  /* Charcoal wash so white type always clears WCAG AA over the photo */
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(105deg, rgba(18, 22, 26, 0.93) 0%, rgba(26, 31, 36, 0.86) 38%, rgba(26, 31, 36, 0.54) 66%, rgba(26, 31, 36, 0.3) 100%);
}

/* Mobile stacks the copy over the full width of the photo, so the wash has to
   stay heavier here than on desktop to keep white type above 4.5:1. */
@media (max-width: 1023px) {
  .hero-bg::after {
    background: linear-gradient(180deg, rgba(18, 22, 26, 0.92) 0%, rgba(26, 31, 36, 0.86) 55%, rgba(26, 31, 36, 0.9) 100%);
  }
}

.trust-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.7rem 1rem;
  border-radius: 0.85rem;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.13);
  color: #fff;
  font-size: 0.875rem;
  font-weight: 600;
  line-height: 1.3;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
}

.trust-chip svg { flex: 0 0 auto; color: var(--lime); }

/* Phones: the chip rows are FIXED — 1 / 1 / 2 / 1 — via a 2-column grid, so
   the pattern is identical on every device instead of depending on how flex
   wrapping happens to land at that width. Chips 1, 2 and 5 span both columns
   and centre; "Financing Available" + "Serving since 2005" share the row.
   Font scales with the viewport so the pair fits its tracks from 320px up. */
@media (max-width: 639.98px) {
  /* doubled class beats the Tailwind CDN's runtime .flex rule on specificity */
  .trust-rail.trust-rail {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.625rem;
  }
  .trust-rail li:nth-child(1),
  .trust-rail li:nth-child(2),
  .trust-rail li:nth-child(5) { grid-column: 1 / -1; justify-self: center; }
  .trust-rail li:nth-child(3) { justify-self: end; }
  .trust-rail li:nth-child(4) { justify-self: start; }

  /* Same pill design as desktop — same proportions of padding, gap and icon
     (converted to em so the whole pill scales as one unit). Only the font
     size adapts, hitting the full desktop 0.875rem from ~458px-wide phones
     and shrinking proportionally on narrower ones so the paired row fits. */
  .trust-chip {
    gap: 0.65em;
    padding: 0.8em 1.14em;
    font-size: clamp(0.7rem, 3.2vw, 0.875rem);
  }
  .trust-chip svg { width: 1.14em; height: 1.14em; }
}

/* --------------------------------------------------------------------------
   Dark photo-section overlays (sections 3, 4 and 7)

   These were Tailwind gradient utilities. Do not put them back — the Tailwind
   CDN silently failed to emit the via-/to- colour stops for the custom `ink`
   palette, and the failure was invisible in the markup:
     §3 and §7  `from-ink-950/95 via-… to-…`  compiled to a gradient that faded
                to fully TRANSPARENT at the bottom;
     §4         `bg-gradient-to-br from-… via-… to-…`  compiled to `none`, so
                white headings sat directly on a bright photo of a pink house.
   Written as plain CSS the result is deterministic in every browser.
   -------------------------------------------------------------------------- */

.photo-overlay {
  position: absolute;
  inset: 0;
  z-index: -10;
}

/* Vertical wash — sections 3 and 7 */
.photo-overlay-v {
  background: linear-gradient(
    180deg,
    rgba(18, 22, 26, 0.95) 0%,
    rgba(26, 31, 36, 0.92) 50%,
    rgba(18, 22, 26, 0.96) 100%
  );
}

/* Diagonal wash — section 4 */
.photo-overlay-d {
  background: linear-gradient(
    135deg,
    rgba(18, 22, 26, 0.96) 0%,
    rgba(26, 31, 36, 0.93) 50%,
    rgba(35, 42, 48, 0.91) 100%
  );
}

/* --------------------------------------------------------------------------
   Offer sticker — rotated badge pinned to the form card corner
   -------------------------------------------------------------------------- */

.offer-sticker {
  position: absolute;
  top: -1.15rem;
  right: -0.85rem;
  z-index: 20;
  width: 7.5rem;
  height: 7.5rem;
  display: grid;
  place-items: center;
  text-align: center;
  border-radius: 999px;
  transform: rotate(11deg);
  background: radial-gradient(circle at 32% 28%, var(--lime) 0%, var(--green) 78%);
  color: var(--ink-950);
  box-shadow: 0 14px 30px -8px rgba(90, 157, 31, 0.65);
  border: 3px dashed rgba(255, 255, 255, 0.75);
  animation: sticker-pop 4.5s ease-in-out infinite;
}

.offer-sticker span {
  display: block;
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1.12;
  padding-inline: 0.4rem;
}

.offer-sticker .sticker-sm { font-size: 0.6rem; text-transform: uppercase; letter-spacing: 0.12em; }
.offer-sticker .sticker-lg { font-size: 1.45rem; }

@keyframes sticker-pop {
  0%, 100% { transform: rotate(11deg) scale(1); }
  50%      { transform: rotate(11deg) scale(1.045); }
}

@media (max-width: 480px) {
  .offer-sticker { width: 6.2rem; height: 6.2rem; top: -0.9rem; right: -0.4rem; }
  .offer-sticker .sticker-lg { font-size: 1.15rem; }
  .offer-sticker .sticker-sm { font-size: 0.52rem; }
}

/* --------------------------------------------------------------------------
   Form
   -------------------------------------------------------------------------- */

.form-card {
  background: #fff;
  border-radius: 1.5rem;
  box-shadow: var(--shadow-float);
  position: relative;
}

/* The offer sticker is absolutely positioned over the top-right corner of the
   card, so the heading and the privacy line underneath it have to reserve that
   width or the sticker sits on top of the text. Kept here next to the sticker
   sizing rules above so the two stay in step; the required clearance is
   (sticker width - its negative right offset - the card's own padding). */
.sticker-clear { padding-right: 5.5rem; }

@media (max-width: 480px) {
  .sticker-clear { padding-right: 4.75rem; }
}

.field-label {
  display: block;
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--charcoal);
  margin-bottom: 0.45rem;
}

.field-label .req { color: var(--green-text); }

.field-input {
  width: 100%;
  padding: 0.95rem 1rem;
  font-size: 1rem;
  font-family: inherit;
  color: var(--ink-900);
  background-color: var(--paper);
  border: 1.5px solid var(--field-border);
  border-radius: 0.8rem;
  transition: border-color 0.2s ease, box-shadow 0.2s ease, background-color 0.2s ease;
  -webkit-appearance: none;
  appearance: none;
}

.field-input::placeholder { color: #6f777f; }

/* `background-color`, never the `background` shorthand — the shorthand resets
   background-image, which wiped the custom chevron off every <select> the
   instant it was focused. Same reason on the invalid state below. */
.field-input:focus {
  outline: none;
  background-color: #fff;
  border-color: var(--green-text);
  box-shadow: 0 0 0 4px rgba(69, 125, 24, 0.22);
}

.field-input[aria-invalid='true'] {
  border-color: var(--error);
  background-color: #fff6f6;
}

/* Native select arrow replaced so it looks identical across browsers */
select.field-input {
  background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2355606b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3e%3cpolyline points='6 9 12 15 18 9'%3e%3c/polyline%3e%3c/svg%3e");
  background-repeat: no-repeat;
  background-position: right 0.9rem center;
  background-size: 1.15rem;
  padding-right: 2.75rem;
}

.field-error {
  display: none;
  margin-top: 0.4rem;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--error);
}

.field-error.is-shown { display: block; }

.progress-track {
  height: 4px;
  border-radius: 999px;
  background: var(--line);
  overflow: hidden;
}

.progress-fill {
  height: 100%;
  width: 50%;
  border-radius: 999px;
  background: var(--lime);
  transition: width 0.45s cubic-bezier(0.16, 1, 0.3, 1);
}

.form-step[hidden] { display: none; }

.form-step {
  animation: step-in 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes step-in {
  from { opacity: 0; transform: translateX(14px); }
  to   { opacity: 1; transform: none; }
}

/* Honeypot — kept out of the layout and away from assistive tech.
   MUST be display:none, not clip/visually-hidden. A clip-hidden text input is
   still a rendered field, and Chrome's profile autofill happily fills it from
   the saved "organization" value — which made the bot check reject genuine
   visitors, silently, with no error shown. Autofill skips non-rendered fields. */
.hp-field { display: none !important; }

/* --------------------------------------------------------------------------
   Review carousel
   -------------------------------------------------------------------------- */

.review-track {
  display: flex;
  align-items: flex-start; /* expanding one card must not stretch the others */
  gap: 1.5rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  padding-block: 0.5rem 1.5rem;
  scrollbar-width: none;
  /* Without this, swiping past the first card hands the gesture to the browser
     and navigates back out of the page. */
  overscroll-behavior-x: contain;
}

.review-track::-webkit-scrollbar { display: none; }

.review-card {
  flex: 0 0 88%;
  scroll-snap-align: center;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 1.25rem;
  padding: 1.75rem;
  display: flex;
  flex-direction: column;
}

@media (min-width: 640px) { .review-card { flex-basis: 46%; } }
@media (min-width: 1024px) { .review-card { flex-basis: 30.5%; } }
@media (min-width: 1280px) { .review-card { flex-basis: 23%; } }

.review-avatar {
  width: 3rem;
  height: 3rem;
  border-radius: 999px;
  display: grid;
  place-items: center;
  color: #fff;
  font-weight: 700;
  font-size: 1.15rem;
  flex: 0 0 auto;
}

/* Review body — clamped to a standard 7-line block so every collapsed card
   is exactly the same height; .is-clamped is removed per-card by "Read more". */
.review-body {
  line-height: 1.625;
}

.review-body.is-clamped {
  display: -webkit-box;
  -webkit-line-clamp: 7;
  -webkit-box-orient: vertical;
  overflow: hidden;
  height: calc(7 * 1.625em); /* fixed, not max — short reviews keep the size */
}

/* Fixed-height slot for the link so cards with and without one stay equal */
.review-action {
  height: 1.6rem;
  margin-top: 0.35rem;
  display: flex;
  align-items: center;
}

/* Inline "Read more" link */
.review-more-btn {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-weight: 700;
  color: var(--green);
  cursor: pointer;
  white-space: nowrap;
}
.review-more-btn:hover { color: var(--green-dk); text-decoration: underline; }
.review-more-btn:focus-visible { outline: 2px solid var(--lime); outline-offset: 2px; border-radius: 2px; }

.carousel-btn {
  width: 3rem;
  height: 3rem;
  border-radius: 999px;
  display: grid;
  place-items: center;
  background: #fff;
  border: 1px solid var(--line);
  color: var(--ink-900);
  box-shadow: 0 8px 20px -6px rgba(18, 22, 26, 0.18);
  transition: background-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
  cursor: pointer;
}

@media (hover: hover) {
  .carousel-btn:hover { background: var(--green-text); color: #fff; border-color: var(--green-text); }
}
.carousel-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.carousel-btn:focus-visible {
  outline: 3px solid var(--ink-950);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px rgba(157, 202, 0, 0.85);
}

/* --------------------------------------------------------------------------
   Process step cards
   -------------------------------------------------------------------------- */

.step-card {
  position: relative;
  border-radius: 1.5rem;
  padding: 2rem;
  background: rgba(255, 255, 255, 0.055);
  border: 1px solid rgba(255, 255, 255, 0.1);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  transition: transform 0.4s ease, border-color 0.4s ease, background-color 0.4s ease;
}

@media (hover: hover) {
  .step-card:hover {
    transform: translateY(-6px);
    border-color: rgba(157, 202, 0, 0.5);
    background: rgba(255, 255, 255, 0.085);
  }
}

.step-pill {
  display: inline-block;
  padding: 0.35rem 0.85rem;
  border-radius: 999px;
  background: rgba(157, 202, 0, 0.2);
  color: var(--lime);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
}

/* Watermark numeral behind each card. It duplicates the "Step 1/2/3" pill, so
   it carries aria-hidden in the markup and is exempt from text contrast. */
.step-num {
  position: absolute;
  top: 1.75rem;
  right: 1.9rem;
  font-size: 2rem;
  color: rgba(255, 255, 255, 0.16);
}

/* --------------------------------------------------------------------------
   Certificate of Protection
   -------------------------------------------------------------------------- */

.cert-card {
  border-radius: 1.5rem;
  padding: 2.5rem 2rem;
  background: linear-gradient(165deg, rgba(35, 42, 48, 0.97) 0%, rgba(18, 22, 26, 0.97) 100%);
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-top: 3px solid var(--lime);
  box-shadow: var(--shadow-float);
}

.cert-icon {
  width: 5rem;
  height: 5rem;
  border-radius: 999px;
  display: grid;
  place-items: center;
  margin-inline: auto;
  border: 2px solid var(--lime);
  color: var(--lime);
  box-shadow: 0 0 32px -4px rgba(157, 202, 0, 0.55);
}

.cert-tick {
  display: flex;
  align-items: flex-start;
  gap: 0.85rem;
  color: #fff;
  font-weight: 600;
  font-size: 0.98rem;
  line-height: 1.45;
}

.cert-tick .tick-mark {
  flex: 0 0 auto;
  width: 1.6rem;
  height: 1.6rem;
  margin-top: 0.05rem;
  border-radius: 999px;
  display: grid;
  place-items: center;
  border: 2px solid var(--lime);
  color: var(--lime);
}

/* --------------------------------------------------------------------------
   Before / After slider
   -------------------------------------------------------------------------- */

.ba-slider {
  position: relative;
  border-radius: 1.25rem;
  overflow: hidden;
  aspect-ratio: 4 / 3;
  background: var(--mist);
  box-shadow: var(--shadow-card);
  touch-action: pan-y;
  -webkit-user-select: none;
  user-select: none;
  cursor: ew-resize;
}

.ba-slider img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  pointer-events: none;
  -webkit-user-drag: none;
}

/* The BEFORE photo is the clipped top layer and fills everything to the LEFT
   of the handle; the AFTER photo is the untouched base layer showing through on
   the right. The handle therefore reads as a divider between the two, matching
   the "Before" tag at bottom-left and "After" at bottom-right. (Originally the
   AFTER image was the clipped layer, which put the new paint on the left and
   left both tags labelling the wrong half.) */
.ba-before-wrap {
  position: absolute;
  inset: 0;
  clip-path: inset(0 50% 0 0);
  will-change: clip-path;
}

.ba-handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 3px;
  background: #fff;
  transform: translateX(-50%);
  pointer-events: none;
  box-shadow: 0 0 18px rgba(0, 0, 0, 0.45);
}

.ba-knob {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 3rem;
  height: 3rem;
  border-radius: 999px;
  background: #fff;
  display: grid;
  place-items: center;
  color: var(--ink-900);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.4);
}

.ba-tag {
  position: absolute;
  bottom: 1rem;
  padding: 0.35rem 0.8rem;
  border-radius: 999px;
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  pointer-events: none;
  backdrop-filter: blur(4px);
}

.ba-tag-before { left: 1rem; background: rgba(18, 22, 26, 0.78); color: #fff; }
.ba-tag-after  { right: 1rem; background: var(--lime); color: var(--ink-950); }

/* Range input sits invisibly on top so the slider is keyboard operable */
.ba-range {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  margin: 0;
  cursor: ew-resize;
}

.ba-range:focus-visible + .ba-handle {
  box-shadow: 0 0 0 3px var(--lime), 0 0 18px rgba(0, 0, 0, 0.45);
}

.ba-meta {
  position: absolute;
  top: 1rem;
  left: 1rem;
  right: 1rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  pointer-events: none;
}

.ba-chip {
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  background: var(--lime);
  color: var(--ink-950);
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* Approximate neighbourhood of each project. Sits beside the .ba-chip in
   .ba-meta. A translucent dark pill rather than bare white text, because these
   labels have to stay legible over a white-painted house as well as a dark one
   — a text-shadow alone washes out on the light after-photos. */
.ba-loc {
  display: inline-flex;
  align-items: center;
  gap: 0.32rem;
  padding: 0.3rem 0.7rem 0.3rem 0.6rem;
  border-radius: 999px;
  background: rgba(18, 22, 26, 0.62);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  border: 1px solid rgba(255, 255, 255, 0.16);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.01em;
  color: #fff;
  white-space: nowrap;
  min-width: 0;
}

.ba-loc svg {
  width: 0.85rem;
  height: 0.85rem;
  flex: 0 0 auto;
  color: var(--lime);
}

/* On the narrowest phones the chip + a long name can outgrow the card */
.ba-loc span {
  overflow: hidden;
  text-overflow: ellipsis;
}

@media (max-width: 400px) {
  .ba-loc { font-size: 0.68rem; padding: 0.28rem 0.6rem 0.28rem 0.5rem; }
  /* Drop the parenthetical clarifier rather than let the name truncate to
     "Allandale (North Aus…" — the neighbourhood alone still reads as real. */
  .ba-loc-sub { display: none; }
}

/* --------------------------------------------------------------------------
   Inline highlights — the marker-pen treatment used on the founder story and
   every FAQ answer. `box-decoration-break: clone` keeps the rounded corners and
   the side padding intact when a highlight wraps across two lines.
   Three tones, used consistently: green = what we do / commit to, amber =
   numbers, dates and money, ink = objects, materials and documents.
   -------------------------------------------------------------------------- */

.hl {
  padding: 0.05em 0.34em;
  margin: 0 -0.06em;
  border-radius: 0.35em;
  font-weight: 600;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}

/* On light sections */
.hl-green { background: #e6f3d7; color: #3f6f18; }
.hl-amber { background: #fdefd2; color: #7c5300; }
.hl-ink   { background: #e6ebf0; color: #1f2933; }

/* On the dark sections (FAQ) the same three tones go translucent so they read
   as a wash over the photo backdrop rather than as pasted-on light chips. */
.faq-answer .hl-green { background: rgba(157, 202, 0, 0.18); color: #cfe97a; }
.faq-answer .hl-amber { background: rgba(255, 193, 71, 0.18); color: #ffd98d; }
.faq-answer .hl-ink   { background: rgba(255, 255, 255, 0.13); color: #ffffff; }

/* --------------------------------------------------------------------------
   Founder
   -------------------------------------------------------------------------- */

.founder-video {
  width: 100%;
  border-radius: 1.25rem;
  display: block;
  background: var(--ink-900);
  box-shadow: var(--shadow-card);
  aspect-ratio: 16 / 9;
  object-fit: cover;
}

.founder-quote {
  border-left: 4px solid var(--lime);
  background: rgba(157, 202, 0, 0.11);
  border-radius: 0 1rem 1rem 0;
  padding: 1.25rem 1.4rem;
}

/* --------------------------------------------------------------------------
   FAQ accordion
   -------------------------------------------------------------------------- */

.faq-shell {
  border-radius: 1.5rem;
  background: rgba(18, 22, 26, 0.72);
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-top: 3px solid var(--lime);
  backdrop-filter: blur(12px);
  overflow: hidden;
}

.faq-item + .faq-item { border-top: 1px solid rgba(255, 255, 255, 0.1); }

.faq-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.5rem 1.5rem;
  text-align: left;
  background: none;
  border: none;
  color: #fff;
  cursor: pointer;
  transition: background-color 0.25s ease;
}

@media (min-width: 768px) { .faq-trigger { padding: 1.75rem 2.25rem; } }

.faq-trigger:hover { background: rgba(255, 255, 255, 0.04); }
.faq-trigger:focus-visible { outline: 3px solid var(--lime); outline-offset: -3px; }

.faq-q {
  font-family: 'Instrument Serif', Georgia, serif;
  font-size: 1.15rem;
  line-height: 1.35;
}

@media (min-width: 768px) { .faq-q { font-size: 1.4rem; } }

.faq-icon {
  flex: 0 0 auto;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: 999px;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.09);
  border: 1px solid rgba(255, 255, 255, 0.16);
  transition: transform 0.35s ease, background-color 0.25s ease, color 0.25s ease;
}

.faq-trigger[aria-expanded='true'] .faq-icon {
  transform: rotate(180deg);
  background: var(--lime);
  color: var(--ink-950);
  border-color: var(--lime);
}

.faq-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}

.faq-panel.is-open { grid-template-rows: 1fr; }

.faq-panel > div { overflow: hidden; }

.faq-answer {
  padding: 0 1.5rem 1.6rem;
  color: rgba(255, 255, 255, 0.76);
  line-height: 1.8;
  font-weight: 300;
}

@media (min-width: 768px) { .faq-answer { padding: 0 2.25rem 1.9rem; } }

/* --------------------------------------------------------------------------
   Interior photo gallery (interior page only)

   The exterior page uses before/after sliders; there are no "before" photos
   for the interior work, so that page gets a plain photo grid instead. Tiles
   share the slider's silhouette — same radius, same shadow, same 4:3 frame —
   so the two pages still feel like one site.
   -------------------------------------------------------------------------- */

.photo-tile {
  position: relative;
  overflow: hidden;
  border-radius: 1.25rem;
  aspect-ratio: 4 / 3;
  background: var(--mist);
  box-shadow: 0 18px 40px -24px rgba(18, 22, 26, 0.45);
  border: 1px solid var(--line);
}

.photo-tile img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.7s cubic-bezier(0.16, 1, 0.3, 1);
}

/* A portrait shot centre-crops into the same 4:3 frame as the rest, so one
   odd aspect ratio cannot break the row. */
@media (hover: hover) {
  .photo-tile:hover img { transform: scale(1.05); }
}

/* Gradient only at the foot of the tile, so the chip stays readable on a
   bright kitchen without dimming the whole photo. */
.photo-tile::after {
  content: '';
  position: absolute;
  inset: auto 0 0 0;
  height: 38%;
  background: linear-gradient(to top, rgba(18, 22, 26, 0.55), transparent);
  pointer-events: none;
}

.photo-tile .tile-chip {
  position: absolute;
  left: 0.9rem;
  bottom: 0.9rem;
  z-index: 1;
  padding: 0.3rem 0.75rem;
  border-radius: 999px;
  background: var(--lime);
  color: var(--ink-950);
  font-size: 0.65rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   Legal pages (privacy policy, terms & conditions)
   Long-form reading copy: a single measured column, generous leading, and
   headings that are scannable without shouting. Deliberately plain.
   -------------------------------------------------------------------------- */

.legal-prose { color: var(--body); font-weight: 300; line-height: 1.75; }

.legal-prose > section + section { margin-top: 2.75rem; }

.legal-prose h2 {
  font-family: 'Instrument Serif', Georgia, serif;
  font-weight: 400;
  color: var(--ink-900);
  font-size: 1.6rem;
  line-height: 1.25;
  margin-bottom: 0.85rem;
}

@media (min-width: 768px) { .legal-prose h2 { font-size: 1.85rem; } }

.legal-prose p + p,
.legal-prose ul + p,
.legal-prose p + ul { margin-top: 0.9rem; }

.legal-prose ul { list-style: none; padding: 0; }

.legal-prose ul li {
  position: relative;
  padding-left: 1.35rem;
  margin-top: 0.55rem;
}

.legal-prose ul li::before {
  content: '';
  position: absolute;
  left: 0.15rem;
  top: 0.68em;
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--green);
}

.legal-prose a { color: var(--green-dk); font-weight: 600; }
.legal-prose a:hover { text-decoration: underline; }

.legal-prose strong { color: var(--ink-900); font-weight: 700; }

/* Callout for the "we are not the contractor" style statements */
.legal-note {
  border-left: 4px solid var(--lime);
  background: rgba(157, 202, 0, 0.11);
  border-radius: 0 1rem 1rem 0;
  padding: 1.15rem 1.35rem;
  margin-top: 1.1rem;
  color: var(--ink-900);
  font-weight: 400;
}

/* In-page contents list at the top of a legal page */
.legal-toc {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: 1.25rem;
  padding: 1.5rem 1.6rem;
}

.legal-toc ol {
  list-style: none;
  padding: 0;
  margin: 0.85rem 0 0;
  display: grid;
  gap: 0.5rem;
}

@media (min-width: 640px) { .legal-toc ol { grid-template-columns: 1fr 1fr; gap: 0.5rem 1.75rem; } }

.legal-toc a { color: var(--body); font-weight: 400; font-size: 0.95rem; }
.legal-toc a:hover { color: var(--green-dk); }

/* --------------------------------------------------------------------------
   Sticky mobile CTA bar
   -------------------------------------------------------------------------- */

.mobile-cta {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 60;
  display: grid;
  grid-template-columns: 0.8fr 1.2fr; /* call ~40%, estimate ~60%, like the reference */
  gap: 0.7rem;
  padding: 0.8rem 1rem calc(0.8rem + env(safe-area-inset-bottom));
  background: rgba(18, 22, 26, 0.97);
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  backdrop-filter: blur(12px);
  transform: translateY(110%);
  transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1);
}

/* Latched on by script.js the first time the visitor scrolls past the hero;
   never removed after that, so the bar stays fixed for the rest of the visit. */
.mobile-cta.is-visible { transform: none; }

@media (min-width: 1024px) { .mobile-cta { display: none; } }

.mobile-cta a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.95rem 0.5rem;
  border-radius: 0.8rem;
}

/* Ghost button, sentence case, lime phone icon — mirrors the reference bar */
.cta-call {
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.25);
  font-size: 0.95rem;
  font-weight: 600;
}
.cta-call svg { color: var(--lime); }

/* Solid brand button, bold caps, calendar icon */
.cta-quote {
  background: var(--lime);
  color: var(--ink-950);
  font-size: 0.85rem;
  font-weight: 800;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

/* Keeps the sticky bar from covering page content on mobile */
@media (max-width: 1023px) {
  body { padding-bottom: 4.75rem; }
}

/* --------------------------------------------------------------------------
   Header
   -------------------------------------------------------------------------- */

/* Solid, not translucent. The header sits above the hero rather than over it,
   so a 55%-alpha dark bar had nothing behind it but the white page and read as
   a washed-out grey band. Solid --ink-950 matches the top of the hero gradient
   and the footer, so the page opens and closes on the same charcoal. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  transition: box-shadow 0.35s ease, border-color 0.35s ease;
  background: var(--ink-950);
  border-bottom: 1px solid transparent;
}

.site-header.is-stuck {
  border-bottom-color: rgba(255, 255, 255, 0.1);
  box-shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.6);
}

/* Skip link for keyboard users */
.skip-link {
  position: absolute;
  left: 1rem;
  top: -4rem;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  border-radius: 0.6rem;
  background: var(--lime);
  color: var(--ink-950);
  font-weight: 700;
  transition: top 0.2s ease;
}

.skip-link:focus { top: 1rem; }
