/*
 * Provider detail page.
 *
 * Loaded only on this route. services.css is already the hub's and the results
 * view's whole composition; making them download a detail page's styles to
 * render a grid of tiles is a cost with nothing on the other side of it.
 *
 * SCOPED UNDER .tp-services-page, like every other sheet in this tree, so a
 * loaded Services asset cannot restyle an ordinary Locations page. Tokens come
 * from locations.css's :root — none are redefined here.
 */

/* ------------------------------------------------------------ layout --- */

.tp-services-page.tp-services-provider {
  /* No top padding: the crumb band below sits flush against the product bar,
     as it does in the design source, and carries the gap itself. */
  padding-block: 0 64px;
  background: var(--tpl-white);
}

/* The crumb strip: full width, the product bar's 18px gutter, and the page's
   own top spacing hanging off its bottom edge. */
.tp-services-page .tp-services-provider__crumbs-band {
  margin-bottom: 28px;
  border-bottom: 1px solid var(--tpl-line);
  background: var(--tpl-surface-alt);
}

.tp-services-page .tp-services-provider__crumbs {
  padding: 11px 18px;
}

.tp-services-page .tp-services-provider__layout {
  display: grid;
  gap: 48px;
  grid-template-columns: minmax(0, 1fr) 372px;
  align-items: start;
}

.tp-services-page .tp-services-provider__main {
  min-width: 0;
}

.tp-services-page .tp-services-provider__stack {
  display: flex;
  flex-direction: column;
  gap: 64px;
  margin-top: 64px;
}

.tp-services-page .tp-services-provider__section {
  min-width: 0;
}

.tp-services-page .tp-services-provider__section-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  flex-wrap: wrap;
  margin-bottom: 12px;
}

/* The heading's own margin is the row's now. */
.tp-services-page .tp-services-provider__section-head .tp-services-provider__h2 {
  margin: 0;
}

/* ------------------------------------------------------- typography --- */

.tp-services-page .tp-services-provider__title {
  margin: 0 0 14px;
  color: var(--tpl-ink);
  font-family: Poppins, system-ui, sans-serif;
  font-size: 40px;
  font-weight: 700;
  letter-spacing: -1px;
  line-height: 1.18;
}

.tp-services-page .tp-services-provider__h2 {
  margin: 0 0 12px;
  color: var(--tpl-ink);
  font-family: Poppins, system-ui, sans-serif;
  font-size: 23px;
  font-weight: 600;
  line-height: 1.35;
}

/* The source's two uses of this level are the review breakdown's headings at
   13px. The 15px one belonged to "What is on site?", which is not rendered —
   see _provider-capabilities.blade.php. */
.tp-services-page .tp-services-provider__h3 {
  margin: 0 0 12px;
  color: var(--tpl-ink);
  font-size: 13px;
  font-weight: 600;
}

.tp-services-page .tp-services-provider__answer {
  margin: 0 0 12px;
  /* THE ANSWER IS THE PAGE'S OWN VOICE, NOT A FOOTNOTE. The design source sets
     it in the primary ink; it had been rendering in the tertiary caption colour,
     which put the longest and first paragraph on the page a full level lighter
     than everything it introduces. */
  color: var(--tpl-ink);
  /* 16.5px in the source; the named Body L role is 16. */
  font-size: 16px;
  line-height: 1.7;
  /* THE SOURCE ASKS FOR THIS AND NOTHING WAS CARRYING IT. `text-wrap: pretty`
     lets the browser avoid leaving one word alone on the last line; where it is
     not supported the paragraph wraps exactly as it did before. */
  text-wrap: pretty;
  /* THE `max-width: 84ch` THAT USED TO BE HERE WAS COPIED OFF THE WRONG
     ELEMENT (2026-09-22). In the design source the answer paragraph has no
     max-width — it runs the full content column. The 84ch belongs to the
     "no prices on file" notice further down the page (`prov.noPricesCopy`),
     which is a bordered aside and does want a shorter measure. Carrying it up
     here broke the first and longest paragraph on the page early, and nothing
     in the source asked for that. */
}

/* A SECTION'S STANDFIRST IS BODY, NOT CAPTION. The design source sets it in
   --tp-text-2, the supporting-text role, and it used to be set here in
   --tp-text-3 — the caption role, a level lighter than the paragraph it is.
   The two blocks that genuinely want the caption weight say so below. */
.tp-services-page .tp-services-provider__sub {
  max-width: 80ch;
  margin: 0 0 14px;
  color: var(--tpl-ink-secondary);
  font-size: 14px;
  line-height: 1.75;
}

.tp-services-page .tp-services-provider__foot {
  max-width: 84ch;
  margin: 11px 0 0;
  /* proto @37270 `color:var(--tp-text-3)` — Caption ink, not the faint role. */
  color: var(--tpl-ink-soft);
  /* 11.5px in the source; the named Caption role is 12. */
  font-size: 12px;
  line-height: 1.65;
}

.tp-services-page .tp-services-provider__dot {
  color: var(--tpl-ink-faint);
}

/* --------------------------------------------------- crumbs / tools --- */

.tp-services-page .tp-services-provider__crumbs ol {
  display: flex;
  flex-wrap: wrap;
  margin: 0;
  padding: 0;
  gap: 9px;
  list-style: none;
  color: var(--tpl-ink-soft);
  /* Prototype: 12.5px. Named Caption role instead. */
  font-size: 12px;
}

.tp-services-page .tp-services-provider__crumbs li + li::before {
  content: '›';
  margin-right: 6px;
  color: var(--tpl-ink-soft);
}

/* A LINKED LEVEL IS A LINK. The source leaves its crumb anchors to the canvas's
   own `a { color: var(--tp-brand) }` — the same brand blue every other link on
   the page gets — and spends the nav's grey on the levels that are only words.
   Painted grey the one crumb you can actually press looked exactly like the
   three you cannot. */
.tp-services-page .tp-services-provider__crumbs a {
  color: var(--tpl-blue);
  text-decoration: none;
}

.tp-services-page .tp-services-provider__crumbs a:hover {
  text-decoration: underline;
}

/* AND THE PAGE YOU ARE ON IS THE DARKEST THING IN THE TRAIL — proto @1023
   `color:var(--tp-text-1);font-weight:500`. It is the end of the trail and the
   name of what you are looking at, so it carries full ink while the levels
   above it stay in the nav's grey. */
.tp-services-page .tp-services-provider__crumbs [aria-current='page'] {
  color: var(--tpl-ink);
  font-weight: 500;
}

/* FLUSH RIGHT, BECAUSE THE LEFT HALF IS GONE. The design source's utility bar
   is `space-between` over two children — "Back to the N shops in Cheyenne" on
   the left and the controls on the right. The back link went with the city page
   it pointed at (Confluence CT/4460904527 item 20), and `space-between` over a
   single child parks that child at the start, which is how the controls ended
   up under the breadcrumb instead of opposite it. */
.tp-services-page .tp-services-provider__tools {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 16px;
  flex-wrap: wrap;
  margin: 16px 0 20px;
}

/* NOT A BRAND-BLUE LINK. The source draws this one as text — `font:500 13px`
   on `--tp-text-2` (proto @1378) — and it sits directly above the H1 beside
   Share / Save, which are the same weight and the same ink. Painted blue at
   14px it read as the loudest thing in the utility row, which is the row a
   driver is meant to look past. */
.tp-services-page .tp-services-provider__back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--tpl-ink-secondary);
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
}

.tp-services-page .tp-services-provider__back .tp-site-icon {
  fill: currentColor;
  transform: rotate(180deg);
}

.tp-services-page .tp-services-provider__tools-right {
  display: inline-flex;
  align-items: center;
  gap: 10px;
}

.tp-services-page .tp-services-provider__tool {
  padding: 8px 14px;
  border: 1px solid var(--tpl-line);
  border-radius: 6px;
  background: var(--tpl-white);
  color: var(--tpl-ink-secondary);
  cursor: pointer;
  font-family: inherit;
  font-size: 13px;
}

/*
 * The claim chip carries the same urgent colour as the banner below it, because
 * they are the same offer said twice — once where a scanning eye lands and once
 * where it can be read.
 */
.tp-services-page .tp-services-provider__claim-chip {
  padding: 8px 14px;
  border: 1px solid var(--tpl-warn);
  border-radius: 6px;
  background: var(--tpl-caution-wash);
  color: var(--tpl-warn);
  font-size: 13px;
  font-weight: 600;
  text-decoration: none;
}

/* ------------------------------------------------------ owner banner --- */

/*
 * The only urgent-coloured surface in the Services tree.
 *
 * It earns that because everything it says is fixable in one free phone call,
 * and because the person it is addressed to did not come here looking for it.
 */
/*
 * The design source is one flex row: copy, then the claim button, then the
 * demand link. The two actions keep their own width so the argument and the
 * thing it argues for stay on the same line.
 */
.tp-services-page .tp-services-provider__owner {
  display: flex;
  align-items: center;
  gap: 20px;
  margin-bottom: 32px;
  padding: 16px 20px;
  border: 1.5px solid var(--tpl-warn);
  border-radius: 12px;
  background: var(--tpl-caution-wash);
}
.tp-services-page .tp-services-provider__owner-copy {
  flex: 1;
  min-width: 0;
}
.tp-services-page .tp-services-provider__owner-cta,
.tp-services-page .tp-services-provider__owner-link {
  flex: none;
  white-space: nowrap;
}

/*
 * STACKED, NOT WRAPPED.
 *
 * `flex-wrap` did nothing here and could not: wrapping only happens when the
 * items no longer fit, and the copy column carries `min-width: 0` so it always
 * "fits" — it just gets narrower. Beside a `flex: none` button that refuses to
 * wrap its own label, the column was squeezed to 59px at 390, which set the
 * heading and the paragraph one word per line and ran the banner past a full
 * screen.
 *
 * Below the point where the argument and the button stop fitting side by side,
 * the banner becomes what it reads as: the case, then the thing it asks for.
 *
 * 743px is where they genuinely collide — the button is ~230px, the demand
 * link ~180px and two 20px gaps, so the copy has nothing usable left under
 * about 690px of inner width.
 */
@media (max-width: 743px) {
  .tp-services-page .tp-services-provider__owner {
    flex-direction: column;
    align-items: stretch;
    gap: 14px;
  }

  /* Full width once they are on their own rows — a 230px button sitting alone
     at the left edge of a 390px screen reads as an afterthought, and it is the
     one thing this banner exists to be pressed. */
  .tp-services-page .tp-services-provider__owner-cta,
  .tp-services-page .tp-services-provider__owner-link {
    text-align: center;
    white-space: normal;
  }
}

/* THE URGENT ROLE IS THE FRAME, NOT THE WORDS. The source spends
   `prov.ownerAccent` on three things and only three — this banner's border,
   its background tint and its CTA — while the heading is ordinary ink
   (proto @3345 `--tp-text-1`), the body is body ink (@3471 `--tp-text-2`) and
   the secondary link is the same body ink (@3919). Painting the copy orange
   too made the banner shout at a driver, who is not the reader it is for: it
   is addressed to the owner searching their own shop's name, and it has the
   whole page's only coloured frame to find them with. */
.tp-services-page .tp-services-provider__owner-head {
  margin: 0 0 4px;
  color: var(--tpl-ink);
  font-family: Poppins, system-ui, sans-serif;
  font-size: 15px;
  font-weight: 600;
}

.tp-services-page .tp-services-provider__owner-body {
  max-width: 92ch;
  margin: 0;
  color: var(--tpl-ink-secondary);
  font-size: 13px;
  line-height: 1.7;
}

.tp-services-page .tp-services-provider__owner-actions {
  display: flex;
  align-items: center;
  gap: 16px;
  flex-wrap: wrap;
}

/*
 * Uppercased here rather than in the template. The source string carries an em
 * dash and the phone number carries parentheses; baking the capitals in would
 * run those through the same transform and they do not survive it.
 */
.tp-services-page .tp-services-provider__owner-cta {
  padding: 13px 22px;
  border-radius: 8px;
  background: var(--tpl-warn);
  color: var(--tpl-white);
  font-size: 13px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-decoration: none;
  text-transform: uppercase;
}

.tp-services-page .tp-services-provider__owner-link {
  color: var(--tpl-ink-secondary);
  /* 12.5px in the source; the named Caption role is 12. */
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
}

/* ------------------------------------------------------------ chips --- */

.tp-services-page .tp-services-provider__chips {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-bottom: 10px;
  font-size: 13px;
}

.tp-services-page .tp-services-provider__reviews-count {
  color: var(--tpl-ink-secondary);
}

/*
 * A chip, not loose text. The design source gives the category a filled
 * background — it is a label on the listing, and a label that looks like prose
 * reads as part of the sentence beside it.
 */
.tp-services-page .tp-services-provider__kicker {
  padding: 4px 8px;
  border-radius: 4px;
  background: var(--tpl-blue-wash);
  color: var(--tpl-blue-strong);
  /* Prototype: 10.5px. The named Caption role instead. */
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.05em;
}

.tp-services-page .tp-services-provider__verify {
  display: flex;
  flex-direction: column;
  margin: 0 0 32px;
  padding: 0;
  gap: 7px;
  list-style: none;
}

.tp-services-page .tp-services-provider__verify li {
  display: flex;
  /* CENTRED, AS THE SOURCE DRAWS IT (2026-09-22). This read `flex-start`, which
     is indistinguishable on a one-line item and wrong the moment one wraps: the
     tick rides up against the first line instead of sitting level with the
     block it marks. */
  align-items: center;
  gap: 8px;
  color: var(--tpl-ink-soft);
  font-size: 13px;
}

/*
 * `check` is a stroked icon, not a filled one — its path takes currentColor as
 * its stroke and has no fill at all. Colouring it with `fill` did nothing, so
 * these ticks were inheriting the line's own grey while the design source draws
 * them in success green. Set on `color`, which is what the stroke follows.
 */
.tp-services-page .tp-services-provider__verify .tp-site-icon,
.tp-services-page .tp-services-provider__creds .tp-site-icon {
  flex: none;
  /* `--tpl-success` IS NOT A TOKEN. This read var(--tpl-go) and
     had been running on the fallback since it was written — a custom property
     that does not exist fails silently and the hex beside it wins, so the
     colour was right by luck and detached from the palette. The real name
     carries the same value. */
  color: var(--tpl-go);
}

/* ---------------------------------------------------------- address --- */

/*
 * A CARD, WITH ITS HEADING INSIDE IT. The design source draws a bordered box
 * round the whole block — heading, rows and the two actions at the foot. It is
 * the one block on the page that is a lookup table rather than prose, and the
 * border is what says so.
 */
.tp-services-page .tp-services-provider__section_address {
  padding: 18px 20px;
  border: 1px solid var(--tpl-line);
  border-radius: 12px;
}
.tp-services-page .tp-services-provider__section_address .tp-services-provider__h2 {
  margin: 0 0 10px;
  font-size: 15px;
}

.tp-services-page .tp-services-provider__address {
  display: flex;
  flex-direction: column;
  margin: 0;
  gap: 1px;
}

.tp-services-page .tp-services-provider__address > div {
  display: grid;
  gap: 16px;
  /* 116px in the design source, where the label is 11px. The named Caption
     role is 12px, and "WHERE TO TURN IN" wraps at 116. Widened to hold it on
     one line rather than shrinking the type to fit — page-style.md is explicit
     that a fractional size is not a density tool. */
  grid-template-columns: 132px minmax(0, 1fr) auto;
  align-items: center;
  padding: 11px 0;
  border-top: 1px solid var(--tpl-line-soft);
}

.tp-services-page .tp-services-provider__address dt {
  color: var(--tpl-ink-soft);
  /* Prototype: 11px uppercase. The named Caption role at 12px. */
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.07em;
  text-transform: uppercase;
}

.tp-services-page .tp-services-provider__address dd {
  margin: 0;
  color: var(--tpl-ink);
  font-size: 14px;
  line-height: 1.55;
}

.tp-services-page .tp-services-provider__address dd a {
  color: var(--tpl-blue);
  text-decoration: none;
}

/*
 * The per-row action is a button in the design source, and it needs to be: it
 * is the only thing on the row a driver can press, and a grey word beside a
 * grey label does not read as one.
 */
.tp-services-page .tp-services-provider__address-act {
  padding: 7px 12px;
  border: 1px solid transparent;
  border-radius: 5px;
  background: var(--tpl-blue-wash);
  color: var(--tpl-blue-strong);
  font-size: 12px;
  font-weight: 500;
  white-space: nowrap;
  /* It is an <a> since 2026-09-20 and was a <span> before it. The pill already
     carries its own colour and shape, so the browser's underline is the only
     thing the change would have altered visually. */
  text-decoration: none;
  text-align: center;
}

/* Calling is a different kind of action from opening the app, and the design
   gives it the quieter treatment. */
.tp-services-page .tp-services-provider__address-act_call {
  border-color: var(--tpl-line);
  background: var(--tpl-white);
  color: var(--tpl-ink-soft);
}

.tp-services-page .tp-services-provider__ghost_light {
  color: rgba(255, 255, 255, 0.72);
}

.tp-services-page .tp-services-provider__address-cta {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--tpl-line-soft);
}
.tp-services-page .tp-services-provider__address-cta > * {
  padding: 10px 16px;
  border-radius: 6px;
  /* 12.5px in the source; the named Body S role is 13. */
  font-size: 13px;
  font-weight: 500;
  text-decoration: none;
}

/* ONE BUTTON IN THIS ROW NOW. Its outlined neighbour, "How far is it from
   me?", was removed on 2026-09-21 (page owner): it asked a question this
   application cannot answer and had no destination to give it. The outline
   rule went with it rather than being left for a button that no longer
   exists — `__cta-outline` matched nothing in any template. */
.tp-services-page .tp-services-provider__cta-solid {
  padding: 11px 16px;
  border: 1.5px solid var(--tpl-ink-deep);
  background: var(--tpl-ink-deep);
  color: var(--tpl-white);
}

/* ---------------------------------------------------------- prices --- */

/*
 * TWO MISSING-INFORMATION BLOCKS, AND THE SOURCE DRAWS THEM DIFFERENTLY.
 *
 * They had one treatment here — a left rule on a grey ground — which read as
 * one recurring warning. The source makes them two different kinds of thing:
 *
 *   The price block is a bordered card. It stands in for the rate table a Pro
 *   listing shows in that slot, so it holds the slot's shape.
 *
 *   The gate block is prose, a step larger than body copy and with no frame at
 *   all. Nothing is missing from a slot there; the whole answer is the
 *   paragraph.
 */
.tp-services-page .tp-services-provider__noprice {
  max-width: 84ch;
  /* Source: h2 margin 4 + p margin-top 14 = 18. The h2 here carries the
     page-wide 12, so the paragraph makes up the remaining 6. */
  margin: 6px 0 22px;
  padding: 14px 17px;
  border: 1px solid var(--tpl-line);
  border-radius: 8px;
  color: var(--tpl-ink-secondary);
  font-size: 14px;
  line-height: 1.75;
}

.tp-services-page .tp-services-provider__missing {
  max-width: 78ch;
  margin: 0;
  color: var(--tpl-ink-secondary);
  /* 15.5px in the source; the named Body L role is 16, and this paragraph is
     deliberately a step above body copy. */
  font-size: 16px;
  line-height: 1.8;
}

/* ---------------------------------------------------------- rivals --- */

/* The heading and its standfirst are one statement here, so the source closes
   the gap between them: 6px rather than the 12px a section heading carries when
   the next thing is a block rather than a sentence explaining it. */
.tp-services-page .tp-services-provider__section_rivals .tp-services-provider__h2 {
  margin-bottom: 6px;
}

.tp-services-page .tp-services-provider__rivals,
.tp-services-page .tp-services-provider__ads {
  display: grid;
  gap: 12px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}

.tp-services-page .tp-services-provider__rival,
.tp-services-page .tp-services-provider__ad {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 15px 16px;
  border: 1px solid var(--tpl-line);
  border-radius: 11px;
  background: var(--tpl-white);
}

/* THE WHOLE CARD OPENS THE BUSINESS — page owner, 2026-09-22.
   Only the name was the target, which is a three-word strip inside a card the
   size of a business card; everything around it — the town, the distance, the
   opening hours, the white space — looked equally pressable and was not.

   DONE WITHOUT TOUCHING THE MARKUP, and that is the point. The link's
   accessible name stays the business's name rather than becoming the name plus
   the town plus the bearing plus the closing time, which is what wrapping the
   card in an <a> would have read out. One tab stop, one announced label, and
   the card's own text is still text.

   `a.` IS LOAD-BEARING: a row the upstream gave no `ident` renders its name as
   a <span>, and that card must stay unclickable — the same rule the template
   states. An attribute selector on the tag is what keeps the two in step
   without a second flag to forget.

   NOT ON `__ad`, although it shares the rule above. A sponsored card's link
   carries rel="sponsored" and its own measurement; widening its hit area is a
   separate decision with a different owner. */
.tp-services-page .tp-services-provider__rival {
  position: relative;
}

.tp-services-page a.tp-services-provider__rival-name::after {
  content: '';
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
}

/* A filled chip beside the name, not a coloured word above it. The design
   source puts the two on one baseline — the badge qualifies the name, and a
   line of its own reads as a heading for the card. */
.tp-services-page .tp-services-provider__rival-head {
  display: flex;
  align-items: baseline;
  gap: 7px;
  flex-wrap: wrap;
  margin-bottom: 5px;
}
.tp-services-page .tp-services-provider__rival-tier {
  padding: 3px 6px;
  border-radius: 4px;
  background: var(--tpl-go);
  color: var(--tpl-white);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.tp-services-page .tp-services-provider__rival-name,
.tp-services-page .tp-services-provider__ad-name,
.tp-services-page .tp-services-provider__organic-name {
  color: var(--tpl-ink);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.3;
  text-decoration: none;
}

/* SUPPORTING TEXT, NOT A CAPTION. All three of the design source's row captions
   — competitor, sponsored and the nearest list — are --tp-text-2. This rule had
   them a level lighter, which read as a row whose second line was fading out. */
.tp-services-page .tp-services-provider__rival-meta,
.tp-services-page .tp-services-provider__ad-place,
.tp-services-page .tp-services-provider__organic-meta {
  color: var(--tpl-ink-secondary);
  font-size: 13px;
  line-height: 1.7;
}

.tp-services-page .tp-services-provider__rival-price,
.tp-services-page .tp-services-provider__ad-price {
  margin-top: 4px;
  color: var(--tpl-ink);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.6;
}

/* Filled on a competitor card, outlined on a paid one. The competitor block is
   the page's own argument and leads with it; a placement someone bought sits a
   step quieter than the page's own recommendations. */
.tp-services-page .tp-services-provider__rival-cta,
.tp-services-page .tp-services-provider__ad-cta {
  margin-top: 6px;
  padding: 9px 12px;
  border-radius: 8px;
  background: var(--tpl-blue);
  color: var(--tpl-white);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: center;
  text-transform: uppercase;
}

.tp-services-page .tp-services-provider__ad-cta {
  border: 1px solid var(--tpl-blue);
  background: var(--tpl-white);
  color: var(--tpl-blue);
}

.tp-services-page .tp-services-provider__ad-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.tp-services-page .tp-services-provider__ad-tag {
  padding: 3px 7px;
  border: 1px solid var(--tpl-line);
  border-radius: 4px;
  color: var(--tpl-ink-soft);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

/* The paid band's heading is smaller than the page's own sections. It is a
   recommendation strip, not one of the answers the page is organised around,
   and the design source sizes it that way. */
.tp-services-page .tp-services-provider__section_band .tp-services-provider__h2 {
  font-size: 17px;
}

.tp-services-page .tp-services-provider__ad-why {
  color: var(--tpl-ink-soft);
  font-size: 12px;
}

/* ----------------------------------------------------- capabilities --- */

.tp-services-page .tp-services-provider__cap-note {
  color: var(--tpl-ink-soft);
  font-size: 13px;
}

.tp-services-page .tp-services-provider__caps {
  display: grid;
  gap: 9px;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  margin: 0;
  padding: 0;
  list-style: none;
}

/*
 * NO FRAME, WHICH IS THE DESIGN SOURCE'S OWN TREATMENT. Twenty-two boxed tiles
 * draw twenty-two rectangles the reader has to look past to reach the
 * drawings; the source sets the tiles on the page itself and lets the icon and
 * the word be the tile. The 36px drawing is the source's size too — at 24 the
 * grid read as a legend rather than as the page's answer to "what do they work
 * on".
 *
 * 12px, not the source's 12.5: AGENTS.md maps fractional sizes onto the named
 * integer roles, and this is Caption.
 */
.tp-services-page .tp-services-provider__cap {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  padding: 18px 6px;
  color: var(--tpl-ink);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
  text-align: center;
}

/*
 * Dimmed, not hidden. Twenty-two tiles with four lit is a picture of how much
 * nobody has told us; four tiles on their own would read as a small shop.
 */
.tp-services-page .tp-services-provider__cap_off {
  color: var(--tpl-ink-faint);
  opacity: 0.35;
}

.tp-services-page .tp-services-provider__cap_off img {
  filter: grayscale(1);
}

/* --------------------------------------------------------- reviews --- */

/* The number above the sentence that qualifies it, not beside it. */
.tp-services-page .tp-services-provider__score {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  margin-bottom: 8px;
}

/* Mentions are their own thought and run the full width under the pair above. */
.tp-services-page .tp-services-provider__mentions-row {
  margin-bottom: 24px;
}

.tp-services-page .tp-services-provider__score-value {
  /* The design source's own colour for a scored listing: the same warn orange
     the compact rating uses, so the number reads the same in both places. */
  color: var(--tpl-warn);
  font-family: Poppins, system-ui, sans-serif;
  font-size: 60px;
  font-weight: 700;
  letter-spacing: -2px;
  line-height: 1;
}

.tp-services-page .tp-services-provider__score-unit {
  color: var(--tpl-ink);
  font-size: 15px;
  font-weight: 600;
}

/* Score and distribution, centred against each other and ruled off below —
   the design source's own treatment. They are one statement in two halves. */
.tp-services-page .tp-services-provider__breakdown {
  display: grid;
  gap: 40px;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  align-items: center;
  margin: 0 0 22px;
  padding: 6px 0 22px;
  border-bottom: 1px solid var(--tpl-line-soft);
}

/* The distribution only renders when there is one, and the score should not
   sit in half a row when it is alone. */
.tp-services-page .tp-services-provider__breakdown > :only-child {
  grid-column: 1 / -1;
}

/* THE ONE STANDFIRST THE SOURCE DOES SET IN THE CAPTION ROLE. It is a footnote
   under the score — who may review and what we will not remove — rather than a
   section's opening sentence, and the design source sets it in --tp-text-3. */
.tp-services-page .tp-services-provider__breakdown .tp-services-provider__sub {
  color: var(--tpl-ink-soft);
}

.tp-services-page .tp-services-provider__bars,
.tp-services-page .tp-services-provider__mentions,
.tp-services-page .tp-services-provider__reviews,
.tp-services-page .tp-services-provider__organic,
.tp-services-page .tp-services-provider__symptoms,
.tp-services-page .tp-services-provider__app-reasons {
  margin: 0;
  padding: 0;
  list-style: none;
}

/* THREE COLUMNS, SO FIVE ROWS LINE UP. The design source lays each row out as
   `30px 1fr 28px`; with flex the star column took its width from its own text
   and the tracks started at slightly different x per row. */
.tp-services-page .tp-services-provider__bars li {
  display: grid;
  grid-template-columns: 30px minmax(0, 1fr) 28px;
  align-items: center;
  gap: 9px;
  padding: 3px 0;
  /* 12px in the source, for both the star column and the count. */
  font-size: 12px;
}

/* ONE CELL, TWO THINGS. The design source puts only the digit in this 30px
   column — `<span>{{ b.stars }}</span>`, no mark at all. The star is this
   repository's addition, so the pair is laid out rather than typed, and the
   digit, not the icon, sets the row's baseline.

   RIGHT (page owner, 2026-09-23). The column is 30px and the pair is about 24,
   so the slack has to fall on one side or the other. On the right the digit and
   the star sit next to the bar they label, one gap away from it, and the five
   rows read as one block; on the left they drift off to the edge with the slack
   between them and what they describe.

   BOTH PROPERTIES ARE WRITTEN OUT, not left to defaults. A grid item stretches
   to its column and a flex container starts its content at the inline start,
   so before this the pair sat left by inheritance rather than by instruction —
   and two properties nobody wrote are two properties the next change can move
   without ever touching this rule. The grid's own `gap: 9px` still stands
   between the pair and the track. */
.tp-services-page .tp-services-provider__bar-star {
  display: inline-flex;
  align-items: center;
  justify-content: flex-end;
  justify-self: end;
  gap: 3px;
  color: var(--tpl-ink-soft);
}

.tp-services-page .tp-services-provider__bars .tp-site-icon {
  flex: none;
  /* 14px — page owner, 2026-09-23. It was 12 to keep the row exactly as tall as
     its 12px text; at 14 the row grows by about two pixels, which is the trade
     that was asked for. The pair is still ~24px inside a 30px column, so
     nothing reflows. */
  width: 14px;
  height: 14px;
  fill: var(--tpl-rating);
}

/* THE EMPTY PART OF THE TRACK HAS TO BE VISIBLE. The design source runs it in
   the structural line colour; on --tpl-surface-alt (#f9fafb against a white
   card) a bar at 2% read as no track at all. */
.tp-services-page .tp-services-provider__bar-track {
  height: 7px;
  border-radius: 999px;
  background: var(--tpl-line);
}

.tp-services-page .tp-services-provider__bar-fill {
  display: block;
  width: var(--tp-bar-width, 0%);
  height: 100%;
  border-radius: 999px;
  /* The distribution is read against the score above it, so it takes the
     score's colour rather than the stars'. */
  background: var(--tpl-warn);
}

.tp-services-page .tp-services-provider__bar-count {
  color: var(--tpl-ink-soft);
  text-align: right;
}

/* Chips in a wrapping row, as the design source draws them. A stacked list with
   the count pushed to the far right reads as a table of figures; these are four
   things drivers said, and they are meant to be scanned. */
.tp-services-page .tp-services-provider__mentions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.tp-services-page .tp-services-provider__mentions li {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 11px 15px;
  border: 1px solid var(--tpl-line);
  border-radius: 12px;
  background: var(--tpl-white);
  box-shadow: 0 2px 10px rgba(1, 25, 50, 0.06);
  font-size: 13px;
  font-weight: 600;
}

.tp-services-page .tp-services-provider__mention-count {
  color: var(--tpl-ink-soft);
  font-size: 12px;
  font-weight: 400;
}

/* The bookings figure is a pill beside the name — it qualifies the reviewer,
   and plain text beside a plain name reads as part of it. */
.tp-services-page .tp-services-provider__review-bookings {
  padding: 3px 8px;
  border-radius: 999px;
  background: var(--tpl-blue-wash);
  color: var(--tpl-blue-strong);
  font-size: 12px;
  font-weight: 500;
}

/* "Show all N" is a button in the design source. It is the only control in the
   section, and plain grey text does not read as one. */
.tp-services-page .tp-services-provider__reviews-all {
  display: inline-block;
  margin-top: 16px;
  padding: 11px 20px;
  border: 1px solid var(--tpl-line);
  border-radius: 6px;
  background: var(--tpl-white);
  color: var(--tpl-ink);
  font-size: 13px;
  font-weight: 500;
  /* It became an anchor on 2026-09-22 (it opens the app). Same line the rail's
     own CTA carries for the same reason. */
  text-decoration: none;
}

.tp-services-page .tp-services-provider__review {
  padding: 16px 0;
  border-top: 1px solid var(--tpl-line-soft);
}

/*
 * TWO RULES THAT ARE EACH RIGHT ALONE. The distribution closes with a bottom
 * border and every review opens with a top one, and the tag band sits between
 * them. The upstream answers no tags for any record measured, so the band is
 * empty and the two borders land 22px apart — read as a double rule with a gap
 * in it rather than as one separator.
 *
 * THE FIRST SELECTOR STOPPED MATCHING WHEN THE BAND BECAME CSR (2026-09-20),
 * AND THAT IS WHY THE DOUBLE RULE CAME BACK. `+` is a DOM relationship, not a
 * rendered one: the band is now always in the HTML as
 * `<div data-services-mentions hidden>`, so the review list is no longer the
 * distribution's adjacent sibling even though nothing is drawn between them.
 * `display: none` removes a box from the layout; it does not remove the element
 * from the selector's reckoning.
 *
 * SO THE CONDITION IS THE ATTRIBUTE, NOT THE ADJACENCY. `[hidden]` is exactly
 * the state in which nothing is drawn between the two borders, and the script
 * clears it (`row.hidden = false`) at the moment it has tags to show — so the
 * border comes back by itself when the band is there to need it. No second
 * flag, no class for the script to remember to toggle.
 *
 * The first selector is kept for the shape where the band is not emitted at
 * all: it costs nothing and it is the one that states the original intent.
 */
.tp-services-page .tp-services-provider__breakdown + .tp-services-provider__reviews
  > .tp-services-provider__review:first-child,
.tp-services-page .tp-services-provider__breakdown
  + .tp-services-provider__mentions-row[hidden]
  + .tp-services-provider__reviews
  > .tp-services-provider__review:first-child {
  border-top: 0;
}

.tp-services-page .tp-services-provider__review-head {
  display: flex;
  align-items: center;
  /* The gap IS the separator here — see the partial. */
  gap: 10px;
  flex-wrap: wrap;
  color: var(--tpl-ink-soft);
  font-size: 13px;
}

.tp-services-page .tp-services-provider__review-name {
  color: var(--tpl-ink);
  /* 13.5px in the source; the named Body role is 14. */
  font-size: 14px;
  font-weight: 600;
}

.tp-services-page .tp-services-provider__review-when {
  font-size: 12px;
}

/* THE COMPACT RATING, SIZED FOR A ROW RATHER THAN A PAGE HEAD. The Foundation
   draws it at 16px/700 with a 16px mark, which is the page head's scale; the
   source sets this one at 12.5px beside a 13.5px name. The mark and the icon
   inside it are both sized — the primitive's own icon keeps the registry's sm
   otherwise and overflows the box it sits in. */
.tp-services-page .tp-services-provider__review-head .tp-data-rating_compact {
  gap: 4px;
  /* 12.5px in the source; the named Body Small role is 13. */
  font-size: 13px;
  font-weight: 600;
}

.tp-services-page .tp-services-provider__review-head .tp-data-rating__mark,
.tp-services-page .tp-services-provider__review-head .tp-data-rating__mark > .tp-site-icon {
  width: 13px;
  height: 13px;
}

.tp-services-page .tp-services-provider__review-text {
  max-width: 84ch;
  margin: 8px 0 0;
  /* Supporting text, not a caption: the source sets the body of a review in
     --tp-text-2, the same role the row captions take. */
  color: var(--tpl-ink-secondary);
  font-size: 14px;
  line-height: 1.7;
}

/* --------------------------------------------------------- organic --- */

.tp-services-page .tp-services-provider__organic li {
  display: flex;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
  padding: 12px 0;
  border-bottom: 1px solid var(--tpl-line-soft);
}

/* The whole row is the link now, not the name inside it — a name alone is a
 * small target on a phone held in one hand at a fuel island. The flex that used
 * to sit on the `li` moves here so the figure still pushes to the end. */
.tp-services-page .tp-services-provider__organic-row {
  display: flex;
  align-items: baseline;
  gap: 12px;
  width: 100%;
  text-decoration: none;
}

/* `a.`, because the row is a span when the answer carried no address to open
   — an underline on hover over something that cannot be clicked is a promise
   the row does not keep. */
.tp-services-page a.tp-services-provider__organic-row:hover
  .tp-services-provider__organic-name {
  text-decoration: underline;
}

/* THE SOURCE'S `figure` OVER `figureK`, stacked and right-aligned — not a
   number sitting beside its unit. See the partial: the unit belongs to the
   figure, and the small line under it says what the distance is measured
   from. */
.tp-services-page .tp-services-provider__organic-figure {
  display: block;
  margin-left: auto;
  text-align: right;
}

.tp-services-page .tp-services-provider__organic-figure strong {
  display: block;
  color: var(--tpl-ink);
  font-size: 13px;
  font-weight: 700;
  line-height: 1;
}

.tp-services-page .tp-services-provider__organic-figure-k {
  display: block;
  margin-top: 3px;
  color: var(--tpl-ink-soft);
  /* 10px in the source; 11px is the smallest named role. */
  font-size: 11px;
}

/* ------------------------------------------------------------- app --- */

/* THE NAV DARK, WITH THE SOURCE'S GLOW ON IT. Two things were wrong here: the
   ground was --tpl-ink, the text colour, where the source asks for --tp-nav-dark
   (the same #05101C this page's own topbar sits on); and the blue wash the
   source throws from the top right was missing entirely, which is what made the
   band read as a flat navy rectangle. The gradient's own fade colour is --tpl-ink
   at zero alpha — a gradient cannot take a token through rgba(), so it is written
   out here and only here. */
.tp-services-page .tp-services-provider__app {
  overflow: hidden;
  padding: 34px 36px;
  border: 1px solid rgba(255, 255, 255, 0.09);
  border-radius: 16px;
  background:
    radial-gradient(120% 140% at 88% 10%, rgba(24, 172, 246, 0.28) 0%, rgba(1, 25, 50, 0) 55%),
    var(--tpl-ink-nav);
  color: var(--tpl-white);
}

.tp-services-page .tp-services-provider__app .tp-services-provider__h2,
.tp-services-page .tp-services-provider__app .tp-services-provider__sub {
  color: var(--tpl-white);
}

/* The band's own headline is larger than a section heading — it is the one
   place on the page selling something rather than answering something. */
.tp-services-page .tp-services-provider__app .tp-services-provider__h2 {
  max-width: 26ch;
  margin: 0 0 10px;
  font-size: 30px;
  letter-spacing: -0.8px;
  line-height: 1.22;
}

.tp-services-page .tp-services-provider__app .tp-services-provider__sub {
  max-width: 62ch;
  margin: 0 0 22px;
  /* Not flat white: the source runs the standfirst at .66 so the headline above
     it keeps the contrast. The white comes from the rule two above this one. */
  color: rgba(255, 255, 255, 0.66);
  font-size: 14px;
  line-height: 1.7;
}

.tp-services-page .tp-services-provider__app-eyebrow {
  display: block;
  margin-bottom: 9px;
  /* The accent for a dark ground, which is what the source uses here. It was a
     weak white, so the one line naming the product read as a caption. */
  color: var(--tpl-blue-bright);
  /* 10px in the source; 11px is the smallest named role. */
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

/* Boxed, two up — the source frames each reason rather than bulleting it. */
.tp-services-page .tp-services-provider__app-reasons {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  margin: 0 0 22px;
}

.tp-services-page .tp-services-provider__app-reasons li {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 13px 15px;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 10px;
  /* A FILL, NOT JUST A HAIRLINE. The source lifts each card off the band by
     five percent of white; with only the border they read as four outlines. */
  background: rgba(255, 255, 255, 0.05);
  color: rgba(255, 255, 255, 0.9);
  /* 13.5px in the source; the named Body S role is 13. */
  font-size: 13px;
  line-height: 1.6;
}

/* THE MARK IS THE ACCENT BLUE, AND IT IS STROKED. The source draws it in
   --tp-brand-on-dark; this filled it with the success green instead, which is a
   different claim — these are four things the app does, not four things that
   succeeded. The registry's check is a stroked path, so the colour has to reach
   it through `color`, and the `fill` this set had was painting the open path in
   as well. Sized to the source's 14 and dropped to the first line's baseline. */
.tp-services-page .tp-services-provider__app-reasons .tp-site-icon {
  flex: none;
  width: 14px;
  height: 14px;
  margin-top: 4px;
  color: var(--tpl-blue-bright);
  fill: none;
}

.tp-services-page .tp-services-provider__app-stores {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 0;
}

/*
 * THE PLATE IS OURS, THE ARTWORK IS THEIRS.
 *
 * Both supplied files are a bare figure on a transparent ground — no plate, no
 * outline, no padding; sampled, the outermost ring of the white one is fully
 * transparent. So the badge the design source draws (dark plate, hairline,
 * white wordmark, colour Play glyph) is the white artwork with the first three
 * supplied here.
 *
 * Two wrong turns are worth recording, because each looked right in isolation:
 * the black artwork on this card was black on near-black and what remained
 * visible was this frame; removing the frame then left white strokes floating
 * on the navy with nothing to sit on.
 *
 * The plate is a shade deeper than the card rather than pure black — the
 * hairline is what separates them, which is how the source does it too.
 */
.tp-services-page .tp-services-provider__app-stores a {
  display: block;
  padding: 8px 14px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 8px;
  background: var(--tpl-ink-deep);
  line-height: 0;
}

.tp-services-page .tp-services-provider__app-stores img {
  display: block;
  width: auto;
  height: 24px;
}

/* THE BADGES AND THE LINE AFTER THEM ARE ONE ROW. The source puts both stores
   and "Free · no account needed" on a single baseline; the line sat under them
   as its own paragraph, which read as a footnote about the band rather than the
   last thing said about the two buttons. */
.tp-services-page .tp-services-provider__app-get {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
}

.tp-services-page .tp-services-provider__app-tail {
  margin: 0 0 0 6px;
  color: rgba(255, 255, 255, 0.45);
  font-size: 12px;
  line-height: 1.5;
}

/* ------------------------------------------------------------ rail --- */

/*
 * ONE CARD, DIVIDED BY RULES — the source's own construction.
 *
 * It was a card with a grey rounded block inside it and a 20px pad around
 * everything, which reads as two panels stacked. The source gives each band
 * its own 18/20 padding and separates them with a hairline, so the rate
 * statement, the phone number and the app pitch are three parts of one panel
 * rather than three panels.
 */
.tp-services-page .tp-services-provider__rail {
  position: sticky;
  top: 88px;
  display: flex;
  flex-direction: column;
  padding: 0;
  border: 1px solid var(--tpl-line);
  border-radius: 12px;
  background: var(--tpl-white);
  box-shadow: 0 8px 32px rgba(1, 25, 50, 0.1);
  overflow: hidden;
}

.tp-services-page .tp-services-provider__rail-head {
  padding: 18px 20px;
  border-bottom: 1px solid var(--tpl-line-soft);
}

.tp-services-page .tp-services-provider__rail-title {
  color: var(--tpl-ink);
  font-size: 15px;
  font-weight: 600;
  line-height: 1.4;
}

.tp-services-page .tp-services-provider__rail-body {
  margin: 6px 0 0;
  color: var(--tpl-ink-secondary);
  /* 12.5px in the source; the named Caption role is 12. */
  font-size: 12px;
  line-height: 1.65;
}

/*
 * Quiet on purpose. A brand-blue button here would promise somebody is waiting
 * to answer, and on an unclaimed listing nobody is: the number came from our
 * own survey.
 */
.tp-services-page .tp-services-provider__rail-call {
  margin: 18px 20px 0;
  padding: 14px;
  border: 1.5px solid var(--tpl-line);
  border-radius: 6px;
  background: var(--tpl-white);
  color: var(--tpl-ink);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.05em;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
}

.tp-services-page .tp-services-provider__rail-foot {
  margin: 11px 20px 18px;
  color: var(--tpl-ink-soft);
  font-size: 12px;
  line-height: 1.6;
  text-align: center;
}

.tp-services-page .tp-services-provider__rail-app {
  margin: 0 20px 20px;
  padding: 16px;
  border-radius: 10px;
  background: var(--tpl-ink);
  color: rgba(255, 255, 255, 0.86);
  /* 12.5px in the source; the named Caption role is 12. */
  font-size: 12px;
}

.tp-services-page .tp-services-provider__rail-app p {
  margin: 0 0 13px;
  line-height: 1.6;
}

.tp-services-page .tp-services-provider__rail-app-title {
  display: block;
  margin-bottom: 5px;
  color: var(--tpl-white);
  /* 13.5px in the source; the named Body S role is 13. */
  font-size: 13px;
  font-weight: 600;
}

/* --------------------------------------------------------- related --- */

/* THE FLOOR OF THE PAGE, ON ITS OWN GROUND. The design source closes with a
   full-width band — --tp-bg-gray under a --tp-border-1 rule — and puts only the
   links on the 1200 rail inside it. This was a bare section inside the
   container with the lighter of the two rules, which read as one more part of
   the article. Same construction as the breadcrumb band at the top of the file,
   and the same two tokens. */
.tp-services-page .tp-services-provider__related-band {
  margin-top: 48px;
  /* Not a `padding` shorthand: the rail's own gutters live on
     .tp-site-container inside this, and AGENTS.md makes that the owner of them. */
  padding-top: 40px;
  padding-bottom: 48px;
  border-top: 1px solid var(--tpl-line);
  background: var(--tpl-surface-alt);
}

/* ONE GROUP PER ROW, NOT TWO PER ROW. The source stacks them and lets the links
   wrap inside the full width; in two columns the first group folds after five
   links instead of ten and the band reads as a two-column directory. */
.tp-services-page .tp-services-provider__related {
  display: flex;
  flex-direction: column;
  gap: 32px;
}

/* A band label, not a section heading. The source sets these in the caption
   role — uppercase, tracked out, quiet — because the links under them are the
   content and the group name is only telling you which set you are in. */
.tp-services-page .tp-services-provider__related .tp-services-provider__h3 {
  margin: 0 0 11px;
  color: var(--tpl-ink-soft);
  /* 11.5px in the source; the named Caption role is 12. */
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}

.tp-services-page .tp-services-provider__related p {
  margin: 0;
  color: var(--tpl-ink-soft);
  font-size: 14px;
  line-height: 1.9;
}

/* The source spaces the separator rather than relying on the space either
   side of it, which collapses at the end of a wrapped line.

   AND IT IS THE FAINT ROLE, which in this whole page the source spends on
   exactly two things: this separator and the one between the rating and the
   category chip (proto @45219 and @7005 — the only two `--tp-text-4` in the
   template). A separator is the one piece of text that should recede. */
.tp-services-page .tp-services-provider__related p span {
  color: var(--tpl-ink-faint);
  padding: 0 9px;
}

.tp-services-page .tp-services-provider__related a,
.tp-services-page .tp-services-provider__symptoms a {
  color: var(--tpl-blue);
  text-decoration: none;
}

.tp-services-page .tp-services-provider__symptoms {
  display: grid;
  gap: 4px 24px;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  font-size: 13px;
  line-height: 1.9;
}

.tp-services-page .tp-services-provider__disclaimer,
.tp-services-page .tp-services-provider__fixture-note {
  max-width: 90ch;
  margin: 32px 0 0;
  color: var(--tpl-ink-faint);
  font-size: 13px;
  line-height: 1.75;
}

/* TWO LEVELS OF INK, NOT ONE FAINT ONE — proto @45558.
 *
 * The source sets the paragraph in `--tp-text-3` and lifts each `<strong>` to
 * `--tp-text-2`, so the two sentences a driver has to act on — what the page
 * does not stand behind, and what a price would and would not have covered —
 * read a step darker than the sentence around them. Set in the faint role with
 * no distinction at all, the whole block sank below the legal boilerplate it
 * is not.
 *
 * `__fixture-note` keeps the faint role above: it is this repository's own
 * aside about its own data, has no counterpart in the source, and is the one
 * thing here that genuinely should recede.
 */
.tp-services-page .tp-services-provider__disclaimer {
  color: var(--tpl-ink-soft);
}

.tp-services-page .tp-services-provider__disclaimer strong {
  color: var(--tpl-ink-secondary);
}

.tp-services-page .tp-services-provider__fixture-note {
  margin-top: 12px;
  padding: 10px 14px;
  border-left: 3px solid var(--tpl-line);
  background: var(--tpl-surface-alt);
}

/* ------------------------------------------------------------ small --- */

@media (max-width: 1100px) {
  .tp-services-page .tp-services-provider__layout {
    grid-template-columns: minmax(0, 1fr);
  }

  .tp-services-page .tp-services-provider__rail {
    position: static;
  }

  .tp-services-page .tp-services-provider__caps {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }

  /* 40 at desktop, 27 on a phone; without a step between them the heading
     loses a third of its size the pixel after the rail unstacks. */
  .tp-services-page .tp-services-provider__title {
    font-size: 32px;
  }
}

@media (max-width: 743px) {
  .tp-services-page .tp-services-provider__caps {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }

  .tp-services-page .tp-services-provider__rivals,
  .tp-services-page .tp-services-provider__ads,
  .tp-services-page .tp-services-provider__breakdown,
  /* `__related` is not here: it is a single column at every width now. */
  .tp-services-page .tp-services-provider__symptoms {
    grid-template-columns: minmax(0, 1fr);
  }

  /* The label column collapses rather than squeezing the value out of view. */
  .tp-services-page .tp-services-provider__address > div {
    grid-template-columns: minmax(0, 1fr) auto;
  }

  .tp-services-page .tp-services-provider__address dt {
    grid-column: 1 / -1;
  }

  .tp-services-page .tp-services-provider__title {
    font-size: 27px;
  }

  /* The App band's 34/36 is a desktop measurement. At 390 it eats a fifth of
     the width before a word is set, and the two reason cards come out 134px
     wide — narrower than the sentences inside them. */
  .tp-services-page .tp-services-provider__app {
    padding: 24px 20px;
  }

  .tp-services-page .tp-services-provider__app-reasons {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* ------------------------------------------------------- Credentials ----- */

/* Two columns in the design source, one when there is no room for two. */
.tp-services-page .tp-services-provider__creds {
  display: grid;
  margin: 0 0 14px;
  padding: 0;
  gap: 9px 24px;
  grid-template-columns: 1fr 1fr;
  list-style: none;
}
.tp-services-page .tp-services-provider__creds > li {
  display: flex;
  align-items: flex-start;
  gap: 9px;
  color: var(--tpl-ink-secondary);
  /* Prototype: 14.5px. The named Body Small role instead — a fractional size
     is not a density tool. */
  font-size: 14px;
  line-height: 1.6;
}
.tp-services-page .tp-services-provider__creds .tp-site-icon {
  margin-top: 4px;
}
.tp-services-page .tp-services-provider__creds-note {
  max-width: 72ch;
  margin: 0;
  color: var(--tpl-ink-soft);
  font-size: 13px;
  line-height: 1.7;
}

@media (max-width: 720px) {
  .tp-services-page .tp-services-provider__creds {
    grid-template-columns: 1fr;
  }
}

/* The rail's app button: full width, filled, uppercase — the design source's
   primary action for that panel. */
.tp-services-page .tp-services-provider__rail-app-cta {
  display: block;
  width: 100%;
  padding: 13px;
  border-radius: 6px;
  background: var(--tpl-blue);
  color: var(--tpl-white);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-align: center;
  text-decoration: none;
  text-transform: uppercase;
}

/* The badges sit under it, at the rail's own scale. */
.tp-services-page .tp-services-provider__rail-app .tp-services-provider__app-stores {
  margin-top: 9px;
  gap: 7px;
}

/* Tighter than the same badge in the App band — the rail is 372px wide and the
   source shrinks the pair to fit rather than wrapping them. */
/* Smaller in the rail than in the App band — the panel is 372px wide and the
   source shrinks the pair to fit rather than wrapping them. */
.tp-services-page .tp-services-provider__rail-app .tp-services-provider__app-stores a {
  padding: 7px 10px;
}

.tp-services-page .tp-services-provider__rail-app .tp-services-provider__app-stores img {
  height: 20px;
}

/* A bought placement asks more quietly than the page's own recommendation. */
.tp-services-page .tp-services-provider__ad-cta {
  border: 1.5px solid var(--tpl-blue);
  background: var(--tpl-white);
  color: var(--tpl-blue);
}

/* ------------------------------------------------- not-for-sale lists ---- */

/*
 * Nearest and also-called are one card each, rows ruled off inside it. The
 * design source draws them that way, and the box is what separates them from
 * the paid strip above: these are lists, not offers.
 */
.tp-services-page .tp-services-provider__organic {
  padding: 0 16px;
  border: 1px solid var(--tpl-line);
  border-radius: 12px;
  background: var(--tpl-white);
  overflow: hidden;
}
.tp-services-page .tp-services-provider__organic li {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: nowrap;
  padding: 12px 0;
  border-top: 1px solid var(--tpl-line-soft);
  border-bottom: 0;
}
.tp-services-page .tp-services-provider__organic li:first-child {
  border-top: 0;
}
.tp-services-page .tp-services-provider__organic-name {
  flex: 1;
  min-width: 0;
}
.tp-services-page .tp-services-provider__organic-figure {
  flex: none;
  text-align: right;
}

/* These two bands are a level below the page's own questions. */
.tp-services-page .tp-services-provider__section_list .tp-services-provider__h2 {
  margin: 0 0 4px;
  font-size: 18px;
}

/* And their standfirst is smaller than a section's — it names what the list is
   sorted by rather than arguing anything. */
.tp-services-page .tp-services-provider__section_list .tp-services-provider__sub {
  color: var(--tpl-ink-soft);
  /* 12.5px in the source; the named Caption role is 12. */
  font-size: 12px;
  line-height: 1.7;
}

/* A boxed block on a quiet ground — the design source's treatment for the
   symptom band, which is a way out of the page rather than one of its answers. */
.tp-services-page .tp-services-provider__section_card {
  padding: 20px 22px;
  border: 1px solid var(--tpl-line);
  border-radius: 12px;
  background: var(--tpl-surface-alt);
}
.tp-services-page .tp-services-provider__section_card .tp-services-provider__h2 {
  font-size: 20px;
}

/* The link grid's vertical rhythm, from the design source. */
.tp-services-page .tp-services-provider__symptoms {
  gap: 9px 20px;
}

/* Name over meta, as the design source stacks them. On one line the meta
   competes with the figure on the right and the row reads as three columns
   when it is two. */
.tp-services-page .tp-services-provider__organic-copy {
  display: block;
  flex: 1;
  min-width: 0;
}
.tp-services-page .tp-services-provider__organic-name {
  display: block;
  font-size: 14px;
}
.tp-services-page .tp-services-provider__organic-meta {
  display: block;
  margin-top: 2px;
  font-size: 12px;
}
