/* =============================================================
   TrustLight — directory surfaces (homepage grid + /search).

   Loaded AFTER site.css. Everything here is built from site.css tokens:
   the navy/blue/green palette, 14px card radii, Archivo headings, Inter
   body, and the site's existing soft-shadow language. There is no second
   design system — a card here must look like it belongs to the same site
   as the nine-checks grid directly below it.

   HEADER = H2. No masthead. The title block sits on plain white with a
   hairline rule dividing it from the body. Trade above the name, place
   below, and the compact lockup inline to the right of the name.

   GREEN IS RESERVED FOR VERIFICATION. It appears on the trust chips and
   nowhere else on a card. Blue stays the page/DTI accent.

   THE UNVETTED CARD IS NOT STYLED HERE. It uses `.card.dim` / `.lock` /
   `.unv-cta`, which already exist in site.css and already read correctly.
   The gap between a verified card and a plain unvetted one is the whole
   product; do not redesign that tier to match this one.
   ============================================================= */

/* ── Grid ─────────────────────────────────────────────────────────────── */
/* auto-fit rather than auto-fill: /featured currently returns three
   businesses, and three cards must fill the row and look deliberate
   instead of leaving six empty columns. */
.tl-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:18px; align-items:stretch;}
@media(min-width:1040px){.tl-grid{grid-template-columns:repeat(3,1fr);}}

/* ── The verified card ────────────────────────────────────────────────── */
.tl-card{background:#fff; border:1px solid var(--line); border-radius:14px; display:flex; flex-direction:column; overflow:hidden; box-shadow:0 2px 4px rgba(11,29,58,.04), 0 12px 28px rgba(11,29,58,.07); transition:box-shadow .18s ease, border-color .18s ease;}
.tl-card:hover{border-color:var(--dim-border); box-shadow:0 4px 8px rgba(11,29,58,.06), 0 18px 38px rgba(11,29,58,.11);}

/* ── The whole verified card is a link ────────────────────────────────── */
/* Unvetted cards are NOT linked - there is no profile to send anyone to,
   and inventing one would imply we know something we have not checked. */
.tl-card-link{text-decoration:none; color:inherit; cursor:pointer;}
.tl-card-link:hover{border-color:var(--blue);}

/* ── THE WHOLE-CARD LINK, WITHOUT THE CARD BEING A LINK ───────────────
   .tl-card is a <div>. The business name carries the only anchor, and this
   overlay stretches it across the card so the whole thing is clickable.

   Why not just make the card an <a> again: it was, and adding the
   "Learn how to improve this score" link inside it produced invalid HTML
   (<a> inside <a>). The browser closed the outer anchor at the inner one and
   hoisted the card body out, breaking 34 of 47 cards in production.

   Anything else interactive inside the card MUST sit above this overlay on
   z-index, or the overlay will swallow its clicks. */
.tl-card{position:relative;}
.tl-namerow h3 a.tl-card-a{color:inherit; text-decoration:none;}
.tl-namerow h3 a.tl-card-a::after{content:""; position:absolute; inset:0; z-index:0;}
.tl-card-link:focus-within{border-color:var(--blue);}
/* Above the overlay. The learn link is a real destination of its own. */
.tl-card .tl-dti-learn{position:relative; z-index:2;}

/* ── NAVY HEADERS, BOTH SURFACES ──────────────────────────────────────
   .tl-card has no padding of its own (.tl-hdr carries it), so its header
   needs no negative margin. .card has padding:20px, so its header pulls out
   to reach the edges. */
.tl-card .tl-hdr{background:var(--navy); padding:15px 18px 14px; border-radius:13px 13px 0 0;}
.tl-card .tl-hdr::after{display:none;}
.tl-card .tl-hdr h3{color:#fff; font-size:18.5px; line-height:1.25;}
.tl-card .tl-hdr .tl-namerow{display:block;}
.card.dim .c-hdr{background:#33445C; margin:-20px -20px 0; padding:15px 18px 14px; border-radius:13px 13px 0 0;}
.card.dim .c-hdr h3{color:#E6ECF3; font-size:17px; line-height:1.25;}
/* The unvetted header is a LIGHTER navy with no badge and no chips, so the
   hierarchy survives both cards sharing a colour. */

/* The trade, demoted. It was a padded bordered pill above the name - the
   .tl-trade class collides with the trade FILTER buttons, which is where that
   styling came from. Renamed to .tl-meta so the two cannot collide again. */
.tl-meta{font-size:11.5px; font-weight:700; letter-spacing:.06em; text-transform:uppercase;
  color:#8FB4E8; margin-top:6px;}
.card.dim .tl-meta{color:#9DB2CC;}
.tl-meta .sep{opacity:.5; margin:0 5px;}

/* ── THREE WEIGHTED SEGMENTS ──────────────────────────────────────────
   Each button IS a group, flex-sized by its weight. The inner <i> fills to
   the proportion of that group which is present, so a half-met group reads
   as half a bar rather than all-or-nothing. */
.tl-dti-seg{display:flex; gap:3px;}
.tl-dti-seg button{border:0; padding:0; height:10px; border-radius:2px; overflow:hidden;
  background:var(--dim-border); cursor:pointer; font:inherit; transition:filter .12s;
  position:relative; z-index:2;}
.tl-dti-seg button i{display:block; height:100%; background:var(--blue); border-radius:2px;}
.tl-dti-seg button.unknown{background:repeating-linear-gradient(45deg,
  var(--dim-bg) 0 4px, var(--dim-border) 4px 8px);}
.tl-dti-seg button:hover,.tl-dti-seg button:focus-visible{filter:brightness(1.3);
  outline:2px solid var(--navy); outline-offset:2px;}
.card.dim .tl-dti-seg button i{background:#7D93AC;}

/* The label sits ABOVE the bars: the cursor is on the bars while you point at
   them and would cover text rendered underneath. 4.4em is measured from the
   tallest of the labels, so revealing one never resizes the card. */
.tl-dti-say{font-size:12px; line-height:1.45; color:var(--steel); margin:7px 0 8px; min-height:4.4em;}
.tl-dti-say b{color:var(--navy); display:block;}
.card.dim .tl-dti-say b{color:#48525F;}
.tl-dti-say.idle{font-style:italic; color:var(--dim-text);}

/* ── THE BADGE, AT THE FOOT ───────────────────────────────────────────
   compact-dark.svg is 192x46 on a navy ground - "dark" means dark
   BACKGROUND, so it is the lockup made for a white card. */
.tl-seal{margin-top:15px; padding-top:14px; border-top:1px solid var(--line); text-align:center;}
.tl-seal img{width:176px; height:auto; display:inline-block;}
.tl-card-link:hover .tl-card-cta{background:var(--blue); color:#fff;}
.tl-card-link:hover .tl-card-cta svg{stroke:#fff; transform:translateX(3px);}
/* Keyboard users get the same affordance a mouse user gets on hover, and a
   focus ring that is visible against a white card. */
.tl-card-link:focus-visible{outline:3px solid var(--blue); outline-offset:2px; border-color:var(--blue);}
.tl-card-link:focus-visible .tl-card-cta{background:var(--blue); color:#fff;}
.tl-card-link:focus-visible .tl-card-cta svg{stroke:#fff;}

.tl-card-cta{display:flex; align-items:center; justify-content:space-between; gap:8px; padding:12px 20px; border-top:1px solid var(--line); background:var(--paper); font-size:13px; font-weight:700; color:var(--blue); transition:background .16s ease, color .16s ease;}
.tl-card-cta svg{width:16px; height:16px; flex-shrink:0; fill:none; stroke:var(--blue); stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round; transition:transform .16s ease, stroke .16s ease;}

/* H2 header — no masthead, hairline rule into the body. */
.tl-hdr{padding:20px 20px 0;}
.tl-hdr::after{content:''; display:block; height:1px; background:var(--line); margin-top:16px;}
.tl-trade{display:block; font-size:11px; font-weight:800; letter-spacing:.09em; text-transform:uppercase; color:var(--blue); margin-bottom:7px;}
.tl-namerow{display:flex; align-items:center; gap:12px; flex-wrap:wrap;}
.tl-namerow h3{flex:1; min-width:150px; font-family:'Archivo',sans-serif; font-size:18.5px; font-weight:800; line-height:1.22; color:var(--navy); letter-spacing:-.02em;}
.tl-place{font-size:13px; color:var(--steel); margin-top:6px;}

/* THE BADGE. 152px keeps the lockup's smallest line legible; the
   horizontal lockup at this width drops its third line to ~5px. */
.tl-badge{width:152px; height:auto; flex-shrink:0; display:block;}

.tl-body{padding:16px 20px 20px; flex:1; display:flex; flex-direction:column;}

/* Trust chips — the one place green appears. */
.tl-chips{display:flex; gap:6px; flex-wrap:wrap;}
.tl-chip{font-size:10.5px; font-weight:800; letter-spacing:.04em; text-transform:uppercase; color:var(--green-deep); background:#EAF7EF; border:1px solid #BFE6CD; padding:4px 9px; border-radius:100px; display:inline-flex; align-items:center; gap:5px;}
.tl-chip svg{width:10px; height:10px; stroke:var(--green-deep); fill:none; stroke-width:3;}

/* Rating. A null rating is NOT zero — it renders "No reviews yet" and is
   styled as a plain statement of fact, never as a demerit. */
.tl-rate{display:flex; align-items:center; gap:8px; font-size:13px; margin-top:13px;}
.tl-stars{color:#9A6100; letter-spacing:1px; font-size:14px;}
.tl-rate-n{font-weight:700; color:var(--navy);}
.tl-rate-c{color:var(--steel);}
.tl-rate.none{color:var(--steel); font-style:italic;}

/* Clamped to three lines so blurb length cannot make one card taller
   than its neighbours. min-height reserves the space either way. */
.tl-blurb{font-size:14px; line-height:1.55; color:var(--steel); margin-top:12px; display:-webkit-box; -webkit-line-clamp:3; -webkit-box-orient:vertical; overflow:hidden; min-height:calc(1.55em * 3);}
.tl-blurb.empty{color:var(--steel); font-style:italic;}

/* Pushes the DTI block to the bottom so every card's footer lines up
   across the row regardless of how much text sits above it. */
.tl-grow{flex:1;}

/* Digital Trust Index — segmented bars, matching site.css .dti-bars. */
.tl-dti{margin-top:16px; padding-top:15px; border-top:1px solid var(--line);}
.tl-dti-hd{display:flex; justify-content:space-between; align-items:baseline; font-size:11.5px; font-weight:700; color:var(--steel);}
.tl-dti-hd b{font-family:'Archivo',sans-serif; font-size:17px; font-weight:900; color:var(--blue);}
.tl-dti-bars{display:flex; gap:3px; margin-top:9px;}
.tl-dti-bars i{height:7px; flex:1; border-radius:2px; background:var(--dim-border);}
.tl-dti-bars i.on{background:var(--blue);}
.tl-dti-note{font-size:11px; color:var(--steel); margin-top:8px;}
/* Not scored yet. Occupies the same slot so the footer still aligns and
   the card does not read as broken. */
.tl-dti-none{margin-top:16px; padding-top:15px; border-top:1px solid var(--line); font-size:11.5px; color:var(--steel); font-style:italic;}

/* ── Section chrome ───────────────────────────────────────────────────── */
/* The "verified means" line. One or two sentences, never a paragraph —
   the reader may have lost a roof three days ago. */
.tl-define{border-left:3px solid var(--blue); background:var(--paper); border-radius:0 12px 12px 0; padding:16px 20px; margin:0 0 26px; font-size:15.5px; line-height:1.6; color:var(--navy); max-width:70ch;}

.tl-loading{font-size:15px; color:var(--steel); padding:26px 0;}

.tl-msg{background:var(--paper); border:1px solid var(--line); border-radius:14px; padding:28px 26px; max-width:70ch;}
.tl-msg h3{font-size:19px; font-weight:800; margin-bottom:9px;}
.tl-msg p{font-size:15px; line-height:1.65; color:var(--steel); margin-bottom:9px;}
.tl-msg p:last-child{margin-bottom:0;}
/* A failure must never look like an empty result. Telling a family "no
   contractors" when the truth is "we could not reach our records" would
   be a lie that costs them. */
.tl-msg-err{background:#FFF6F6; border-color:#F3C9C9;}
.tl-msg-err h3{color:#8C1A2B;}

/* The route onward to /search. */
.tl-tosearch{margin-top:30px; padding-top:26px; border-top:1px solid var(--line); display:flex; gap:20px; align-items:center; justify-content:space-between; flex-wrap:wrap;}
.tl-tosearch p{font-size:15.5px; color:var(--steel); max-width:52ch; margin:0;}

/* ── /search only ─────────────────────────────────────────────────────── */
.tl-filters{background:var(--paper); border:1px solid var(--line); border-radius:16px; padding:22px 24px; margin-bottom:26px;}
.tl-filter-row{display:grid; gap:12px; grid-template-columns:repeat(auto-fit,minmax(165px,1fr)); align-items:end;}
.tl-field{display:flex; flex-direction:column; gap:6px;}
.tl-field label{font-size:11px; font-weight:800; letter-spacing:.09em; text-transform:uppercase; color:var(--steel);}
.tl-field input,.tl-field select{padding:12px 14px; border:2px solid var(--line); border-radius:10px; font-size:14.5px; font-family:inherit; color:var(--navy); background:#fff; width:100%;}
.tl-field input:focus,.tl-field select:focus{outline:none; border-color:var(--blue);}
.tl-filter-actions{display:flex; gap:10px; margin-top:16px; flex-wrap:wrap;}

.tl-counts{font-size:14.5px; color:var(--steel); padding-bottom:18px; margin-bottom:26px; border-bottom:1px solid var(--line);}
.tl-counts b{color:var(--navy);}

.tl-tier{margin-top:44px;}
.tl-tier:first-of-type{margin-top:0;}
.tl-tier-head{margin-bottom:10px;}
.tl-tier-head h2{font-size:1.4rem; font-weight:900;}
.tl-tier-note{font-size:14.5px; line-height:1.6; color:var(--steel); margin:0 0 20px; max-width:70ch;}

.tl-pager{display:flex; align-items:center; gap:14px; flex-wrap:wrap; margin-top:40px; padding-top:24px; border-top:1px solid var(--line);}
.tl-pager button{font-family:'Inter',sans-serif; font-size:14.5px; font-weight:700; padding:11px 22px; border:2px solid var(--line); border-radius:10px; background:#fff; color:var(--navy); cursor:pointer;}
.tl-pager button:hover:not(:disabled){border-color:var(--blue); color:var(--blue);}
.tl-pager button:disabled{opacity:.4; cursor:default;}
.tl-pager-info{font-size:14px; color:var(--steel);}

@media(max-width:640px){
  .tl-tosearch{flex-direction:column; align-items:flex-start;}
  .tl-filter-actions .btn{width:100%; justify-content:center;}
}

/* ── Homepage DTI rows, figures removed ───────────────────────────────── */
/* The five pillar rows used to carry invented scores and a fabricated
   "directory average" for each. Every real record returns dti: null, so those
   numbers described nothing. The rows keep the icon and the explanation and
   drop the two figure columns. */
.dti-row.nofig{grid-template-columns:52px 1fr; gap:18px;}
@media(max-width:820px){.dti-row.nofig{grid-template-columns:52px 1fr;}}

/* ── CONTRACTOR PROFILE — /contractor/{slug} ──────────────────────────── */
.crumb-dark{font-size:12.5px; color:var(--steel); margin-bottom:22px;}
.crumb-dark a:hover{color:var(--blue);}

.cp-head{display:flex; gap:26px; align-items:flex-start; flex-wrap:wrap; padding-bottom:26px; border-bottom:1px solid var(--line);}
.cp-badge{width:150px; height:auto; flex-shrink:0;}
.cp-head-b{flex:1; min-width:260px;}
.cp-trade{display:block; font-size:11.5px; font-weight:800; letter-spacing:.09em; text-transform:uppercase; color:var(--blue); margin-bottom:8px;}
.cp-head h1{font-size:clamp(1.7rem,3.6vw,2.3rem); font-weight:900; line-height:1.14; color:var(--navy);}
.cp-place{font-size:15px; color:var(--steel); margin-top:7px;}
.cp-rate{display:flex; align-items:center; gap:8px; font-size:14px; margin-top:12px;}
.cp-stars{color:#9A6100; letter-spacing:1px; font-size:15px;}
.cp-rate-n{font-weight:700; color:var(--navy);}
.cp-rate-c{color:var(--steel);}
/* The link out to the reviews we are quoting. Deliberately quieter than the
   score itself and it wraps to its own line on a phone, because the rating is
   the fact and this is the way to check it. */
.cp-rate-link{font-weight:600; color:var(--blue); text-decoration:none; white-space:nowrap;}
.cp-rate-link:hover{text-decoration:underline;}
@media(max-width:520px){
  .cp-rate{flex-wrap:wrap;}
  .cp-rate-link{flex-basis:100%; margin-top:4px;}
}
.cp-norating{color:var(--steel); font-style:italic;}
.cp-chips{display:flex; gap:6px; flex-wrap:wrap; margin-top:14px;}

/* CONTACT. The reason a homeowner opened this page. Directly under the
   masthead, and the phone is the largest non-heading type here. */
.cp-contact{background:var(--paper); border:1px solid var(--line); border-radius:16px; padding:26px 28px; margin-top:28px;}
.cp-contact h2{font-size:12px; font-weight:800; letter-spacing:.1em; text-transform:uppercase; color:var(--steel); margin-bottom:14px;}
.cp-phone{display:inline-flex; align-items:center; gap:13px; font-family:'Archivo',sans-serif; font-size:clamp(1.55rem,4vw,2.05rem); font-weight:900; color:var(--navy); letter-spacing:-.02em; line-height:1.1;}
.cp-phone svg{width:26px; height:26px; flex-shrink:0; fill:none; stroke:var(--green); stroke-width:2; stroke-linejoin:round; stroke-linecap:round;}
.cp-phone:hover{color:var(--blue);}
.cp-phone:hover svg{stroke:var(--blue);}
.cp-contact-rows{margin-top:18px; display:flex; flex-direction:column; gap:11px;}
.cp-row{display:flex; gap:14px; font-size:14.5px; line-height:1.5; align-items:flex-start;}
.cp-row-l{flex:0 0 92px; font-size:11.5px; font-weight:800; letter-spacing:.07em; text-transform:uppercase; color:var(--steel); padding-top:3px;}
.cp-row a{color:var(--blue); font-weight:600; word-break:break-word;}
.cp-row a:hover{text-decoration:underline;}

.cp-about,.cp-checks,.cp-facts,.cp-dti{margin-top:34px;}
.cp-about h2,.cp-checks h2,.cp-facts h2,.cp-dti h2{font-size:1.25rem; font-weight:900; color:var(--navy); margin-bottom:10px;}
.cp-about p{font-size:15.5px; line-height:1.65; color:var(--steel);}
.cp-lead{font-size:14.5px; line-height:1.6; color:var(--steel); margin-bottom:16px; max-width:66ch;}
.cp-lead strong{color:var(--navy);}

.cp-check-list{list-style:none; display:grid; grid-template-columns:repeat(auto-fit,minmax(250px,1fr)); gap:9px;}
.cp-check-list li{display:flex; gap:9px; align-items:flex-start; font-size:14px; color:var(--navy); background:#EAF7EF; border:1px solid #BFE6CD; border-radius:10px; padding:10px 13px;}
.cp-check-list svg{width:13px; height:13px; flex-shrink:0; margin-top:3px; stroke:var(--green-deep); fill:none; stroke-width:3;}
.cp-when{font-size:13px; color:var(--steel); margin-top:14px;}

.cp-facts-g{display:flex; gap:14px; flex-wrap:wrap;}
.cp-fact{background:#fff; border:1px solid var(--line); border-radius:12px; padding:14px 20px; text-align:center;}
.cp-fact b{display:block; font-family:'Archivo',sans-serif; font-size:24px; font-weight:900; color:var(--navy);}
.cp-fact span{font-size:11.5px; color:var(--steel); text-transform:uppercase; letter-spacing:.06em;}
.cp-services{list-style:none; display:flex; gap:7px; flex-wrap:wrap; margin-top:16px;}
.cp-services li{font-size:13px; color:var(--navy); background:var(--paper); border:1px solid var(--line); border-radius:100px; padding:6px 13px;}

.cp-dti-total{display:flex; align-items:baseline; gap:9px; margin-bottom:20px;}
.cp-dti-total b{font-family:'Archivo',sans-serif; font-size:40px; font-weight:900; color:var(--blue); line-height:1;}
.cp-dti-total span{font-size:13px; color:var(--steel);}
.cp-pillar{margin-top:16px;}
.cp-pillar-h{display:flex; justify-content:space-between; align-items:baseline; font-size:14px; font-weight:700; color:var(--navy);}
.cp-pillar-h b{font-family:'Archivo',sans-serif; font-size:16px; font-weight:900; color:var(--blue);}
.cp-pillar .tl-dti-bars{margin-top:7px;}
.cp-pillar-n{font-size:12.5px; color:var(--steel); margin-top:6px;}

.cp-foot{margin-top:40px; padding-top:26px; border-top:1px solid var(--line);}
.cp-foot p{font-size:14.5px; color:var(--steel); line-height:1.6; max-width:64ch; margin-bottom:16px;}

@media(max-width:620px){
  .cp-head{gap:18px;}
  .cp-badge{width:112px;}
  .cp-contact{padding:22px 20px;}
  .cp-row{flex-direction:column; gap:3px;}
  .cp-row-l{flex:none;}
}

/* ── THE TRADE GRID ───────────────────────────────────────────────────────
   The primary control on /search, and for most visitors the only one they
   will touch. Built mobile-first: two columns at 375px with a 44px+ target,
   widening on larger screens. Nothing here may cause horizontal scroll -
   min-width:0 on the button and a wrapping label are what guarantee it. */
.tl-trades{margin-bottom:26px;}
.tl-trades-h{font-family:'Archivo',sans-serif; font-size:1.15rem; font-weight:900; color:var(--navy); margin-bottom:14px;}

.tl-trade-grid{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:10px;}
@media(min-width:520px){.tl-trade-grid{grid-template-columns:repeat(3,minmax(0,1fr));}}
@media(min-width:800px){.tl-trade-grid{grid-template-columns:repeat(4,minmax(0,1fr));}}

.tl-trade{
  display:flex; flex-direction:column; align-items:flex-start; justify-content:center; gap:3px;
  min-width:0;                      /* lets the label wrap instead of pushing the grid wide */
  min-height:62px; padding:12px 14px;
  background:#fff; border:2px solid var(--line); border-radius:12px;
  font-family:'Inter',sans-serif; text-align:left; cursor:pointer;
  transition:border-color .14s ease, background .14s ease, color .14s ease;
  -webkit-tap-highlight-color:transparent;
}
.tl-trade-l{font-size:15px; font-weight:700; color:var(--navy); line-height:1.2; overflow-wrap:anywhere;}
/* The count. Absent until it loads, and absent for ever if it fails - the
   button works either way, so it must never look broken while empty. */
.tl-trade-n{font-size:12px; color:var(--steel); font-variant-numeric:tabular-nums; min-height:1em;}
/* THE SPLIT IS NOW IN THE MARKUP, not in a ::after suffix: the button shows
   "2 verified · 300 listed". "listed", not "nearby" or "available" - most of
   these are businesses we have not checked, there is no geographic filter
   applied, and the word has to say exactly that and nothing warmer. */
.tl-trade-v{font-weight:800; color:var(--green-deep);}
.tl-trade-sep{font-style:normal; opacity:.45; margin:0 5px;}
.tl-trade.is-on .tl-trade-v{color:#6EE7A8;}

.tl-trade:hover{border-color:var(--blue-lt);}
.tl-trade:focus-visible{outline:3px solid var(--blue); outline-offset:2px;}

/* Selected. Unmistakable at a glance and at arm's length: filled navy, not a
   tint. The count inverts with it so it stays legible. */
.tl-trade.is-on{background:var(--navy); border-color:var(--navy);}
.tl-trade.is-on .tl-trade-l{color:#fff;}
.tl-trade.is-on .tl-trade-n{color:var(--blue-lt);}

.tl-trade-clear{
  margin-top:14px; padding:11px 20px; min-height:44px;
  background:#fff; border:2px solid var(--navy); border-radius:10px;
  font-family:'Inter',sans-serif; font-size:14.5px; font-weight:700; color:var(--navy); cursor:pointer;
}
.tl-trade-clear:hover{background:var(--navy); color:#fff;}

/* ── Secondary filters ────────────────────────────────────────────────────
   Collapsed by default. It exists for the minority who want to narrow
   further, and must not compete with the grid above it. */
.tl-more{border:1px solid var(--line); border-radius:12px; background:var(--paper); margin-bottom:26px;}
.tl-more > summary{
  cursor:pointer; padding:14px 18px; min-height:44px;
  font-family:'Inter',sans-serif; font-size:14.5px; font-weight:700; color:var(--navy);
  display:flex; align-items:center; gap:10px; flex-wrap:wrap; list-style:none;
}
.tl-more > summary::-webkit-details-marker{display:none;}
.tl-more > summary::before{content:"+"; font-size:17px; font-weight:800; color:var(--blue); line-height:1;}
.tl-more[open] > summary::before{content:"\2212";}
.tl-more-hint{font-weight:400; color:var(--steel); font-size:13px;}
.tl-more .tl-filters{background:transparent; border:none; border-top:1px solid var(--line); border-radius:0; margin-bottom:0;}

@media(max-width:400px){
  .tl-trade{min-height:58px; padding:10px 12px;}
  .tl-trade-l{font-size:14px;}
  .tl-more-hint{display:none;}
}

/* ── Online-presence gaps, on a contractor's own profile ──────────────────
   Deliberately NOT styled as a warning. It sits below the checks and the
   score, in the site's paper tone, because a business without online booking
   has a smaller web presence and not a smaller claim to being trustworthy.
   A homeowner reads this too - there is no login - so it must never look
   like a mark against the business. */
.cp-gaps{margin-top:34px; background:var(--paper); border:1px solid var(--line); border-radius:14px; padding:22px 24px;}
.cp-gaps h2{font-size:1.1rem; font-weight:900; color:var(--navy); margin-bottom:9px;}
.cp-gaps p{font-size:14.5px; line-height:1.6; color:var(--steel);}
/* Consecutive paragraphs were running together: the fact and the offer are
   two different statements and need to read as two. */
.cp-gaps p + p{margin-top:12px;}
.cp-gaps-cta{margin-top:13px; padding-top:13px; border-top:1px solid var(--line); color:var(--navy) !important;}
.cp-gaps-cta b{color:var(--navy);}
/* :not(.btn) matters. This rule used to paint the CTA link blue, and when the
   CTA became a green button it painted the LABEL blue on green - unreadable.
   Inline links here stay blue; a button keeps whatever .btn-* gives it. */
.cp-gaps-cta a:not(.btn){color:var(--blue); font-weight:700;}
.cp-gaps-cta a:not(.btn):hover{text-decoration:underline;}

/* ── An explained zero ────────────────────────────────────────────────
   A 0 is only ever printed when we actually checked, and it never appears
   without the sentence that says what kind of nothing we found. Amber, not
   red: this is a finding about a website, not a warning about a business. */
.tl-dti-zero .tl-dti-hd b{color:#B45309;}
.tl-dti-why{font-size:12px; line-height:1.5; color:var(--steel); margin-top:6px;}
.tl-dti-why b{color:var(--navy);}
.tl-dti-learn{display:inline-block; margin-top:8px; font-size:11.5px; font-weight:700; color:var(--blue);}
.tl-dti-learn:hover{text-decoration:underline;}
.card.dim .tl-dti-learn{color:#4B6C9B;}
.card.dim .tl-dti{margin-top:14px; padding-top:13px; border-top:1px dashed var(--dim-border);}
.card.dim .tl-dti-hd b{color:#55606E;}
.card.dim .tl-dti-bars i.on{background:#7D93AC;}
.card.dim .unv-cta a.unv-grow{background:var(--blue); margin-bottom:7px;}
.card.dim .unv-cta a.unv-grow:hover{background:var(--blue-deep);}

/* The gap-to-fix list. Each row names something we measured and the thing
   that closes it, so the block answers "why isn't it 100" instead of only
   stating it. */
.cp-fix{list-style:none; margin:12px 0 0; padding:0; display:flex; flex-direction:column; gap:10px;}
.cp-fix li{font-size:14.5px; line-height:1.55; color:var(--steel);
  padding-left:16px; position:relative;}
.cp-fix li::before{content:""; position:absolute; left:0; top:9px;
  width:6px; height:6px; border-radius:50%; background:var(--green);}
.cp-fix li b{color:var(--navy); font-weight:800;}
.cp-fix-run{margin-top:14px; font-size:14px; color:var(--steel);}
/* The CTA is a button here, not an inline link, so the border-top rule that
   suited a sentence would sit oddly above it. */
.cp-gaps .cp-gaps-cta{border-top:0; padding-top:0; margin-top:14px;}

/* ── /b/<slug> — a business's own page ────────────────────────────────
   The page is the VERIFIED PROFILE with the lights off, so it borrows the
   .cp-* classes wholesale and only adds two things: the navy pitch band on
   top, and the "switched off" treatment. Mobile first throughout: this is
   opened on a phone, from a text message, by someone standing next to a
   truck. */

/* ── the pitch band ── */
.bizhero{
  background:radial-gradient(ellipse 90% 70% at 20% -10%, rgba(37,99,235,.34) 0%, transparent 68%), var(--navy);
  color:#fff; padding:52px 0 46px;
}
.bizhero-eyebrow{
  font-size:11px; font-weight:800; letter-spacing:.13em; text-transform:uppercase;
  color:var(--blue-lt); margin-bottom:14px;
}
.bizhero h1{
  color:#fff; font-size:clamp(1.9rem,6.4vw,3rem); font-weight:900;
  line-height:1.08; letter-spacing:-.01em;
}
/* The second line is deliberately quieter and smaller than their name: the
   business is the subject of the sentence, we are the predicate. */
.bizhero-h2{
  display:block; font-style:normal; font-size:clamp(1.05rem,3.4vw,1.5rem);
  font-weight:700; color:var(--blue-lt); margin-top:10px; letter-spacing:0;
}
.bizhero-lede{
  color:rgba(255,255,255,.72); font-size:16px; line-height:1.68;
  margin-top:20px; max-width:54ch;
}
.bizhero-stat{
  display:flex; gap:14px; flex-wrap:wrap; margin-top:28px;
}
.bizhero-n{
  background:rgba(255,255,255,.055); border:1px solid rgba(255,255,255,.13);
  border-radius:13px; padding:15px 19px; min-width:156px;
}
.bizhero-n b{
  display:block; font-family:'Archivo',sans-serif; font-size:2.1rem;
  font-weight:900; color:#fff; line-height:1;
}
.bizhero-n span{
  display:block; font-size:12px; color:rgba(255,255,255,.6);
  margin-top:6px; line-height:1.4;
}
/* "1 of them is yours" is the line that has to land, so it gets the accent. */
.bizhero-n-you{background:rgba(37,99,235,.2); border-color:rgba(96,165,250,.45);}
.bizhero-n-you b{color:var(--blue-lt);}
.bizhero-n-you span{color:rgba(255,255,255,.8);}
.bizhero-cta{display:flex; gap:16px; align-items:center; flex-wrap:wrap; margin-top:30px;}
.bizhero-skip{color:rgba(255,255,255,.62); font-size:13.5px; font-weight:600;}
.bizhero-skip:hover{color:#fff; text-decoration:underline;}

/* ── the profile, switched off ──────────────────────────────────────────
   THE HEADING STAYS SHARP. A blurred heading reads as a broken page; a sharp
   heading over blurred content reads as a real section that is off, which is
   the whole message of this page. */
.bizprofile{padding-top:34px;}
.cp-off-hd{
  display:flex; align-items:center; gap:12px; flex-wrap:wrap;
  margin-bottom:12px;
}
.cp-off-hd h2{margin-bottom:0 !important;}
.cp-off-pill{
  display:inline-flex; align-items:center; gap:6px; font-size:11.5px;
  font-weight:700; color:var(--blue); background:rgba(37,99,235,.09);
  border:1px solid rgba(37,99,235,.26); border-radius:100px; padding:4px 11px;
}
.cp-lock-i{width:11px; height:11px; stroke:currentColor; fill:none; stroke-width:2.2; flex-shrink:0;}

.cp-off-wrap{position:relative; border-radius:16px; overflow:hidden;}
/* 1.6px, not 4px, and .72 opacity rather than .42. The point is that they
   RECOGNISE this as their own profile with the lights off — at 4px it was an
   unreadable grey field, which reads as a rendering fault rather than as
   something switched off. At this strength the shape, the green check pills
   and the layout are all legible and the text is not. */
.cp-off-body{
  /* grayscale(.55), not (1). Full desaturation turned the green confirmation
     pills to near-white and took away the one colour cue that says "these are
     checks that passed" - which is the thing they are being shown. Partial
     desaturation still reads as off; the scrim and the lock pill carry that. */
  filter:blur(1.6px) grayscale(.55); opacity:.72; pointer-events:none;
  user-select:none; -webkit-user-select:none;
  /* Blur bleeds past the box, so scale up slightly and let overflow:hidden on
     the wrapper crop it. Without this the edges fade to nothing. */
  transform:scale(1.01); transform-origin:center;
}
.cp-off-body *{pointer-events:none !important;}
/* An icon, three or four words, and the button. Nobody reads a sentence laid
   over a blur — the old overlay carried a full clause and it was skipped. The
   scrim is lighter now too, because the content beneath it is the argument. */
.cp-off-over{
  position:absolute; inset:0; display:flex; flex-direction:column;
  align-items:center; justify-content:center; gap:10px; text-align:center;
  padding:22px 20px; background:rgba(255,255,255,.34);
}
.cp-off-over p{
  font-size:16px; font-weight:800; line-height:1.3; color:var(--navy);
  max-width:22ch; margin:0; letter-spacing:-.01em;
}
.cp-off-ico{
  display:flex; align-items:center; justify-content:center;
  width:46px; height:46px; border-radius:50%;
  background:rgba(37,99,235,.11); border:1px solid rgba(37,99,235,.24);
}
.cp-off-ico svg{width:22px; height:22px; fill:var(--blue);}
.cp-off-ico svg.ico-stroke{fill:none; stroke:var(--blue); stroke-width:1.9;
  stroke-linecap:round; stroke-linejoin:round;}
.cp-off-btn{padding:9px 18px; font-size:13.5px;}

/* The contact block keeps its paper panel so the shape is recognisably the
   real one. .cp-contact's own padding would double up inside the wrapper. */
.cp-contact.cp-off{background:none; border:0; padding:0;}
/* The panel lives on the WRAPPER, not on the blurred body: a background that
   is itself blurred and at 42% opacity vanishes, and the block reads as a
   white hole rather than the contact card with its lights off. */
.cp-contact.cp-off .cp-off-wrap{background:var(--paper); border:1px solid var(--line);}
.cp-contact.cp-off .cp-off-body{padding:26px 28px;}
.cp-ph-phone{
  display:flex; align-items:center; gap:10px; font-family:'Archivo',sans-serif;
  font-size:26px; font-weight:900; color:var(--green-deep);
}
.cp-ph-phone svg{width:21px; height:21px; fill:var(--green-deep);}

/* Badge and chips: present at full size, just not lit. */
.cp-badge-off{position:relative; flex-shrink:0; line-height:0;}
.cp-badge-off .cp-badge{filter:grayscale(1); opacity:.34;}
.cp-badge-lock{
  position:absolute; inset:0; display:flex; align-items:center; justify-content:center;
}
.cp-badge-lock .cp-lock-i{
  width:34px; height:34px; stroke:var(--steel); stroke-width:1.6;
  background:rgba(255,255,255,.88); border-radius:50%; padding:7px;
  box-shadow:0 2px 10px rgba(11,29,58,.14);
}
.cp-chips-off .tl-chip{
  color:var(--steel); background:#F1F3F6; border-color:var(--line);
}
.cp-chips-off .tl-chip .cp-lock-i{stroke:var(--steel);}

.cp-dti-lead{font-size:14.5px; line-height:1.6; color:var(--steel); margin-bottom:16px; max-width:66ch;}
.cp-dti-lead b{color:var(--navy);}
.cp-gaps h3{font-size:1.1rem; font-weight:900; color:var(--navy); margin-bottom:9px;}
.cp-gaps ul{margin:10px 0 0; padding-left:20px;}
.cp-gaps li{font-size:14px; line-height:1.6; color:var(--steel); margin-bottom:5px;}
.cp-gaps .btn{margin-top:14px;}
.biz-foot .btn{margin-top:4px;}

/* ── the verification sections below the profile ── */
.biz-story{display:grid; grid-template-columns:1fr; gap:26px; align-items:start;}
@media(min-width:820px){.biz-story{grid-template-columns:1fr 1fr; gap:32px;}}
.biz-story-copy h2{font-size:1.35rem; color:var(--navy); margin-bottom:12px;}
.biz-story-copy p{font-size:15px; line-height:1.68; color:var(--steel); margin-bottom:13px;}
.biz-story-copy b{color:var(--navy);}

.biz-checks{list-style:none; counter-reset:c; margin:18px 0 0; padding:0;}
.biz-checks li{counter-increment:c; position:relative; padding-left:38px; margin-bottom:12px;
  font-size:14.5px; line-height:1.6; color:var(--steel);}
.biz-checks li::before{content:counter(c); position:absolute; left:0; top:1px;
  width:25px; height:25px; border-radius:50%; background:var(--navy); color:#fff;
  font-size:12px; font-weight:800; display:flex; align-items:center; justify-content:center;}
.biz-checks li b{color:var(--navy);}
.biz-lead{font-size:15px; line-height:1.65; color:var(--steel); margin-top:20px; max-width:62ch;}

.biz-prices{display:grid; grid-template-columns:1fr; gap:14px; margin-top:26px;}
@media(min-width:720px){.biz-prices{grid-template-columns:1fr 1fr;}}
.biz-price{border:1px solid var(--line); border-radius:14px; padding:20px; background:#fff;}
.biz-price-x{border-color:var(--navy); border-width:2px;}
.biz-price-n{font-size:11.5px; font-weight:800; letter-spacing:.07em; text-transform:uppercase; color:var(--steel);}
.biz-price-v{font-size:2rem; font-weight:900; color:var(--navy); margin-top:5px; line-height:1;}
.biz-price-v span{font-size:1rem; font-weight:700; color:var(--steel);}
.biz-price-was{font-size:12.5px; color:var(--dim-text); text-decoration:line-through; margin-top:3px;}
.biz-price p{font-size:13.5px; line-height:1.55; color:var(--steel); margin-top:11px;}
.biz-price p b{color:var(--navy);}

.biz-refund{margin-top:20px; padding:13px 16px; border-radius:10px;
  background:rgba(22,163,74,.09); border:1px solid rgba(22,163,74,.3);
  font-size:14px; font-weight:700; color:var(--navy);}
.biz-cta{margin-top:20px; display:flex; flex-wrap:wrap; gap:11px;}
.btn-lg{padding:14px 22px; font-size:15px;}
.biz-note{font-size:12.5px; color:var(--dim-text); margin-top:14px; font-style:italic;}
.biz-close h2{font-size:1.4rem; color:var(--navy);}
.biz-close p{font-size:15px; line-height:1.65; color:var(--steel); margin-top:11px; max-width:60ch;}

@media(max-width:620px){
  .bizhero{padding:40px 0 36px;}
  .bizhero-n{flex:1; min-width:0; padding:13px 15px;}
  .bizhero-n b{font-size:1.75rem;}
  .cp-contact.cp-off .cp-off-body{padding:22px 20px;}
  .cp-off-over p{font-size:13.5px;}
  .cp-ph-phone{font-size:22px;}
}

/* ── THE UNVETTED CARD CLICKS THROUGH TO /b/<slug> ────────────────────
   Same overlay pattern as .tl-card, for the same reason: the card already
   contains .unv-cta links, so it can never be wrapped in an anchor. The
   overlay lives on the name; the CTA links sit above it on z-index. */
.card.dim{position:relative;}
.card.dim .c-hdr h3 a.tl-card-a{color:inherit; text-decoration:none;}
.card.dim .c-hdr h3 a.tl-card-a::after{content:""; position:absolute; inset:0; z-index:0;}
.card.dim.card-link{transition:border-color .16s ease, background .16s ease;}
.card.dim.card-link:hover, .card.dim.card-link:focus-within{
  border-color:var(--blue); background:rgba(37,99,235,.025);
}
.card.dim.card-link:hover .unv-see{color:var(--blue);}
.unv-see{font-size:12.5px; font-weight:700; color:#8B96A3; margin-top:11px; transition:color .16s ease;}
/* Above the overlay: these are real destinations of their own. */
.card.dim .unv-cta{position:relative; z-index:2;}

/* The nine checks stack to nine rows on a phone, which is ~1,400px of blur to
   scroll past. Cropping to four rows with a fade keeps the shape and the
   message ("there are more of these") without the dead scroll. The full nine
   are listed sharp further down the page. */
.cp-checks.cp-off .cp-off-body{max-height:430px; overflow:hidden;}
.cp-checks.cp-off .cp-off-wrap::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:90px;
  background:linear-gradient(to bottom, rgba(255,255,255,0), #fff);
  pointer-events:none;
}

/* ── HOW LONG THEY HAVE BEEN VERIFIED ─────────────────────────────────
   Under 30 days this prints a month, over it a day count. See verifiedFor()
   in api.js for why. Quiet type: it is a supporting fact next to the badge,
   not a competing claim. */
.tl-since{font-size:11.5px; font-weight:700; color:var(--steel); margin-top:7px; letter-spacing:.01em;}
.cp-since{font-size:12.5px; font-weight:700; color:var(--steel); margin-top:11px;}

/* The hero's second paragraph and the urgency line. */
.bizhero-lede2{margin-top:14px;}
.bizhero-now{
  color:#fff; font-size:15.5px; line-height:1.6; font-weight:600;
  margin-top:24px; max-width:50ch;
  border-left:3px solid var(--green-lt); padding-left:15px;
}

/* The parish average, on /b/<slug>. Only ever rendered once it clears the
   30-day floor - see verifiedFor(). */
.biz-avg{
  margin-top:16px; padding:13px 16px; border-radius:11px;
  background:var(--paper); border:1px solid var(--line);
  font-size:14px; line-height:1.55; color:var(--steel);
}
.biz-avg b{color:var(--navy);}

/* On a phone the middle stat's label ("verified general contractors in
   Tangipahoa Parish") wraps to six lines in a third of the width and drags the
   whole row out of shape. Below 560px the stats become a list instead: number
   left, label beside it, one row each. Same facts, a quarter of the height. */
@media(max-width:560px){
  .bizhero-stat{display:block;}
  .bizhero-n{
    display:flex; align-items:baseline; gap:12px; min-width:0;
    padding:12px 15px; margin-bottom:9px;
  }
  .bizhero-n b{font-size:1.65rem; min-width:3.4ch;}
  .bizhero-n span{margin-top:0; font-size:13px;}
}

/* ── WHY THE SCORE EXISTS, AND HOW IT IS BUILT ────────────────────────
   Above the number on /b/<slug>. A score with no explanation is the worst
   version of this page: a contractor reads a bare figure about his own
   business and either dismisses it or resents it. */
.cp-why{
  background:var(--paper); border:1px solid var(--line); border-radius:14px;
  padding:19px 21px; margin-bottom:20px;
}
.cp-why p{font-size:14.5px; line-height:1.62; color:var(--steel);}
.cp-why p + p{margin-top:13px;}
.cp-why b{color:var(--navy);}
.cp-why a{color:var(--blue); font-weight:700;}
.cp-why a:hover{text-decoration:underline;}
@media(max-width:620px){ .cp-why{padding:16px 17px;} }

/* ── THE OFFER BLOCK ON /b/<slug> ─────────────────────────────────────
   Sits directly under the claim line, inside the navy hero. The prices used
   to live mid-paragraph below, which is where an offer goes to be skipped. */
.bizoffer{
  margin-top:22px; padding:19px 21px; border-radius:15px;
  background:rgba(255,255,255,.055);
  border:1px solid rgba(255,255,255,.15);
  border-left:3px solid var(--gold, #E0A82E);
}
.bizoffer-h{
  font-size:clamp(1.05rem,3.6vw,1.3rem); font-weight:800; color:#fff;
  line-height:1.3; letter-spacing:-.01em; margin:0;
}
.bizoffer-btns{display:flex; flex-wrap:wrap; gap:11px; margin-top:16px;}
.bizoffer-btns .btn{flex:1 1 auto; justify-content:center; text-align:center;}
.bizoffer-fine{
  font-size:12.5px; line-height:1.5; color:rgba(255,255,255,.62); margin-top:13px;
}

/* GOLD, for the exclusive. The green button is verification and appears all
   over the site; the exclusive needs to read as the rarer thing beside it, and
   gold is the seal colour the badge already uses. */
.btn-gold{
  background:linear-gradient(180deg,#E8B94A 0%,#D29A22 100%);
  color:#2A1B02; border:1px solid rgba(255,255,255,.22);
  font-weight:800; text-shadow:0 1px 0 rgba(255,255,255,.22);
}
.btn-gold:hover{background:linear-gradient(180deg,#F0C55E 0%,#DCA62C 100%); color:#2A1B02;}
.btn-gold:focus-visible{outline:3px solid #fff; outline-offset:2px;}

/* Below 560 the two buttons stack, and the exclusive keeps the top slot. */
@media(max-width:560px){
  .bizoffer{padding:16px 17px;}
  .bizoffer-btns{flex-direction:column; gap:9px;}
  .bizoffer-btns .btn{width:100%;}
}
