/* Skin: foundry. Classic local-contractor look: near-white ground, tight 4px
   geometry, brand-color buttons and brand-color bands, conventional blocks.
   Calibrated to the measured V1 house style (R3 to R5 in
   the parity notes (PM docs) and re-measured
   live on 2026-08-12 against the primary reference. Geometry and art direction
   only; every color flows from the derived palette tokens.
   Copied to src/generated/skin.css by the build orchestrator.

   Nothing here is lifted from the reference. Every selector is one of our own
   class names from docs/design-reference/skin-hooks.md and every rule is
   written fresh. What is shared is the measured NUMBERS (radii, shadow
   geometry, padding, container width, nav height, type scale). Deviations from
   the task brief's starting values, and the contrast work behind every new
   color pairing, are recorded in docs/design-reference/checklist-foundry.md. */

[data-skin='foundry'] {
  /* Live reference computes 4px on buttons, cards and images (the reference
     pack recorded 3px; the difference is one pixel and the live value wins). */
  --radius: 4px;
  --radius-card: 4px;
  --radius-button: 4px;
  --radius-image: 4px;

  /* Measured: 1200px container, 48px gutter, 80px section rhythm, 86px nav. */
  --container-max: 75rem;
  --container-pad: clamp(1.25rem, 3.75vw, 3rem);
  --section-pad: clamp(3.5rem, 8vw, 5rem);
  --nav-height: 5.4rem;
  --nav-height-mobile: 4.5rem;

  /* One shadow family across buttons and cards, as the reference has. */
  --shadow-card: 0 4px 16px rgba(0, 0, 0, 0.12);
  --shadow-card-hover: 0 6px 22px rgba(0, 0, 0, 0.16);
  --shadow-button: 0 4px 16px rgba(0, 0, 0, 0.12);
  --shadow-button-hover: 0 6px 20px rgba(0, 0, 0, 0.16);
  --motion: 0.3s ease-in-out;

  /* Alternating bands are a 2 to 3 percent step off the page ground, not the
     full bg-alt jump. Both ends are contrast-guaranteed grounds, so anything
     legible on bg and bg_alt is legible on the blend. */
  --band-quiet: color-mix(in srgb, var(--color-bg-alt) 58%, var(--color-bg));

  /* Angled section divider: 29px at 1280px, matching the reference's hero
     edge, and proportionally shorter on narrow screens. */
  --wedge-h: clamp(14px, 2.3vw, 30px);

  /* Flat ink scrim over hero photography (the reference uses a flat 70%). */
  --hero-scrim: color-mix(in srgb, var(--color-bg-dark) 72%, transparent);

  /* Brand-tinted label ink for small link text. --color-accent alone is only
     guaranteed at 3:1 on the page ground, which is short of the 4.5:1 that
     small informational text needs; this blend clears 4.5:1 on bg and bg_alt
     across all six presets in both themes (worst 5.39:1). */
  --label-ink: color-mix(in srgb, var(--color-accent) 70%, var(--color-heading));

  /* Universal five-star amber, deliberately not brand-colored. */
  --star: #d99a06;
}

/* ---------------------------------------------------------------- type --
   Montserrat ships 400/600/700/800 and Inter 400/500/600 (data/fonts.json),
   so no weight below asks for something the pairing cannot render. The
   reference sets headings at weight 700, zero tracking, 1.12 line height and
   title case, which is the single loudest signal of this house style. */

[data-skin='foundry'] body { font-size: var(--oc-owner-font-body-size, 1.125rem); line-height: 1.6; }
[data-skin='foundry'] h1,
[data-skin='foundry'] h2,
[data-skin='foundry'] h3,
[data-skin='foundry'] h4 {
  letter-spacing: normal;
  line-height: 1.12;
  text-transform: capitalize;
}
/* 2026-09-05 (fix/theme-tokens-apply): h1/h2/h3 split out of the shared
   h1..h4 rule above so each can read its own --oc-owner-font-<el>-size/
   weight, falling back to today's exact literal. h4 keeps the old shared
   rule's font-weight:700 untouched -- it isn't one of the Text Styles
   elements (eyebrow/h1/h2/h3/body). */
[data-skin='foundry'] h4 { font-weight: 700; }
[data-skin='foundry'] h1 { font-size: var(--oc-owner-font-h1-size, clamp(30px, 4vw, 52px)); font-weight: var(--oc-owner-font-h1-weight, 700); }
[data-skin='foundry'] h2 { font-size: var(--oc-owner-font-h2-size, clamp(26px, 3.05vw, 39px)); font-weight: var(--oc-owner-font-h2-weight, 700); }
[data-skin='foundry'] h3 { font-size: var(--oc-owner-font-h3-size, clamp(20px, 1.8vw, 23px)); font-weight: var(--oc-owner-font-h3-weight, 700); }
[data-skin='foundry'] .lead,
[data-skin='foundry'] .subhead { font-size: 1.2rem; }
[data-skin='foundry'] .card-body p { font-size: 1rem; }

/* ------------------------------------------------------------ eyebrows --
   2026-09-10 (section-openers, Hannah's own pick #2): the uppercase caps
   line + diamond marker are gone from the screen. The word itself stays
   in the markup, clipped to a single pixel (never display:none), so a
   screen reader still announces it just before the heading. A short
   accent-color rule sits under the heading instead. */

[data-skin='foundry'] .eyebrow {
  /* Theme-panel eyebrow font-size token stays wired even though the text
     is now clipped -- an owner's saved value must still reach the DOM. */
  font-size: var(--oc-owner-font-eyebrow-size, 0.8125rem);
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
[data-skin='foundry'] .eyebrow::before { content: none; }
[data-skin='foundry'] .eyebrow + h2::after,
[data-skin='foundry'] .eyebrow + h3::after {
  content: '';
  display: block;
  width: 48px;
  height: 3px;
  margin-top: 14px;
  background: var(--color-accent);
}
[data-skin='foundry'] .credentials .eyebrow,
[data-skin='foundry'] .calc-embed .eyebrow,
[data-skin='foundry'] .reviews .eyebrow { justify-content: center; }

/* --------------------------------------------------------------- ground --
   Near-white page, quiet alternating bands closed by hairline rules. */

[data-skin='foundry'] .container {
  max-width: var(--container-max);
  padding-inline: var(--container-pad);
}
[data-skin='foundry'] section { padding: var(--section-pad) 0; position: relative; }
[data-skin='foundry'] .intro-section { padding-bottom: 1rem; }
/* Banding mirrors base.css line 127 exactly, including its `nth-of-type(even)`
   selector. That selector counts every sibling <section>, not just rich ones,
   so the alternation depends on how many sections a page emits before the rich
   run: the roofing homepage puts the first rich block at an even index, which
   is what makes the banding land correctly there and on the service, area and
   about pages (all verified in the browser). It is deliberately not "fixed"
   here, because base owns the same selector for the bg-alt fill: changing only
   the skin's copy would leave the two rules banding different sections. The
   robust fix is a class emitted by RichSections.astro, consumed by base and
   every skin at once. */
[data-skin='foundry'] .services-grid-section,
[data-skin='foundry'] .reviews,
[data-skin='foundry'] .credentials,
[data-skin='foundry'] .calc-embed,
[data-skin='foundry'] .rich-section:nth-of-type(even) {
  background: var(--band-quiet);
}

/* ------------------------------------------------------- angled dividers --
   The reference cuts every section boundary with a flat triangular wedge: a
   full-bleed shape thin at the left edge and the wedge's full height at the
   right, painted in the ground color of the section BELOW the boundary. It
   measures 29px tall at 1280px on the hero edge (2.3% of the viewport width)
   and shrinks with the viewport.

   Ours is built the other way round so the color is always self-evident: each
   section carries the wedge on its own top edge, offset upward into whatever
   sits above it, and fills it with its own ground. Nothing has to know what
   follows it, so the sequence stays correct on every page and in every theme.
   The clip path is the same geometry the reference's path describes: the fill
   starts 90% of the way down at the left edge and at the very top on the
   right. This is background-on-background decoration with no text over it, so
   no contrast pairing is introduced. */

[data-skin='foundry'] .trustbar,
[data-skin='foundry'] .site-footer { position: relative; }

[data-skin='foundry'] .whyus::before,
[data-skin='foundry'] .process-section::before,
[data-skin='foundry'] .financing::before,
[data-skin='foundry'] .faq-section::before,
[data-skin='foundry'] .gallery::before,
[data-skin='foundry'] .coverage-section::before,
[data-skin='foundry'] .value-section::before,
[data-skin='foundry'] .bullets-section::before,
[data-skin='foundry'] .contact-section::before,
[data-skin='foundry'] .intro-section::before,
[data-skin='foundry'] .hail-stats::before,
[data-skin='foundry'] .rich-section::before,
[data-skin='foundry'] .services-grid-section::before,
[data-skin='foundry'] .reviews::before,
[data-skin='foundry'] .credentials::before,
[data-skin='foundry'] .calc-embed::before,
[data-skin='foundry'] .rich-section:nth-of-type(even)::before,
[data-skin='foundry'] .areas-grid-section::before,
[data-skin='foundry'] .cta-band::before,
[data-skin='foundry'] .trustbar::before,
[data-skin='foundry'] .site-footer::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: calc(-1 * var(--wedge-h));
  height: var(--wedge-h);
  clip-path: polygon(0 90%, 100% 0, 100% 100%, 0 100%);
  pointer-events: none;
}
/* Ground color per wedge, one group per ground. Each section class appears in
   exactly one group, so nothing here can win the wrong color by specificity. */
[data-skin='foundry'] .whyus::before,
[data-skin='foundry'] .process-section::before,
[data-skin='foundry'] .financing::before,
[data-skin='foundry'] .faq-section::before,
[data-skin='foundry'] .gallery::before,
[data-skin='foundry'] .coverage-section::before,
[data-skin='foundry'] .value-section::before,
[data-skin='foundry'] .bullets-section::before,
[data-skin='foundry'] .contact-section::before,
[data-skin='foundry'] .intro-section::before,
[data-skin='foundry'] .hail-stats::before,
[data-skin='foundry'] .rich-section::before { background: var(--color-bg); }
[data-skin='foundry'] .services-grid-section::before,
[data-skin='foundry'] .reviews::before,
[data-skin='foundry'] .credentials::before,
[data-skin='foundry'] .calc-embed::before,
[data-skin='foundry'] .rich-section:nth-of-type(even)::before { background: var(--band-quiet); }
[data-skin='foundry'] .areas-grid-section::before,
[data-skin='foundry'] .cta-band::before { background: var(--color-accent); }
[data-skin='foundry'] .trustbar::before,
[data-skin='foundry'] .site-footer::before { background: var(--color-bg-dark); }
[data-skin='foundry'] .section-intro { max-width: 42rem; }
/* Long-form section copy keeps a readable measure instead of running the full
   1104px content width, which is what the reference's two-column blocks do. */
[data-skin='foundry'] .rich-section p,
[data-skin='foundry'] .rich-section li,
[data-skin='foundry'] .intro-section p,
[data-skin='foundry'] .legal p { max-width: 46rem; }
[data-skin='foundry'] .reviews { text-align: center; }
/* .section-intro is a block, so centring it is a margin job; .reviews-subline
   is the flex row and needs the justification. */
[data-skin='foundry'] .reviews .section-intro { margin-inline: auto; }
[data-skin='foundry'] .reviews-subline { justify-content: center; margin-inline: auto; }

/* ---------------------------------------------------------------- hero --
   Photo under a flat ink scrim, copy left, two buttons. */

[data-skin='foundry'] .hero {
  background: var(--band-quiet);
  text-align: left;
  padding: clamp(3.5rem, 9vw, 6rem) 0;
}
[data-skin='foundry'] .hero-compact { padding: clamp(2.5rem, 6vw, 4rem) 0; }
[data-skin='foundry'] .hero-image {
  background:
    linear-gradient(var(--hero-scrim), var(--hero-scrim)),
    var(--hero-img) center / cover no-repeat;
}
[data-skin='foundry'] .hero-content { max-width: 46rem; }
[data-skin='foundry'] .hero .subhead { margin: 1rem 0 0; max-width: 36rem; }
[data-skin='foundry'] .hero-actions { justify-content: flex-start; margin-top: 2rem; }
[data-skin='foundry'] .hero-stats { justify-content: flex-start; }
/* Over the scrim, base tints sub-copy with body-alt, which is only
   contrast-guaranteed against a flat bg-dark and drops to 3.80:1 against a
   72% scrim over a pale photo. The near-white heading token holds 5.23:1
   there in the worst of the twelve preset/theme combinations. */
[data-skin='foundry'] .hero-image .subhead,
[data-skin='foundry'] .hero-image .lead,
[data-skin='foundry'] .hero-image .breadcrumbs { color: var(--color-heading-alt); }
/* Plain proof line with a small marker instead of a glass pill. */
[data-skin='foundry'] .hero-badge {
  background: none;
  border: 0;
  padding: 0;
  border-radius: 0;
  font-size: 0.95rem;
  font-weight: 600;
  margin-bottom: 0.9rem;
}
[data-skin='foundry'] .hero-image .hero-badge {
  background: none;
  border: 0;
  color: var(--color-heading-alt);
}
[data-skin='foundry'] .hero-badge-dot {
  width: 9px;
  height: 9px;
  flex: none;
  background: var(--star);
}
/* The service-area credential line is 18px at weight 600, below the WCAG
   large-text threshold on both counts, so it needs the full 4.5:1. On those
   pages the hero is `hero hero-compact` and the line sits on a flat pale
   ground, where accent bottoms out at 3.68:1 across the twelve preset and
   theme combinations. The heading token is contract-guaranteed there. */
[data-skin='foundry'] .hero-cred { color: var(--color-heading); }
[data-skin='foundry'] .hero-image .hero-cred { color: var(--color-heading-alt); }
[data-skin='foundry'] .stat-tile { border-radius: var(--radius-card); }
[data-skin='foundry'] .stat-suffix-star { color: var(--star); }

/* ------------------------------------------------------------- buttons --
   4px corners, 13px by 24px, weight 700, one soft drop shadow, no lift. */

[data-skin='foundry'] .btn {
  border-radius: var(--radius-button);
  border-width: 1px;
  padding: 0.8125rem 1.5rem;
  font-size: 1rem;
  font-weight: 700;
  line-height: 1.25;
  transition: background var(--motion), color var(--motion),
    border-color var(--motion), box-shadow var(--motion);
}
[data-skin='foundry'] .btn-lg { padding: 1rem 2rem; font-size: 1rem; }
[data-skin='foundry'] .btn-primary,
[data-skin='foundry'] .btn-inverse { box-shadow: var(--shadow-button); }
[data-skin='foundry'] .btn-primary:hover,
[data-skin='foundry'] .btn-inverse:hover { box-shadow: var(--shadow-button-hover); }
/* Secondary action: light fill, 2px brand edge, brand-tinted label. The
   reference's secondary button is exactly this, white on the photo hero. */
[data-skin='foundry'] .btn-glass,
[data-skin='foundry'] .hero-image .btn-glass {
  background: var(--color-bg);
  border: 2px solid var(--color-accent);
  color: var(--label-ink);
  box-shadow: var(--shadow-button);
  padding: 0.75rem 1.4375rem;
}
[data-skin='foundry'] .btn-glass.btn-lg,
[data-skin='foundry'] .hero-image .btn-glass.btn-lg { padding: 0.9375rem 1.9375rem; }
[data-skin='foundry'] .btn-glass:hover,
[data-skin='foundry'] .hero-image .btn-glass:hover {
  background: var(--color-accent);
  color: var(--color-on-accent);
}

/* --------------------------------------------------------------- cards --
   Page-ground fill, hairline border, 4px corners, one soft shadow, and a
   shadow-only hover. Base's 3px accent cap is dropped: the reference has no
   colored rule on its cards. */

[data-skin='foundry'] .card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  transition: box-shadow var(--motion);
}
[data-skin='foundry'] .card:hover {
  transform: none;
  box-shadow: var(--shadow-card-hover);
}
[data-skin='foundry'] .card-body { padding: 1.25rem 1.4rem 1.4rem; }
[data-skin='foundry'] .card-cta { color: var(--label-ink); }
/* Demo briefs ship no service photography, so the placeholder is visible far
   more often than it should be. Base blends accent into secondary, which
   lands on an off-brand hue; this keeps it inside the brand ramp. */
[data-skin='foundry'] .card-img-placeholder,
[data-skin='foundry'] .whyus-img-placeholder {
  background: linear-gradient(135deg,
    color-mix(in srgb, var(--color-accent) 88%, black),
    color-mix(in srgb, var(--color-accent) 45%, var(--color-bg-alt)));
  opacity: 1;
}
[data-skin='foundry'] .icon-badge { border-radius: var(--radius-card); }
[data-skin='foundry'] .whyus-img,
[data-skin='foundry'] .gallery-grid figure,
[data-skin='foundry'] .hours-card,
[data-skin='foundry'] .review-card { border-radius: var(--radius-image); }
[data-skin='foundry'] .whyus-img,
[data-skin='foundry'] .review-card { box-shadow: var(--shadow-card); }
[data-skin='foundry'] .coverage-card {
  border-radius: var(--radius-card);
  border-color: var(--color-border);
  box-shadow: var(--shadow-card);
}
[data-skin='foundry'] .gallery-grid figure:hover img { transform: none; }

/* ------------------------------------------------------------- reviews --
   Quote-marked cards, gold stars, squared avatar. */

[data-skin='foundry'] .review-card {
  border: 1px solid var(--color-border);
  padding: 1.5rem 1.6rem;
  text-align: left;
}
[data-skin='foundry'] .stars { color: var(--star); }
[data-skin='foundry'] .avatar { border-radius: var(--radius-card); }
[data-skin='foundry'] .review-card cite {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-size: 0.85rem;
}

/* ----------------------------------------------------------- brand band --
   The service-area block and the closing call to action are solid brand
   panels, the way both live V1 references carry one mid-page and one at the
   end. Flat accent, never a lightened gradient: --color-on-accent is the only
   token the palette guarantees at 4.5:1 on accent, and that guarantee is void
   the moment the ground is tinted away from accent (a 10% white blend drops
   the worst case to 3.99:1). */

[data-skin='foundry'] .areas-grid-section,
[data-skin='foundry'] .cta-band {
  background: var(--color-accent);
  color: var(--color-on-accent);
  border: 0;
}
[data-skin='foundry'] .areas-grid-section h2,
[data-skin='foundry'] .areas-grid-section p,
[data-skin='foundry'] .areas-grid-section .eyebrow,
[data-skin='foundry'] .cta-band h2,
[data-skin='foundry'] .cta-band p { color: var(--color-on-accent); }
[data-skin='foundry'] .areas-grid-section .eyebrow::before { background: var(--color-on-accent); }
/* City links sit straight on the band as a plain list, the way the reference
   lists its towns. On-accent is the one token guaranteed at 4.5:1 there, and
   a translucent fill under it would void that guarantee (on-accent at 10%
   over accent already drops the worst case to 3.99:1), so the tiles stay
   unfilled and hover moves the border instead. */
[data-skin='foundry'] .areas-grid-section .area-links a {
  background: transparent;
  border-color: color-mix(in srgb, var(--color-on-accent) 32%, transparent);
  border-radius: var(--radius-card);
  box-shadow: none;
  color: var(--color-on-accent);
  font-weight: 600;
}
[data-skin='foundry'] .areas-grid-section .area-links a:hover {
  background: transparent;
  border-color: var(--color-on-accent);
  color: var(--color-on-accent);
  box-shadow: none;
}
/* Base draws the outline button in heading-alt, which sinks to 1.87:1 on a
   light-theme accent band. On-accent is the guaranteed pair. The hover state
   is left to base: it fills with heading-alt and prints bg-dark on it, a pair
   the palette guarantees at 4.5:1 regardless of what the band under it is. */
[data-skin='foundry'] .cta-band .btn-outline {
  border-color: var(--color-on-accent);
  color: var(--color-on-accent);
}
[data-skin='foundry'] .cta-actions { margin-top: 2rem; }

/* ------------------------------------------------------------- process --
   Numbered squares rather than circles, to stay with the tight geometry. */

[data-skin='foundry'] .step-num {
  width: 2.4rem;
  height: 2.4rem;
  border-radius: var(--radius-card);
  font-family: var(--font-heading);
  margin-bottom: 0.8rem;
}

/* ----------------------------------------------------------------- faq --
   Full-width rows with a brand-tinted rule and a plus affordance. */

[data-skin='foundry'] .faq {
  border-bottom: 1px solid color-mix(in srgb, var(--color-accent) 30%, var(--color-border));
  padding: 0.5rem 0;
}
[data-skin='foundry'] .faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  list-style: none;
  padding: 0.8rem 0;
}
[data-skin='foundry'] .faq summary::-webkit-details-marker { display: none; }
[data-skin='foundry'] .faq summary::after {
  content: '+';
  font-size: 1.35rem;
  font-weight: 400;
  line-height: 1;
  color: var(--color-accent);
  flex: none;
}
[data-skin='foundry'] .faq[open] summary::after { content: '\2212'; }

/* ------------------------------------------- credentials, chips, pills --
   Everything that base rounds to a pill is squared off to the 4px scale. */

[data-skin='foundry'] .badge,
[data-skin='foundry'] .chip {
  border-radius: var(--radius-card);
  border-color: var(--color-border);
}
[data-skin='foundry'] .badge:hover {
  transform: none;
  box-shadow: var(--shadow-card);
}
[data-skin='foundry'] .area-links a {
  border-radius: var(--radius-card);
  box-shadow: none;
  font-weight: 600;
}
[data-skin='foundry'] .area-links a:hover {
  color: var(--label-ink);
  box-shadow: var(--shadow-card);
}

/* ----------------------------------------------------------- financing --
   Same panel, squared, with the brand edge kept. */

[data-skin='foundry'] .financing .container-narrow {
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}

/* ---------------------------------------------------------- calc embed --
   Hairline frame in place of base's gradient glow ring. */

[data-skin='foundry'] .calc-frame-wrap {
  background: var(--color-border);
  padding: 1px;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
[data-skin='foundry'] .calc-frame-wrap iframe { border-radius: 3px; }

/* --------------------------------------------------------------- chrome --
   Taller white header with a hairline rule; footer keeps the ink ground so
   the brand band at the CTA stays the one brand slab at the foot of the page
   (R5 carries a brand footer, R3 a pale gray one; ink reads with both). */

[data-skin='foundry'] .header-row { min-height: var(--nav-height); }
[data-skin='foundry'] .site-header { border-bottom-color: var(--color-border-light); }
[data-skin='foundry'] .site-nav { gap: 1.7rem; }
[data-skin='foundry'] .site-nav a { font-weight: 500; }
[data-skin='foundry'] .brand-logo { max-height: 3rem; }
[data-skin='foundry'] .footer-head {
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: 0.85rem;
}
/* A hairline keeps the ink footer from merging into the brand CTA band above
   it when the brand color is itself a deep blue. */
[data-skin='foundry'] .site-footer {
  padding-top: 3.5rem;
  border-top: 1px solid color-mix(in srgb, var(--color-heading-alt) 20%, transparent);
}

/* ---------------------------------------------------------- sticky bar --
   The bar is dark, so its secondary button takes the light-on-dark treatment
   instead of the light-ground one used everywhere else. */

[data-skin='foundry'] .sticky-cta .btn {
  border-radius: var(--radius-button);
  padding: 0.55rem 1rem;
  font-size: 0.9rem;
  box-shadow: none;
  white-space: nowrap;
}
[data-skin='foundry'] .sticky-cta .btn-glass {
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.18);
  color: var(--color-heading-alt);
}
[data-skin='foundry'] .sticky-cta .btn-glass:hover { background: rgba(255, 255, 255, 0.16); }
[data-skin='foundry'] .sticky-cta-place { font-size: 0.8rem; white-space: nowrap; }

/* ------------------------------------------------------------- mobile --- */

@media (max-width: 820px) {
  [data-skin='foundry'] .header-row { min-height: var(--nav-height-mobile); gap: 0.9rem; }
  [data-skin='foundry'] .site-nav { top: var(--nav-height-mobile); }
  /* Our .btn padding is larger than base's, so the compact header button has
     to be restated here or the header overflows at phone widths. */
  [data-skin='foundry'] .header-actions .btn-primary {
    padding: 0.5em 0.9em;
    font-size: 0.92rem;
    box-shadow: none;
  }
}

@media (max-width: 640px) {
  [data-skin='foundry'] .header-actions .btn-primary { display: none; }
  [data-skin='foundry'] .hero-actions .btn { width: 100%; text-align: center; }
  [data-skin='foundry'] .btn-lg { padding: 0.9375rem 1.5rem; }
  [data-skin='foundry'] .card-body { padding: 1.1rem 1.2rem 1.3rem; }
}

/* Skin: harbor. Image-led, square surfaces, warm accent lines.
   Calibrated to the measured Pacific reference (R2 in
   the parity notes (PM docs) 2026-08-12).
   Geometry and art direction only; colors flow from derived tokens.
   Copied to src/generated/skin.css by the build orchestrator.

   Nothing here is copied from the reference: every selector below is one of
   our own class names from docs/design-reference/skin-hooks.md, and every rule
   is written fresh. What is shared is the measured NUMBERS (radii, shadow
   geometry, gradient stops, nav height, type scale). */

[data-skin='harbor'] {
  /* Surfaces are square; only cards/images/buttons carry radius. */
  --radius: 0px;
  --radius-card: 4px;
  --radius-button: 10px;
  --radius-image: 4px;

  --nav-height: 5rem;
  --nav-height-mobile: 4.5rem;
  --section-pad: clamp(3rem, 8vw, 4rem);

  /* Buttons carry an accent-tinted lift; cards stay deliberately flat. */
  --shadow-button: 0 0.5rem 1rem color-mix(in srgb, var(--color-accent) 16%, transparent);
  --shadow-button-hover: 0 0.8rem 1.45rem color-mix(in srgb, var(--color-accent) 24%, transparent);
  --shadow-card: 0 5px 5px color-mix(in srgb, var(--color-heading) 5%, transparent);

  /* Signature: a short bar under every section label. */
  --accent-line-w: clamp(2.75rem, 4vw, 3.5rem);
  --accent-line-h: 3px;

  /* Large radius for the dark "shell" block that closes the page. */
  --shell-radius: clamp(1rem, 3vw, 2rem);

  /* Ink used for photo scrims: near-black warmed toward the brand color. */
  --hero-ink: color-mix(in srgb, var(--color-bg-dark) 74%, var(--color-accent));

  --motion: 180ms ease;
}

/* ---------------------------------------------------------------- type --
   Poppins ships 400/600/700 and Open Sans 400/500/600 (data/fonts.json), so
   nothing here asks for a weight the pairing cannot render. */

[data-skin='harbor'] body { font-size: var(--oc-owner-font-body-size, 1.125rem); line-height: 1.7; }
/* 2026-09-05 (fix/theme-tokens-apply): the old shared h1..h4{font-weight:700}
   rule is gone -- h1/h2/h3 now each carry their own font-weight (still 700
   by default) alongside their font-size, so both can read
   --oc-owner-font-<el>-weight/-size. h4 keeps its own font-weight:700 rule,
   untouched -- not a Text Styles element. */
[data-skin='harbor'] h4 { font-weight: 700; }
[data-skin='harbor'] h1 {
  font-size: var(--oc-owner-font-h1-size, clamp(34px, 5vw, 63px));
  font-weight: var(--oc-owner-font-h1-weight, 700);
  line-height: 1.04;
  letter-spacing: -0.035em;
}
[data-skin='harbor'] h2 {
  font-size: var(--oc-owner-font-h2-size, clamp(28px, 3vw, 36px));
  font-weight: var(--oc-owner-font-h2-weight, 700);
  line-height: 1.14;
  letter-spacing: -0.01em;
}
[data-skin='harbor'] h3 { font-size: var(--oc-owner-font-h3-size, 20px); font-weight: var(--oc-owner-font-h3-weight, 700); line-height: 1.3; }
[data-skin='harbor'] .lead { font-size: 1.2rem; }
/* Poppins tops out at 700, so 800 would be synthesised. */
[data-skin='harbor'] .wordmark { font-weight: 700; letter-spacing: -0.02em; }
[data-skin='harbor'] .stat-value { font-weight: 700; }

/* ------------------------------------------------------------ eyebrows --
   The section label becomes a shrink-to-fit column so its underline bar can
   sit under the text and follow whatever alignment the section uses. */

[data-skin='harbor'] .eyebrow {
  display: inline-flex;
  flex-direction: column;
  align-items: flex-start;
  font-size: var(--oc-owner-font-eyebrow-size, 1rem);
  font-weight: var(--oc-owner-font-eyebrow-weight, 600);
  letter-spacing: 0;
  text-transform: none;
  color: var(--color-heading);
  margin-bottom: 0.85rem;
}
[data-skin='harbor'] .eyebrow::after {
  content: '';
  display: block;
  width: var(--accent-line-w);
  height: var(--accent-line-h);
  margin-top: 0.65rem;
  border-radius: 999px;
  background: var(--color-secondary);
}
/* Sections whose copy is centred centre the bar with it. */
[data-skin='harbor'] .credentials .eyebrow,
[data-skin='harbor'] .calc-embed .eyebrow,
[data-skin='harbor'] .process-section .eyebrow { align-items: center; }

/* FAQ and the closing CTA carry no label in our markup, so the bar rides
   above the heading instead. The motif stays on every section. */
[data-skin='harbor'] .faq-section h2::before,
[data-skin='harbor'] .cta-band h2::before {
  content: '';
  display: block;
  width: var(--accent-line-w);
  height: var(--accent-line-h);
  margin: 0 0 1.1rem;
  border-radius: 999px;
  background: var(--color-secondary);
}
[data-skin='harbor'] .cta-band h2::before { margin-inline: auto; }

/* ---------------------------------------------------------------- hero --
   Photo-backed, copy left, ink gradient thinning to the right so the picture
   stays legible on the open side. Stops are the measured reference values. */

[data-skin='harbor'] .hero {
  text-align: left;
  padding: clamp(3.5rem, 8vw, 5.5rem) 0;
}
[data-skin='harbor'] .hero-compact { padding: clamp(2.5rem, 6vw, 4rem) 0; }
[data-skin='harbor'] .hero-content { max-width: 49rem; }
[data-skin='harbor'] .hero .subhead {
  margin-inline: 0;
  max-width: 34rem;
  font-size: 1.15rem;
}
/* Over the photo, hero copy takes the near-white heading token rather than
   base's dimmer body-alt: body-alt only clears AA against a flat bg-dark, and
   a scrim over an unknown photo is a softer ground than that. */
[data-skin='harbor'] .hero-image .subhead,
[data-skin='harbor'] .hero-image .lead,
[data-skin='harbor'] .hero-image .breadcrumbs { color: var(--color-heading-alt); }
[data-skin='harbor'] .hero-actions { justify-content: flex-start; margin-top: 2.25rem; }
[data-skin='harbor'] .hero h1 { margin-bottom: 0.45em; }
[data-skin='harbor'] .hero-image {
  background:
    linear-gradient(90deg,
      color-mix(in srgb, var(--hero-ink) 94%, transparent) 0%,
      color-mix(in srgb, var(--hero-ink) 84%, transparent) 42%,
      color-mix(in srgb, var(--hero-ink) 48%, transparent) 64%,
      color-mix(in srgb, var(--hero-ink) 16%, transparent) 82%,
      transparent 96%),
    var(--hero-img) center / cover no-repeat;
}
/* Hero label: plain bold line with a status dot, not a glass pill. */
[data-skin='harbor'] .hero-badge {
  background: none;
  border: 0;
  padding: 0;
  font-size: 1rem;
  font-weight: 600;
  margin-bottom: 1.1rem;
}
[data-skin='harbor'] .hero-image .hero-badge {
  background: none;
  border: 0;
  color: var(--color-heading-alt);
}
[data-skin='harbor'] .hero-badge-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: none;
  background: var(--color-secondary);
}
[data-skin='harbor'] .hero-stats { gap: 0.85rem; margin-top: 2.25rem; }
[data-skin='harbor'] .stat-tile { border-radius: var(--radius-card); }
/* The credential line is 18px/600 informational text, so it needs 4.5:1.
   On a service-area page the hero is `hero hero-compact` with no photo, so
   this text lands on a flat --color-bg-alt. Neither --color-secondary (worst
   2.25:1) nor base's --color-accent (worst 3.33:1) clears AA there across the
   six presets in both themes, so it takes the heading token, which the palette
   contract guarantees against bg_alt (worst 12.80:1). Over a photo it takes
   heading-alt against the ink scrim instead (worst 5.11:1). */
[data-skin='harbor'] .hero-cred { color: var(--color-heading); }
[data-skin='harbor'] .hero-image .hero-cred { color: var(--color-heading-alt); }

/* --------------------------------------------------------------- chrome --
   Nav sits at 5rem desktop / 4.5rem mobile with a hairline rule. */

[data-skin='harbor'] .site-header { border-bottom-color: var(--color-border-light); }
[data-skin='harbor'] .header-row { min-height: var(--nav-height); }
[data-skin='harbor'] .site-nav a { font-weight: 500; }
[data-skin='harbor'] .brand-logo { max-height: 3rem; }

/* ------------------------------------------------------------- buttons --
   10px corners, accent-tinted drop, a 1px hover rise and nothing else. */

[data-skin='harbor'] .btn {
  border-radius: var(--radius-button);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.4;
  padding: 0.85em 1.5em;
  transition: background var(--motion), color var(--motion),
    border-color var(--motion), box-shadow var(--motion), transform var(--motion);
}
[data-skin='harbor'] .btn-lg { padding: 1.05em 2.35em; font-size: 1rem; }
[data-skin='harbor'] .btn-primary { box-shadow: var(--shadow-button); }
[data-skin='harbor'] .btn-primary:hover {
  box-shadow: var(--shadow-button-hover);
  transform: translateY(-1px);
}
[data-skin='harbor'] .btn-outline:hover,
[data-skin='harbor'] .btn-inverse:hover { transform: translateY(-1px); }
/* Forward arrow on the page-level calls to action only (never on a phone
   number or a glass secondary). */
[data-skin='harbor'] .btn-primary.btn-lg::after,
[data-skin='harbor'] .btn-outline.btn-lg::after {
  content: '\2192';
  margin-left: 0.65em;
  font-weight: 400;
}
[data-skin='harbor'] .btn-glass {
  border-radius: var(--radius-button);
  box-shadow: none;
}

/* -------------------------------------------------------------- ground --
   Alternating sections take a soft vertical wash instead of a flat fill. */

[data-skin='harbor'] section { padding: var(--section-pad) 0; }
[data-skin='harbor'] .intro-section { padding-bottom: 1rem; }
[data-skin='harbor'] .services-grid-section,
[data-skin='harbor'] .areas-grid-section,
[data-skin='harbor'] .reviews,
[data-skin='harbor'] .credentials,
[data-skin='harbor'] .calc-embed,
[data-skin='harbor'] .rich-section:nth-of-type(even) {
  /* Symmetric wash: the two ends match, so back-to-back alt sections meet
     without a visible seam. */
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--color-bg-alt) 58%, var(--color-bg)) 0%,
    var(--color-bg-alt) 50%,
    color-mix(in srgb, var(--color-bg-alt) 58%, var(--color-bg)) 100%);
}
[data-skin='harbor'] .section-intro { max-width: 40rem; }

/* --------------------------------------------------------------- cards --
   4px corners, one flat shadow, no hover lift. Images share the radius. */

[data-skin='harbor'] .card {
  border-top: 0;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  transition: box-shadow var(--motion);
}
[data-skin='harbor'] .card:hover {
  transform: none;
  box-shadow: var(--shadow-card);
}
/* Wider crop than base's 3/2, since the reference's cards are image-led bands. */
[data-skin='harbor'] .card-img {
  aspect-ratio: 16 / 9;
  border-radius: var(--radius-image) var(--radius-image) 0 0;
}
[data-skin='harbor'] .card-img-placeholder {
  background: linear-gradient(150deg,
    color-mix(in srgb, var(--color-accent) 90%, black),
    color-mix(in srgb, var(--color-accent) 55%, var(--color-secondary)));
  opacity: 1;
}
[data-skin='harbor'] .card-body { padding: 1.4rem 1.5rem 1.6rem; }
[data-skin='harbor'] .card-body h3 { margin-bottom: 0.45em; }
[data-skin='harbor'] .card-cta { margin-top: 0.3rem; display: inline-block; }
[data-skin='harbor'] .icon-badge {
  border-radius: var(--radius-card);
  background: color-mix(in srgb, var(--color-accent) 10%, var(--color-bg));
}
/* -------------------------------------------------- service tiles ------
   Harbor takes the photo-tile variant of ServicesGrid: the picture fills the
   whole card, the service name is laid over it bottom-left, and there is no
   icon chip, blurb or "learn more" line on the tile face. The scrim stops
   below are OURS, not the reference's: the reference's resting gradient
   reaches only 38% ink at 58% of the tile height, which puts white type over
   a bright photo at 3.5:1 in the worst of our twelve palette combinations.
   Ours holds 76% from 58% down, which is 4.85:1 in that same worst case
   (working shown in docs/design-reference/checklist-harbor.md). */

[data-skin='harbor'] .card-grid-tiles {
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1.25rem;
}
[data-skin='harbor'] .card-tile {
  position: relative;
  isolation: isolate;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--hero-ink);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
/* Scrim. Sits above the picture and below the copy via the tile's own
   stacking context, so no wrapper element is needed. */
[data-skin='harbor'] .card-tile::after {
  content: '';
  position: absolute;
  z-index: -1;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    color-mix(in srgb, var(--hero-ink) 8%, transparent) 0%,
    color-mix(in srgb, var(--hero-ink) 18%, transparent) 30%,
    color-mix(in srgb, var(--hero-ink) 76%, transparent) 58%,
    color-mix(in srgb, var(--hero-ink) 94%, transparent) 100%);
}
[data-skin='harbor'] .card-tile-img {
  position: absolute;
  z-index: -2;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: inherit;
  transition: transform 420ms ease;
}
/* Without a photo the tile fills with the brand ramp instead of an empty
   frame, so a service with no image still reads as a designed panel. */
[data-skin='harbor'] .card-tile-img.card-img-placeholder { aspect-ratio: auto; }
[data-skin='harbor'] .card-tile-body {
  position: relative;
  z-index: 1;
  display: flex;
  flex: 1;
  min-height: 100%;
  flex-direction: column;
  justify-content: flex-end;
  padding: clamp(1.25rem, 3vw, 1.75rem);
}
[data-skin='harbor'] .card-tile-body h3 {
  margin: 0;
  color: var(--color-heading-alt);
  transition: transform var(--motion);
}
[data-skin='harbor'] .card-tile:hover .card-tile-body h3,
[data-skin='harbor'] .card-tile:focus-visible .card-tile-body h3 {
  transform: translateY(-0.15rem);
}
[data-skin='harbor'] .card-tile:hover img.card-tile-img { transform: scale(1.05); }
/* The tile clips its own overflow, so the focus ring is drawn inside it. */
[data-skin='harbor'] .card-tile:focus-visible {
  outline: 2px solid var(--color-heading-alt);
  outline-offset: -4px;
}

@media (max-width: 900px) {
  [data-skin='harbor'] .card-grid-tiles { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  [data-skin='harbor'] .card-grid-tiles { grid-template-columns: 1fr; }
}
@media (prefers-reduced-motion: reduce) {
  [data-skin='harbor'] .card-tile-img,
  [data-skin='harbor'] .card-tile-body h3 { transition: none; }
  [data-skin='harbor'] .card-tile:hover img.card-tile-img,
  [data-skin='harbor'] .card-tile:hover .card-tile-body h3,
  [data-skin='harbor'] .card-tile:focus-visible .card-tile-body h3 { transform: none; }
}

[data-skin='harbor'] .whyus-img,
[data-skin='harbor'] .gallery-grid figure,
[data-skin='harbor'] .coverage-card,
[data-skin='harbor'] .hours-card,
[data-skin='harbor'] .review-card {
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
[data-skin='harbor'] .gallery-grid figure { border: 0; }
[data-skin='harbor'] .gallery-grid figure:hover img { transform: none; }
[data-skin='harbor'] .coverage-card { border-color: var(--color-border-light); }

/* ------------------------------------------------------------- reviews --
   Stars stay the universal five-star amber; the card itself goes flat. */

[data-skin='harbor'] .review-card { padding: 1.5rem 1.6rem; }
[data-skin='harbor'] .stars { color: #d99a06; }
[data-skin='harbor'] .stat-suffix-star { color: #d99a06; }
[data-skin='harbor'] .reviews-subline { font-weight: 500; }
[data-skin='harbor'] .marquee-track { align-items: flex-start; }
[data-skin='harbor'] .reviews-grid { align-items: start; }

/* --------------------------------------------------------------- lists --
   Square area tiles and squared credential/chip pills keep the geometry
   consistent with the flat surfaces. */

[data-skin='harbor'] .area-links a {
  border-radius: 0;
  border-color: var(--color-border-light);
  box-shadow: none;
  padding: 0.85rem 1.1rem;
  font-weight: 600;
}
[data-skin='harbor'] .area-links a:hover { box-shadow: var(--shadow-card); }
[data-skin='harbor'] .badge,
[data-skin='harbor'] .chip { border-radius: var(--radius-card); }
[data-skin='harbor'] .badge:hover { transform: none; box-shadow: var(--shadow-card); }
/* The sparkle glyph keeps base's accent: secondary drops to 2.43:1 on the
   badge's --color-bg ground, where accent is guaranteed at least 3:1. */

/* ------------------------------------------------------------- process --
   Centred header and steps; the number becomes a square tile. */

[data-skin='harbor'] .process-section { text-align: center; }
[data-skin='harbor'] .process-section .section-intro { margin-inline: auto; }
[data-skin='harbor'] .process-steps { gap: 2rem; margin-top: 2.5rem; }
[data-skin='harbor'] .step-num {
  width: 2.6rem;
  height: 2.6rem;
  border-radius: var(--radius-card);
  font-family: var(--font-heading);
  margin-bottom: 0.9rem;
}

/* ----------------------------------------------------------------- faq --
   Filled panels with a plus/minus affordance rather than hairline rows. */

[data-skin='harbor'] .faq {
  background: var(--color-bg-alt);
  border-bottom: 0;
  border-radius: var(--radius-card);
  padding: 0.35rem 1.3rem;
  margin-bottom: 0.7rem;
}
[data-skin='harbor'] .faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  list-style: none;
  padding: 0.85rem 0;
}
[data-skin='harbor'] .faq summary::-webkit-details-marker { display: none; }
[data-skin='harbor'] .faq summary::after {
  content: '+';
  font-size: 1.4rem;
  font-weight: 400;
  line-height: 1;
  color: var(--color-accent);
  flex: none;
}
[data-skin='harbor'] .faq[open] summary::after { content: '\2212'; }
[data-skin='harbor'] .faq p { padding-bottom: 0.9rem; }

/* ----------------------------------------------------------- financing --
   Square panel with the accent kept as a left edge. */

[data-skin='harbor'] .financing .container-narrow {
  border-radius: 0;
  border-color: var(--color-border-light);
  border-left: 4px solid var(--color-secondary);
}

/* --------------------------------------------------------- calc embed --
   Quiet hairline frame in place of the gradient glow ring. */

[data-skin='harbor'] .calc-frame-wrap {
  background: var(--color-border-light);
  padding: 1px;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
[data-skin='harbor'] .calc-frame-wrap iframe { border-radius: 3px; }

/* --------------------------------------------------- closing dark shell --
   The CTA band is a deep brand-inked panel; the footer rides up over it with
   a large top radius so the page closes on one rounded shell. */

[data-skin='harbor'] .cta-band {
  background: linear-gradient(135deg,
    var(--hero-ink),
    color-mix(in srgb, var(--color-bg-dark) 92%, var(--color-accent)));
  padding-bottom: calc(var(--section-pad) + var(--shell-radius));
}
[data-skin='harbor'] .cta-band h2 { margin-bottom: 0.5em; }
[data-skin='harbor'] .cta-actions { margin-top: 2rem; }
[data-skin='harbor'] .site-footer {
  position: relative;
  z-index: 1;
  border-radius: var(--shell-radius) var(--shell-radius) 0 0;
  margin-top: calc(-1 * var(--shell-radius));
  padding-top: calc(3rem + var(--shell-radius));
}
[data-skin='harbor'] .footer-brand { font-size: 1.2rem; }
[data-skin='harbor'] .footer-head { color: var(--color-heading-alt); }

/* -------------------------------------------------------- trust band --
   The proof strip is ours; the reference has no equivalent, and as a thin
   dark bar of tick glyphs it read as a bolt-on. Rebuilt here in the
   reference's own proof language: a full band on the same ink as the hero
   scrim and the closing shell, square, on the band rhythm the reference uses
   for a proof row, each fact opening with the skin's short accent bar, the
   same motif that opens every section on the page. Ticks and the vertical
   hairline dividers go; the reference separates with space, not rules.

   --trust-accent lifts --color-secondary toward the near-white heading token
   so the bar clears the 3:1 non-text bar on ink (worst of twelve 3.56:1;
   raw --color-secondary is 2.10:1 on that ground). */

[data-skin='harbor'] .trustbar {
  --trust-accent: color-mix(in srgb, var(--color-secondary) 70%, var(--color-heading-alt));
  background: var(--hero-ink);
  border-top: 1px solid color-mix(in srgb, var(--color-heading-alt) 14%, transparent);
  border-radius: 0;
  padding: clamp(1.75rem, 4vw, 2.5rem) 0;
}
[data-skin='harbor'] .trustbar-row {
  flex-direction: row;
  align-items: flex-start;
  justify-content: flex-start;
  gap: 1.5rem;
}
[data-skin='harbor'] .trustbar-item {
  flex: 1 1 11rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.8rem;
  padding: 0;
  color: var(--color-heading-alt);
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: 0;
}
[data-skin='harbor'] .trustbar-item + .trustbar-item { border-left: 0; }
[data-skin='harbor'] .trustbar-item::before {
  content: '';
  flex: none;
  width: var(--accent-line-w);
  height: var(--accent-line-h);
  border-radius: 999px;
  background: var(--trust-accent);
}

/* -------------------------------------------------------- sticky bar --- */

[data-skin='harbor'] .sticky-cta .btn {
  border-radius: var(--radius-button);
  padding: 0.55rem 1rem;
  font-size: 0.9rem;
  white-space: nowrap;
}
/* The bar is dark, so its glass button needs the light-ground treatment
   (base styles .btn-glass for a light page). */
[data-skin='harbor'] .sticky-cta .btn-glass {
  background: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.18);
  color: var(--color-heading-alt);
}
[data-skin='harbor'] .sticky-cta .btn-glass:hover { background: rgba(255, 255, 255, 0.16); }
[data-skin='harbor'] .sticky-cta-place { font-size: 0.8rem; white-space: nowrap; }

/* ------------------------------------------------------------- mobile --- */

@media (max-width: 820px) {
  [data-skin='harbor'] .header-row { min-height: var(--nav-height-mobile); gap: 0.9rem; }
  [data-skin='harbor'] .site-nav { top: var(--nav-height-mobile); }
  /* Our .btn padding is larger than base's, so restate base's compact
     header button here rather than letting the skin re-inflate it. */
  [data-skin='harbor'] .header-actions .btn-primary {
    padding: 0.55em 0.95em;
    font-size: 0.92rem;
  }
  [data-skin='harbor'] .wordmark { font-size: 1.1rem; }
}

@media (max-width: 720px) {
  /* Stacked scrim: the copy sits over the whole frame at this width, so the
     gradient runs top-to-bottom instead of left-to-right. */
  /* Reference stacks at 72% -> 82%; ours starts at 78% because our palettes
     span six brand colors and the copy runs the full width here. 78% is the
     floor at which the near-white type clears AA on every preset even over a
     white photo (see docs/design-reference/checklist-harbor.md). */
  [data-skin='harbor'] .hero-image {
    background:
      linear-gradient(180deg,
        color-mix(in srgb, var(--hero-ink) 78%, transparent) 0%,
        color-mix(in srgb, var(--hero-ink) 88%, transparent) 100%),
      var(--hero-img) center / cover no-repeat;
  }
  [data-skin='harbor'] .hero-content { max-width: none; }
  [data-skin='harbor'] .hero-actions .btn { width: 100%; text-align: center; }
}

@media (max-width: 640px) {
  /* Phone-width header carries the mark and the menu only, because the hero
     CTA and the sticky bottom bar already cover the call to action. */
  [data-skin='harbor'] .header-actions .btn-primary { display: none; }
  [data-skin='harbor'] .wordmark { font-size: 1.15rem; }
  [data-skin='harbor'] .card-body { padding: 1.2rem 1.25rem 1.4rem; }
  [data-skin='harbor'] .btn-lg { padding: 1em 1.6em; }
  /* Two columns rather than base's centred stack: four facts in a tall
     single file pushes the rest of the page down on a phone. */
  [data-skin='harbor'] .trustbar-row { gap: 1.25rem 1rem; }
  [data-skin='harbor'] .trustbar-item {
    flex: 0 1 calc(50% - 0.5rem);
    font-size: 0.95rem;
    gap: 0.6rem;
  }
}

/* Skin: sage. Quiet editorial: serif display on a warm paper ground, even 8px
   geometry, gentle heading-tinted shadows, sans subheads, and a light footer.
   Calibrated to the measured Lightning default (R1 in
   the parity notes (PM docs) and re-measured
   live on 2026-08-12 against that reference site. Geometry and art direction
   only; every color flows from the derived palette tokens except the two
   neutral paper tints declared below, which are the skin's warm-ground recipe.
   Copied to src/generated/skin.css by the build orchestrator.

   Nothing here is lifted from the reference. Every selector is one of our own
   class names from docs/design-reference/skin-hooks.md and every rule is
   written fresh. What is shared is the measured NUMBERS (radii, shadow
   geometry, gradient stops, type scale, section rhythm, nav height).
   Deviations from the task brief's starting values, the corrections the live
   reference forced on the reference pack, and the contrast work behind every
   new color pairing are recorded in docs/design-reference/checklist-sage.md. */

[data-skin='sage'] {
  /* One radius for everything: cards, buttons, images, panels, frames. */
  --radius: 8px;
  --radius-card: 8px;
  --radius-button: 8px;
  --radius-image: 8px;

  /* Measured: 1216px content inside a 1280px frame, 96px section rhythm,
     73px sticky nav (72px plus a hairline). */
  --container-max: 80rem;
  --container-pad: clamp(1rem, 2.5vw, 2rem);
  --section-pad: clamp(3rem, 8vw, 6rem);
  --nav-height: 4.5rem;
  --nav-height-mobile: 4rem;
  --grid-gap: 1.25rem;
  --motion: 180ms ease;

  /* Shadows are heading-tinted and deliberately soft: nothing here reads as a
     drop shadow, only as a page that is slightly off the paper. */
  --shadow-card: 0 0.18rem 0.55rem color-mix(in srgb, var(--color-heading) 7%, transparent);
  --shadow-card-hover: 0 0.45rem 1rem color-mix(in srgb, var(--color-heading) 10%, transparent);
  --shadow-button: 0 0.45rem 1rem color-mix(in srgb, var(--color-heading) 12%, transparent);
  --shadow-button-hover: 0 0.7rem 1.35rem color-mix(in srgb, var(--color-heading) 16%, transparent);

  /* Warm ground. The derived palette pulls both grounds from the brand hue, so
     a blue brand lands on a cool white and a green one on a pale mint. This
     skin's defining read is warm paper, so both grounds are mixed toward a
     neutral warm tint: cream for the page, a warm gray for the alternating
     band. 55/45 is the strongest mix that still lets the brand hue through;
     the WCAG cost is measured in checklist-sage.md (worst case across the six
     presets in both themes: body 7.47:1, heading 12.02:1, both well over AA). */
  --paper: #F5EFE2;
  --paper-alt: #E4E1D8;
  --ground: color-mix(in srgb, var(--color-bg) 55%, var(--paper));
  --ground-alt: color-mix(in srgb, var(--color-bg-alt) 55%, var(--paper-alt));

  /* Brand-tinted ink for the small label text this skin sets in the brand
     color (eyebrows at 16px/700, card calls to action at 16px/600, link hover).
     All of it is below the WCAG large-text threshold, so it needs 4.5:1, and
     --color-accent alone is only guaranteed at 3:1 on the page ground (worst
     measured 3.68:1 across the twelve preset and theme combinations). This
     blend clears 5.39:1 in the worst of those twelve. */
  --label-ink: color-mix(in srgb, var(--color-accent) 70%, var(--color-heading));

  /* Photo scrim ink. The reference uses its flat near-black rather than a
     brand-tinted one, so ours takes bg-dark untinted. */
  --hero-ink: var(--color-bg-dark);

  /* Universal five-star amber, deliberately not brand-colored. */
  --star: #d99a06;
}

/* A cream tint only makes sense on a light ground: mixed into a dark theme's
   page it lifts the ground toward mid gray and eats the contrast the palette
   earned for the light type on it. A dark theme therefore keeps the derived
   grounds exactly as they come out of derive_palette.
   Declaring the untinted values LAST is also what keeps this file readable to
   tools/check_skin_contrast.py, which resolves a skin's custom properties once
   per file with no theme scoping and takes the final declaration. It therefore
   checks every sage text pair against the raw derived grounds, which is the
   true value in a dark theme and the conservative one in a light theme: the
   cream mix moves the light ground slightly DARKER (97.5% to about 95.6%
   lightness), so every dark-on-light pair on the shipped page scores at or
   above what the guard measures. The tinted numbers are in
   checklist-sage.md. */
html[data-theme='dark'][data-skin='sage'] {
  --ground: var(--color-bg);
  --ground-alt: var(--color-bg-alt);
}

/* ---------------------------------------------------------------- type --
   Playfair Display ships 400/600/700 and Inter 400/500/600 (data/fonts.json),
   so nothing below asks for a weight the pairing cannot render. The reference's
   loudest signal is the split: serif for the display sizes (h1, h2) and the
   body face for everything smaller, including h3. Its h3 computes at weight
   800, which Inter does not ship here, so ours takes 600, the honest maximum. */

[data-skin='sage'] body {
  font-size: var(--oc-owner-font-body-size, 1.125rem);
  font-weight: var(--oc-owner-font-body-weight, 500);
  line-height: 1.6;
}
/* 2026-09-05 (fix/theme-tokens-apply): h1/h2 font-weight moved off the
   shared rule below into their own font-size rules so each reads its own
   --oc-owner-font-<el>-weight; h3 split out of the h3+h4 rule the same way.
   h4 gets its own copy of the unwrapped literals, untouched. */
[data-skin='sage'] h1,
[data-skin='sage'] h2 {
  letter-spacing: normal;
  line-height: 1.08;
}
[data-skin='sage'] h1 { font-size: var(--oc-owner-font-h1-size, clamp(30px, 4.4vw, 58px)); font-weight: var(--oc-owner-font-h1-weight, 700); }
[data-skin='sage'] h2 { font-size: var(--oc-owner-font-h2-size, clamp(28px, 3vw, 36px)); font-weight: var(--oc-owner-font-h2-weight, 700); }
[data-skin='sage'] h3 {
  font-family: var(--font-body);
  font-size: var(--oc-owner-font-h3-size, 1.25rem);
  font-weight: var(--oc-owner-font-h3-weight, 600);
  letter-spacing: normal;
  line-height: 1.16;
}
[data-skin='sage'] h4 {
  font-family: var(--font-body);
  font-size: 1.25rem;
  font-weight: 600;
  letter-spacing: normal;
  line-height: 1.16;
}
[data-skin='sage'] .lead,
[data-skin='sage'] .subhead { font-size: 1.25rem; line-height: 1.6; }
[data-skin='sage'] .card-body p { font-size: 1rem; line-height: 1.62; }
/* Playfair tops out at 700, so base's 800 would be synthesised. */
[data-skin='sage'] .wordmark { font-weight: 700; letter-spacing: normal; }
[data-skin='sage'] .stat-value { font-weight: 700; }

/* -------------------------------------------------------------- ground --
   Warm paper page, warm gray alternating band, wide quiet container. */

[data-skin='sage'] body { background: var(--ground); }
/* :not() keeps this off the blocks that combine .container with
   .container-narrow, which are meant to stay at their reading measure. */
[data-skin='sage'] .container:not(.container-narrow) {
  max-width: var(--container-max);
  padding-inline: var(--container-pad);
}
[data-skin='sage'] .container-narrow { padding-inline: var(--container-pad); }
[data-skin='sage'] section { padding: var(--section-pad) 0; }
/* The trust strip is a <section> too, so the rhythm above would inflate a
   0.85rem band into a 96px one. */
[data-skin='sage'] .trustbar { padding: 0.85rem 0; }
[data-skin='sage'] .intro-section { padding-bottom: 1rem; }
/* Three service cards to a row and four area tiles, as the reference lays
   them out; base's 17rem and 13rem tracks give five and six at this width. */
[data-skin='sage'] .card-grid { grid-template-columns: repeat(auto-fill, minmax(20rem, 1fr)); gap: var(--grid-gap); }
[data-skin='sage'] .area-links { grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); }
[data-skin='sage'] .section-intro { max-width: 42rem; margin-bottom: 2rem; }
/* The services grid keeps the page ground, as the reference's does; the
   alternating blocks take the warm gray band. Base's banding selectors are
   mirrored exactly so the two rules can never disagree about which section is
   which. */
[data-skin='sage'] .areas-grid-section,
[data-skin='sage'] .reviews,
[data-skin='sage'] .credentials,
[data-skin='sage'] .calc-embed,
[data-skin='sage'] .rich-section:nth-of-type(even) { background: var(--ground-alt); }
[data-skin='sage'] .services-grid-section { background: var(--ground); }

/* ------------------------------------------------------------ eyebrows --
   Small spaced-free caps above each heading, in brand-tinted ink, with no
   underline bar: the accent line is the Pacific reference's signature, and
   this one deliberately does without. */

[data-skin='sage'] .eyebrow {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-body);
  font-size: var(--oc-owner-font-eyebrow-size, 1rem);
  font-weight: var(--oc-owner-font-eyebrow-weight, 700);
  letter-spacing: 0;
  text-transform: uppercase;
  color: var(--label-ink);
  margin-bottom: 0.75rem;
}

/* ---------------------------------------------------------------- hero --
   Full-bleed photo, copy left, an ink wash that is dense under the text and
   opens toward the empty right-hand side, plus a light vertical wash so the
   top and bottom edges never blow out. Stop positions follow the reference;
   the alpha values are raised where our copy column runs wider than theirs
   (they park a form card over the right half; ours leaves the photo open).
   The floor is set by contrast, not taste: over a pure-white photo the
   near-white heading token needs an effective ink alpha of 0.655 to clear
   4.5:1 in the worst of the twelve preset and theme combinations, and the
   stops below hold 0.82 or better across the whole copy column. */

[data-skin='sage'] .hero {
  background: var(--ground-alt);
  text-align: left;
  padding: clamp(4rem, 9vw, 6rem) 0;
}
[data-skin='sage'] .hero-compact { padding: clamp(2.5rem, 6vw, 4rem) 0; }
[data-skin='sage'] .hero-image {
  background:
    linear-gradient(90deg,
      color-mix(in srgb, var(--hero-ink) 94%, transparent) 0%,
      color-mix(in srgb, var(--hero-ink) 88%, transparent) 34%,
      color-mix(in srgb, var(--hero-ink) 74%, transparent) 60%,
      color-mix(in srgb, var(--hero-ink) 36%, transparent) 82%,
      color-mix(in srgb, var(--hero-ink) 12%, transparent) 100%),
    linear-gradient(180deg,
      color-mix(in srgb, var(--hero-ink) 32%, transparent) 0%,
      color-mix(in srgb, var(--hero-ink) 54%, transparent) 100%),
    var(--hero-img) center / cover no-repeat;
}
[data-skin='sage'] .hero-content { max-width: 46rem; }
[data-skin='sage'] .hero h1 { margin-bottom: 0; }
[data-skin='sage'] .hero .subhead {
  margin: 1.25rem 0 0;
  max-width: 39rem;
}
/* Over a scrimmed photo base tints sub-copy with body-alt, which is only
   contrast-guaranteed against a flat bg-dark. The near-white heading token is
   the safe pair over an unknown photograph. */
[data-skin='sage'] .hero-image .subhead,
[data-skin='sage'] .hero-image .lead,
[data-skin='sage'] .hero-image .breadcrumbs { color: var(--color-heading-alt); }
[data-skin='sage'] .hero-actions { justify-content: flex-start; margin-top: 2rem; }
[data-skin='sage'] .hero-stats { justify-content: flex-start; margin-top: 2rem; }
/* The proof line is a plain rating row, not a glass pill. */
[data-skin='sage'] .hero-badge {
  background: none;
  border: 0;
  padding: 0;
  border-radius: 0;
  gap: 0.45rem;
  font-size: 1rem;
  font-weight: 500;
  margin-bottom: 1rem;
  color: var(--color-heading);
}
[data-skin='sage'] .hero-image .hero-badge {
  background: none;
  border: 0;
  color: var(--color-heading-alt);
}
[data-skin='sage'] .hero-badge-dot {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  flex: none;
  background: var(--color-accent);
}
/* The service-area credential line is 18px at weight 600, below the WCAG
   large-text threshold on both counts, so it needs the full 4.5:1. On a
   photoless area hero it sits on a flat pale ground where accent bottoms out
   near 3:1; the heading token is contract-guaranteed there. */
[data-skin='sage'] .hero-cred { color: var(--color-heading); }
[data-skin='sage'] .hero-image .hero-cred { color: var(--color-heading-alt); }
[data-skin='sage'] .stat-tile { border-radius: var(--radius-card); }
[data-skin='sage'] .stat-suffix-star { color: var(--star); }

/* --------------------------------------------------------------- chrome --
   Sticky 4.5rem bar on the page ground with a hairline rule under it. */

[data-skin='sage'] .site-header {
  background: color-mix(in srgb, var(--ground) 96%, transparent);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border-bottom-color: var(--color-border-light);
}
[data-skin='sage'] .header-row { min-height: var(--nav-height); }
[data-skin='sage'] .site-nav { gap: 1.6rem; }
[data-skin='sage'] .site-nav a {
  font-size: 1rem;
  font-weight: 600;
  color: var(--color-heading);
}
[data-skin='sage'] .site-nav a:hover,
[data-skin='sage'] .site-nav a[aria-current='page'] { color: var(--label-ink); }
[data-skin='sage'] .brand-logo { max-height: 2.8rem; }

/* ------------------------------------------------------------- buttons --
   8px corners, 16px labels at weight 600, one soft heading-tinted drop and a
   1px rise on hover. Page-level primaries carry a forward arrow, as the
   reference's do; phone links and secondaries do not. */

[data-skin='sage'] .btn {
  border-radius: var(--radius-button);
  border-width: 1px;
  font-family: var(--font-body);
  font-size: 1rem;
  font-weight: 600;
  line-height: 1.2;
  padding: 0.8rem 1.25rem;
  transition: background var(--motion), color var(--motion),
    border-color var(--motion), box-shadow var(--motion), transform var(--motion);
}
[data-skin='sage'] .btn-lg { padding: 0.9rem 1.5rem; font-size: 1rem; }
[data-skin='sage'] .btn-primary { box-shadow: var(--shadow-button); }
[data-skin='sage'] .btn-primary:hover {
  box-shadow: var(--shadow-button-hover);
  transform: translateY(-1px);
}
[data-skin='sage'] .btn-primary.btn-lg::after {
  content: '\2192';
  margin-left: 0.6em;
  font-weight: 400;
}
[data-skin='sage'] .btn-inverse:hover,
[data-skin='sage'] .btn-outline:hover { transform: translateY(-1px); }
/* Secondary on a light ground: no fill, a hairline in heading ink, heading
   label. Over the hero photo base already supplies the light-on-dark variant,
   so only the corner radius is restated there. */
[data-skin='sage'] .btn-glass {
  background: transparent;
  border: 1px solid var(--color-heading);
  border-radius: var(--radius-button);
  color: var(--color-heading);
  box-shadow: none;
}
[data-skin='sage'] .btn-glass:hover {
  background: color-mix(in srgb, var(--color-heading) 8%, transparent);
}
/* Base's own photo-ground variant of .btn-glass ties with the rule above on
   specificity and loses on order, so the light-on-dark treatment is restated
   here at a weight that wins. */
[data-skin='sage'] .hero-image .btn-glass {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: var(--radius-button);
  color: var(--color-heading-alt);
}
[data-skin='sage'] .hero-image .btn-glass:hover { background: rgba(255, 255, 255, 0.16); }

/* --------------------------------------------------------------- cards --
   Page-ground fill, hairline border, 8px corners, one gentle shadow, a 2px
   lift and a slow image push on hover. Base's 3px accent cap is dropped: the
   reference has no colored rule on its cards. */

[data-skin='sage'] .card {
  background: var(--ground);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  transition: transform var(--motion), box-shadow var(--motion),
    border-color var(--motion);
}
[data-skin='sage'] .card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-card-hover);
  border-color: var(--color-border);
}
/* Wider crop than base's 3/2: the reference's card photograph is a band. */
[data-skin='sage'] .card-img {
  aspect-ratio: 16 / 9.5;
  transition: transform 320ms ease;
}
[data-skin='sage'] .card:hover .card-img { transform: scale(1.04); }
/* An empty photo slot stays quiet here rather than becoming a saturated brand
   panel: the reference fills its missing images with a plain alternate-ground
   block, and six loud gradients would fight everything else on the page. */
[data-skin='sage'] .card-img-placeholder,
[data-skin='sage'] .whyus-img-placeholder {
  background: linear-gradient(160deg,
    color-mix(in srgb, var(--color-accent) 12%, var(--ground-alt)),
    var(--ground-alt));
  opacity: 1;
}
/* Title, blurb, link: the blurb takes the slack so every card in a row lands
   its call to action on the same line, as the reference's do. */
[data-skin='sage'] .card-body {
  display: grid;
  grid-template-rows: auto 1fr auto;
  gap: 0.72rem;
  padding: 1.35rem;
  flex: 1;
}
[data-skin='sage'] .card-body h3,
[data-skin='sage'] .card-body p { margin: 0; }
/* The card's call to action is a small spaced cap with a forward arrow. */
[data-skin='sage'] .card-cta {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  width: -moz-fit-content;
  width: fit-content;
  color: var(--label-ink);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1;
  text-transform: uppercase;
}
/* No arrow pseudo-element here: ServicesGrid.astro already ships one inside
   the link text, and adding a second is exactly the bug the first visual pass
   caught. */
[data-skin='sage'] .icon-badge {
  border-radius: var(--radius-card);
  background: color-mix(in srgb, var(--color-accent) 12%, var(--ground));
}
/* Service cards are photograph, title, blurb, link. The reference carries no
   icon chip inside them and the badge is purely decorative, so it steps out of
   the card here (it still appears wherever else base uses it). */
[data-skin='sage'] .card .icon-badge { display: none; }
/* Photography everywhere else takes the same hairline-and-shadow frame the
   reference puts around its about and process images. */
[data-skin='sage'] .whyus-img,
[data-skin='sage'] .gallery-grid figure,
[data-skin='sage'] .coverage-card,
[data-skin='sage'] .hours-card,
[data-skin='sage'] .review-card {
  border-radius: var(--radius-image);
  border: 1px solid var(--color-border-light);
  box-shadow: var(--shadow-card);
}
[data-skin='sage'] .whyus-img { aspect-ratio: 10 / 9; }
[data-skin='sage'] .coverage-card { background: var(--ground); }
[data-skin='sage'] .hours-card { background: var(--ground-alt); }
[data-skin='sage'] .calc-frame-wrap iframe { background: var(--ground); }

/* ------------------------------------------------------------- reviews --
   Quiet cards on the warm band, universal amber stars, round avatar kept. */

[data-skin='sage'] .review-card {
  background: var(--ground);
  padding: 1.5rem 1.6rem;
}
[data-skin='sage'] .stars { color: var(--star); }
[data-skin='sage'] .reviews-subline { font-weight: 500; }
[data-skin='sage'] .avatar { background: color-mix(in srgb, var(--color-accent) 14%, var(--ground)); }
[data-skin='sage'] .marquee-track { align-items: flex-start; }
[data-skin='sage'] .reviews-grid { align-items: start; }

/* -------------------------------------------------------------- lists --
   Area tiles and credential pills take the 8px scale and the same hairline;
   checklist bullets get the reference's filled round check badge. */

[data-skin='sage'] .area-links a {
  background: var(--ground);
  border-color: var(--color-border-light);
  border-radius: var(--radius-card);
  box-shadow: none;
  padding: 0.8rem 1.05rem;
  font-weight: 600;
}
[data-skin='sage'] .area-links a:hover {
  border-color: var(--color-border);
  color: var(--label-ink);
  box-shadow: var(--shadow-card);
}
[data-skin='sage'] .badge {
  background: var(--ground);
  border-color: var(--color-border-light);
  border-radius: var(--radius-card);
}
[data-skin='sage'] .badge:hover {
  transform: none;
  border-color: var(--color-border);
  box-shadow: var(--shadow-card);
}
[data-skin='sage'] .chip { border-radius: var(--radius-card); }
[data-skin='sage'] .bullets li { padding-left: 2.3rem; }
[data-skin='sage'] .whyus-bullets li { padding-left: 2.3rem; }
[data-skin='sage'] .bullets li::before,
[data-skin='sage'] .whyus-bullets li::before {
  content: '\2713';
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 1.45rem;
  height: 1.45rem;
  border-radius: 50%;
  background: var(--color-accent);
  color: var(--color-on-accent);
  font-size: 0.78rem;
  font-weight: 700;
  box-shadow: 0 4px 12px color-mix(in srgb, var(--color-accent) 22%, transparent);
}
[data-skin='sage'] .bullets li::before { top: 0.45rem; }
[data-skin='sage'] .whyus-bullets li::before { top: 0.3rem; }

/* ------------------------------------------------------------- process --
   Centred header and steps with a large round number, the way the reference
   lays its process row out. */

[data-skin='sage'] .process-section { text-align: center; }
[data-skin='sage'] .process-section .section-intro { margin-inline: auto; }
[data-skin='sage'] .process-steps {
  gap: clamp(1.5rem, 4vw, 3rem);
  margin-top: 2.5rem;
}
[data-skin='sage'] .process-steps > li { text-align: center; }
[data-skin='sage'] .process-steps p { max-width: 30ch; margin-inline: auto; }
[data-skin='sage'] .step-num {
  width: 3.5rem;
  height: 3.5rem;
  border-radius: 50%;
  font-family: var(--font-heading);
  font-size: 1.25rem;
  margin-bottom: 1.1rem;
}

/* ----------------------------------------------------------------- faq --
   Hairline rows, question left, a plus that turns into a minus. No fill: the
   reference keeps this block as quiet as the rest of the page. */

[data-skin='sage'] .faq {
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
  padding: 0;
}
[data-skin='sage'] .faq + .faq { border-top: 0; }
[data-skin='sage'] .faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  list-style: none;
  padding: 1rem 0;
  transition: color var(--motion);
}
[data-skin='sage'] .faq summary::-webkit-details-marker { display: none; }
[data-skin='sage'] .faq summary:hover { color: var(--label-ink); }
[data-skin='sage'] .faq summary::after {
  content: '+';
  font-size: 1.4rem;
  font-weight: 400;
  line-height: 1;
  color: var(--label-ink);
  flex: none;
}
[data-skin='sage'] .faq[open] summary::after { content: '\2212'; }
[data-skin='sage'] .faq p { padding-bottom: 1rem; }

/* ----------------------------------------------------------- financing --
   Same panel at the 8px scale, hairline instead of the thick accent edge. */

[data-skin='sage'] .financing .container-narrow {
  background: var(--ground);
  border: 1px solid var(--color-border-light);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
[data-skin='sage'] .financing-partner { border-top-color: var(--color-border-light); }

/* ---------------------------------------------------------- calc embed --
   Hairline frame in place of base's gradient glow ring. */

[data-skin='sage'] .calc-frame-wrap {
  background: var(--color-border-light);
  padding: 1px;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
}
[data-skin='sage'] .calc-frame-wrap iframe { border-radius: 7px; }

/* ----------------------------------------------------- closing sequence --
   One ink slab at the end of the page (the trust strip and the call to
   action), then a LIGHT footer on the page ground closed by a hairline. The
   light footer is the single biggest thing the reference pack missed: the
   live reference's footer is its cream ground with a border-light rule on
   top, not the dark slab base.css assumes, and it is a large part of why the
   page reads quiet rather than corporate. */

[data-skin='sage'] .cta-band { padding: var(--section-pad) 0; }
[data-skin='sage'] .cta-band h2 { margin-bottom: 0.4em; }
[data-skin='sage'] .cta-band .eyebrow { color: var(--color-heading-alt); }
[data-skin='sage'] .cta-actions { margin-top: 2rem; }
[data-skin='sage'] .trustbar { border-top-color: color-mix(in srgb, var(--color-heading-alt) 20%, transparent); }
/* Base tints the strip's check marks with accent, which sinks toward 2:1 on
   the ink ground. The near-white heading token is the guaranteed pair there,
   and it keeps the strip as quiet as the rest of the page. */
[data-skin='sage'] .trustbar-item::before { color: var(--color-heading-alt); }

[data-skin='sage'] .site-footer {
  background: var(--ground);
  color: var(--color-body);
  border-top: 1px solid var(--color-border-light);
  padding: clamp(2.5rem, 6vw, 4rem) 0 1.75rem;
}
[data-skin='sage'] .footer-brand {
  color: var(--color-heading);
  font-size: 1.15rem;
}
[data-skin='sage'] .footer-head {
  color: var(--color-heading);
  font-family: var(--font-body);
  font-size: 1.125rem;
  font-weight: 700;
  margin-bottom: 0.75rem;
}
[data-skin='sage'] .footer-blurb,
[data-skin='sage'] .footer-hours { color: var(--color-body); }
[data-skin='sage'] .site-footer a { color: var(--color-body); font-size: 1rem; }
[data-skin='sage'] .site-footer a:hover { color: var(--label-ink); }
/* Base falls back to a white-alpha rule here, which is invisible on a light
   footer. */
[data-skin='sage'] .footer-legal { border-top-color: var(--color-border-light); }

/* ---------------------------------------------------------- sticky bar --
   The bar is dark, so its secondary button takes the light-on-dark treatment
   rather than the hairline used on the page. */

[data-skin='sage'] .sticky-cta .btn {
  border-radius: var(--radius-button);
  padding: 0.55rem 1rem;
  font-size: 0.9rem;
  box-shadow: none;
  white-space: nowrap;
}
[data-skin='sage'] .sticky-cta .btn-primary.btn-lg::after,
[data-skin='sage'] .sticky-cta .btn-primary::after { content: none; }
[data-skin='sage'] .sticky-cta .btn-glass {
  background: rgba(255, 255, 255, 0.1);
  border: 1px solid rgba(255, 255, 255, 0.18);
  color: var(--color-heading-alt);
}
[data-skin='sage'] .sticky-cta .btn-glass:hover { background: rgba(255, 255, 255, 0.16); }
[data-skin='sage'] .sticky-cta-place { font-size: 0.8rem; white-space: nowrap; }

/* ------------------------------------------------------------- mobile --- */

@media (max-width: 820px) {
  [data-skin='sage'] .header-row { min-height: var(--nav-height-mobile); gap: 0.9rem; }
  [data-skin='sage'] .site-nav {
    top: var(--nav-height-mobile);
    background: var(--ground);
    border-bottom-color: var(--color-border-light);
  }
  /* Our .btn padding is larger than base's, so the compact header button has
     to be restated here or the header overflows at phone widths. */
  [data-skin='sage'] .header-actions .btn-primary {
    padding: 0.5rem 0.85rem;
    font-size: 0.92rem;
    box-shadow: none;
  }
  [data-skin='sage'] .header-actions .btn-primary::after { content: none; }
}

@media (max-width: 720px) {
  /* Stacked scrim: at this width the copy sits over the whole frame, so the
     wash runs top to bottom. 80% at the top is the floor at which the
     near-white heading token clears AA over even a white photo in all twelve
     preset and theme combinations. */
  [data-skin='sage'] .hero-image {
    background:
      linear-gradient(180deg,
        color-mix(in srgb, var(--hero-ink) 80%, transparent) 0%,
        color-mix(in srgb, var(--hero-ink) 90%, transparent) 100%),
      var(--hero-img) center / cover no-repeat;
  }
  [data-skin='sage'] .hero-content { max-width: none; }
  [data-skin='sage'] .hero-actions .btn { width: 100%; text-align: center; }
}

@media (max-width: 640px) {
  /* Phone-width header carries the mark and the menu only: the hero call to
     action and the sticky bottom bar already cover the conversion path. */
  [data-skin='sage'] .header-actions .btn-primary { display: none; }
  [data-skin='sage'] .card-body { padding: 1.15rem 1.2rem 1.3rem; }
  [data-skin='sage'] .btn-lg { padding: 0.85rem 1.4rem; }
  [data-skin='sage'] .step-num { width: 3rem; height: 3rem; }
}

/* Skin: summit — navy-editorial, Gates-calibrated: serif-weight display type,
   resting card shadows, glass hero chrome, pill areas, blurred sticky header.
   Copied to src/generated/skin.css by the build orchestrator. */
:root { --radius: 14px; }

/* Type register */
/* 2026-09-05 (fix/theme-tokens-apply): font-weight split off h1/h2 into
   their own declarations so each reads --oc-owner-font-<el>-weight; the
   shared letter-spacing rule is untouched. */
[data-skin='summit'] h1, [data-skin='summit'] h2 { letter-spacing: -0.015em; }
[data-skin='summit'] h1 { font-weight: var(--oc-owner-font-h1-weight, 800); }
[data-skin='summit'] h2 { font-weight: var(--oc-owner-font-h2-weight, 800); font-size: var(--oc-owner-font-h2-size, clamp(2rem, 4.2vw, 2.75rem)); } /* base's 2.1rem cap reads small next to summit's display h1 */
[data-skin='summit'] .hero h1 { font-size: var(--oc-owner-font-h1-size, clamp(2.4rem, 5vw, 3.6rem)); line-height: 1.06; color: var(--color-heading-alt); }
[data-skin='summit'] .hero .h1-accent { color: color-mix(in srgb, var(--color-accent) 60%, white); }
[data-skin='summit'] .hero .hero-cred { color: color-mix(in srgb, var(--color-accent) 60%, white); }
/* On the flat bg-dark ground (no photo) this passes AA in all twelve
   preset/theme combos, worst case burgundy/light at 4.92:1. Over a photo
   the scrim can run close to bg-dark plus a sliver of the image showing
   through; against a near-white photo that drops burgundy/light to 4.38:1
   and charcoal/light to 4.49:1, both under the 4.5:1 this text needs at
   18px/600. heading-alt is already trusted against this same scrim by
   .hero h1 above and clears it comfortably (worst case 12.08:1). */
[data-skin='summit'] .hero-image .hero-cred { color: var(--color-heading-alt); }
[data-skin='summit'] .eyebrow { font-size: var(--oc-owner-font-eyebrow-size, 0.7rem); letter-spacing: 0.2em; }

/* Buttons: flat solid primary + glass secondary; large radius */
[data-skin='summit'] .btn { border-radius: 14px; font-weight: 600; }
[data-skin='summit'] .btn-lg { padding: 16px 32px; font-size: 0.95rem; }
[data-skin='summit'] .btn-primary::after { content: ' →'; }
[data-skin='summit'] .site-header .btn-primary { border-radius: 100px; }
[data-skin='summit'] .site-header .btn-primary::after { content: ''; }

/* Sticky blurred header */
[data-skin='summit'] .site-header {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--color-bg-dark) 88%, transparent);
  -webkit-backdrop-filter: blur(24px); backdrop-filter: blur(24px);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
[data-skin='summit'] .site-header a, [data-skin='summit'] .site-header .phone-link { color: var(--color-heading-alt); }
@supports not (backdrop-filter: blur(1px)) {
  [data-skin='summit'] .site-header { background: var(--color-bg-dark); }
}

/* Dark hero with photo overlay */
[data-skin='summit'] .hero { background: var(--color-bg-dark); color: var(--color-heading-alt); }
[data-skin='summit'] .hero-image {
  background-image: linear-gradient(color-mix(in srgb, var(--color-bg-dark) 78%, transparent),
    color-mix(in srgb, var(--color-bg-dark) 78%, transparent)), var(--hero-img);
  background-size: cover; background-position: center;
}
[data-skin='summit'] .hero .subhead { color: var(--color-body-alt); font-size: 1.06rem; line-height: 1.7; }

/* Cards: resting elevation, accent top border, lift on hover */
[data-skin='summit'] .card {
  border: 0; border-top: 3px solid var(--color-accent);
  border-radius: 18px;
  box-shadow: 0 2px 12px rgba(15, 23, 42, 0.06);
  transition: transform 0.35s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.35s cubic-bezier(0.4, 0, 0.2, 1),
    background-color 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
[data-skin='summit'] .card:hover { transform: translateY(-3px); box-shadow: 0 10px 28px rgba(15, 23, 42, 0.12); }

/* Service cards: icon-led, no thumbnail — matches the Gates-style card set
   exactly (icon badge, no image, no "Learn more" link, dark hover fill). */
[data-skin='summit'] .card-img { display: none; }
[data-skin='summit'] .card-cta { display: none; }
[data-skin='summit'] .card-body { padding: 1.75rem 1.5rem 2rem; }
[data-skin='summit'] .icon-badge {
  width: 48px; height: 48px; border-radius: 12px;
  background: color-mix(in srgb, var(--color-accent) 8%, var(--color-bg));
  transition: background-color 0.35s cubic-bezier(0.4, 0, 0.2, 1), color 0.35s cubic-bezier(0.4, 0, 0.2, 1);
}
[data-skin='summit'] .card:hover { background: var(--color-bg-dark); }
[data-skin='summit'] .card:hover .card-body h3 { color: var(--color-heading-alt); }
[data-skin='summit'] .card:hover .card-body p { color: var(--color-body-alt); }
[data-skin='summit'] .card:hover .icon-badge {
  background: color-mix(in srgb, var(--color-heading-alt) 12%, transparent);
  color: var(--color-heading-alt);
}

/* Process: centered header, glowing accent circles, per-segment connector */
[data-skin='summit'] .process-section { text-align: center; }
[data-skin='summit'] .process-section .section-intro { margin-inline: auto; }
[data-skin='summit'] .process-steps { position: relative; }
[data-skin='summit'] .step-num {
  width: 4rem; height: 4rem; border-radius: 50%;
  background: var(--color-accent); color: var(--color-on-accent);
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-heading); font-weight: 800; font-size: 1.35rem;
  position: relative; z-index: 1;
  box-shadow: 0 0 0 10px color-mix(in srgb, var(--color-accent) 12%, transparent);
}
@media (min-width: 768px) {
  [data-skin='summit'] .process-steps { display: flex; gap: 2rem; text-align: center; }
  [data-skin='summit'] .process-steps > li { flex: 1; position: relative; }
  /* Line starts/ends clear of each circle's glow (32px radius + 10px halo),
     leaving a visible gap instead of running under the circle. */
  [data-skin='summit'] .process-steps > li:not(:last-child)::after {
    content: ''; position: absolute; top: 1.98rem; left: calc(50% + 58px);
    width: calc(100% + 2rem - 116px); height: 2px; z-index: 0;
    background: linear-gradient(to right, var(--color-accent), var(--color-border));
  }
}

/* Why-us: numbered 2x2 soft cards */
[data-skin='summit'] .whyus-bullets {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1rem;
  list-style: none; padding: 0; counter-reset: whyus;
}
[data-skin='summit'] .whyus-bullets > li {
  background: var(--color-bg-alt); border: 1px solid rgba(15, 23, 42, 0.04);
  border-radius: 18px; padding: 24px 20px; counter-increment: whyus;
}
[data-skin='summit'] .whyus-bullets > li::before {
  content: '0' counter(whyus); display: block;
  color: var(--color-accent); font-weight: 800; font-size: 0.85rem;
  letter-spacing: 0.1em; margin-bottom: 0.5rem;
}
@media (max-width: 640px) { [data-skin='summit'] .whyus-bullets { grid-template-columns: 1fr; } }

/* Reviews: centered header + rating link, left-aligned premium cards, edge-fade marquee */
[data-skin='summit'] .reviews { text-align: center; }
[data-skin='summit'] .reviews-subline {
  justify-content: center; font-weight: 500; color: var(--color-body); margin-top: 0;
}
[data-skin='summit'] .reviews-subline .stars { margin: 0; font-size: 1.1rem; }
[data-skin='summit'] .reviews-subline a { color: inherit; text-decoration: underline; text-underline-offset: 3px; }
[data-skin='summit'] .reviews-marquee,
[data-skin='summit'] .reviews-grid { margin-top: 3rem; }
[data-skin='summit'] .marquee-track,
[data-skin='summit'] .reviews-grid { gap: 1.75rem; }
[data-skin='summit'] .reviews-marquee .review-card { width: 22rem; }
[data-skin='summit'] .review-card {
  background: var(--color-bg); border: 0;
  border-radius: 20px; padding: 32px 30px;
  box-shadow: 0 1px 2px rgba(15, 23, 42, 0.04), 0 16px 36px rgba(15, 23, 42, 0.10);
  text-align: left;
}
[data-skin='summit'] .review-card .stars { font-size: 1.05rem; letter-spacing: 3px; }
[data-skin='summit'] .review-card p { font-size: 1.02rem; line-height: 1.65; color: var(--color-body); }
[data-skin='summit'] .review-card footer { justify-content: space-between; }
[data-skin='summit'] .review-card cite { font-size: 0.98rem; }
[data-skin='summit'] .review-source {
  margin-top: 0.9rem; padding-top: 0.9rem; border-top: 1px solid var(--color-border);
}
[data-skin='summit'] .avatar {
  width: 2.75rem; height: 2.75rem; font-size: 0.85rem; color: #fff;
}
[data-skin='summit'] .stars { color: #d99a06; } /* amber: universal 5-star gold, deliberately not brand-colored */
[data-skin='summit'] .reviews-marquee {
  -webkit-mask-image: linear-gradient(to right, transparent, black 4%, black 96%, transparent);
  mask-image: linear-gradient(to right, transparent, black 4%, black 96%, transparent);
}
/* Cards size to their own review length instead of stretching to match the
   tallest sibling in the row — flex/grid cross-axis default is stretch. */
[data-skin='summit'] .marquee-track { align-items: flex-start; }
[data-skin='summit'] .reviews-grid { align-items: start; }

/* Area pills: centered header + centered pill grid, matching the reference's
   wide-open Denver-metro layout instead of a left-aligned wrapped list. */
[data-skin='summit'] .areas-grid-section { text-align: center; }
[data-skin='summit'] .areas-grid-section .section-intro { margin-inline: auto; }
[data-skin='summit'] .area-links {
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: 0.75rem 1rem; list-style: none; padding: 0; margin-top: 2rem;
}
[data-skin='summit'] .area-links li a {
  display: inline-block; border-radius: 100px;
  border: 1.5px solid rgba(15, 23, 42, 0.1);
  padding: 13px 26px; font-size: 0.95rem; font-weight: 600; text-decoration: none;
  color: var(--color-heading); transition: all 0.2s;
}
[data-skin='summit'] .area-links li a:hover {
  background: var(--color-accent); border-color: var(--color-accent); color: var(--color-on-accent);
}

/* Stat tiles polish */
[data-skin='summit'] .stat-tile { border-radius: 14px; }
[data-skin='summit'] .hero .stat-tile {
  background: rgba(15, 23, 42, 0.35);
  border-color: rgba(255, 255, 255, 0.14);
  color: var(--color-heading-alt);
  -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
}
[data-skin='summit'] .stat-suffix { color: var(--color-accent); }
[data-skin='summit'] .stat-suffix-star { color: #d99a06; } /* same universal 5-star gold as .stars, not brand-colored */

/* Glass chrome: summit's hero is always dark, so the original glass
   treatment (dark-alpha fill + blur + shadow, light text) belongs here,
   not in base.css. Matches the depth of the hero-calc-card glass below. */
[data-skin='summit'] .hero-badge {
  background: rgba(15, 23, 42, 0.35);
  border-color: rgba(255, 255, 255, 0.14);
  color: var(--color-heading-alt);
  -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
}
[data-skin='summit'] .hero-badge-dot {
  width: 8px; height: 8px; border-radius: 50%; flex-shrink: 0;
  background: #22c55e;
  box-shadow: 0 0 0 4px rgba(34, 197, 94, 0.18);
}
[data-skin='summit'] .btn-glass {
  background: rgba(15, 23, 42, 0.35); color: var(--color-heading-alt);
  border: 1px solid rgba(255, 255, 255, 0.14);
  -webkit-backdrop-filter: blur(16px); backdrop-filter: blur(16px);
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
}
[data-skin='summit'] .btn-glass:hover { background: rgba(15, 23, 42, 0.5); }
@supports not (backdrop-filter: blur(1px)) {
  [data-skin='summit'] .hero-badge,
  [data-skin='summit'] .btn-glass,
  [data-skin='summit'] .hero .stat-tile { background: rgba(15, 23, 42, 0.6); }
}

/* Split hero calculator card: glass treatment matching summit's dark hero.
   Grid geometry (.hero-split .hero-grid etc.) lives in base.css now -- it's
   shared by every skin's split hero, not summit-exclusive. */
[data-skin='summit'] .hero-calc-card {
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.12);
  -webkit-backdrop-filter: blur(24px); backdrop-filter: blur(24px);
  border-radius: 20px; padding: 10px;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.35);
}
[data-skin='summit'] .hero-calc-card iframe {
  display: block; width: 100%; height: 560px; border: 0;
  border-radius: 14px; background: var(--color-bg);
}
@supports not (backdrop-filter: blur(1px)) {
  [data-skin='summit'] .hero-calc-card { background: rgba(15, 23, 42, 0.55); }
}
@media (max-width: 900px) {
  [data-skin='summit'] .hero-calc-card iframe { height: 480px; }
}

/* Bottom sticky CTA bar: the Gates reference keeps this bar at every width,
   not just mobile — base.css hides it >=768px by default for other skins.
   Desktop reference has no city label, just the phone + CTA pair centered
   (the place label is a mobile-only compact-bar convention). */
@media (min-width: 768px) {
  [data-skin='summit'] .sticky-cta { display: flex; justify-content: center; }
  [data-skin='summit'] .sticky-cta-place { display: none; }
  [data-skin='summit'] body.has-sticky-cta { padding-bottom: 3.6rem; }
}
