/* ==========================================================================
   ALTAPEAK ROLLOFFS - BRAND CSS
   Single brand codebase. Every page build loads this file and nothing else.
   v3.2 . August 22, 2026 . Magnate Productions
   ==========================================================================

   COMPANY
   Altapeak Rolloffs          LOCKED. Lower-case p. Read off the Google
                              Business Profile, August 21 2026.
   Phone        (303) 718-1298
   tel: href    tel:+13037181298
   Base         Commerce City, Colorado
   Host         WP Engine . https://altapeakrolloffs.com/ . non-www . trailing slash

   FORBIDDEN NAME VARIANTS. Six were live when this build started, two of
   them on the same homepage. None of these renders anywhere:
     AltaPeak Rolloffs . Alta Peak Rolloffs . ALTAPEAK ROLLOFFS
     Alta Peak Roll Offs . AltaPeak Roll-Offs . Altapeakrolloffs
   The brand string is rendered from ONE source. It is not typed into a page.

   HOURS. Read off the GBP. These override the intake form.
   Monday to Friday   8:00 AM to 5:00 PM
   Saturday           9:00 AM to 12:00 PM
   Sunday             Closed
   SATURDAY IS A THREE HOUR WINDOW, NOT A HALF DAY. The intake form said
   8:00 to 12:30 and the GBP says 9:00 to 12:00. Write the real limits.
   "Saturday mornings, 9 to 12" is honest. "We deliver on Saturdays"
   invites a 1:00 PM phone call.

   USP 1  Family owned and operated.
          VERIFIED. Ban 3 whitelist. Ships. The OWNER IS NOT NAMED anywhere,
          per the client's intake instruction.
   USP 2  Tonnage and rental days included in the posted price.
          VERIFIED. The real differentiator, and it is a table not an
          adjective.
   USP 3  Every container is cleaned and inspected before it leaves the
          yard, so what turns up on your driveway is not the one that came
          off the last job an hour ago.
          VERIFIED. Upgrade to "pressure washed and repainted on a schedule"
          the moment the client confirms they repaint.

   BANNED, AND THIS ONE WAS REQUESTED SO IT IS WORTH BEING EXPLICIT:
   "not nasty rust buckets" and every variant of it. It is a claim about
   SOMEBODY ELSE'S containers, which is an unverifiable comparative claim
   about unnamed competitors. Also banned: "unlike other companies",
   "most haulers won't", "we take what others won't". Be more SPECIFIC,
   never more COMPARATIVE. Specificity does the same job and nobody can
   touch it. Seven five-star reviews sell harder than an insult does.

   CONDITIONAL CLAIMS. The condition travels in the SAME sentence, always:
     "Same-Day Delivery, Subject to Availability"
     "Driveway protection is available on request for an additional charge."

   SAME-DAY, REVISED IN v3.1. A Google review from a Local Guide describes
   getting a 30 yard delivered SAME DAY, and says nobody else she called
   could do it. The capability is attested, so the claim ships as a USP.

   THE CLAIM IS TWO LINES. Headline full size, condition in small type
   directly beneath it:
       Same-Day Delivery
       Subject to availability
   Use .ap-claim (section 8.19). It stacks the two lines inside ONE element
   so a reflow can never orphan the condition.

   THE FOUR RULES THAT MAKE THAT SAFE. All four are enforced in .ap-claim:
     1. Both lines live inside the SAME element. Never two siblings a grid
        can separate, never two cells, never two flex children.
     2. Gap between them is 4px. Not a margin, not a section break, and
        never a horizontal rule.
     3. Condition floor is 0.75rem / 12px. "Small font" is not 9px.
     4. Condition contrast floor is 4.5:1 on its own ground. On dark that
        means --ink-on-dark or --gold. NEVER --ink-on-dark-3, which is the
        inactive tone and would put the condition below the legibility
        floor. A disclaimer nobody can read is a disclaimer that is not
        there.

   WHAT IS STILL BANNED: the condition anywhere OTHER than directly under
   the claim. Not at the foot of the section, not in a footnote block, not
   on a different ground, not on the terms page only.

   THE TIME ANCHOR. There is no stated cutoff, so none is invented. The
   office opens at 8:00 AM and that is GBP-verified, so the honest,
   actionable sentence is "call as early in the day as you can, the office
   opens at 8:00 AM". Derived entirely from a verified fact.

   GOOGLE RATING. 4.9 from 7 reviews, GBP-verified August 21 2026.
   ALWAYS RENDERED WITH THE COUNT: "4.9 on Google, 7 reviews".
   NEVER "4.9 stars" alone. Hiding the denominator on a seven-review
   business is the exact small dishonesty this build exists not to commit.
   NOT A HERO BADGE: five competitors within a few miles carry 27, 90, 126,
   239 and 547 reviews, and a 7 in a hero invites a comparison that is not
   winnable yet. About, Contact and the testimonial section only.
   NO aggregateRating AND NO Review MARKUP, ON ANY PAGE, EVER.

   DEAD CLAIMS. These do not ship in any form, on any page:
     junk removal . recycling services . compactors . event and HOA cleanup
     eco-friendly disposal . emergency rentals . unusual items
     any claim that there is no distance surcharge (there is one)
   The first four are on the CURRENT live site. The client has confirmed
   the intake form wins. They do not migrate.

   CONTAINERS
   15 yard  15L x 7W x 4H   2 tons   7 days    $330
   20 yard  20L x 7W x 4H   2 tons   10 days   $380
   30 yard  20L x 7W x 6H   3 tons   14 days   $420
   40 yard  [CONFIRM dims]  4 tons   30 days   $520

   THE 40 YARD IS CONFIRMED IN. Four size cards, four size pages, four
   rows in the size table. Its photo is a PLACEHOLDER until the client
   supplies one. Its dimensions are still outstanding.

   FOUR SIZES, FOUR DIFFERENT RENTAL TERMS. There is no single
   rental-period sentence on this site. One table, four rows. Writing
   "7 days included" as a global claim and then publishing a 30 day term
   manufactures a contradiction out of two true facts.

   THE 15 AND THE 20 BOTH INCLUDE 2 TONS. The $50 between them buys
   volume, not weight. Nobody in the vertical writes that sentence.

   THERE IS NO HEAVY CONTAINER. Concrete, brick, dirt and yard waste are
   all prohibited. Do not build a card, a page, an H3 or a size-grid cell
   for a concrete or dirt container. The question still gets answered,
   once, in Zone 3, honestly.

   PROVISIONAL FIGURES, LAUNCH-GATED. Two tokens carry agency working
   numbers rather than client-confirmed ones:
     {{OVERAGE_TON}}     $150 per ton
     {{PROHIBITED_FEE}}  up to $500 per item
   Both ship to STAGING so the sections can be built and reviewed. NEITHER
   GOES LIVE UNVERIFIED. Both are one edit in the WPCode snippet.
   $150 is inside the corroborated $40 to $250 band but ABOVE the $50 to
   $100 most-cited band, so the pricing section is written as DISCLOSURE
   and never as VALUE. "You will know the rate before you book," never
   "our rates are low."

   CTAs
   Primary      "Book Online"  ->  /cart/
   Secondary    "Call Us"      ->  tel:+13037181298
   No primary CTA resolves to "#". Every one is a real URL.

   FONT PACKAGE  "Front Range"
   Sora           600, 700, 800  (display, headings, buttons, table heads)
   Source Sans 3  400, 600, 700  (body, tables, form controls)

   Sora is chosen for the flat apex on its A, V, M and W, which is the same
   angle as the peak device in section 9. It is NOT condensed, deliberately:
   a condensed display face makes a large H1 read thin, which is a known
   failure mode from a prior build in this portfolio.

   A FONT SWAP DOES NOT GET TO MOVE THE DESIGN. Every size, tracking value,
   line height, spacing token, button metric and breakpoint below is
   independent of the typeface. Swapping the package changes two lines.

   ==========================================================================
   CONTRAST RULES - DO NOT BREAK
   Every ratio below is measured, not estimated.
   ==========================================================================

   THE ROLE SWAP, AND WHY IT IS NOT NEGOTIABLE
   The intake labelled #5E97EF the primary colour and #1739D2 the third.
   Measured against white, #5E97EF is 2.94:1. That fails the 4.5 body floor
   AND the 3.0 large-text floor, so a bigger button does not rescue it.
   #1739D2 against white is 8.23:1.

   #1739D2 ACTS. #5E97EF AND #DFD457 DECORATE.

   1.  Every primary button label is #FFFFFF on #1739D2. 8.23:1.
   2.  #5E97EF is NEVER a button fill carrying white. 2.94:1.
   3.  #5E97EF is NEVER body text or a label on white or on #F2F5FB.
       2.94:1 and 2.75:1. Not as a dimensions line, not at any size.
   4.  #5E97EF carries text ONLY on the two deepest grounds:
       on #0B1E6B 5.06:1 . on #071543 5.97:1
       It does NOT carry text on #1739D2. 2.80:1.
   5.  #DFD457 on white is 1.53:1. Never. Not once, not anywhere, not at
       any size, not as a label, not as a caption.
   6.  #DFD457 carries text on every dark ground:
       on #1739D2 5.36 . on #0B1E6B 9.70 . on #071543 11.44
   7.  #DFD457 as a FILL carries a NEAR-BLACK label only. #DFD457 with
       #111111 is 12.31:1. #DFD457 with white is 1.53:1 and is a bug.
   8.  EITHER accent AS A SHAPE is legal on any ground: rules, peaks,
       ridgelines, markers, icon fills, borders. A shape is not text.
   9.  Body copy on light is #4E5464. 7.56:1 on white, 6.93:1 on tint.
       Never a lighter grey.
   10. Body copy on dark is rgba(255,255,255,.84).
       10.77:1 on #0B1E6B . 12.53:1 on #071543 . 6.23:1 on #1739D2
   11. Green #17693A and red #A93226 are SCOPED to the materials panel.
       White on each is 6.73 and 6.62. They are not alternate accents and
       they never fill a button.
   12. Google gold #FBBC04 is 1.72:1 on white. Decorative only, and only
       beside a numeric rating with an sr-only sentence carrying the same
       value. NOT IN USE until a real GBP rating exists.
   13. Any UI indicator, not just text, needs 3.0:1. The FAQ open/close
       marker is #1739D2 for this reason.
   14. No hue exists outside this file. A build that needs a colour which
       is not here has a design question, not a CSS question.

   THE ONE RULE THIS BUILD LIVES OR DIES ON:
   ONE BLUE ACTS. THE OTHER BLUE AND THE GOLD DECORATE.
   #1739D2 fills every primary button and the label on it is white.
   #5E97EF and #DFD457 carry eyebrows on dark grounds, peak rules,
   ridgelines, timeline markers, stat numerals and list markers.
   A #5E97EF button is a bug. #DFD457 text on white is a bug.

   ========================================================================== */


/* --------------------------------------------------------------------------
   1. FONTS
   -------------------------------------------------------------------------- */

@import url('https://fonts.googleapis.com/css2?family=Sora:wght@600;700;800&family=Source+Sans+3:wght@400;600;700&display=swap');


/* --------------------------------------------------------------------------
   2. TOKENS
   -------------------------------------------------------------------------- */

:root {

  /* --- BRAND. From the intake, roles assigned by measured contrast. ------ */
  --deep-blue:      #1739D2;   /* ACTS. Button fill, headings on light. 8.23 with white */
  --sky:            #5E97EF;   /* DECORATES. Text only on ground-deep and ground-night */
  --gold:           #DFD457;   /* DECORATES. Text on any dark ground. Fill carries #111 only */
  --white:          #FFFFFF;

  /* --- GROUNDS. Never two identical grounds in a row. -------------------- */
  --ground-light:   #FFFFFF;
  --ground-tint:    #F2F5FB;
  --ground-mid:     #1739D2;
  --ground-deep:    #0B1E6B;
  --ground-night:   #071543;

  /* --- INK --------------------------------------------------------------- */
  --ink:            #12299B;                  /* headings on light. 11.56 on white */
  --ink-body:       #4E5464;                  /* body on light. 7.56 on white */
  --ink-soft:       #6B7180;                  /* captions on light. 4.83 on white */
  --ink-on-dark:    rgba(255,255,255,.84);
  --ink-on-dark-2:  rgba(255,255,255,.72);
  --ink-on-dark-3:  rgba(255,255,255,.60);    /* inactive only */
  --rule-line:      rgba(23,57,210,.16);
  --rule-line-dark: rgba(255,255,255,.18);

  /* --- STATUS. Scoped to the materials panel. Rule 11. ------------------- */
  --go:             #17693A;
  --go-soft:        rgba(23,105,58,.12);
  --no:             #A93226;
  --no-soft:        rgba(169,50,38,.12);

  /* --- SEMANTIC. Not a brand colour. Rule 12. Decorative stars only. ---- */
  --g-star:         #FBBC04;

  /* --- TYPOGRAPHY -------------------------------------------------------- */
  --font-display:   'Sora', 'Segoe UI', system-ui, sans-serif;
  --font-body:      'Source Sans 3', system-ui, -apple-system, sans-serif;

  --weight-display:     800;
  --weight-heading:     700;
  --weight-sub:         600;
  --weight-body:        400;
  --weight-body-bold:   600;
  --weight-body-black:  700;

  --tracking-display:  -.025em;
  --tracking-h2:       -.02em;
  --tracking-h3:       -.01em;
  --tracking-eyebrow:  .22em;
  --tracking-btn:      .06em;
  --tracking-tlink:    .10em;
  --tracking-thead:    .14em;
  --tracking-micro:    .08em;

  --h1-size:        clamp(2.125rem, 5.4vw, 4.25rem);   /* 34 / 41 / 55 / 68 */
  --h2-size:        clamp(1.6875rem, 3.6vw, 2.75rem);  /* 27 / 28 / 37 / 44 */
  --h2-band-size:   clamp(1.9375rem, 4.8vw, 3.5rem);   /* 31 / 37 / 49 / 56 */
  --h3-size:        clamp(1.125rem, 1.8vw, 1.4375rem); /* 18 / 18 / 19 / 23 */
  --h4-size:        1.0625rem;
  --lede-size:      clamp(1rem, 1.55vw, 1.1875rem);
  --body-size:      1rem;                              /* 16 everywhere */
  --small-size:     .9375rem;
  --micro-size:     .8125rem;
  --eyebrow-size:   .75rem;
  --thead-size:     .6875rem;
  --btn-size:       clamp(.75rem, 2.3vw, .875rem);
  --stat-size:      clamp(1.375rem, 3.1vw, 2.125rem);
  --quote-size:     clamp(1.25rem, 2.8vw, 2rem);

  --lh-display:     1.06;
  --lh-h2:          1.10;
  --lh-h3:          1.22;
  --lh-body:        1.62;
  --lh-quote:       1.30;
  --lh-tight:       1;

  --measure-lede:   56ch;
  --measure-body:   66ch;
  --measure-block:  56ch;
  --measure-head:   64ch;
  --measure-quote:  24ch;

  /* --- SPACING. Base unit 8px. ------------------------------------------- */
  --s1: .5rem;   --s2: 1rem;   --s3: 1.5rem;
  --s4: 2rem;    --s5: 3rem;   --s6: 4rem;   --s7: 6rem;

  --container:      1220px;
  --gutter:         clamp(1.25rem, 4vw, 2.5rem);
  --section-y:      clamp(3.5rem, 7vw, 6.75rem);
  --grid-gap:       var(--s3);
  --header-h:       76px;
  --utility-h:      42px;

  /* --- SHAPE. The peak language. Section 9. ------------------------------ */
  --r-sm:           4px;
  --r-md:           6px;
  --summit-sm:      polygon(0 0, calc(100% - 14px) 0, 100% 14px, 100% 100%, 0 100%);
  --summit-md:      polygon(0 0, calc(100% - 24px) 0, 100% 24px, 100% 100%, 0 100%);
  --summit-lg:      polygon(0 0, calc(100% - 40px) 0, 100% 40px, 100% 100%, 0 100%);
  --peak:           polygon(50% 0, 100% 100%, 0 100%);
  --ridge-top:      polygon(0 26px, 50% 0, 100% 26px, 100% 100%, 0 100%);
  --ridge-bottom:   polygon(0 0, 100% 0, 100% calc(100% - 26px), 50% 100%, 0 calc(100% - 26px));

  --shadow:         0 18px 40px -22px rgba(7,21,67,.55);
  --shadow-lift:    0 28px 62px -24px rgba(7,21,67,.70);

  /* --- TEXTURE ----------------------------------------------------------- */
  --contour: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cg fill='none' stroke='%23ffffff' stroke-opacity='.055' stroke-width='1'%3E%3Cpath d='M0 200 Q60 150 120 178 T240 140'/%3E%3Cpath d='M0 168 Q60 118 120 146 T240 108'/%3E%3Cpath d='M0 136 Q60 86 120 114 T240 76'/%3E%3Cpath d='M0 104 Q60 54 120 82 T240 44'/%3E%3Cpath d='M0 72 Q60 22 120 50 T240 12'/%3E%3C/g%3E%3C/svg%3E");
  --hero-scrim:  linear-gradient(178deg, rgba(7,21,67,.70) 0%, rgba(7,21,67,.90) 55%, rgba(7,21,67,.97) 100%);
  --slot-fill:   linear-gradient(158deg, rgba(23,57,210,.92) 0%, rgba(11,30,107,.96) 58%, rgba(7,21,67,1) 100%);
  --slot-hatch:  repeating-linear-gradient(135deg, rgba(255,255,255,.05) 0 14px, rgba(255,255,255,0) 14px 28px);
  --mark-ink:    rgba(255,255,255,.045);
  --ridge-tree:  #071543;   /* the darkest treeline band of the ridge photo,
                               measured rgb(8,22,45). It is within a hair of
                               --ground-night, which is why the divider butts
                               against that ground with no visible seam. */

  /* --- MOTION ------------------------------------------------------------ */
  --dur:            .24s;
  --dur-slow:       .58s;
  --ease:           cubic-bezier(.2,.7,.3,1);
  --focus-ring:     3px solid var(--gold);
  --focus-offset:   4px;
}

@media (max-width: 1024px) { :root { --header-h: 68px; } }
@media (max-width: 768px)  { :root { --header-h: 62px; --utility-h: 38px; } }


/* --------------------------------------------------------------------------
   3. RESET AND BASE
   -------------------------------------------------------------------------- */

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

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; }
}

body.ap {
  margin: 0;
  overflow-x: hidden;
  background: var(--ground-light);
  color: var(--ink-body);
  font-family: var(--font-body);
  font-size: var(--body-size);
  font-weight: var(--weight-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

img, video, iframe, svg { max-width: 100%; height: auto; display: block; }

.ap h1, .ap h2, .ap h3, .ap h4 {
  font-family: var(--font-display);
  color: var(--ink);
  margin: 0 0 var(--s2);
  text-wrap: balance;
}

/* GET IT RIGHT: the H1 is Title Case, never uppercase. That is a content
   decision and CSS must not override it. text-transform is set nowhere on
   a heading in this file. */
.ap h1 { font-size: var(--h1-size); font-weight: var(--weight-display); line-height: var(--lh-display); letter-spacing: var(--tracking-display); }
.ap h2 { font-size: var(--h2-size); font-weight: var(--weight-heading); line-height: var(--lh-h2);      letter-spacing: var(--tracking-h2); }
.ap h3 { font-size: var(--h3-size); font-weight: var(--weight-sub);     line-height: var(--lh-h3);      letter-spacing: var(--tracking-h3); }
.ap h4 { font-size: var(--h4-size); font-weight: var(--weight-body-black); line-height: 1.3; letter-spacing: 0; color: var(--ink); }

.ap p  { margin: 0 0 var(--s2); max-width: var(--measure-body); }
.ap p:last-child { margin-bottom: 0; }
.ap strong { font-weight: var(--weight-body-black); color: var(--ink); }
.ap ul, .ap ol { margin: 0 0 var(--s2); padding-left: 1.25rem; }
.ap li { margin-bottom: .4rem; }
.ap li:last-child { margin-bottom: 0; }

.ap a { color: var(--deep-blue); text-decoration-thickness: 1px; text-underline-offset: 3px; }
.ap a:hover { color: var(--ground-deep); }

/* GET IT RIGHT: focus lands on everything, including summary and inputs. */
.ap a:focus-visible,
.ap button:focus-visible,
.ap summary:focus-visible,
.ap input:focus-visible,
.ap select:focus-visible,
.ap textarea:focus-visible {
  outline: var(--focus-ring);
  outline-offset: var(--focus-offset);
}

.ap-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}


/* --------------------------------------------------------------------------
   4. LAYOUT SHELL AND GROUNDS
   -------------------------------------------------------------------------- */

.ap-wrap { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.ap-section { padding-block: var(--section-y); position: relative; }
.ap-section--tight { padding-block: calc(var(--section-y) * .6); }

/* Text colour is ALWAYS set with the background. Never one without the other. */
.ap-g-light { background: var(--ground-light); color: var(--ink-body); }
.ap-g-tint  { background: var(--ground-tint);  color: var(--ink-body); }
.ap-g-mid   { background: var(--ground-mid);   color: var(--ink-on-dark); }
.ap-g-deep  { background: var(--ground-deep);  color: var(--ink-on-dark); }
.ap-g-night { background: var(--ground-night); color: var(--ink-on-dark); }

.ap-g-mid  h1, .ap-g-mid  h2, .ap-g-mid  h3, .ap-g-mid  h4,
.ap-g-deep h1, .ap-g-deep h2, .ap-g-deep h3, .ap-g-deep h4,
.ap-g-night h1, .ap-g-night h2, .ap-g-night h3, .ap-g-night h4 { color: var(--white); }

.ap-g-mid strong, .ap-g-deep strong, .ap-g-night strong { color: var(--white); }
.ap-g-mid a, .ap-g-deep a, .ap-g-night a { color: var(--gold); }
.ap-g-mid a:hover, .ap-g-deep a:hover, .ap-g-night a:hover { color: var(--white); }

/* Ground rhythm: never two identical grounds in a row. A dark ground is
   followed by light or tint, never by another dark, except where the CTA
   band deliberately steps mid -> night. */

.ap-contour { position: relative; }
.ap-contour::before {
  content: ''; position: absolute; inset: 0; background-image: var(--contour);
  background-size: 240px 240px; pointer-events: none; z-index: 0;
}
.ap-contour > * { position: relative; z-index: 1; }


/* --------------------------------------------------------------------------
   5. TYPE COMPONENTS
   -------------------------------------------------------------------------- */

/* --- EYEBROW ------------------------------------------------------------ */
.ap-eyebrow {
  font-family: var(--font-display);
  font-size: var(--eyebrow-size);
  font-weight: var(--weight-heading);
  letter-spacing: var(--tracking-eyebrow);
  text-transform: uppercase;
  color: var(--deep-blue);
  margin: 0 0 var(--s1);
  line-height: var(--lh-tight);
}
/* Rule 4 and 6. On dark grounds the accents are legal as text. */
.ap-g-mid   .ap-eyebrow,
.ap-g-deep  .ap-eyebrow,
.ap-g-night .ap-eyebrow { color: var(--gold); }

/* --- THE PEAK RULE. Device 1. 64 wide, 10 tall, centred under the eyebrow.
   Replaces a flat rule. It is a SHAPE, so either accent is legal on any
   ground (rule 8). ------------------------------------------------------- */
.ap-peak {
  width: 64px; height: 10px; margin: var(--s2) auto var(--s3);
  background: var(--deep-blue); clip-path: var(--peak);
}
.ap-peak--left { margin-inline: 0 auto; }
.ap-g-mid .ap-peak, .ap-g-deep .ap-peak, .ap-g-night .ap-peak { background: var(--gold); }

/* --- SECTION HEAD ------------------------------------------------------- */
.ap-head { max-width: var(--measure-head); margin-inline: auto; text-align: center; }
.ap-head--left { margin-inline: 0; text-align: left; }
.ap-head p { margin-inline: auto; max-width: var(--measure-lede); font-size: var(--lede-size); }
.ap-head--left p { margin-inline: 0; }

.ap-lede { font-size: var(--lede-size); max-width: var(--measure-lede); line-height: 1.55; }
.ap-micro { font-size: var(--micro-size); letter-spacing: var(--tracking-micro); text-transform: uppercase; color: var(--ink-soft); }
.ap-g-mid .ap-micro, .ap-g-deep .ap-micro, .ap-g-night .ap-micro { color: var(--ink-on-dark-2); }


/* --------------------------------------------------------------------------
   6. BUTTONS, LINKS, FORMS
   -------------------------------------------------------------------------- */

.ap-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--font-display);
  font-size: var(--btn-size);
  font-weight: var(--weight-heading);
  letter-spacing: var(--tracking-btn);
  text-transform: uppercase;
  text-decoration: none;
  padding: 1rem 1.75rem;
  min-height: 48px;
  border: 2px solid transparent;
  border-radius: var(--r-sm);
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease), transform var(--dur) var(--ease);
  text-align: center;
  white-space: nowrap;
}
.ap-btn:hover { transform: translateY(-1px); }

/* PRIMARY. Rule 1. White on #1739D2, 8.23:1. */
.ap-btn--primary { background: var(--deep-blue); color: var(--white); border-color: var(--deep-blue); }
.ap-btn--primary:hover { background: var(--ground-deep); border-color: var(--ground-deep); color: var(--white); }

/* SECONDARY on light. Outline, deep blue label. */
.ap-btn--secondary { background: transparent; color: var(--deep-blue); border-color: var(--deep-blue); }
.ap-btn--secondary:hover { background: var(--deep-blue); color: var(--white); }

/* ON DARK. The inverse pair. */
.ap-btn--light { background: var(--white); color: var(--deep-blue); border-color: var(--white); }
.ap-btn--light:hover { background: var(--gold); color: #111111; border-color: var(--gold); }
.ap-btn--ghost { background: transparent; color: var(--white); border-color: rgba(255,255,255,.55); }
.ap-btn--ghost:hover { background: var(--white); color: var(--deep-blue); border-color: var(--white); }

/* GOLD FILL. Rule 7. The label is NEAR-BLACK, never white. Used sparingly,
   currently on one element sitewide: the mobile sticky book button. */
.ap-btn--gold { background: var(--gold); color: #111111; border-color: var(--gold); }
.ap-btn--gold:hover { background: var(--white); color: var(--deep-blue); border-color: var(--white); }

/* PAIRS. Grid, two equal columns, at EVERY width. Never flex-wrap.
   A wrapped button pair is the single most common mobile break in this
   portfolio and this rule is why it does not happen here. */
.ap-btn-pair { display: grid; grid-template-columns: 1fr 1fr; gap: .75rem; margin-top: var(--s3); }
.ap-btn-pair .ap-btn { width: 100%; padding-inline: 1rem; overflow: hidden; text-overflow: ellipsis; }
@media (max-width: 420px) { .ap-btn-pair { gap: .5rem; } .ap-btn-pair .ap-btn { padding-inline: .625rem; } }

/* --- TEXT LINK with a CSS-drawn arrow. Do not turn this back into a text
   character: a > or an arrow glyph is read aloud by a screen reader. ------ */
.ap-tlink {
  display: inline-flex; align-items: center; gap: .55rem;
  font-family: var(--font-display); font-size: var(--micro-size);
  font-weight: var(--weight-heading); letter-spacing: var(--tracking-tlink);
  text-transform: uppercase; text-decoration: none; color: var(--deep-blue);
}
.ap-tlink::after {
  content: ''; width: 18px; height: 2px; background: currentColor; position: relative;
  transition: width var(--dur) var(--ease);
}
.ap-tlink::before {
  content: ''; order: 2; width: 8px; height: 8px; margin-left: -9px;
  border-top: 2px solid currentColor; border-right: 2px solid currentColor;
  transform: rotate(45deg);
}
.ap-tlink:hover::after { width: 26px; }
.ap-g-mid .ap-tlink, .ap-g-deep .ap-tlink, .ap-g-night .ap-tlink { color: var(--gold); }

/* --- FORM CONTROLS ------------------------------------------------------ */
.ap-field { margin-bottom: var(--s2); }
.ap-label {
  display: block; font-family: var(--font-display); font-size: var(--micro-size);
  font-weight: var(--weight-sub); letter-spacing: var(--tracking-micro);
  text-transform: uppercase; color: var(--ink); margin-bottom: .4rem;
}
.ap-input, .ap-select, .ap-textarea {
  width: 100%; max-width: 100%;
  /* GET IT RIGHT: 16px minimum on inputs. Anything smaller and iOS Safari
     zooms the viewport on focus, which reads as a broken form. */
  font-family: var(--font-body); font-size: 1rem; line-height: 1.4;
  padding: .8125rem .875rem; min-height: 48px;
  color: var(--ink-body); background: var(--white);
  border: 1px solid var(--rule-line); border-radius: var(--r-sm);
}
.ap-textarea { min-height: 132px; resize: vertical; }
.ap-input::placeholder, .ap-textarea::placeholder { color: var(--ink-soft); }
.ap-input:focus, .ap-select:focus, .ap-textarea:focus { border-color: var(--deep-blue); }
.ap-g-deep .ap-label, .ap-g-night .ap-label, .ap-g-mid .ap-label { color: var(--white); }

/* --- IMAGE SLOTS. Every slot reserves its ratio before the image loads,
   so nothing shifts on a slow connection. -------------------------------- */
.ap-slot { position: relative; overflow: hidden; background: var(--slot-fill); border-radius: var(--r-md); }
.ap-slot::after { content: ''; position: absolute; inset: 0; background-image: var(--slot-hatch); pointer-events: none; }
.ap-slot > img { width: 100%; height: 100%; object-fit: cover; }
.ap-slot--43  { aspect-ratio: 4 / 3; }
.ap-slot--32  { aspect-ratio: 3 / 2; }
.ap-slot--169 { aspect-ratio: 16 / 9; }
.ap-slot--11  { aspect-ratio: 1 / 1; }
.ap-slot--summit { clip-path: var(--summit-md); border-radius: 0; }


/* --------------------------------------------------------------------------
   7. PAGE FURNITURE
   -------------------------------------------------------------------------- */

/* --- 7.1 UTILITY BAR. Ground night. ------------------------------------- */
.ap-utility {
  background: var(--ground-night); color: var(--ink-on-dark-2);
  font-size: var(--micro-size); min-height: var(--utility-h);
  display: flex; align-items: center;
}
.ap-utility .ap-wrap { display: flex; align-items: center; justify-content: space-between; gap: var(--s2); width: 100%; }
.ap-utility strong { color: var(--white); font-weight: var(--weight-body-black); }
.ap-utility a { color: var(--white); text-decoration: none; }
.ap-utility a:hover { color: var(--gold); }
@media (max-width: 768px) { .ap-utility { display: none; } }

/* --- 7.2 HEADER. Transparent over the hero, solid from scrollY 70. ------- */
.ap-header {
  position: sticky; top: 0; z-index: 900; min-height: var(--header-h);
  display: flex; align-items: center;
  background: transparent;
  transition: background var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ap-header.is-solid { background: var(--ground-night); box-shadow: 0 1px 0 var(--rule-line-dark); }
.ap-header .ap-wrap { display: flex; align-items: center; justify-content: space-between; gap: var(--s3); width: 100%; }
.ap-logo { display: flex; align-items: center; }
.ap-logo img { max-height: 46px; width: auto; }
.ap-nav { display: flex; align-items: center; gap: var(--s3); }
.ap-nav a {
  font-family: var(--font-display); font-size: var(--micro-size);
  font-weight: var(--weight-sub); letter-spacing: var(--tracking-micro);
  text-transform: uppercase; color: var(--white); text-decoration: none;
}
.ap-nav a:hover, .ap-nav a[aria-current="page"] { color: var(--gold); }
.ap-burger { display: none; background: none; border: 0; padding: .5rem; min-height: 44px; min-width: 44px; cursor: pointer; }
.ap-burger span { display: block; width: 26px; height: 2px; background: var(--white); margin: 5px 0; }
@media (max-width: 1024px) { .ap-nav { display: none; } .ap-burger { display: block; } }

/* --- 7.3 BREADCRUMB. Ground deep. Emitted by Yoast, styled here. -------- */
.ap-crumb { background: var(--ground-deep); color: var(--ink-on-dark-2); font-size: var(--micro-size); padding-block: .875rem; }
.ap-crumb a { color: var(--white); text-decoration: none; }
.ap-crumb a:hover { color: var(--gold); }
.ap-crumb [aria-current="page"] { color: var(--ink-on-dark-3); }

/* --- 7.4 HERO. Ground night. The negative top margin pulls the hero under
   the sticky transparent header so the image starts at the viewport top. -- */
.ap-hero {
  position: relative; margin-top: calc(var(--header-h) * -1);
  padding-top: calc(var(--header-h) + var(--section-y));
  padding-bottom: var(--section-y);
  background: var(--ground-night); color: var(--ink-on-dark);
  overflow: hidden;
}
.ap-hero__bg { position: absolute; inset: 0; z-index: 0; }
.ap-hero__bg img { width: 100%; height: 100%; object-fit: cover; }
.ap-hero__bg::after { content: ''; position: absolute; inset: 0; background: var(--hero-scrim); }
.ap-hero .ap-wrap { position: relative; z-index: 2; }
.ap-hero h1 { color: var(--white); max-width: 18ch; }
/* The H1's second line carries the accent. Legal: gold on ground-night is
   11.44:1. */
.ap-hero h1 .ap-accent { color: var(--gold); }
.ap-hero .ap-lede { color: var(--ink-on-dark); }

/* Two-column hero, text 60 / media 40, per the page template registry. */
.ap-hero--split .ap-wrap { display: grid; grid-template-columns: 6fr 4fr; gap: var(--s5); align-items: center; }
@media (max-width: 900px) { .ap-hero--split .ap-wrap { grid-template-columns: 1fr; gap: var(--s4); } }

/* --- 7.5 TRUST BADGE ROW. Ban 3 governs WHICH badges. This governs how
   they behave. Two to three in a hero. Any single badge appears in at most
   two places SITEWIDE. Keep a running tally. --------------------------- */
.ap-badges { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: var(--s3); padding: 0; list-style: none; }
.ap-badge {
  display: inline-flex; align-items: center; gap: .4rem;
  font-family: var(--font-display); font-size: .8125rem; font-weight: var(--weight-sub);
  letter-spacing: .04em; text-transform: uppercase; white-space: nowrap;
  padding: .5rem 1rem; border-radius: var(--r-sm);
  background: rgba(255,255,255,.10); color: var(--white);
  border: 1px solid rgba(255,255,255,.22);
}
.ap-badge::before { content: ''; width: 8px; height: 8px; background: var(--gold); clip-path: var(--peak); }

/* CONDITIONAL BADGE. Two stacked lines inside ONE badge. The condition
   cannot be orphaned by a reflow because it is not a sibling. */
.ap-badge--claim { flex-direction: column; align-items: flex-start; gap: 4px; padding-block: .5rem; line-height: 1.15; }
.ap-badge--claim .ap-badge__cond {
  font-family: var(--font-body); font-size: .75rem; font-weight: var(--weight-body);
  letter-spacing: 0; text-transform: none; color: var(--ink-on-dark);
}
@media (max-width: 768px) { .ap-badge--claim { align-items: center; text-align: center; } }
@media (max-width: 768px) {
  .ap-badges { display: grid; grid-template-columns: 1fr 1fr; gap: .375rem; }
  .ap-badge { padding: .375rem .625rem; font-size: .6875rem; justify-content: center; text-align: center; }
}
@media (max-width: 400px) { .ap-badge { padding: .3rem .5rem; font-size: .625rem; } }

/* --- 7.6 FOOTER. Ground night. ------------------------------------------ */
.ap-footer { background: var(--ground-night); color: var(--ink-on-dark-2); padding-block: var(--s6) var(--s4); }
.ap-footer h4 {
  color: var(--white); font-size: var(--micro-size); letter-spacing: var(--tracking-micro);
  text-transform: uppercase; margin-bottom: var(--s2);
}
.ap-footer__grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: var(--s4); }
.ap-footer ul { list-style: none; padding: 0; margin: 0; }
.ap-footer li { margin-bottom: .5rem; }
.ap-footer a { color: var(--ink-on-dark-2); text-decoration: none; font-size: var(--small-size); }
.ap-footer a:hover { color: var(--gold); }
/* NAP. One address string, matching the Google Business Profile character
   for character. If this and the schema node disagree, the schema is wrong. */
.ap-footer__nap { font-style: normal; font-size: var(--small-size); line-height: 1.75; color: var(--ink-on-dark); }
.ap-footer__nap strong { display: block; color: var(--white); font-family: var(--font-display); font-size: 1.0625rem; margin-bottom: .35rem; }
.ap-footer__base { border-top: 1px solid var(--rule-line-dark); margin-top: var(--s5); padding-top: var(--s3); font-size: var(--micro-size); display: flex; flex-wrap: wrap; gap: var(--s2); justify-content: space-between; }
@media (max-width: 900px) { .ap-footer__grid { grid-template-columns: 1fr 1fr; gap: var(--s3); } }
@media (max-width: 560px) { .ap-footer__grid { grid-template-columns: 1fr; } }

/* --- 7.7 MOBILE STICKY CTA. Base is visible, hidden from 769 up. -------- */
.ap-sticky {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 950;
  display: flex; flex-wrap: nowrap; gap: .5rem;
  padding: .75rem 1rem calc(.75rem + env(safe-area-inset-bottom));
  background: rgba(7,21,67,.97);
  border-top: 1px solid var(--rule-line-dark);
}
.ap-sticky .ap-btn { flex: 1; min-width: 0; padding-inline: .5rem; font-size: clamp(.625rem, 2.5vw, .8125rem); min-height: 46px; }
@media (min-width: 769px) { .ap-sticky { display: none; } }
@media (max-width: 768px) { body.ap { padding-bottom: 74px; } }


/* --------------------------------------------------------------------------
   8. CONTENT COMPONENTS
   -------------------------------------------------------------------------- */

/* --- 8.1 SERVICE BLOCK. The spine of Zone 1. Alternates left and right
   down the stack. Every block carries one image and no CTA: one CTA per
   zone, not one per block. ---------------------------------------------- */
.ap-service { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s5); align-items: center; margin-bottom: var(--s5); }
.ap-service:last-child { margin-bottom: 0; }
.ap-service:nth-child(even) .ap-slot { order: -1; }
.ap-service h3 { margin-bottom: .625rem; }
.ap-service p { max-width: var(--measure-block); }
.ap-service__spec { font-size: var(--small-size); color: var(--ink-soft); border-left: 3px solid var(--gold); padding-left: .75rem; margin-top: var(--s2); }
@media (max-width: 820px) {
  .ap-service { grid-template-columns: 1fr; gap: var(--s3); margin-bottom: var(--s4); }
  .ap-service:nth-child(even) .ap-slot { order: 0; }
}

/* --- 8.2 FEATURE GRID. "Why choose us", four items, check + H3 + text. -- */
.ap-features { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s3) var(--s4); margin-top: var(--s3); }
.ap-feature { display: grid; grid-template-columns: auto 1fr; gap: .875rem; align-items: start; }
.ap-feature__mark { width: 26px; height: 26px; flex: none; background: var(--deep-blue); border-radius: var(--r-sm); position: relative; }
.ap-feature__mark::after {
  content: ''; position: absolute; left: 8px; top: 6px; width: 7px; height: 12px;
  border-right: 2.5px solid var(--white); border-bottom: 2.5px solid var(--white); transform: rotate(42deg);
}
.ap-g-mid .ap-feature__mark, .ap-g-deep .ap-feature__mark, .ap-g-night .ap-feature__mark { background: var(--gold); }
.ap-g-mid .ap-feature__mark::after, .ap-g-deep .ap-feature__mark::after, .ap-g-night .ap-feature__mark::after { border-color: #111111; }
.ap-feature h3 { font-size: 1.0625rem; margin-bottom: .3rem; }
.ap-feature p { font-size: var(--small-size); margin: 0; }
@media (max-width: 700px) { .ap-features { grid-template-columns: 1fr; } }

/* --- 8.3 CARD. Whole card is the anchor, so the tap target is the card. -- */
.ap-cards { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--grid-gap); }
.ap-cards--2 { grid-template-columns: repeat(2, 1fr); }
.ap-cards--4 { grid-template-columns: repeat(4, 1fr); }
.ap-card {
  display: block; text-decoration: none; color: inherit; background: var(--white);
  border: 1px solid var(--rule-line); border-radius: var(--r-md); overflow: hidden;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ap-card:hover { transform: translateY(-3px); box-shadow: var(--shadow); }
.ap-card__body { padding: var(--s3); }
.ap-card h3 { font-size: 1.1875rem; margin-bottom: .5rem; }
.ap-card p { font-size: var(--small-size); margin-bottom: var(--s2); }
@media (max-width: 900px) { .ap-cards, .ap-cards--4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .ap-cards, .ap-cards--2, .ap-cards--4 { grid-template-columns: 1fr; } }

/* --- 8.4 SIZE CARD AND SIZE GRID. FOUR containers, 2 x 2 on desktop.
   There is no fifth cell. No concrete card, no dirt card, no heavy card:
   this operator does not run one. ---------------------------------------- */
.ap-sizes { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--grid-gap); }
.ap-size {
  background: var(--white); border: 1px solid var(--rule-line);
  border-radius: var(--r-md); overflow: hidden; display: flex; flex-direction: column;
}
.ap-size__head { background: var(--ground-tint); padding: var(--s3) var(--s3) var(--s2); }
.ap-size__head h3 { margin: 0; }
/* GET IT RIGHT: the dimensions line is GREY, not an accent. Rule 3: #5E97EF
   on white is 2.94 and #DFD457 on white is 1.53. Both are bugs here. */
.ap-size__dims { font-size: var(--micro-size); color: var(--ink-soft); margin: .35rem 0 0; letter-spacing: .02em; }
.ap-size__body { padding: var(--s3); flex: 1; }
.ap-size__specs { list-style: none; padding: 0; margin: 0 0 var(--s3); font-size: var(--small-size); }
.ap-size__specs li { display: flex; justify-content: space-between; gap: var(--s2); padding: .5rem 0; border-bottom: 1px solid var(--rule-line); }
.ap-size__specs li:last-child { border-bottom: 0; }
.ap-size__specs span:first-child { color: var(--ink-soft); }
.ap-size__specs span:last-child { font-weight: var(--weight-body-black); color: var(--ink); }
.ap-size__foot { padding: 0 var(--s3) var(--s3); }
@media (max-width: 1024px) { .ap-sizes { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px)  { .ap-sizes { grid-template-columns: 1fr; } }

/* --- 8.5 TABLES. Real tables. The consensus answers cost and sizing with a
   table, so these are <table> elements with <thead> and th[scope], never
   styled divs. ----------------------------------------------------------- */
.ap-table { width: 100%; overflow-x: auto; -webkit-overflow-scrolling: touch; margin-bottom: var(--s3); }
.ap-table table { width: 100%; border-collapse: collapse; font-size: var(--small-size); min-width: 520px; }
.ap-table th, .ap-table td { padding: .875rem 1rem; text-align: left; border-bottom: 1px solid var(--rule-line); vertical-align: top; }
.ap-table thead th {
  background: var(--deep-blue); color: var(--white);
  font-family: var(--font-display); font-size: var(--thead-size);
  font-weight: var(--weight-heading); letter-spacing: var(--tracking-thead);
  text-transform: uppercase; white-space: nowrap;
}
.ap-table tbody th { font-family: var(--font-display); font-weight: var(--weight-sub); color: var(--ink); white-space: nowrap; }
.ap-table tbody tr:nth-child(even) { background: var(--ground-tint); }
.ap-table caption { caption-side: bottom; padding-top: .75rem; font-size: var(--micro-size); color: var(--ink-soft); text-align: left; }

/* Mobile: the table becomes a stack of labelled rows. display:block matters;
   without it the th scope is lost to assistive tech. Requires data-label on
   every td. */
@media (max-width: 640px) {
  .ap-table table { min-width: 0; display: block; }
  .ap-table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
  .ap-table tbody, .ap-table tr, .ap-table td, .ap-table tbody th { display: block; width: 100%; }
  .ap-table tr { border: 1px solid var(--rule-line); border-radius: var(--r-sm); margin-bottom: var(--s2); padding: .25rem .75rem; background: var(--white); }
  .ap-table tbody tr:nth-child(even) { background: var(--ground-tint); }
  .ap-table td { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, auto); gap: var(--s2); border-bottom: 1px solid var(--rule-line); padding: .625rem 0; }
  .ap-table td:last-child { border-bottom: 0; }
  .ap-table td::before { content: attr(data-label); font-family: var(--font-display); font-size: var(--thead-size); letter-spacing: var(--tracking-thead); text-transform: uppercase; color: var(--ink-soft); }
  .ap-table tbody th { padding: .75rem 0 .5rem; font-size: 1.0625rem; border-bottom: 2px solid var(--deep-blue); }
}

/* PRICE TOKEN. Every figure on this site is a {{TOKEN}} rendered by the
   site-wide WPCode PHP snippet. An UNRESOLVED token renders NOTHING, which
   is the whole point: an empty cell is honest, an invented number is not.
   Dollar amounts appear in exactly two places, the pricing table and the
   cost variables table, and nowhere else. */
.ap-price { font-family: var(--font-display); font-weight: var(--weight-display); color: var(--ink); font-size: 1.25rem; letter-spacing: -.01em; }
.ap-price:empty { display: none; }
.ap-price:empty ~ .ap-price-note { display: none; }

/* --- 8.6 MATERIALS PANEL. TWO separate lists, accepted and prohibited,
   side by side. NEVER merged into one list: the two-list pattern is the
   single most consistent structure in the source pool and merging it
   breaks the extraction. ------------------------------------------------- */
.ap-materials { display: grid; grid-template-columns: 1fr 1fr; gap: var(--grid-gap); }
.ap-mat { background: var(--white); border: 1px solid var(--rule-line); border-radius: var(--r-md); padding: var(--s3); }
.ap-mat h3 { display: flex; align-items: center; gap: .625rem; font-size: 1.125rem; }
.ap-mat ul { list-style: none; padding: 0; margin: 0; font-size: var(--small-size); }
.ap-mat li { display: flex; gap: .625rem; padding: .5rem 0; border-bottom: 1px solid var(--rule-line); }
.ap-mat li:last-child { border-bottom: 0; }
.ap-mat li::before { content: ''; width: 18px; height: 18px; flex: none; border-radius: 50%; margin-top: .15rem; }
.ap-mat--go h3 { color: var(--go); }
.ap-mat--go li::before { background: var(--go-soft); box-shadow: inset 0 0 0 2px var(--go); }
.ap-mat--no h3 { color: var(--no); }
.ap-mat--no li::before { background: var(--no-soft); box-shadow: inset 0 0 0 2px var(--no); }
.ap-mat__note { margin-top: var(--s2); padding: .875rem 1rem; background: var(--ground-tint); border-left: 3px solid var(--deep-blue); font-size: var(--micro-size); border-radius: 0 var(--r-sm) var(--r-sm) 0; }
@media (max-width: 700px) { .ap-materials { grid-template-columns: 1fr; } }

/* --- 8.7 CALL-FIRST CARD. Ground light, card deep. ---------------------- */
.ap-callfirst { background: var(--ground-deep); color: var(--ink-on-dark); border-radius: var(--r-md); padding: var(--s4); clip-path: var(--summit-lg); }
.ap-callfirst h3 { color: var(--white); }
.ap-callfirst__num { display: inline-block; font-family: var(--font-display); font-size: var(--stat-size); font-weight: var(--weight-display); color: var(--gold); text-decoration: none; letter-spacing: -.01em; }
/* A fee POINTER, not a fee. No dollar amount lives here. */
.ap-callfirst__pointer { font-size: var(--micro-size); color: var(--ink-on-dark-2); }

/* --- 8.8 HEADS-UP BAR. Ground light. ----------------------------------- */
.ap-headsup { display: flex; gap: .875rem; align-items: flex-start; padding: 1rem 1.25rem; background: var(--ground-tint); border-left: 4px solid var(--gold); border-radius: 0 var(--r-sm) var(--r-sm) 0; font-size: var(--small-size); }
.ap-headsup strong { display: block; margin-bottom: .2rem; }

/* --- 8.9 CTA BAND. Ground mid, or night for the closing instance.
   Alternate urgent and laid-back across banners on the same page. -------- */
.ap-cta { background: var(--ground-mid); color: var(--ink-on-dark); padding-block: calc(var(--section-y) * .72); position: relative; overflow: hidden; }
.ap-cta--night { background: var(--ground-night); }
.ap-cta .ap-wrap { position: relative; z-index: 1; text-align: center; }
.ap-cta h2 { font-size: var(--h2-band-size); color: var(--white); max-width: 20ch; margin-inline: auto; }
.ap-cta p { margin-inline: auto; max-width: var(--measure-lede); color: var(--ink-on-dark); }
.ap-cta__num { display: inline-block; margin: var(--s2) 0 var(--s1); font-family: var(--font-display); font-size: var(--stat-size); font-weight: var(--weight-display); color: var(--gold); text-decoration: none; }
.ap-cta__num:hover { color: var(--white); }
.ap-cta .ap-btn-pair { max-width: 460px; margin-inline: auto; }
/* Device 2: the ridgeline. A shallow peak cut on the band's top edge. */
.ap-cta--ridge { clip-path: var(--ridge-top); }

/* --- 8.10 PROCESS LIST. A real ordered list. The numerals come from
   counter(), not from typed spans. A typed numeral is a numeral a screen
   reader announces twice and a reorder gets wrong. ----------------------- */
.ap-process { counter-reset: apstep; list-style: none; padding: 0; margin: 0; }
.ap-process > li { counter-increment: apstep; position: relative; padding-left: 4.25rem; padding-bottom: var(--s4); }
.ap-process > li:last-child { padding-bottom: 0; }
.ap-process > li::before {
  content: counter(apstep); position: absolute; left: 0; top: -.25rem;
  width: 48px; height: 48px; display: grid; place-items: center;
  font-family: var(--font-display); font-size: 1.25rem; font-weight: var(--weight-display);
  background: var(--deep-blue); color: var(--white); border-radius: var(--r-sm);
}
.ap-process > li::after { content: ''; position: absolute; left: 23px; top: 3rem; bottom: .75rem; width: 2px; background: var(--rule-line); }
.ap-process > li:last-child::after { display: none; }
.ap-process h3 { font-size: 1.125rem; margin-bottom: .35rem; }
.ap-process p { font-size: var(--small-size); margin: 0; }
.ap-g-deep .ap-process > li::before, .ap-g-night .ap-process > li::before { background: var(--gold); color: #111111; }
.ap-g-deep .ap-process > li::after, .ap-g-night .ap-process > li::after { background: var(--rule-line-dark); }

/* --- 8.11 RENTAL TIMELINE. Ground night. Four terms, four markers.
   This component exists BECAUSE the four containers have four different
   rental periods. It is the visual form of the rule that no single
   rental-period sentence covers all four. -------------------------------- */
.ap-timeline { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s2); list-style: none; padding: 0; margin: 0; counter-reset: apterm; }
.ap-timeline li { position: relative; padding-top: var(--s3); }
.ap-timeline li::before { content: ''; position: absolute; left: 0; top: 0; width: 22px; height: 12px; background: var(--gold); clip-path: var(--peak); }
.ap-timeline li::after { content: ''; position: absolute; left: 0; right: 0; top: 5px; height: 2px; background: var(--rule-line-dark); z-index: -1; }
.ap-timeline__size { font-family: var(--font-display); font-size: var(--micro-size); letter-spacing: var(--tracking-micro); text-transform: uppercase; color: var(--ink-on-dark-2); }
.ap-timeline__days { font-family: var(--font-display); font-size: var(--stat-size); font-weight: var(--weight-display); color: var(--white); line-height: 1.1; }
@media (max-width: 640px) { .ap-timeline { grid-template-columns: 1fr 1fr; gap: var(--s3); } }

/* --- 8.12 STAT ROW. A description list, so the pairing survives without
   CSS. Ban 5 governs which numbers are allowed here: no city count, no
   county count, no radius, no fleet count. ------------------------------- */
.ap-stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--s3); margin: 0; }
.ap-stats > div { text-align: center; }
.ap-stats dt { font-family: var(--font-display); font-size: var(--stat-size); font-weight: var(--weight-display); color: var(--gold); line-height: 1.1; }
.ap-stats dd { margin: .35rem 0 0; font-size: var(--micro-size); letter-spacing: var(--tracking-micro); text-transform: uppercase; color: var(--ink-on-dark-2); }
@media (max-width: 560px) { .ap-stats { grid-template-columns: 1fr; gap: var(--s2); } }

/* --- 8.13 FAQ. Native details and summary. ------------------------------
   GET IT RIGHT: the question text is in the DOM whether the panel is open
   or closed. Do not build this with JS that injects the answer on click:
   an answer that is not in the DOM is not in the index. ------------------ */
.ap-faq { max-width: 900px; margin-inline: auto; }
.ap-faq details { border-bottom: 1px solid var(--rule-line); }
.ap-faq summary {
  display: flex; align-items: center; justify-content: space-between; gap: var(--s2);
  padding: 1.125rem 0; cursor: pointer; list-style: none; min-height: 48px;
}
.ap-faq summary::-webkit-details-marker { display: none; }
.ap-faq summary h3 { margin: 0; font-size: 1.0625rem; }
/* Indicator, not decoration. Rule 13: 3.0:1 minimum on a UI indicator.
   #DFD457 on white is 1.53 and would be a bug here. */
.ap-faq summary::after {
  content: ''; flex: none; width: 12px; height: 12px; margin-right: 2px;
  border-right: 2.5px solid var(--deep-blue); border-bottom: 2.5px solid var(--deep-blue);
  transform: rotate(45deg) translate(-3px, -3px); transition: transform var(--dur) var(--ease);
}
.ap-faq details[open] summary::after { transform: rotate(-135deg) translate(-3px, -3px); }
.ap-faq__answer { padding: 0 0 1.25rem; font-size: var(--small-size); }
.ap-faq__answer p { max-width: var(--measure-body); }

/* --- 8.14 AREA GRID. County and city link cards. Every entry resolves to
   a real page in the workbook's Tab 4. A tile for a city with no page is a
   ghost link and it does not ship. --------------------------------------- */
.ap-areas { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--s2); list-style: none; padding: 0; margin: 0; }
.ap-areas a {
  display: flex; align-items: center; gap: .625rem; padding: .875rem 1rem;
  background: var(--white); border: 1px solid var(--rule-line); border-radius: var(--r-sm);
  text-decoration: none; color: var(--ink); font-size: var(--small-size);
  font-weight: var(--weight-body-bold); min-height: 48px;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.ap-areas a::before { content: ''; width: 10px; height: 6px; flex: none; background: var(--deep-blue); clip-path: var(--peak); }
.ap-areas a:hover { border-color: var(--deep-blue); background: var(--ground-tint); }
@media (max-width: 900px) { .ap-areas { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 420px) { .ap-areas { grid-template-columns: 1fr; } }

/* --- 8.15 MAP FRAME. lazy-loaded, ratio reserved. ----------------------- */
.ap-map { position: relative; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--r-md); border: 1px solid var(--rule-line); background: var(--ground-tint); }
.ap-map iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* --- 8.16 SPLIT. The generic 60/40 two-column used by "why choose us",
   "about snippet" and the service-area section. -------------------------- */
.ap-split { display: grid; grid-template-columns: 6fr 4fr; gap: var(--s5); align-items: center; }
.ap-split--reverse > *:first-child { order: 2; }
.ap-split--even { grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) {
  .ap-split, .ap-split--even { grid-template-columns: 1fr; gap: var(--s4); }
  .ap-split--reverse > *:first-child { order: 0; }
}

/* --- 8.17 LEGAL PAGE. Single column, generous measure, no decoration. --- */
.ap-legal { max-width: 74ch; margin-inline: auto; }
.ap-legal h2 { font-size: 1.5rem; margin-top: var(--s5); }
.ap-legal h2:first-of-type { margin-top: var(--s4); }
.ap-legal h3 { font-size: 1.125rem; margin-top: var(--s4); }
.ap-legal p, .ap-legal li { font-size: var(--small-size); }
.ap-legal ul, .ap-legal ol { max-width: var(--measure-body); }


/* --- 8.19 CONDITIONAL CLAIM. The same-day pattern, and anything else that
   needs a condition attached. Headline full size, condition small directly
   beneath, both inside ONE element.

   <p class="ap-claim">Same-Day Delivery
     <span class="ap-claim__cond">Subject to availability</span></p>

   The four rules from the header block are enforced here, not left to the
   person writing the page. -------------------------------------------- */
.ap-claim {
  display: block; margin: 0;
  font-family: var(--font-display); font-weight: var(--weight-heading);
  font-size: var(--h3-size); line-height: 1.15; letter-spacing: var(--tracking-h3);
  color: var(--ink);
}
.ap-claim__cond {
  display: block; margin-top: 4px;              /* rule 2, and it is a gap not a break */
  font-family: var(--font-body); font-weight: var(--weight-body);
  font-size: .8125rem;                          /* rule 3, floor is .75rem */
  line-height: 1.3; letter-spacing: 0; text-transform: none;
  color: var(--ink-soft);                       /* rule 4, 4.83:1 on white */
}
.ap-g-mid .ap-claim, .ap-g-deep .ap-claim, .ap-g-night .ap-claim { color: var(--white); }
/* --ink-on-dark, not --ink-on-dark-3. The inactive tone would put the
   condition under the legibility floor and that is the one way this
   pattern becomes dishonest. */
.ap-g-mid .ap-claim__cond,
.ap-g-deep .ap-claim__cond,
.ap-g-night .ap-claim__cond { color: var(--ink-on-dark); }
/* Large form, for a hero or a section head. Condition scales WITH it, so
   the ratio between the two lines never widens. */
.ap-claim--lg { font-size: var(--h2-size); font-weight: var(--weight-display); letter-spacing: var(--tracking-h2); }
.ap-claim--lg .ap-claim__cond { font-size: .875rem; margin-top: 6px; }

/* --- 8.18 REVIEW CARD. Seven real, named, linkable Google reviews replace
   the three fabricated testimonials on the old site. Quote VERBATIM. Do not
   tidy spelling or grammar. First name and last initial, as Google shows
   them. The section links to the Google Business Profile so the whole set
   is one click away. No review appears on more than two pages.
   THERE IS NO Review OR aggregateRating MARKUP ON THIS COMPONENT. ------- */
.ap-reviews { display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--grid-gap); }
.ap-review {
  background: var(--white); border: 1px solid var(--rule-line);
  border-radius: var(--r-md); padding: var(--s3); display: flex; flex-direction: column;
}
.ap-review blockquote { margin: 0 0 var(--s2); font-size: var(--small-size); line-height: 1.6; }
.ap-review blockquote p { margin-bottom: .75rem; }
.ap-review blockquote p:last-child { margin-bottom: 0; }
.ap-review figcaption { margin-top: auto; padding-top: var(--s2); border-top: 1px solid var(--rule-line); font-size: var(--micro-size); }
.ap-review__name { font-family: var(--font-display); font-weight: var(--weight-sub); color: var(--ink); display: block; }
.ap-review__meta { color: var(--ink-soft); }
/* Stars are DECORATIVE. An sr-only sentence carries the value, because
   #FBBC04 is 1.72:1 on white and cannot be the only carrier of meaning. */
.ap-review__stars { display: inline-flex; gap: 2px; margin-bottom: .5rem; }
.ap-review__stars i { width: 13px; height: 13px; background: var(--g-star); clip-path: polygon(50% 0,61% 35%,98% 35%,68% 57%,79% 91%,50% 70%,21% 91%,32% 57%,2% 35%,39% 35%); }
@media (max-width: 900px) { .ap-reviews { grid-template-columns: 1fr 1fr; } }
@media (max-width: 600px) { .ap-reviews { grid-template-columns: 1fr; } }

/* RATING LINE. Renders the score AND the count. The count is not optional
   and it is not rendered smaller than the score by more than one step.
   One without the other does not ship. */
.ap-rating { display: inline-flex; align-items: baseline; gap: .5rem; font-size: var(--small-size); }
.ap-rating__score { font-family: var(--font-display); font-weight: var(--weight-display); font-size: 1.375rem; color: var(--ink); }
.ap-rating__count { color: var(--ink-soft); }
.ap-g-deep .ap-rating__score, .ap-g-night .ap-rating__score, .ap-g-mid .ap-rating__score { color: var(--white); }
.ap-g-deep .ap-rating__count, .ap-g-night .ap-rating__count, .ap-g-mid .ap-rating__count { color: var(--ink-on-dark-2); }


/* --- 8.20 THE COLORADO RIDGE. A real photograph of the Front Range with a
   transparent sky, used as a section transition.

   THIS IS THE STRONGEST DEVICE ON THE BUILD and it is the brand name made
   literal. Altapeak. A high peak.

   HOW IT WORKS. The asset is transparent above the summit line and solid
   below it, so the section ABOVE bleeds through the sky and the mountains
   appear to rise out of it. The photo is cropped to end on its darkest
   treeline band, measured rgb(8,22,45), which sits within a hair of
   --ground-night. That is why the bottom edge butts against a night ground
   with no seam to hide.

   THE RULE: light or tint ABOVE, night BELOW. In that order, every time.
   Reversed it reads as a photograph somebody pasted in.

   ONE PER PAGE. A device used everywhere is a texture, not a device. On a
   page that already carries .ap-cta--ridge, the clip-path ridgeline and the
   photograph never sit on the same edge.

   <div class="ap-ridge" aria-hidden="true">
     <img src="/wp-content/uploads/altapeak-colorado-ridge-divider.webp"
          alt="" width="1366" height="300" loading="lazy" decoding="async">
   </div>
   <section class="ap-section ap-g-night"> ... </section>
   -------------------------------------------------------------------------- */
.ap-ridge {
  position: relative;
  width: 100%;
  line-height: 0;          /* kills the inline descender gap under the img */
  margin-bottom: -1px;     /* kills any subpixel seam at fractional zoom */
  overflow: hidden;
  pointer-events: none;
}
.ap-ridge img {
  display: block;
  width: 100%;
  height: auto;
  /* The asset is 1366 wide. Past roughly 2000px it would render tall enough to
     stop being a divider and start being a hero, so cap it and crop from the
     TOP, which removes transparent sky before it ever touches the summit. */
  max-height: clamp(120px, 22vw, 430px);
  object-fit: cover;
  object-position: center bottom;
}
/* Belt and braces. If a future page puts the ridge above a ground that is not
   --ground-night, this fades the treeline into whatever is below it. */
.ap-ridge--blend::after {
  content: '';
  position: absolute; left: 0; right: 0; bottom: 0; height: 34px;
  background: linear-gradient(to bottom, rgba(7,21,67,0) 0%, var(--ground-night) 100%);
}
/* The full range, for a feature block rather than a transition. About page. */
.ap-ridge--full img { max-height: clamp(180px, 32vw, 620px); }

/* --- 8.21 THE COLORADO FLAG. The client is proud of it and it is a real
   local signal in a market where every competitor is a national broker.

   TWO PLACES SITEWIDE, MAXIMUM. Footer base bar, and the About page beside
   the family-owned line. Any more and it stops being a signal.

   WHAT IT MUST NEVER DO. It is decorative and geographic. It is NOT a
   credential. It never sits inside a badge, a roundel, a seal or a shield,
   it never appears beside the words licensed, certified, approved, official
   or state, and it never sits in the trust row with DOT #2644006. A state
   flag styled as a certification mark implies an endorsement that does not
   exist.

   The border is not decoration. The flag carries a white band, and without a
   hairline it disappears into a light ground. --------------------------- */
.ap-flag {
  display: inline-block;
  height: 22px;
  width: auto;
  vertical-align: -4px;
  border-radius: 2px;
  border: 1px solid rgba(255,255,255,.28);
  margin-right: .5rem;
}
.ap-g-light .ap-flag,
.ap-g-tint  .ap-flag { border-color: var(--rule-line); }

.ap-flag-line {
  display: inline-flex;
  align-items: center;
  gap: .125rem;
  font-size: var(--small-size);
}
@media (max-width: 480px) { .ap-flag { height: 18px; vertical-align: -3px; } }


/* --------------------------------------------------------------------------
   9. THE DESIGN DEVICES
   Four devices, used deliberately and sparingly. A device used everywhere
   is a texture, not a device.
   -------------------------------------------------------------------------- */

/* Device 1. THE PEAK. A wide, flat triangle. Lives under an eyebrow, on a
   list marker, on a timeline marker, on a badge and on an area tile. It is
   the letterform of the brand name turned into a shape. See .ap-peak. */

/* Device 2. THE RIDGELINE, in two forms.

   2a. THE PHOTOGRAPH. A real Front Range panorama with a transparent sky,
       used at the primary light-to-dark transition. See .ap-ridge, section
       8.20. This is the better of the two and it is the one a visitor
       remembers.

   2b. THE CLIP PATH. A shallow peak cut on a band's top edge, for the CTA
       band where loading another image would not earn its weight. See
       .ap-cta--ridge.

   ONE OF EACH PER PAGE, MAXIMUM, AND NEVER ON THE SAME EDGE. Two ridgelines
   meeting is not a motif, it is a mistake. */

/* Device 3. THE SUMMIT CORNER. A single clipped top-right corner. Reads as
   a slope, not as a generic rounded card. See --summit-*. */
.ap-summit-sm { clip-path: var(--summit-sm); border-radius: 0; }
.ap-summit-md { clip-path: var(--summit-md); border-radius: 0; }
.ap-summit-lg { clip-path: var(--summit-lg); border-radius: 0; }

/* Device 4. THE CONTOUR GROUND. A topographic line texture on dark grounds
   only. Never on light: at any opacity that reads on white it also reads
   as noise. See .ap-contour. */

/* Watermark. An oversized letterform behind a dark section. Decorative,
   aria-hidden, and never carrying content. */
.ap-mark {
  position: absolute; right: -2%; bottom: -14%; z-index: 0; pointer-events: none;
  font-family: var(--font-display); font-weight: var(--weight-display);
  font-size: clamp(9rem, 26vw, 22rem); line-height: .8; letter-spacing: -.05em;
  color: var(--mark-ink); user-select: none;
}


/* --------------------------------------------------------------------------
   10. PRINT
   -------------------------------------------------------------------------- */

@media print {
  .ap-header, .ap-utility, .ap-sticky, .ap-cta, .ap-map, .ap-burger { display: none !important; }
  body.ap { color: #000; background: #fff; padding-bottom: 0; }
  .ap h1, .ap h2, .ap h3 { color: #000; }
  .ap-table table { min-width: 0; }
  .ap-faq details { display: block; }
  .ap-faq .ap-faq__answer { display: block !important; }
}


/* ==========================================================================
   GATE CHECKLIST. Run before this file ships with any page.

   1. No hue appears in a page build that is not a token in section 2.
   2. No #5E97EF or #DFD457 text on white or on --ground-tint. Anywhere.
   3. No #5E97EF button fill. No white label on a gold fill.
   4. Every primary CTA resolves to a real URL. No "#".
   5. Every button pair uses .ap-btn-pair, which is a grid. No flex-wrap.
   6. Every tappable element clears 44px on mobile.
   7. Every table is a real <table> with <thead> and th[scope], and every
      <td> carries data-label for the mobile stack.
   8. No dollar amount is typed. Every figure is a {{TOKEN}}.
   9. Accepted and prohibited are two <ul> elements, never one.
   10. There are four size cards. Not five. No concrete or dirt container
       exists at this company.
   11. No em dash and no en dash renders anywhere, including in the phone
       number.
   12. No radius, county count, city count or fleet count appears in
       .ap-badge or .ap-stats.
   13. The brand string is rendered from one source. It is not typed, and
       it is ALWAYS "Altapeak Rolloffs" with a lower-case p.
   14. No .ap-badge contains the words "Same Day". There is no cutoff time.
   15. Neither {{OVERAGE_TON}} nor {{PROHIBITED_FEE}} is live in production
       until the client has confirmed it in writing. Staging only.
   16. Saturday is written as 9:00 AM to 12:00 PM. Never "half day",
       never "Saturday service" without the window.
   17. No comparative claim about an unnamed competitor renders anywhere.
       Specifically: no "rust bucket" in any wording.
   18. Every conditional claim uses .ap-claim or .ap-badge--claim, so the
       condition sits directly beneath the headline INSIDE one element.
       Condition is never smaller than .75rem, never below 4.5:1 on its
       ground, and never anywhere other than directly under the claim.
   19. Every rating renders with its review count beside it. "4.9" alone
       is a bug. No aggregateRating or Review markup exists in the DOM.
   20. Every quoted review is verbatim and attributed. No invented,
       composite or "representative" testimonial exists on this site.
   21. At most ONE .ap-ridge photograph per page, and the ground below it is
       always --ground-night. Never the same edge as .ap-cta--ridge.
   22. The Colorado flag appears in at most TWO places sitewide, never inside
       a badge or seal, and never beside the words licensed, certified,
       approved, official or state.
   ========================================================================== */
