/* ==========================================================================
   Imperial Landscaping — Atlantic County, NJ

   PALETTE: taken from the client's business card — a bright yellow-green and
   a deeper forest green, with white and a dark neutral for text.

   Every pair below was measured with the WCAG relative-luminance formula
   before use and the ratio is in the comment. Nothing here is estimated.

   THE BRIGHT GREEN IS NEVER A TEXT COLOUR. --lime on white is 2.04:1 and on
   --paper 1.98:1, so it appears only as a surface (button fills, badges, the
   logo's bright blades) always carrying --ink on top at 8.71:1, or as accent
   text on the dark forest band at 6.16:1. A darkened yellow-green reaches
   only 4.11:1 on white, so that is not used as text either.

   Lowest text ratio anywhere on the site: 6.11:1 (links on --paper).

   Mobile first. Breakpoints at 480, 768, 1024. Tested 320 -> 1440.
   ========================================================================== */

/* -------------------------------------------------------------- fonts
   Self-hosted, latin subset only. No external request, nothing render
   blocking, and font-display:swap so text paints immediately in the
   fallback and reflows once.                                             */

@font-face {
  font-family: "Fraunces";
  src: url("../fonts/fraunces-700.woff2") format("woff2");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Sans 3";
  src: url("../fonts/sourcesans-400.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Source Sans 3";
  src: url("../fonts/sourcesans-600.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}

:root {
  --forest: #123b1e;      /* header, footer, dark bands, headings — 11.75:1 on paper */
  --forest-dp: #0e2f18;   /* deepest band, label text on lime — 7.15:1 on lime */
  --forest-mid: #1e6b36;  /* links, input borders — 6.11:1 on paper */
  --lime: #8dc63f;        /* SURFACE ONLY — ink on it is 8.71:1 */
  --lime-lt: #b6e06b;     /* accent text on forest — 8.30:1 */
  --mist: #d9e8c4;        /* body text on dark bands — 9.75:1 on forest */
  --paper: #f6f8f2;       /* page background */
  --band: #e9efe0;        /* alternating band */
  --ink: #111a12;         /* body text — 16.63:1 on paper */
  --muted: #4c5a4b;       /* secondary text — 6.84:1 on paper */
  --line: #d5ddc8;        /* card hairline */

  --display: "Fraunces", Georgia, "Times New Roman", serif;
  --body: "Source Sans 3", system-ui, -apple-system, "Segoe UI", sans-serif;

  --gutter: 1.25rem;
  --radius: 10px;
  --maxw: 68rem;

  --shadow: 0 1px 2px rgba(17, 26, 18, 0.07), 0 6px 18px rgba(17, 26, 18, 0.06);
}

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* The sticky header must not cover a section you just jumped to. */
  scroll-padding-top: 5.5rem;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 1.0625rem;
  line-height: 1.65;
  /* Belt and braces against sideways scroll at 320px. */
  overflow-x: hidden;
}

h1, h2, h3 {
  font-family: var(--display);
  font-weight: 700;
  line-height: 1.12;
  color: var(--forest);
  margin: 0 0 0.6rem;
  letter-spacing: -0.01em;
}
h1 { font-size: clamp(2rem, 1.55rem + 2.1vw, 3.25rem); }
h2 { font-size: clamp(1.6rem, 1.35rem + 1.2vw, 2.35rem); }
h3 { font-size: 1.2rem; }
p { margin: 0 0 1rem; }

a { color: var(--forest-mid); }          /* 6.11:1 on paper */
a:hover { color: var(--forest); }

img { max-width: 100%; height: auto; }

.wrap { width: 100%; max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); }

.section { padding: 3rem 0; }
.section-alt { background: var(--band); }
.lede { max-width: 60ch; color: var(--muted); font-size: 1.125rem; }

/* ------------------------------------------------------------- the logo

   PLACEHOLDER — an SVG approximation of the mark on the client's business
   card (curved grass blades fanning upward in two greens), drawn from a
   description of the card rather than from the original artwork. Replace
   the five paths with the real logo when the client sends the file; the two
   custom properties below and the .brand / .footer-brand markup can stay
   exactly as they are.

   The deep green swaps to a lighter forest on dark bands so the mark keeps
   at least 3:1 against whatever it sits on: #1E6B36 is 6.11:1 on --paper,
   and #35994C is 3.48:1 on --forest. The bright blades are unchanged in
   both directions, so the two-green identity survives the swap.          */

.logo-mark {
  --blade-deep: #1e6b36;
  --blade-bright: #8dc63f;
  flex: none;
}
.on-dark .logo-mark { --blade-deep: #35994c; }

/* Every interactive thing gets the same unmissable ring. */
a:focus-visible,
button:focus-visible,
summary:focus-visible {
  outline: 3px solid var(--forest-mid);   /* 6.11:1 on paper */
  outline-offset: 3px;
  border-radius: 3px;
}
.site-header a:focus-visible,
.site-footer a:focus-visible,
.feature a:focus-visible,
.hero a:focus-visible { outline-color: var(--lime); }   /* 6.16:1 on forest */

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 200;
  min-height: 48px;
}
.skip-link:focus {
  left: 0.75rem;
  top: 0.75rem;
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0 1rem;
  background: var(--lime);
  color: var(--ink);
  font-weight: 600;
  text-decoration: none;
  border-radius: var(--radius);
}

/* ------------------------------------------------------------- buttons
   48px is the floor everywhere. The primary sits at 52 so it still clears
   it once a browser rounds things off.

   The primary is a lime surface with --ink on it (8.71:1). Lime against
   --paper is only 2.04:1, which is not enough edge for a control, so the
   button carries a --forest border at 11.75:1 to define its boundary.    */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 52px;
  padding: 0.7rem 1.4rem;
  border: 2px solid transparent;
  border-radius: var(--radius);
  font-family: var(--body);
  font-size: 1.0625rem;
  font-weight: 600;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.15s ease, border-color 0.15s ease, transform 0.08s ease;
}
.btn:active { transform: translateY(1px); }

.btn-primary {
  background: var(--lime);
  color: var(--ink);                 /* 8.71:1 */
  border-color: var(--forest);       /* 11.75:1 against paper */
}
.btn-primary:hover { background: #9ed450; color: var(--ink); }

.btn-secondary {
  background: transparent;
  color: var(--forest);
  border-color: var(--forest-mid);
}
.btn-secondary:hover { background: var(--mist); color: var(--forest); }

.btn-ghost-dark {
  background: transparent;
  color: #fff;
  border-color: rgba(217, 232, 196, 0.55);
}
.btn-ghost-dark:hover { background: rgba(217, 232, 196, 0.14); color: #fff; }


/* -------------------------------------------------------- sticky header */

.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--forest);
  border-bottom: 3px solid var(--lime);
}
.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  min-height: 68px;
  padding: 0.5rem var(--gutter);
  max-width: var(--maxw);
  margin: 0 auto;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: #fff;                     /* 12.57:1 on forest */
  text-decoration: none;
  font-family: var(--display);
  font-weight: 700;
  font-size: 1.15rem;
  line-height: 1.05;
}
.brand:hover { color: var(--lime-lt); }

/* -------------------------------------------------- 48px tap targets

   Three links came in under 48px on the first keyboard/touch audit: the
   brand in the header at 39px, and the two inline phone links inside
   paragraphs at 26px and 25px.

   The brand just gets a min-height. The inline ones cannot — an inline-flex
   phone number inside a sentence breaks the line box. They get vertical
   padding instead, which grows the hit area to 48px without taking the
   number out of the sentence it belongs in. The negative margin keeps the
   surrounding paragraph leading unchanged.
   ------------------------------------------------------------------- */

.brand { min-height: 48px; }

p a[href^="tel:"],
p a[href^="sms:"] {
  display: inline-block;
  padding: 0.7rem 0.15rem;
  margin: -0.7rem -0.15rem;
  font-weight: 600;
}

.header-call {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  min-height: 48px;
  padding: 0 1rem;
  background: var(--lime);
  color: var(--ink);               /* 8.71:1 */
  border-radius: var(--radius);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
}
.header-call:hover { background: #9ed450; color: var(--ink); }
.header-call .call-word { display: none; }

/* 320px. The full number plus the brand does not fit beside itself on the
   smallest phone still in use, so the number drops and the button reads
   "Call". The aria-label on the link keeps the number for screen readers. */
@media (max-width: 359px) {
  .header-call .call-word { display: inline; }
  .header-call .call-num { display: none; }
  .header-call { padding: 0 0.85rem; }
  .brand { font-size: 1rem; }
  .brand .logo-mark { width: 28px; height: 28px; }
}

/* ------------------------------------------------------------------ hero
   At 375x667 the name, the one-liner and the Call button all sit above the
   fold. The image is deliberately below them in the source and capped in
   height so it can never push the button off the first screen.            */

.hero {
  background: var(--forest);
  color: #fff;
  padding: 2rem 0 0;
}
.hero h1 { color: #fff; margin-bottom: 0.75rem; }
.hero h1 .hl { color: var(--lime); }   /* 6.16:1 on forest */
.hero-sub {
  max-width: 36ch;
  color: var(--mist);                  /* 9.75:1 on forest */
  font-size: 1.1875rem;
  margin-bottom: 0.35rem;
}
.hero-free {
  color: var(--lime-lt);               /* 8.30:1 on forest */
  font-weight: 600;
  margin-bottom: 1.25rem;
}
.hero-actions { display: flex; flex-direction: column; gap: 0.75rem; }
.hero-actions .btn { width: 100%; }
.hero-actions .btn-primary { border-color: var(--lime); }
.hero-figure { margin: 1.75rem 0 0; }
.hero-figure img {
  display: block;
  width: 100%;
  height: auto;
  max-height: 40vh;
  object-fit: cover;
  border-top: 4px solid var(--lime);
}

/* ------------------------------------------------- the swoosh accent

   The business card uses broad green swoosh shapes as a design accent.
   This is that idea reduced to one decorative band: a wide curve that
   carries the eye from the hero into the featured service below it.
   Purely ornamental and aria-hidden, so nothing is lost if it fails
   to paint.                                                             */

.swoosh {
  display: block;
  width: 100%;
  height: 34px;
  margin: 0;
  color: var(--lime);
  background: var(--forest-dp);
}
.swoosh path { fill: currentColor; }

/* --------------------------------------------- featured service: driveways

   Stone driveways are the highest-value job on the list, so they do not sit
   in the grid where they would read as one card among six. They get the
   full width directly under the hero, on the darkest band, with their own
   Call button.                                                            */

.feature {
  background: var(--forest-dp);
  color: #fff;
  padding: 2rem 0 3rem;
}
.feature h2 { color: #fff; }
.feature .eyebrow {
  display: inline-block;
  margin: 0 0 0.75rem;
  padding: 0.3rem 0.8rem;
  border-radius: 999px;
  background: var(--lime);
  color: var(--forest-dp);        /* 7.15:1 */
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.feature p { color: var(--mist); max-width: 56ch; }   /* 11.32:1 on forest-dp */
.feature-points {
  list-style: none;
  margin: 1.25rem 0 1.5rem;
  padding: 0;
  display: grid;
  gap: 0.55rem;
  max-width: 56ch;
}
.feature-points li {
  position: relative;
  padding-left: 1.6rem;
  color: var(--mist);
}
.feature-points li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 9px;
  height: 9px;
  border-radius: 2px;
  background: var(--lime);
}
.feature-actions { display: flex; flex-direction: column; gap: 0.75rem; }
.feature-actions .btn { width: 100%; }
.feature-actions .btn-primary { border-color: var(--lime); }

/* -------------------------------------------------------------- services */

.grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1rem;
  margin-top: 1.75rem;
  padding: 0;
  list-style: none;
}
.card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.35rem 1.25rem;
  box-shadow: var(--shadow);
}
.card h3 { margin-bottom: 0.4rem; }
.card p { margin: 0; color: var(--muted); }   /* 7.31:1 on white */

/* ------------------------------------------------------- photo cards

   The service cards used to lead with a small line icon. Next to real
   photographs everywhere else on the page they read as clip art, so each
   card now opens with a photograph instead.

   The card loses its own padding and hands it to .card-body, which lets the
   image sit flush to the edges; overflow:hidden is what keeps the square
   corners of the photo inside the card's rounded ones.                    */

.card-media { padding: 0; overflow: hidden; }
.card-media .card-body { padding: 1.25rem 1.25rem 1.4rem; }

.card-photo { display: block; }
.card-photo img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-bottom: 3px solid var(--lime);
}

/* ------------------------------------------------------------------- why */

.why .card { display: flex; gap: 1rem; align-items: flex-start; }
.why-num {
  flex: none;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  background: var(--lime);
  color: var(--forest-dp);        /* 7.15:1 */
  font-family: var(--display);
  font-size: 1.15rem;
}

/* --------------------------------------------------------------- gallery */

.gallery { display: grid; gap: 1.5rem; margin-top: 1.75rem; }
.ba {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
}
.ba-pair { display: grid; grid-template-columns: 1fr 1fr; }
.ba-pair figure { margin: 0; position: relative; }
.ba-pair img { display: block; width: 100%; height: auto; }
.ba-tag {
  position: absolute;
  left: 0.5rem;
  top: 0.5rem;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  font-size: 0.8125rem;
  font-weight: 600;
  background: rgba(14, 47, 24, 0.9);
  color: #fff;
}
.ba-tag.is-after { background: var(--lime); color: var(--forest-dp); }
.ba-caption { padding: 0.9rem 1.1rem; margin: 0; color: var(--muted); font-size: 0.95rem; }

/* ----------------------------------------------------------- service area */

.towns {
  margin: 1.25rem 0 0;
  padding: 0;
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
.towns li {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 0.4rem 0.9rem;
  font-weight: 600;
  color: var(--forest-mid);       /* 6.54:1 on white */
}

/* ------------------------------------------------- quote / contact card

   There is no form on this site. Quotes come in by phone and text, so this
   is the number at a size you can read across a yard, and two buttons sized
   for a thumb. Same white card as the service tiles so it sits in the same
   family.                                                                 */

.contact-card {
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 1.5rem 1.25rem;
  box-shadow: var(--shadow);
  margin-top: 1.5rem;
}
.contact-num {
  margin: 0 0 1.1rem;
  font-family: var(--display);
  font-size: clamp(2rem, 1.4rem + 2.6vw, 2.9rem);
  line-height: 1.1;
  letter-spacing: -0.01em;
}
/* The big number overrides the inline tel: padding rule further up, whose
   negative margin would drag the buttons up into it. It still has to clear
   48px itself: at the bottom of the clamp the type is 2rem, which boxes at
   35px — under the floor — so the min-height does that job instead of
   padding. inline-flex rather than inline-block so the min-height actually
   centres the digits. */
.contact-card .contact-num a[href^="tel:"] {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  padding: 0;
  margin: 0;
  color: var(--forest);            /* 12.57:1 on white */
  text-decoration: none;
  font-weight: 700;
}
.contact-card .contact-num a[href^="tel:"]:hover { color: var(--forest-mid); }

.contact-actions { display: flex; flex-direction: column; gap: 0.75rem; }
.contact-actions .btn { width: 100%; }

.contact-note { margin: 1.35rem 0 0; color: var(--muted); max-width: 54ch; }
.contact-hours {
  margin: 0.9rem 0 0;
  padding-top: 0.9rem;
  border-top: 1px solid var(--line);
  color: var(--muted);
  font-size: 0.95rem;
}

/* ---------------------------------------------------------------- footer */

.site-footer {
  background: var(--forest);
  color: var(--mist);              /* 9.75:1 */
  padding: 2.5rem 0 1.5rem;
}
.site-footer h2 { color: #fff; font-size: 1.35rem; }
.site-footer a { color: var(--lime); }    /* 6.16:1 on forest */
.site-footer a:hover { color: var(--lime-lt); }
.footer-brand {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  margin-bottom: 0.4rem;
}
.footer-brand h2 { margin: 0; }
.footer-grid { display: grid; gap: 1.5rem; }
.footer-phone {
  display: inline-flex;
  align-items: center;
  min-height: 48px;
  font-size: 1.35rem;
  font-weight: 600;
}
.footer-bottom {
  margin-top: 1.75rem;
  padding-top: 1.25rem;
  border-top: 1px solid rgba(217, 232, 196, 0.25);
  font-size: 0.9rem;
}

/* ------------------------------------------------------- reveal on scroll
   Opt-in: the class is only added by JS after IntersectionObserver fires, so
   with JS disabled everything is simply visible from the start.            */

.reveal { opacity: 0; transform: translateY(14px); }
.reveal.is-visible {
  opacity: 1;
  transform: none;
  transition: opacity 0.5s ease, transform 0.5s ease;
}

/* ===================================================================
   480px and up
   =================================================================== */
@media (min-width: 480px) {
  .hero-actions, .feature-actions { flex-direction: row; flex-wrap: wrap; }
  .hero-actions .btn, .feature-actions .btn { width: auto; min-width: 13.5rem; }
  .header-call .call-word { display: inline; }
}

/* ===================================================================
   768px and up
   =================================================================== */
@media (min-width: 768px) {
  .section { padding: 4.5rem 0; }
  .hero { padding-top: 3.5rem; }
  .feature { padding: 2.75rem 0 4rem; }
  .grid { grid-template-columns: repeat(2, 1fr); gap: 1.25rem; }
  .gallery { grid-template-columns: repeat(2, 1fr); }
  .footer-grid { grid-template-columns: repeat(3, 1fr); }
  .brand { font-size: 1.35rem; }
  .contact-card { padding: 2rem; }
  .contact-actions { flex-direction: row; flex-wrap: wrap; }
  .contact-actions .btn { width: auto; min-width: 13.5rem; }
  .swoosh { height: 52px; }

  /* The featured band goes two-up on a wide screen. Left as one column it
     leaves half the width empty, which reads as an unfinished section
     rather than a deliberate one. */
  .feature-grid {
    display: grid;
    grid-template-columns: 1.15fr 1fr;
    gap: 0 3rem;
    align-items: start;
  }
  .feature-grid .feature-actions { grid-column: 1 / -1; margin-top: 0.5rem; }
  .feature-points { margin-top: 0; }
}

/* ===================================================================
   1024px and up
   =================================================================== */
@media (min-width: 1024px) {
  .grid { grid-template-columns: repeat(3, 1fr); }
  .hero-figure img { max-height: 46vh; }
}

/* ------------------------------------------------- reduced motion
   Anyone who asked their OS for less motion gets none: no smooth scroll,
   no fade-ins.                                                          */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .reveal { opacity: 1; transform: none; }
  .reveal.is-visible { transition: none; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
}

/* -------------------------------------------------------------- print
   Someone printing this wants the phone number and what the business does.
   Strip the furniture, put the real URL and number where they can be read. */

@media print {
  .site-header, .hero-figure, .gallery, .skip-link, .swoosh,
  .hero-actions, .feature-actions, .contact-actions { display: none !important; }

  body { background: #fff; color: #000; font-size: 12pt; }
  .section { padding: 0.75rem 0; }
  .card, .contact-card, .towns li { border: 1px solid #999; box-shadow: none; }
  .hero, .feature, .site-footer { background: #fff !important; color: #000 !important; }
  .hero h1, .hero h1 .hl, .hero-sub, .hero-free,
  .feature h2, .feature p, .feature-points li, .feature .eyebrow,
  .site-footer, .site-footer h2, .site-footer a { color: #000 !important; }
  .feature .eyebrow { background: none !important; padding: 0 !important; }

  a[href^="tel:"]::after { content: " (" attr(href) ")"; }
  a[href^="tel:"] { text-decoration: none; }
  #quote::after {
    content: "To book: call or text 609-389-1578.";
    display: block;
    font-weight: 700;
    margin-top: 0.5rem;
  }
}
