/*
 Theme Name:   Norsk Klimasenter
 Theme URI:    https://kilowott.com
 Author:       Kilowott
 Author URI:   https://kilowott.com
 Description:  Modern default base theme for Norsk Klimasenter, generated by the Kilowott Docker Project Generator. Includes WooCommerce theme support out of the box.
 Version:      1.0.0
 Requires at least: 6.0
 Requires PHP: 8.0
 Text Domain:  norsk-klimasenter

 Standalone theme (no parent) - customize it directly.
*/

:root {
  --color-bg: #fff;
  --color-surface: #f7f8fa;
  --color-text: #1a1d23;
  --color-text-muted: #6b7280;
  --color-primary: #2f6fed;
  --color-primary-hover: #1d56d1;
  --color-border: #e5e7eb;
  --font-sans: -apple-system, "BlinkMacSystemFont", "Segoe UI", "Roboto", "Helvetica", "Arial", sans-serif;
  --container-width: 1140px;
  --radius: 10px;
  --transition: 0.2s ease;
}

* {
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;

  /* Guards against width:100vw breakout sections (e.g.
     .service-section-full-bleed below) overshooting the visible
     viewport - vw units are defined to include the scrollbar's own
     width, while % values (like the 50% half of that breakout's
     margin calc) are not, so on a real browser with a vertical
     scrollbar the two sides of that calc disagree by the scrollbar's
     width and the page gains a few pixels of horizontal scroll.
     Headless Chrome has no visible scrollbar by default, which is why
     this didn't show up in automated overflow checks. */
  overflow-x: hidden;
}

body {
  margin: 0;
  font-family: var(--wp--preset--font-family--sans);
  font-size: 16px;
  line-height: 1.56;
  color: var(--color-text);
  background: var(--color-bg);
}

/* Longer Norwegian headings: lines of similar length rather than one word
   left on the last line, and paragraphs avoid a lone last word where the
   browser supports it. kw-nowrap wraps short hyphenated compounds
   ("luft-til-vann") in headings, titles, buttons and breadcrumbs (see
   kw_keep_compounds_together() in functions.php), so they don't break
   after a hyphen. */
h1,
h2,
h3,
h4,
h5,
h6 {
  text-wrap: balance;
}

p,
li {
  text-wrap: pretty;
}

.kw-nowrap {
  white-space: nowrap;
}

/* On the site this colour wins over theme.json's Text body, as style.css
   loads after the global styles; in the editor the order is reversed, so
   text with no colour of its own showed in Text body while editing and
   near-black on the site. Matching the editor to the site keeps that text
   the same colour in both. */
body.editor-styles-wrapper {
  color: var(--color-text);
}

/* Service pages: a paragraph added next to the intro's Text body
   paragraphs (e.g. a new last line in a column) has no colour of its own,
   so it showed in the near-black default instead of matching them. It
   takes their colour; bold lead-in lines (set with a font weight) keep
   theirs. */
.single-service .wp-block-post-content :is(.wp-block-column, .wp-block-group):has(> p.has-text-body-color) > p:not(.has-text-color, [style*="font-weight"]),
.editor-styles-wrapper :is(.wp-block-column, .wp-block-group):has(> p.has-text-body-color) > p:not(.has-text-color, [style*="font-weight"]) {
  color: var(--wp--preset--color--text-body);
}

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

a {
  color: var(--color-primary);
  text-decoration: none;
  transition: color var(--transition);
}

a:hover {
  color: var(--color-primary-hover);
}

.screen-reader-text {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(1px, 1px, 1px, 1px);
  white-space: nowrap;
}

.screen-reader-text:focus {
  position: fixed;
  top: 10px;
  left: 10px;
  width: auto;
  height: auto;
  padding: 10px 16px;
  background: var(--color-primary);
  color: #fff;
  z-index: 999999;
  border-radius: var(--radius);
}

.site-header-inner,
.site-footer-inner {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 0 24px;
}

/* Header */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgb(255 255 255 / 90%);
  backdrop-filter: saturate(180%) blur(8px);
  border-bottom: 1px solid var(--color-border);
}

/* The mobile nav's full-screen overlay (core's .wp-block-navigation__responsive-container)
   is position:fixed and expects to size/position itself against the
   viewport - but backdrop-filter on .site-header (its ancestor) creates a
   new containing block for fixed descendants, so the overlay was instead
   sizing itself against the 73px-tall header bar, collapsing the whole
   mobile menu to a sliver. Core adds .has-modal-open to <html> the moment
   the menu opens, so dropping the filter only then restores the overlay
   to the real viewport without touching the header's normal blur. */
html.has-modal-open .site-header {
  backdrop-filter: none;
}

.site-header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 16px 24px;
  padding-top: 16px;
  padding-bottom: 16px;
}

.site-branding {
  display: flex;
  align-items: center;
  gap: 12px;
  min-width: 0;
}

/* Logo constrained to 160px wide (Figma spec) regardless of the uploaded
   image's own dimensions - add_theme_support('custom-logo') below only sets
   the suggested upload size, this is what actually enforces it on render. */
.custom-logo-link img,
.custom-logo {
  width: 160px;
  max-width: 160px;
  height: auto;
}

.site-title {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
}

.site-title a {
  color: var(--color-text);
  opacity: 1;
  transition: opacity 0.2s ease;
}

.site-title a:hover {
  opacity: 0.8;
}

.site-description {
  margin: 0;
  font-size: 13px;
  color: var(--color-text-muted);
}

.menu-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 40px;
  height: 40px;
  padding: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  background: transparent;
  cursor: pointer;
}

.menu-toggle span {
  display: block;
  width: 18px;
  height: 2px;
  margin: 0 auto;
  background: var(--color-text);
}

.main-navigation ul {
  list-style: none;
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px 28px;
  margin: 0;
  padding: 0;
}

.main-navigation li {
  position: relative;
}

.main-navigation a {
  display: inline-block;
  padding: 8px 0;
  font-size: 15px;
  font-weight: 500;
  color: var(--color-text);
}

.main-navigation a:hover {
  color: var(--color-primary);
}

/* Header navigation (parts/header.html) - a real wp:navigation block,
   not the .main-navigation rules above (those target a classic menu
   markup this theme doesn't actually render). Had no hover state at
   all; brand-cyan on hover mirrors the accent-color pairing already
   used for the header's own CTA button and site-wide links. */
.site-header .wp-block-navigation-item__content {
  transition: color 0.2s ease;
}

.site-header .wp-block-navigation-item__content:hover {
  color: var(--wp--preset--color--brand-cyan) !important;
}

.main-navigation ul ul {
  display: none;
  position: absolute;
  top: 100%;
  left: 0;
  flex-direction: column;
  gap: 0;
  min-width: 200px;
  padding: 8px;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius);
  box-shadow: 0 12px 24px rgb(0 0 0 / 8%);
}

.main-navigation li:hover > ul,
.main-navigation li:focus-within > ul {
  display: flex;
}

.main-navigation ul ul a {
  padding: 8px 12px;
  border-radius: 6px;
}

.main-navigation ul ul a:hover {
  background: var(--color-surface);
}

@media (max-width: 782px) {
  .menu-toggle {
    display: flex;
  }

  .main-navigation {
    display: none;
    width: 100%;
    order: 3;
  }

  .main-navigation.is-open {
    display: block;
  }

  .main-navigation ul {
    flex-direction: column;
    align-items: flex-start;
    gap: 4px;
    padding: 16px 0;
  }

  .main-navigation ul ul {
    position: static;
    box-shadow: none;
    border: none;
    padding-left: 16px;
    min-width: 0;
  }
}

/* Main content */
.site-content {
  max-width: var(--container-width);
  margin: 0 auto;
  padding: 48px 24px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 40px;
}

.has-sidebar.site-content {
  grid-template-columns: 2fr 1fr;
}

@media (max-width: 900px) {
  .has-sidebar.site-content {
    grid-template-columns: 1fr;
  }
}

.site-main {
  min-width: 0;
}

article {
  margin-bottom: 40px;
  padding-bottom: 40px;
  border-bottom: 1px solid var(--color-border);
}

article:last-child {
  border-bottom: none;
  margin-bottom: 0;
}

.entry-title {
  margin: 0 0 12px;
  font-size: 28px;
  line-height: 1.3;
}

.entry-title a {
  color: var(--color-text);
}

.entry-title a:hover {
  color: var(--color-primary);
}

.entry-meta {
  margin: 0 0 16px;
  font-size: 13px;
  color: var(--color-text-muted);
}

.entry-thumbnail {
  margin-bottom: 20px;
}

.entry-thumbnail img {
  border-radius: var(--radius);
}

.entry-content p:first-child {
  margin-top: 0;
}

.read-more {
  display: inline-block;
  margin-top: 12px;
  font-weight: 600;
}

/* Sidebar */
.widget-area .widget {
  margin-bottom: 32px;
  padding: 24px;
  background: var(--color-surface);
  border-radius: var(--radius);
}

.widget-title {
  margin: 0 0 16px;
  font-size: 16px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* Footer */
.site-footer {
  border-top: 1px solid var(--color-border);
  background: var(--color-surface);
  margin-top: 48px;
}

.site-footer-inner {
  padding-top: 48px;
  padding-bottom: 24px;
}

.footer-widgets {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 32px;
  margin-bottom: 32px;
}

.footer-widgets .widget {
  padding: 0;
  background: transparent;
}

.footer-navigation ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 20px;
  margin: 0;
  padding: 0;
}

.footer-navigation a {
  font-size: 14px;
  color: var(--color-text-muted);
}

.footer-navigation a:hover {
  color: var(--color-primary);
}

.site-footer-bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding-top: 24px;
  border-top: 1px solid var(--color-border);
  font-size: 13px;
  color: var(--color-text-muted);
}

.posts-navigation {
  display: flex;
  justify-content: space-between;
  gap: 20px;
  margin-top: 40px;
  font-weight: 600;
}

/* Block-based header (parts/header.html) responsiveness */
@media (max-width: 782px) {
  .site-header {
    padding-left: 16px;
    padding-right: 16px;
  }
}

/* Tablets and small laptops get the phone header too. Core only collapses
   the Navigation block into its hamburger below 600px, and the full menu,
   phone number and CTA need about 1065px in Norwegian (a little more in
   English), so below that the phone number and CTA wrapped onto a second
   header row (or, up to 782px, were hidden with no hamburger to reach the
   menu). At 1140px and below: the hamburger replaces the inline menu, and
   the phone number and CTA give way to the call icon - both still
   reachable via the menu and further down the page. */
@media (max-width: 1140px) {
  .site-header .header-actions {
    display: none;
  }

  .site-header nav.wp-block-navigation {
    margin-left: 12px;
  }

  .site-header .wp-block-navigation__responsive-container-open:not(.always-shown) {
    display: flex;
  }

  .site-header .wp-block-navigation__responsive-container:not(.hidden-by-default, .is-menu-open) {
    display: none;
  }
}

/* Mobile menu open state - core's full-screen white overlay (centered
   links, every submenu forced open, header hidden) restyled as a panel
   that drops down under the header, per the live norsk-klimasenter.no
   menu: the header stays visible with a cyan close X where the hamburger
   was, full-width left-aligned rows on a light grey panel, and submenus
   that expand in place from a caret (toggled by js/mobile-menu.js, which
   also sets the --nk-header-* offsets). The page below is dimmed, and
   tapping it closes the menu.
   The long selector outranks core's own
   .wp-block-navigation:not(.has-background) ... background rule. */
.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
  top: var(--nk-header-bottom, 81px);
  bottom: 0;
  padding: 0;
  overflow: visible;
  background-color: rgb(28 36 75 / 35%);
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-close,
.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-dialog {
  max-width: none;
  margin: 0;
}

/* Lifted out of the panel into the header bar, over the hamburger. */
.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-close {
  top: calc(var(--nk-header-h, 81px) / -2 - 12px);
  right: 16px;
  color: var(--wp--preset--color--brand-cyan);
}

html.has-modal-open .site-header .wp-block-navigation__responsive-container-open {
  visibility: hidden;
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content {
  align-items: stretch;
  max-height: calc(100dvh - var(--nk-header-bottom, 81px));
  padding: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  background-color: var(--wp--preset--color--surface-paper);
  box-shadow: 0 12px 24px rgb(28 36 75 / 12%);
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__container {
  align-items: stretch;
  gap: 0;
  width: 100%;
  margin: 0;
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation-item {
  align-items: stretch;
  width: 100%;
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation-item__content {
  display: flex;
  align-items: center;
  min-height: 46px;
  padding: 12px 16px;
}

/* Core forces list items transparent with !important, so the current
   page's lighter row sits on the link itself. */
.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .current-menu-item > .wp-block-navigation-item__content {
  background-color: #f9fafd;
}

/* Parent row: label, then the caret button filling the rest of the row
   (a wide tap target, with the caret right after the label as on the
   live site), then the submenu on its own line. */
.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .has-child {
  flex-flow: row wrap;
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .has-child > .wp-block-navigation-item__content {
  flex: 0 1 auto;
  padding-right: 8px;
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__submenu-icon {
  display: flex;
  flex: 1 1 auto;
  align-items: center;
  width: auto;
  height: auto;
  min-height: 46px;
  margin: 0;
  padding: 0 16px 0 0;
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__submenu-icon svg {
  width: 12px;
  height: 12px;
  margin: 0;
  transition: transform var(--transition);
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .has-child.is-sub-open > .wp-block-navigation__submenu-icon svg {
  transform: rotate(180deg);
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .has-child .wp-block-navigation__submenu-container {
  flex-basis: 100%;
  min-width: 0;
  padding: 0;
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .has-child:not(.is-sub-open) > .wp-block-navigation__submenu-container {
  display: none;
}

.site-header .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
  padding-left: 32px;
}

/* Mobile call icon (hooked after the header logo in functions.php) - the header's phone number is
   hidden with .header-actions on mobile, so a tap-to-call icon sits
   next to the hamburger instead. Hidden on desktop, where the full
   number is already shown. */
.site-header .header-call-mobile {
  display: none;
  margin: 0;
}

@media (max-width: 1140px) {
  .site-header .header-call-mobile {
    display: block;
    margin-left: auto;
  }

  .site-header .header-call-mobile a {
    display: block;
    border-radius: 50%;
    transition: filter var(--transition);
  }

  .site-header .header-call-mobile a:hover {
    filter: brightness(0.9);
  }

  .site-header .header-call-mobile img {
    width: 40px;
    height: 40px;
  }
}

/* The GTranslate language switcher (fixed, 20px from the bottom left)
   covered the left end of the cookie banner - while the banner shows it
   sits above it. --kw-consent-banner-h is the banner's height, kept up to
   date by js/consent-banner.js (0 once the banner is closed). */
[id="gt_float_wrapper"] {
  bottom: calc(20px + var(--kw-consent-banner-h, 0px)) !important;
}

/* Mobile "Call | Book" bar (output on wp_footer in functions.php) - pinned to the bottom of
   the viewport on mobile so calling or booking is one tap away however
   far down the page the visitor is. */
.mobile-cta-bar {
  display: none;
}

@media (max-width: 782px) {
  .mobile-cta-bar {
    display: flex;
    position: fixed;
    right: 0;
    bottom: 0;
    left: 0;
    z-index: 99;
    gap: 8px;
    margin: 0;
    padding: 8px 16px calc(8px + env(safe-area-inset-bottom));
    background: var(--wp--preset--color--surface-white);
    border-top: 0.5px solid rgb(0 0 0 / 12%);
    box-shadow: 0 -4px 16px rgb(28 36 75 / 8%);
  }

  /* Hidden while the mobile menu overlay is open, so it can't cover the
     bottom of the menu. */
  html.has-modal-open .mobile-cta-bar {
    display: none;
  }

  /* The GTranslate plugin's floating language switcher (fixed, 20px from
     the bottom) sat on top of the bar's Call button - it floats just above
     the bar instead. The bar is 65px tall plus the safe area. The cookie
     banner covers the bar, so while it shows the switcher sits above it. */
  [id="gt_float_wrapper"] {
    bottom: max(calc(77px + env(safe-area-inset-bottom)), calc(12px + var(--kw-consent-banner-h, 0px))) !important;
  }

  html.has-modal-open [id="gt_float_wrapper"] {
    bottom: 20px !important;
  }

  .mobile-cta-bar a {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 48px;
    border-radius: 100px;
    font-size: var(--wp--preset--font-size--small);
    font-weight: 500;
    white-space: nowrap;
    text-decoration: none;
    transition: filter var(--transition), background-color var(--transition);
  }

  .mobile-cta-bar img {
    display: inline-block;
    width: 16px;
    height: 16px;
  }

  .mobile-cta-bar-call {
    color: var(--wp--preset--color--brand-navy);
    border: 1px solid var(--wp--preset--color--border);
  }

  .mobile-cta-bar-call:hover {
    background-color: var(--wp--preset--color--surface-mist);
  }

  .mobile-cta-bar-book {
    color: var(--wp--preset--color--text-button);
    background-color: var(--wp--preset--color--brand-cyan);
  }

  /* The theme's global link hover (brand navy) recoloured the text but not
     the arrow beside it. The text keeps its colour - the whole button
     darkens instead - and the arrow is drawn in the text's own colour, so
     the two always match. */
  .mobile-cta-bar-book:hover,
  .mobile-cta-bar-book:focus-visible {
    color: var(--wp--preset--color--text-button);
    filter: brightness(0.9);
  }

  .mobile-cta-bar-arrow {
    width: 16px;
    height: 16px;
    background-color: currentcolor;
    mask: url("assets/icons/arrow-right.svg") center / contain no-repeat;
  }

  /* Room under the footer so the fixed bar never covers its last row. */
  body {
    padding-bottom: calc(64px + env(safe-area-inset-bottom));
  }
}

/* Footer (parts/footer.html) */
.site-footer .footer-about {
  max-width: 260px;
}

/* More space between the logo/address column and the nav columns, per design. */
.footer-top-row {
  column-gap: 120px;
}

.site-footer .footer-nav-columns {
  flex: 1;
}

/* Footer nav columns use wp:navigation (link list) instead of wp:list so
   items are real nav links with a hover state, not bulleted list items.
   Core's nav block falls back to a 2em row gap with no blockGap style set -
   tightened to match the original list's 12px spacing. */
.site-footer .footer-nav.wp-block-navigation .wp-block-navigation__container {
  gap: 12px;
}

.site-footer .footer-nav .wp-block-navigation-item a {
  transition: color var(--transition);
}

.site-footer .footer-nav .wp-block-navigation-item a:hover {
  color: var(--color-bg);
}

/* Between 901px and 1199px the four menu columns sit side by side but
   narrower than on desktop, so longer links ("Produkter og tjenester",
   "Ofte stilte spørsmål") wrapped onto two lines. Slightly smaller menu
   text and tighter gaps keep each item on one line. */
@media (min-width: 901px) and (max-width: 1199px) {
  .footer-top-row {
    column-gap: 48px;
  }

  .site-footer .footer-nav-columns {
    column-gap: 20px !important;
  }

  .site-footer .footer-nav .wp-block-navigation-item {
    font-size: 13px;
  }

  .site-footer .footer-nav-columns p {
    font-size: 11px !important;
  }
}

@media (max-width: 900px) {
  .site-footer {
    padding-left: 16px;
    padding-right: 16px;
  }

  .site-footer .footer-about {
    max-width: none;
  }

  /* Stacks the logo/address block above the nav columns instead of
     squeezing both into the same row, which wrapped unevenly (a single
     nav column dropping to its own line) once the 120px gap above left
     too little room for everything to fit side by side. align-items
     defaults to center once the row switches to a column direction (the
     block's own justifyContent:space-between only ever set the main
     axis), so it's reset to flex-start to keep everything left-aligned. */
  .footer-top-row {
    flex-direction: column;
    align-items: flex-start;
  }

  .site-footer .footer-nav-columns {
    width: 100%;
    flex-wrap: wrap;
  }

  /* calc() accounts for the row's own 32px column gap so two 50% columns
     plus that gap don't add up to slightly over 100% and wrap to one
     per row instead of the intended 2x2 grid. */
  .site-footer .footer-nav-columns > .wp-block-column {
    flex-basis: calc(50% - 16px) !important;
  }
}

/* Buttons, site-wide */

/* Core's own word-break:break-word on .wp-block-button__link lets a
   button's text wrap once its flex container gets tight (e.g. two
   buttons side by side in a narrow column), which splits an arrow (or
   icon) from the word before it onto its own line. Buttons here are
   always meant to read as one line - the design has no multi-line
   button copy - so this is safe to apply everywhere. */
.wp-block-button__link {
  white-space: nowrap;
  transition: filter 0.2s ease, background-color 0.2s ease;
}

/* No hover state existed for any wp:button variant sitewide - every CTA
   ("Book a free inspection", "See all services", etc.) was static.
   brand-cyan buttons use dark text (text-button, #2c2c2c) sized for a
   light background, so swapping straight to brand-navy on hover (as
   the global link color does) left dark text on a near-black
   background - unreadable. A brightness filter darkens the same cyan
   a little without changing its hue, so the existing text color stays
   legible against it. */
.wp-block-button__link.has-brand-cyan-background-color:hover {
  filter: brightness(0.9);
}

.wp-block-button__link.has-surface-white-background-color:hover {
  background-color: var(--wp--preset--color--surface-mist) !important;
}

/* A button added in the editor with no colour or style picked (e.g. the
   "Varmepumpehus i metall ->" / "i tre ->" links at the bottom of the
   housing pages) got the bare theme default - a cyan pill, the look kept
   for "Bestill gratis befaring". It gets the site's standard secondary
   button instead, the white outline pill used for links like "Se hva vi
   tilbyr ->". Buttons with their own colours or style are untouched. */
.wp-block-button:not([class*="is-style-"]) > .wp-block-button__link:not(.has-background, .has-text-color) {
  padding: 0.667em 1.33em;
  border: 1px solid currentcolor;
  border-radius: 100px;
  color: var(--wp--preset--color--text-button);
  background-color: var(--wp--preset--color--surface-white);
}

.wp-block-button:not([class*="is-style-"]) > .wp-block-button__link:not(.has-background, .has-text-color):hover {
  background-color: var(--wp--preset--color--surface-mist);
}

/* On a light-blue (surface-mist) section or card, that hover colour is the
   background's own, so the button seemed to vanish - it darkens to the
   brand cyan's lightest tint there instead. */
.has-surface-mist-background-color .wp-block-button__link.has-surface-white-background-color:hover {
  background-color: #cceffd !important;
}

/* Hero (patterns/hero.php) */

/* wp:cover has no native width attribute like wp:image, so the 773px media
   width from the source design is set here instead. An empty cover with no
   image/video renders fully transparent (dimRatio:0, no fill) - the
   placeholder fill here keeps it visible until real media is picked in
   the editor, at which point WordPress's own background/video layer
   covers it.

   flex-shrink:0 keeps the media at its full 773px above the 1024px stack
   breakpoint - it's the text column that should give up width first (via
   its own min-width:0 below), not the media. Giving the media flex-shrink
   instead (as a prior fix did) let it collapse to a few hundred px even at
   1440px+ any time the text column's content pushed back, which visibly
   shrank the hero video/image well below its intended size.

   No placeholder background fill here - the hero always has a real video
   set, so the fill only ever showed as a brief flash of the placeholder
   image on every page load/reload before the video painted over it. */
.hero-media {
  width: 773px;
  max-width: 100%;
  flex-shrink: 0;
}

/* .hero-row's own layout attribute has no verticalAlignment set, which
   Gutenberg renders as align-items:center - the row's height already
   matches the 500px media (its tallest child), but centering means the
   shorter text column floats in the middle of that height rather than
   starting at the same top edge as the media. Stretch is required before
   height:100% below has anything meaningful to size against. */
.hero-row {
  align-items: stretch;
}

/* Text column (eyebrow/heading/body + buttons) - stretched to the row's
   full height (now equal to the media's, via align-items:stretch above),
   but the eyebrow/heading/body group and the buttons group were only as
   tall as their own content, leaving the CTA row wherever the text
   happened to end rather than pinned to the same bottom edge as the hero
   media beside it. space-between distributes the column's height between
   the two groups, dropping the buttons to the bottom to match. */
.hero-text-col {
  justify-content: space-between;
}

/* Eyebrow above the hero heading: the pill icon sits level with the first
   line when the text wraps onto two, instead of centred between them. */
.hero-text-col .wp-block-group.is-nowrap:has(> figure img[src*="pill-icon"]) {
  align-items: flex-start;
}

.hero-text-col .wp-block-group.is-nowrap > figure:has(img[src*="pill-icon"]) {
  margin-top: 1px;
}

/* Desktop: the eyebrow stays on one line. The text column shrinks first
   (see .hero-row below), down to its min-content width, which a wrapping
   eyebrow didn't count - so it broke with one word on its own line while
   the media kept its width. Unwrapped, it is part of that minimum and the
   media gives way instead. It still wraps at 1024px and below. */
@media (min-width: 1025px) {
  .hero-text-col .wp-block-group.is-nowrap:has(> figure img[src*="pill-icon"]) > p {
    white-space: nowrap;
  }
}

@media (max-width: 1024px) {
  .hero-text-col {
    justify-content: flex-start;
  }
}

/* Between the 1024px stacking breakpoint below and the 1280px content-size
   the hero row is designed for, .hero-row's two columns (773px media +
   the text column's own intrinsic minimum) can add up to more than the
   viewport provides - e.g. at 1200px wide. The text column needs to be
   allowed to shrink and wrap instead, which min-width:0 on it enables. */
.hero-row > *:first-child {
  min-width: 0;
  flex-shrink: 1;
}

/* min-width:0 alone isn't enough in this band: it lets the H1 wrap
   narrower, but .hero-media keeps flex-shrink:0 and its full 773px, so the
   wrapped heading/body text renders directly underneath the (visually on
   top, later in source order) media instead of actually making room for
   it - an invisible-until-you-look overlap, not a layout crash. Letting
   the media shrink too (down to a sane floor) in just this band gives the
   text column enough width to avoid wrapping under it, without touching
   the full-width mobile stack below 1024px.

   That applies at every desktop width, not just below 1225px: how wide
   the text column needs to be depends on its (nowrap) button row, and the
   Products & Services and About heroes' buttons are wide enough that the
   video slid under them just above that band. min-width:min-content keeps
   the text column at least as wide as its button row, and the video gives
   way instead. The text column's much larger flex-shrink makes it give up
   its width first, so the media keeps its full 773px until the text
   column is down to that minimum - only then does the video shrink. */
@media (min-width: 1025px) {
  .hero-row > .hero-text-col {
    min-width: min-content;
    flex-shrink: 1000;
  }

  /* The button row may run on into the row's 88px gap (as it always has at
     full width), but no closer than 32px to the media - the negative margin
     takes those 56px off the width the text column has to reserve for it. */
  .hero-row > .hero-text-col > .hero-buttons {
    margin-right: -56px;
  }

  .hero-media {
    flex-shrink: 1;
    min-width: 340px;
  }
}

@media (max-width: 1024px) {
  /* The outer hero row is flexWrap:nowrap unconditionally (no responsive
     override in the block's own layout attribute) - without flipping it
     to a column here, the text and media columns stay side-by-side and
     .hero-media's width:100% just means "100% of whatever sliver it's
     squeezed into", not "full width on its own row". This is what caused
     the page-wide horizontal scroll on mobile/tablet. */
  .hero-row {
    flex-direction: column;
    gap: 40px !important;
  }

  /* Direct children of a flex row default to min-width:auto, which
     refuses to shrink below their content's intrinsic width (here, the
     H1) even after flipping to a column - min-width:0 is required for
     the column to actually respect the viewport. */
  .hero-row > * {
    min-width: 0;
    max-width: 100%;
  }

  /* Stacked, the hero's video (or photo) leads, above the text - with
     less than the side-by-side layout's 88px gap between them (set on
     .hero-row above). */
  .hero-media {
    width: 100%;
    order: -1;
  }
}

/* Phones: the hero video was 500px tall (the cover block's inline
   min-height), which filled the screen before the headline. */
@media (max-width: 600px) {
  .hero-media.wp-block-cover {
    min-height: 340px !important;
  }
}

@media (max-width: 480px) {
  /* Two pill buttons genuinely don't both fit on one line at true phone
     widths, even after the hero row itself stacks to a column above -
     flexWrap:nowrap (added deliberately so the buttons don't stack at
     tablet/desktop widths) has to give here instead of forcing the row
     wider than the viewport. */
  .hero-buttons,
  .services-product-info-buttons {
    flex-wrap: wrap;
  }
}

/* Products & Services "Not sure which system fits?" (homeowner and
   business): side by side with the image on tablets (782-1023px), the
   text column is narrower than the two buttons, so the nowrap row ran
   ~75px off the right edge and dragged the heading and text with it.
   Wrapping only stacks them when they don't fit. With the Norwegian
   labels they also ran 2-3px past the edge at 1024-1029px, so this reaches
   up to the widths where they always fit. */
@media (max-width: 1199px) {
  .services-product-info-buttons {
    flex-wrap: wrap;
  }
}

/* Trust Proof (patterns/trust-proof.php) */

/* Logos row is a hard 5-or-none requirement - see the pattern file's own
   comment. This just lays the (always five) logos out evenly. */
.trust-logos {
  flex-wrap: wrap;
  align-items: center;
  row-gap: 24px;
}

/* Phones: the logos stack into a column and the "We've done this before"
   heading followed straight on in the same navy band, with nothing to
   mark the change. A faint rule under the logos separates the two. */
@media (max-width: 600px) {
  .trust-logos {
    padding-bottom: 40px;
    border-bottom: 1px solid rgb(255 255 255 / 16%);
  }
}

/* Every logo sits in the same 200x56 box whatever size its image was
   uploaded at (e.g. an 800x224 @4x export) - scaled to fit, never cropped
   or stretched out of shape. Above 900px the five stay on one line and
   shrink together if the row runs short of space; below that they wrap as
   before. */
.trust-logos > .wp-block-image {
  flex: 0 1 200px;
  min-width: 0;
  margin: 0;
}

/* Linked and unlinked logos line up the same way: the <a> most of them
   are wrapped in would otherwise add an inline line box around the image. */
.trust-logos > .wp-block-image a {
  display: block;
}

.trust-logos > .wp-block-image img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 200 / 56;
  object-fit: contain;
}

/* The Samsung logo file has no margin around its wordmark (artwork fills
   92% of the canvas width, against ~62-68% for the other four logos), so
   in the same box it looked a size bigger. Padding the image inside its
   box brings the wordmark to ~130px of 200px, in line with Panasonic and
   Toshiba. Matched by file name, since the image block has no class or
   alt text - if the logo is re-exported with padding like the others,
   this rule should be removed. */
.trust-logos > .wp-block-image img[src*="samsung"] {
  box-sizing: border-box;
  padding: 0 15%;
}

@media (min-width: 901px) {
  .trust-logos {
    flex-wrap: nowrap;
  }
}

/* Shrinks Trust Proof's 120px blockGap on mobile; targeted via :has() since the wrapper has no className. */
@media (max-width: 600px) {
  .wp-block-group:has(> .trust-logos) > * + * {
    margin-top: 48px !important;
  }
}

/* Subtle vertical dividers between logos, per design - a hairline
   centered in the existing 40px blockGap between each logo. Uses the
   logo <figure> as the border host (not the image) so the line's height
   is consistent across logos regardless of each one's own image height.
   Skipped on wrapped rows (max-width:900px, where row-gap already
   separates logos vertically) since a trailing divider on a row's last
   item looks like a stray mark. */
.trust-logos > .wp-block-image:not(:last-child) {
  position: relative;
}

.trust-logos > .wp-block-image:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: -20px;
  width: 1px;
  background: rgb(255 255 255 / 16%);
}

@media (max-width: 900px) {
  .trust-logos > .wp-block-image:not(:last-child)::after {
    display: none;
  }
}

/* Auto-advancing marquee, no arrows - .trust-marquee clips the overflow;
   .trust-marquee-track (a wp:group) is what marquee.js actually measures
   and translates. Kept as two elements because a node can't clip its own
   overflow while also being the one being transformed.
   width:100% + max-width:100% are required, not decorative: the track's
   width:max-content forces its own ~4000px intrinsic size (10 slides),
   and without an explicit width constraint here, this wrapper just grows
   to match it instead of clipping - overflow:hidden alone does nothing
   unless the parent's own width is pinned independently of its content. */
.trust-marquee {
  overflow: hidden;
  width: 100%;
  max-width: 100%;

  /* .trust-marquee is itself a flex item (child of a vertical flex group).
     Flex items default to min-width:auto, which refuses to shrink below
     the intrinsic width of their content (the ~4000px track) regardless
     of width/max-width/overflow - this is what let the track force the
     whole page wider than the viewport. min-width:0 is the standard
     override for exactly this case. */
  min-width: 0;
}

.trust-marquee-track {
  width: max-content;
}

/* Every marquee slide already has a real image/video set, so no
   placeholder background fill here - it only ever showed as a brief
   flash of the placeholder image on every page load/reload before each
   slide's own image/video painted over it. */
.trust-marquee-slide {
  flex-shrink: 0;
  width: 324px;
}

.trust-marquee-slide.is-size-wide {
  width: 488px;
}

@media (max-width: 782px) {
  .trust-marquee-slide {
    width: 240px;
  }

  .trust-marquee-slide.is-size-wide {
    width: 340px;
  }
}

/* Testimonials (patterns/testimonials.php)
   Now a real 4-column wp:columns block (each column independently editable
   in the editor) rather than a flex-wrap grid, so cards fill their column's
   width instead of a fixed px value. */
.testimonial-card.is-style-quote {
  min-height: 295px;
}

.testimonial-card.is-style-stat {
  min-height: 200px;
}

/* Mittanbud card: nudge "4.6" up, pin logo to bottom-right regardless of text length. */
.testimonial-card-mittanbud {
  position: relative;
  align-items: flex-start !important;
}

/* Reserves space for the absolutely-positioned logo so text can't grow under it. */
.testimonial-card-mittanbud > div:first-child {
  padding-bottom: 59px;
}

.testimonial-card-mittanbud .wp-block-image {
  position: absolute;
  right: 26px;
  bottom: 16px;
  margin: 0;
}

/* Column 1's "See all reviews" button spans the card's full width, unlike
   the default auto-width pill buttons used everywhere else on the site. */
.testimonial-full-width-button {
  width: 100%;
}

.testimonial-full-width-button .wp-block-button,
.testimonial-full-width-button .wp-block-button__link {
  width: 100%;
}

.testimonial-full-width-button .wp-block-button__link {
  text-align: center;
}

/* Google/Trustpilot logos: more breathing room above (not Mittanbud, which is a row layout). */
.testimonial-card.is-style-stat.is-vertical .wp-block-image:last-child {
  margin-top: 11px;
}

.testimonial-card-trustpilot .wp-block-image {
  align-self: flex-end;
}

/* Fills remaining column height so col 4 stays flush with the others. */
.testimonial-card-trustpilot {
  flex: 1;
}

/* Forces equal column heights - core sets align-items:normal !important by default. */
.testimonials-grid {
  align-items: stretch !important;
}

/* Cols 2-4 carry verticalAlignment:"top" (needed - see e856410b), which opts them out of
   the stretch above; overridden here instead of touching that attribute. */
.testimonials-grid > .wp-block-column {
  display: flex;
  flex-direction: column;
  align-self: stretch !important;
}

/* Column 2's dedicated photo slot, sitting above its stat card - fixed
   height (not the full column) since it shares the column with a card
   below it, unlike column 3's photo which fills its entire column. */
.testimonial-stat-image {
  margin: 0 0 20px;
  flex-shrink: 0;
}

.testimonial-stat-image img {
  width: 100%;
  height: 300px;
  object-fit: cover;
  border-radius: 20px;
}

.testimonial-stat-image + .testimonial-card.is-style-stat {
  flex: 1;
}

/* Fills remaining column height so col 1 stays flush with the others. */
.testimonial-card.is-style-stat + .testimonial-card.is-style-quote {
  flex: 1;
}

/* Negative margin overlaps the photo into column 4, per design. */
.testimonial-image-column {
  padding-right: 0 !important;
  margin-right: -20px;
}

.testimonial-photo-card {
  flex: 1;
  min-height: 620px;
}

figure.testimonial-photo-card img {
  width: 100%;
  height: 100%;
  min-height: 620px;
  object-fit: cover;
}

@media (max-width: 782px) {
  .testimonials-grid {
    flex-wrap: wrap;
  }

  .testimonials-grid > .wp-block-column {
    flex-basis: 100% !important;
  }

  /* Stacked, the photo is as wide as the cards (the right padding and the
     desktop 620px min-height kept it narrower, flush left and 620px tall). */
  .testimonial-image-column {
    padding-right: 0 !important;
    margin-right: 0;
  }

  .testimonial-photo-card {
    min-height: 320px;
  }

  figure.testimonial-photo-card img {
    height: 320px;
    min-height: 0;
  }
}

/* Tablets (601-1023px): a 2x2 grid. Below 783px the four columns
   stacked into one 700px-wide column (the 320px strip cropped the
   installer photo to a band, with the source image's blank right edge
   showing); from 783px they jumped straight to four ~175px columns. Two
   columns give the cards a readable width and each photo a portrait-ish
   frame, the installer photo filling the height of the cards beside it.
   Core's stacking rule (flex-basis:100% !important) is out-specified by
   the extra class, and the desktop overlap into column 4 is dropped. */
@media (min-width: 601px) and (max-width: 1023px) {
  .wp-block-columns.testimonials-grid {
    flex-wrap: wrap !important;
    row-gap: 20px;
  }

  .wp-block-columns.testimonials-grid > .wp-block-column {
    flex-basis: calc(50% - 10px) !important;
    flex-grow: 0;
  }

  /* The photo fills its column without adding to the row's height, so
     the row is as tall as the cards beside it. */
  .wp-block-columns.testimonials-grid > .testimonial-image-column {
    position: relative;
    min-height: 320px;
    padding-right: 0 !important;
    margin-right: 0;
  }

  /* The source photo has a blank strip down its right edge, which the
     desktop overlap into column 4 hides; here the rounded frame clips it
     (the photo is drawn 12% wider, anchored left). */
  .testimonial-image-column .testimonial-photo-card {
    position: absolute;
    inset: 0;
    min-height: 0;
    margin: 0;
    overflow: hidden;
    border-radius: 20px;
  }

  .testimonial-image-column figure.testimonial-photo-card img {
    width: 112%;
    max-width: none;
    height: 100%;
    min-height: 0;
    border-radius: 0 !important;
  }
}

/* Final CTA (patterns/final-cta.php)
   The panel is a wp:cover so an editor can upload a background image/video;
   dimRatio:70 gives a proper dark overlay once a photo is set, but with no
   media at all that same 70%-opacity tint sits over a transparent/white
   base and reads as washed-out lavender instead of navy. This background
   is the solid fallback fill for the no-media state - WordPress's own
   image/video layer paints over it once real media is picked. */
.final-cta-row {
  background-color: #1c244b;
}

.final-cta-content {
  flex: 0 1 532px;
  min-width: 0;
}

.final-cta-form {
  flex: 0 0 468px;
  width: 468px;
  box-shadow: 0 16px 44px rgb(28 36 75 / 12%);
}

/* Overlay in the CTA Panel's #0c284f. Figma's 88% buries the photo in the
   browser (the Figma render shows it much more clearly), so 62% is used to
   match how the design actually looks. */
.final-cta-row > .wp-block-cover__background {
  background-color: #0c284f !important;
  opacity: 0.62 !important;
}

.final-cta-content h2 {
  line-height: 1.14;
  letter-spacing: -0.32px;
}

.final-cta-content h2 + p {
  font-size: 16px;
  line-height: 1.56;
  color: #b9c8e4 !important;
}

/* "Or call us directly" + number */
.final-cta-content figure + .wp-block-group > p:first-child {
  font-size: 12px !important;
  font-weight: 600;
  line-height: 1.2;
  color: #b9c8e4 !important;
}

.final-cta-content figure + .wp-block-group > p:last-child {
  line-height: 1.28;
  letter-spacing: -0.06px;
  color: #f7f9fa !important;
}

/* Desktop: the copy column runs the full height of the form - heading and
   intro at the top (just below the form's own top edge), phone number and
   checklist at the bottom, level with the form's bottom edge. */
@media (min-width: 1101px) {
  /* 532px copy + 132px gap + 468px form only fit from about 1250px; below
     that the form wrapped under the copy, leaving the right half empty.
     Down to the 1101px stacking point they stay side by side: the gap
     narrows and the columns may give up some width (the form no less than
     400px, see .final-cta-form below). */
  .final-cta-row .final-cta-inner-row {
    flex-wrap: nowrap;
    align-items: stretch;
    gap: clamp(40px, 8vw, 132px) !important;
  }

  /* 59.5px from the checklist to the panel's bottom edge (Figma); the
     panel's own 28px plus 31.5px here. */
  .final-cta-row .final-cta-content {
    align-self: stretch;
    justify-content: space-between;
    padding-top: 48px;
    padding-bottom: 31.5px;
  }

  .final-cta-content h2,
  .final-cta-content h2 + p {
    max-width: 380px;
  }


  .final-cta-row .final-cta-form {
    flex: 0 1 468px;
    width: auto;
    min-width: 400px;
  }
}

@media (max-width: 1100px) {
  /* Stacked, the desktop 132px column gap left a large empty band
     between the checklist and the form. */
  .final-cta-inner-row {
    flex-direction: column;
    gap: 40px !important;
  }

  .final-cta-content,
  .final-cta-form {
    flex-basis: auto;
    width: 100%;
  }
}

/* Homeowners vs Business (patterns/homeowners-vs-business.php)
   Per updated design, the photo is now full-bleed at the top of the
   card (flush with its left/right/top edges) instead of inset with
   padding on all sides, and taller relative to the card. overflow:hidden
   on the card clips the image to the card's own 30px radius - only the
   top two corners actually round off, since the card's bottom edge is
   the text content below, not the image.
   aspect-ratio keeps the crop proportional as the card narrows on
   smaller screens, rather than object-fit:cover cropping more
   aggressively at a fixed pixel height (cutting off feet/heads on
   mobile) - 508:280 matches the updated design's taller media slot. */
.is-style-hvb-media,
.is-style-hvb-media img {
  width: 100%;
  margin: 0;
}

.is-style-hvb-media img {
  aspect-ratio: 294 / 196;
  height: auto;
  object-fit: cover;
  display: block;
  border-radius: 30px 30px 0 0;
}

/* Single service page hero images (e.g. patterns/single-service.php via
   post content) - two plain wp:image blocks side by side at different
   column widths. Each image keeps its own natural aspect ratio by
   default, so their rendered heights only match by coincidence - the
   Figma design has both filling the same height. Stretching the
   columns row to equal height and letting each image (and its figure
   wrapper) fill that height with object-fit:cover crops both to match
   regardless of their own aspect ratio, like the service-card-media
   fix above. */
.service-hero-images-row {
  align-items: stretch;
}

.service-hero-images-row .wp-block-image,
.service-hero-images-row .wp-block-image img {
  height: 100%;
  margin: 0;
}

.service-hero-images-row .wp-block-image img {
  width: 100%;
  object-fit: cover;
  display: block;
}

/* Phones (columns stacked): the two hero photos both came after the long
   intro text. The first now leads, above the text, and the second stays
   below it. The intro row and the photos row are separate blocks in each
   service's saved content, so the content area becomes a column flex box
   and the photos row steps aside (display:contents) to let its first
   photo be reordered on its own. */
@media (max-width: 781px) {
  .wp-block-post-content:has(> .service-hero-images-row) {
    display: flex;
    flex-direction: column;
  }

  .wp-block-post-content > .service-hero-images-row {
    display: contents;
  }

  .service-hero-images-row > .wp-block-column:first-child {
    order: -1;
    margin: 0 0 32px;
  }

  .service-hero-images-row > .wp-block-column:last-child {
    margin-top: 32px;
  }
}

/* Section heading rows (patterns/services.php, patterns/trust-proof.php)
   Figma lays the heading and body side by side as two columns at desktop -
   a fixed-width heading on the left, the body copy filling the rest on the
   right - rather than stacking the body below the heading. */
.section-heading-row-title {
  flex: 0 0 auto;
  width: 377px;
  max-width: 100%;
  margin: 0;
}

/* Service Benefits (patterns/service-benefits.php) uses a wider heading.
   Kept before the mobile rule below, which sets it back to 100%. It was an
   inline width:480px, which core/heading can't store, so the editor
   flagged the block as invalid. */
.service-benefits-title {
  width: 480px;
}

/* Capped to the same ~413px width Price and Grants uses for its own body
   copy (see .price-heading-row-body below) - Price's row also sets
   justify-content:space-between (its own block layout attribute) so the
   narrower body is pushed flush against the row's right edge; this row's
   own layout attribute only sets verticalAlignment, so justify-content
   is added here instead to get the same flush-right result. */
.section-heading-row {
  justify-content: space-between;
}

.section-heading-row-body {
  flex: 1 1 320px;
  min-width: 0;
  max-width: 413px;
}

@media (max-width: 900px) {
  .section-heading-row-title {
    width: 100%;
  }

  .section-heading-row-body {
    max-width: 100%;
  }
}

/* Homeowners vs Business cards (patterns/homeowners-vs-business.php) -
   wp:columns stretches the columns to equal height, but each card's own
   flex group only grows to fit its content, so the shorter card's card
   was visibly shorter than the taller one. Stretching the card to fill
   its column keeps both cards the same height until they stack into a
   single column on mobile, where a fixed/matched height is undesirable.
   The image is now a fixed-ratio block above .hvb-card-body (see the
   is-style-hvb-media rules above), so space-between here just stretches
   that body group to fill the remaining height - the CTA-to-bottom
   alignment itself lives on .hvb-card-body below. */
.hvb-card {
  height: 100%;
  overflow: hidden;
  justify-content: space-between;
}

@media (max-width: 782px) {
  .hvb-card {
    height: auto;
    justify-content: flex-start;
  }
}

.hvb-card-body {
  flex: 1 1 auto;
  justify-content: space-between;
}

/* On narrow phones the CTA ("See solutions for your business ->") was
   wider than the card, which stretched the body past the card's edge and
   clipped its right padding. Let the body shrink to the card, with less
   side padding, and let the CTA wrap if it still doesn't fit. The 24px
   top padding puts the eyebrow as far under the photo as other cards'
   first line (20-24px). */
@media (max-width: 600px) {
  .hvb-card-body {
    min-width: 0;
    padding-top: 24px !important;
    padding-right: 24px !important;
    padding-left: 24px !important;
  }

  .hvb-card-body .wp-block-button__link {
    white-space: normal;
  }
}

/* Services cards (patterns/services.php) - same column-stretch issue as
   the Homeowners vs Business cards, plus the "See X ->" links need to
   land at the same vertical position across all three cards regardless
   of each card's own copy length. Stretching the card and pushing its
   text/link group to fill the remaining space (space-between) keeps the
   CTA pinned to the card's bottom edge at every width.

   The card itself is rounded (border-radius:12px, set inline via the
   block's own border style), but the image sits flush at the top with
   square corners, so they poked past the card's rounded top edge instead
   of following it. overflow:hidden clips the image to the card's radius,
   letting only its top corners round off since the rest of the image is
   already inset by the card's own bottom padding.

   The card is a column flex group, which WordPress also gives
   flex-wrap:wrap. A wrapping column box sizes itself from the photo's
   natural height (293px) before the photo is scaled to the card's width,
   so once a card is wider than ~408px (large phones, tablets) the photo
   ran down over the title and text, and overflow:hidden cut the text
   off. Without wrapping the card fits the scaled photo. */
.service-card {
  height: 100%;
  overflow: hidden;
  flex-wrap: nowrap !important;
}

.service-card-body {
  flex: 1 1 auto;
  justify-content: space-between;
}

/* Every card pattern sets 24px left / 56px right padding inline, the 56px
   keeping the title clear of the icon chip that hangs over the photo's
   bottom-right corner. On narrower cards that squeezed the description and
   link into a thin column too. The body gets 24px both sides, and only the
   title (beside the chip) keeps the extra 32px. The tablet side-on layout
   below has no chip under the photo and keeps its own padding. */
.service-card > .service-card-body {
  padding-right: 24px !important;
}

.service-card:has(.service-card-icon-chip) > .service-card-body .wp-block-heading:first-child,
.service-card:has(.service-card-icon-chip) > .service-card-body > h5:first-child {
  padding-right: 32px;
}

/* Icon chip badge overlapping the bottom-right corner of each card's
   photo, per design - .service-card-media is the positioning context
   (the photo and chip are siblings, both wrapped by this group so the
   chip's position:absolute is relative to the photo, not the whole
   card). Each chip is a separate wp:image block so an editor can swap
   it independently of the card's own photo via the block's own Replace
   control. */
.service-card-media {
  position: relative;
}

/* A real uploaded featured image carries its own intrinsic width/height
   HTML attributes (e.g. width="408"), which the global img{max-width:100%}
   rule only ever scales DOWN from - it won't stretch the image back up
   to fill a wider card, which is what happens once .services-grid-item
   goes full-width below the 782px stacking breakpoint. The card's photo
   needs to always fill the card's own width regardless of the source
   image's native size. */
.service-card-media img {
  width: 100%;
}

/* Phones: the card photo's height was left to each browser's flex sizing
   of a figure holding an image with width/height attributes, and on some
   (Safari) the photo ended up taller than its frame, running down over
   the card's title and text. A fixed 408:293 shape on a plain block image
   gives the frame and the photo the same, explicit height everywhere. */
@media (max-width: 782px) {
  .service-card-media > .wp-block-image:not(.service-card-icon-chip) {
    display: block;
    margin: 0;
  }

  .service-card-media > .wp-block-image:not(.service-card-icon-chip) img {
    display: block;
    height: auto;
    aspect-ratio: 408 / 293;
    object-fit: cover;
  }
}

/* Every card photo gets the design's 408x293 frame, cropped to fit, so a
   photo in a different shape (e.g. a 16:9 banner) can't make its card's
   image shorter than its row-mates'. */
.services-grid-item .service-card-media img {
  aspect-ratio: 408 / 293;
  object-fit: cover;
}

.service-card-icon-chip {
  position: absolute;
  right: 16px;
  bottom: -32px;
  margin: 0;
  border-radius: 50%;
  box-shadow: 0 4px 10px rgb(28 36 75 / 10%);
}

@media (max-width: 782px) {
  .service-card {
    height: auto;
  }
}

/* Tablets (601-781px): the three cards of "Already know what you need?"
   (home) and "Why choose our ..." (service pages) stack full width, which
   made each one mostly a ~530px photo. Laid out side-on instead - photo
   left, title, text and link right - they read as a compact list. The
   icon chip moves inside the photo's corner, as there is no text under
   it to overlap. The dynamic service grids and housing cards keep their
   own layouts. */
@media (min-width: 601px) and (max-width: 781px) {
  .wp-block-column > .service-card:not(.housing-card) {
    flex-direction: row;
    align-items: stretch;
    gap: 0;
    padding-bottom: 0 !important;
  }

  /* The photo fills its side of the card without setting the card's
     height (a large upload would otherwise stretch the card to its own
     height) - the text does, with a 220px floor. */
  .wp-block-column > .service-card:not(.housing-card) > .service-card-media {
    flex: 0 0 42%;
    min-height: 220px;
  }

  .wp-block-column > .service-card:not(.housing-card) .service-card-media > .wp-block-image:not(.service-card-icon-chip) {
    position: absolute;
    inset: 0;
  }

  .wp-block-column > .service-card:not(.housing-card) .service-card-media > .wp-block-image:not(.service-card-icon-chip) img {
    height: 100%;
    aspect-ratio: auto;
  }

  .wp-block-column > .service-card:not(.housing-card) .service-card-icon-chip {
    right: 16px;
    bottom: 16px;
  }

  .wp-block-column > .service-card:not(.housing-card) > .service-card-body {
    flex: 1 1 auto;
    justify-content: center;
    padding: 28px !important;
  }
}

/* Price and Grants (patterns/price-and-grants.php)
   This section's heading/body pair uses its own fixed widths (522px/413px)
   rather than the 377px shared by Services/Trust Proof - Figma sizes each
   heading row individually based on its own copy length. */
.price-heading-row-title {
  flex: 0 0 auto;
  width: 522px;
  max-width: 100%;
}

.price-heading-row-body {
  flex: 1 1 320px;
  min-width: 0;
  max-width: 413px;
}

@media (max-width: 900px) {
  .price-heading-row-title {
    width: 100%;
  }

  .price-heading-row-body {
    max-width: 100%;
  }
}

/* Fixed 45x45 circular icon chip (Figma: size-[45px] with a centered 26px
   icon) - the padding-based approach previously here grew wide with the
   emoji's own line-height instead of staying a fixed circle. */
.price-icon-chip {
  width: 45px;
  height: 45px;
  flex-shrink: 0;
}

/* Fixed 300px card height so the three price/grants cards align regardless
   of each card's own copy length, matching the Figma card grid. The card's
   own flex container has no explicit wrap set, so at narrower widths (e.g.
   1024px) where the copy reflows taller, the browser wraps the icon/heading
   row, description and link into a second column instead of overflowing
   vertically - nowrap keeps the three children stacked in one column and
   lets content grow past 300px instead, which is preferable to the CTA
   link jumping beside the icon. */
.price-card {
  height: 300px;
  flex-wrap: nowrap;
}

/* Buttons with the arrow-right.svg icon after the label (header, article
   CTA, terms of sale - the theme files and their Site Editor copies set
   the icon inline with vertical-align:middle, which centres it on the
   lowercase letters and left it ~2px low). Flex centres it on the whole
   line instead; the gap replaces the icon's inline margin. */
.wp-block-button__link:has(> img[src*="arrow-right.svg"]) {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
}

.wp-block-button__link > img[src*="arrow-right.svg"] {
  flex-shrink: 0;
  margin-left: 0 !important;
}

/* Card CTA links (Price and Grants, Services) use a distinct blue (#006fdc)
   in the design, not the site-wide link color (--brand-cyan, used for body
   copy links elsewhere), so they need their own hover state rather than
   relying on theme.json's global link :hover (brand-navy), which would
   clash against this blue instead of reading as a deliberate hover shift. */
.card-link a {
  font-weight: 500;
  color: #006fdc;
  transition: color 0.2s ease;
}

.card-link a:hover {
  color: var(--wp--preset--color--brand-navy);
}

/* Services "Have these checks done before you book service" toggle
   (patterns/services-product-checklist.php) - a native <details> so it
   works without JS. The arrow is arrow-right.svg as a mask so it takes the
   label's blue, turned to point down when closed and up when open. It is
   sized to its label, not stretched like the rest of its column. */
.service-checks {
  align-self: flex-start;
  max-width: 100%;
  box-sizing: border-box;
  background-color: #d3f1fe;
  border-radius: 20px;
  padding: 20px;
}

.service-checks > summary {
  display: flex;
  align-items: center;
  gap: 10px;
  color: #006fdc;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.56;
  letter-spacing: -0.005em;
  cursor: pointer;
  list-style: none;
}

.service-checks > summary::-webkit-details-marker {
  display: none;
}

.service-checks > summary::after {
  content: "";
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  background-color: currentcolor;
  mask: url("assets/icons/arrow-right.svg") center / contain no-repeat;
  transform: rotate(90deg);
  transition: transform 0.3s ease;
}

.service-checks[open] > summary::after {
  transform: rotate(-90deg);
}

.service-checks > summary:focus-visible {
  outline: 2px solid #006fdc;
  outline-offset: 4px;
  border-radius: 4px;
}

.service-checks > .wp-block-group {
  margin-top: 20px;
}

/* Slide open/closed where the browser can animate to auto height
   (Chromium 131+); elsewhere the list just appears. */
@supports (interpolate-size: allow-keywords) {
  .service-checks {
    interpolate-size: allow-keywords;
  }

  .service-checks::details-content {
    block-size: 0;
    overflow: hidden;
    transition: block-size 0.3s ease, content-visibility 0.3s allow-discrete;
  }

  .service-checks[open]::details-content {
    block-size: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .service-checks > summary::after,
  .service-checks::details-content {
    transition: none;
  }
}

/* Footer social links (parts/footer.html) - the design uses outlined icon
   art supplied as SVG files, not WordPress core's own filled wp:social-link
   icon set, so this is plain markup rather than that block. */
.footer-social-links a {
  display: flex;
  opacity: 0.85;
  transition: opacity 0.2s ease;
}

.footer-social-links a:hover {
  opacity: 1;
}

/* Phones and tablets: the social icons (20px in the footer, 16px in the
   Socials section) were too small to tap. Each link's tap area grows to
   44 x 44px; the same negative margin keeps the icons where they were (the
   footer icons are 44px apart, so their tap areas meet without overlapping).
   The footer saved in the Site Editor builds its icons from image blocks,
   hence the second selector. */
@media (max-width: 1024px) {
  .footer-social-links a,
  footer .wp-block-image a:has(> img[src*="/icons/footer-"]),
  .wp-block-social-links .wp-social-link a {
    box-sizing: border-box;
    min-width: 44px;
    min-height: 44px;
    align-items: center;
    justify-content: center;
  }

  .footer-social-links a,
  footer .wp-block-image a:has(> img[src*="/icons/footer-"]) {
    display: flex;
    margin: -12px;
  }

  .wp-block-social-links .wp-social-link a {
    display: flex;
    margin: -14px;
  }
}

/* Footer bottom bar (parts/footer.html) - copyright, "Powered by
   Kilowott" and "Privacy Policy / Terms" are meant to read as one
   uniform muted line, but "Kilowott"/"Privacy Policy"/"Terms" are
   real links, so they were picking up the theme's global `a { color:
   var(--color-primary) }` link color (a bright blue) instead of
   matching their own paragraph's muted on-dark color - and had no
   hover state of their own as a result either. */
.footer-bottom-bar a {
  color: inherit;
  text-decoration: none;
  transition: color 0.2s ease;
}

.footer-bottom-bar a:hover {
  color: var(--wp--preset--color--surface-white);
}

/* The GTranslate language switcher floats at the bottom left (45px tall;
   on phones just above the call/booking bar), so at the end of the page it
   covered the copyright line and the Privacy / Terms / Cookie settings
   links. The bar ends far enough up for the switcher to sit below it. */
.footer-bottom-bar {
  padding-bottom: 64px;
}

/* Section wrappers have fixed desktop padding (40-120px); cut on mobile to
   avoid huge gaps. A wrapper deliberately set to 0 keeps it - the service
   page content wrapper's 0 bottom padding is what lets its last navy
   section meet the navy Other Services section below; forcing 40px left a
   white band between them on phones. */
@media (max-width: 600px) {
  main.wp-block-group > .wp-block-group:not([style*="padding-top:0"]) {
    padding-top: 40px !important;
  }

  /* Not the breadcrumb wrapper at the top of a page, where that raised the
     template's 32px instead: it and <main>'s 24px block gap left ~64px
     between the header and the breadcrumb. */
  main.wp-block-group > .wp-block-group:has(> .content-page-breadcrumb):first-child,
  main.wp-block-group:has(> .content-page-breadcrumb:first-child) {
    padding-top: 20px !important;
  }

  .wp-site-blocks > main.wp-block-group:has(> .wp-block-group:first-child > .content-page-breadcrumb),
  .wp-site-blocks > main.wp-block-group:has(> .content-page-breadcrumb:first-child) {
    margin-block-start: 0;
  }

  main.wp-block-group > .wp-block-group:not([style*="padding-bottom:0"]) {
    padding-bottom: 40px !important;
  }
}

/* The rule above only reaches sections directly inside <main>. Sections
   one level further in - inside a service page's content, or a section's
   own inner group - kept their 60-120px desktop padding on phones, which
   (with the next section's) left 130-200px gaps. Any group padded that
   much gets the same 40px on phones; cards (20-40px) are untouched. */
@media (max-width: 600px) {
  main .wp-block-group[style*="padding-top:60px"],
  main .wp-block-group[style*="padding-top:64px"],
  main .wp-block-group[style*="padding-top:80px"],
  main .wp-block-group[style*="padding-top:88px"],
  main .wp-block-group[style*="padding-top:96px"],
  main .wp-block-group[style*="padding-top:100px"],
  main .wp-block-group[style*="padding-top:120px"] {
    padding-top: 40px !important;
  }

  main .wp-block-group[style*="padding-bottom:60px"],
  main .wp-block-group[style*="padding-bottom:64px"],
  main .wp-block-group[style*="padding-bottom:80px"],
  main .wp-block-group[style*="padding-bottom:88px"],
  main .wp-block-group[style*="padding-bottom:96px"],
  main .wp-block-group[style*="padding-bottom:100px"],
  main .wp-block-group[style*="padding-bottom:120px"] {
    padding-bottom: 40px !important;
  }
}

/* Safeguard against the Elfsight Instagram embed (Socials section) forcing
   horizontal scroll - any Elfsight app, so swapping the feed keeps it. */
[class*="elfsight-app-"],
.eapps-widget {
  max-width: 100%;
  overflow-x: hidden;
}

/* Testimonials review-source logos (Mittanbud/Google/Trustpilot): height-constrained,
   width auto - prevents cropping when a logo's aspect ratio doesn't match a fixed box. */
.testimonial-card.is-style-stat .wp-block-image img {
  width: auto !important;
  object-fit: contain !important;
}

/* Content Page's post-title/entry-content get capped at 700px by the generic
   .is-layout-constrained rule (theme.json's global content-size var) - it
   beats the block's own 1080px per-instance rule since both use :where()
   (zero specificity) and the generic one loads later. */
.content-page-inner .wp-block-post-title,
.content-page-inner .entry-content,
.content-page-inner .entry-content > :not(.alignleft, .alignright, .alignfull) {
  max-width: 1080px !important;
}

/* About page's hero relies on a wrapper block for its 1280px/padding
   constraint - that wrapper has no visible UI in the editor, so ordinary
   edits nearby silently drop it (has happened twice). Enforcing the
   constraint here in CSS instead survives regardless of the page's own
   block structure. */
.page-template-page-about .hero-row {
  max-width: 1280px;
  margin-left: auto;
  margin-right: auto;
  box-sizing: border-box;
}

/* Equal-height "What you can expect" cards - the columns already stretch
   to match the tallest one, but each card only grew to its own content
   height rather than filling the stretched column. Per Figma the cards are
   302px tall, with the icon and title at the top and the description at
   the bottom, and padding 28 / 56 / 28 / 24px. */
.about-expect-card {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 302px;
  padding: 28px 56px 28px 24px !important;
  box-sizing: border-box;
}

.about-expect-card > p:last-child {
  margin-top: auto;
  color: #6a727e !important;
}

@media (max-width: 781px) {
  .about-expect-card {
    min-height: 0;
    padding-right: 24px !important;
  }
}

/* Career "Let's talk anyway" card (patterns/career-openings.php): the
   call-us block and the Book button share a no-wrap row, which on phones
   squeezed the number onto three lines and pushed the button off-screen.
   Matched by structure (phone icon + buttons) because the page's saved
   Site Editor copy has no class to hook onto. */
@media (max-width: 600px) {
  .wp-block-group.is-nowrap:has(> .wp-block-buttons):has(img[src*="icon-phone.svg"]) {
    flex-wrap: wrap;
  }

  .wp-block-group.is-nowrap:has(> .wp-block-buttons):has(img[src*="icon-phone.svg"]) p {
    white-space: nowrap;
  }
}

/* Career search bar: full-width pill input per design, not the narrow
   flex-content-width box wp:group's default layout produces. Explicit
   flex here since this is a wp:html block - WordPress's normal
   is-layout-flex classes/CSS never get applied to raw HTML content. */
.career-search-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  max-width: 846px;
  margin-left: auto;
  margin-right: auto;
}

.career-search-bar svg {
  flex-shrink: 0;
}

/* Career search input replaces a static label - not styled by any wp:paragraph
   block, so its type/size/color are set directly to match. */
.career-search-input {
  border: 0;
  background: transparent;
  outline: none;
  width: 100%;
  padding: 12px 0;
  font-family: var(--wp--preset--font-family--sans);
  font-size: 14px;
  color: var(--wp--preset--color--text-heading);
}

.career-search-input::placeholder {
  color: var(--wp--preset--color--text-muted);
}

/* Career listing category tags: rounded cyan "bulb" pills per design,
   not plain unstyled text. */
.career-listing-tag {
  background: var(--wp--preset--color--surface-mist);
  color: var(--wp--preset--color--text-body);
  border-radius: 100px;
  padding: 4px 12px;
  margin: 0;
}

/* "What it's like working with us" cards - equal height like the other
   3-card grids, and the icon chip badge overlaps the bottom-right of the
   photo per design (same convention as .service-card-icon-chip). */
.career-why-card {
  height: 100%;
  overflow: hidden;
  box-sizing: border-box;
}

.career-why-card-media {
  position: relative;
}

/* Same fix as .service-card-media img - a real uploaded photo's own
   width/height HTML attributes cap how far the global img{max-width:100%}
   rule can scale it, which only ever shrinks, never grows, an image back
   up to fill a wider card (e.g. once these cards stack full-width below
   the mobile breakpoint). */
.career-why-card-media img {
  width: 100%;
}

.career-why-card-icon-chip {
  position: absolute;
  right: 16px;
  bottom: 16px;
  margin: 0;
  border-radius: 50%;
  box-shadow: 0 4px 10px rgb(28 36 75 / 10%);
}

/* Career listing row: tags on the left, description filling the middle,
   Apply button on the right - all on one line, not stacked. The block's
   own layout attribute has no flexWrap set, so Gutenberg defaults it to
   wrap, which let the row wrap early and left Apply stranded instead of
   flush right - nowrap plus a non-shrinking button forces the intended
   single-row layout. */
.career-listing-row {
  width: 100%;
  flex-wrap: nowrap;
  gap: 24px;
}

.career-listing-tags {
  flex-shrink: 0;
}

.career-listing-description {
  flex: 1 1 auto;
  min-width: 0;
  margin: 0;
}

.career-listing-row .wp-block-buttons {
  flex-shrink: 0;
}

@media (max-width: 900px) {
  .career-listing-row {
    flex-flow: column wrap;
    align-items: flex-start;
  }
}

/* Homepage map/location section - the cover holds a client-uploaded video
   (same empty-cover-as-media-placeholder convention as .hero-media, kept
   with no inner content so its saved markup matches the block's own
   output exactly - anything nested inside wp-block-cover__inner-container
   made the block fail Gutenberg's validation and get stuck in "attempt
   recovery"). The "Open in Maps" link is a sibling of the cover instead,
   positioned over it via the shared .map-location-wrap. */
.map-location-wrap {
  position: relative;
}

.map-location-media {
  width: 100%;
  overflow: hidden;
}

/* The map video has a thin dark band along its top edge. In the
   narrower map column on the About and Contact pages, object-fit:cover
   crops less of the height, so the band showed - a slight zoom crops
   it on every page. */
.map-location-media .wp-block-cover__video-background {
  transform: scale(1.03);
}

.map-location-open-link {
  position: absolute;
  top: 24px;
  right: 24px;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background-color: var(--wp--preset--color--surface-white);
  color: #22406f;
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  padding: 8px;
  border-radius: 8px;
  box-shadow: 0 4px 4px rgb(0 0 0 / 16%);
  transition: background-color 0.2s ease;
}

.map-location-open-link:hover {
  background-color: var(--wp--preset--color--surface-mist);
}

/* Services & Product listing: the services grid is built from a live
   WP_Query loop (patterns/services-product-grid.php) rather than static
   wp:columns blocks, since the count depends on how many "service" CPT
   entries exist - so it needs its own flex/wrap rules instead of relying
   on Gutenberg's generated column classes. 3 per row, wrapping to fewer
   on the last row and stacking on mobile, matching the Figma grid.

   max-width:1280px (not none) overrides WordPress core's own
   ".is-layout-constrained > :where(...)" rule, which applies
   --wp--style--global--content-size (this theme's default is 700px) to
   EVERY direct child of a constrained group - .services-grid is plain
   HTML (not a real block with its own layout attribute to opt out
   with), so once it became a direct child of a constrained wrapper
   after the dynamic pattern's content got flattened by a Site Editor
   save, it inherited that 700px cap instead of the 1280px the section
   is meant to use. A plain max-width:none (tried first) isn't enough
   on its own either: margin:auto only centers an element that's
   narrower than its container, and with no max-width at all
   .services-grid just fills 100% of its parent's width, leaving
   nothing for margin:auto to center - it needs an explicit 1280px cap
   of its own to both escape the 700px default AND stay centered/
   aligned with the heading row above it (this class is reused by
   patterns/single-service-other-services.php as well as the listing
   page this comment was originally written for). */
.services-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 40px 25px;
  max-width: 1280px;
  margin-left: auto;
  margin-right: auto;
}

/* flex-grow:0 (not 1) is deliberate - a partial last row (e.g. 2 cards
   when there are 5 services) should stay the same width as every other
   card and leave the remaining row width empty, matching the Figma
   grid, rather than stretching to fill the row. */
.services-grid-item {
  flex: 0 1 calc(33.333% - 17px);
  min-width: 300px;
}

/* .service-card and its children normally get display:flex from
   Gutenberg's own is-layout-flex class when authored as real blocks
   (see patterns/services.php) - the dynamic grid in
   services-product-grid.php writes plain HTML instead (it has to, since
   the card count depends on how many "service" posts exist), so that
   flex behavior has to be declared explicitly here. */
.services-grid-item .service-card {
  display: flex;
  flex-direction: column;
  gap: 20px;
}

/* "Other services" cards on single service pages (homeowner and business -
   business singles get .single-service too) have no border. The card markup sets border-width inline - and the saved
   snapshots of that section in the database carry the same inline style -
   so !important is needed to override it. */
.single-service .services-grid-item .service-card {
  border-width: 0 !important;
}

.services-grid-item .service-card-body {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 12px;
}

@media (max-width: 782px) {
  .services-grid-item {
    flex: 1 1 100%;
  }
}

/* Dynamic service cards (Services & Product, Contact, Other Services),
   per the Figma Card: 40px between rows, a 20px gap under the photo,
   title and description kept together (12px apart) with the link pinned
   to the card's bottom edge - the body's space-between used to spread
   all three evenly, leaving a large gap under the title. The gaps are
   set on .services-grid and its card rules above. */
.services-grid-item .service-card-body > * {
  margin: 0;
}

.services-grid-item .service-card-body h5 {
  font-size: 20px;
  line-height: 1.35;
  color: #10141b;
}

.services-grid-item .service-card-body > p:not(.card-link) {
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: #6a727e;
}

.services-grid-item .service-card-body > .card-link {
  margin-top: auto;
  padding-top: 12px;
}

.services-grid-item .card-link a {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  text-decoration: none;
}

/* Arrow icon in the link's own colour (so it follows the hover colour). */
.services-grid-item .card-link a::after {
  content: "";
  width: 16px;
  height: 16px;
  background-color: currentcolor;
  mask: url("assets/icons/arrow-right.svg") center / contain no-repeat;
}

/* Services & Product heading row: intro text sits level with the bottom
   of the heading, in the design's grey. Also covers the Site Editor's
   saved copy of this row, which still says verticalAlignment:center. */
.section-heading-row:has(> .services-heading-row-body) {
  align-items: flex-end;
}

.services-heading-row-body {
  color: #45454e !important;
}

/* "Not sure which system fits your home?" card - the services grid's last
   item on the Services & Product page (patterns/services-product-grid.php). */
.services-cta-card {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 20px;
  height: 100%;
  min-height: 489px;
  padding: 30px;
  box-sizing: border-box;
  background-color: #f5f6f9;
  border-radius: 20px;
}

/* The card is a Group block: its flow layout's block gap would add to the
   flex gap above. */
.services-cta-card > * {
  margin-top: 0;
}

.services-cta-card-title {
  margin: 0;
  font-size: 32px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.16px;
  color: #111112;
}

.services-cta-card-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 0 0 8px;
  padding: 0;
  list-style: none;
}

.services-cta-card-list li {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: #1c244b;
}

.services-cta-card-list li::before {
  content: "";
  flex: 0 0 20px;
  height: 20px;
  background: url("assets/icons/tick.svg") center / 16px 12px no-repeat;
}

/* The buttons are core Button blocks (editable in the Site Editor), so the
   pill styles go on each one's link rather than the wrapper. */
.services-cta-card-buttons {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 16px;
}

.services-cta-card-button {
  width: 100%;
}

.services-cta-card-button > .wp-block-button__link {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  width: 100%;
  min-height: 44px;
  padding: 11px 18px 11px 24px;
  box-sizing: border-box;
  border: 1px solid transparent;
  border-radius: 100px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: #2c2c2c;
  text-decoration: none;
  transition: filter var(--transition), background-color var(--transition);
}

.services-cta-card-button > .wp-block-button__link::after {
  content: "";
  width: 16px;
  height: 16px;
  background: url("assets/icons/arrow-right.svg") center / contain no-repeat;
}

.services-cta-card-button.is-primary > .wp-block-button__link {
  background-color: var(--wp--preset--color--brand-cyan);
}

.services-cta-card-button.is-primary > .wp-block-button__link:hover {
  filter: brightness(0.9);
}

.services-cta-card-button.is-outline > .wp-block-button__link {
  background-color: var(--wp--preset--color--surface-white);
  border-color: #2c2c2c;
}

.services-cta-card-button.is-outline > .wp-block-button__link:hover {
  background-color: var(--wp--preset--color--surface-mist);
}

@media (max-width: 782px) {
  .services-cta-card {
    min-height: 0;
  }
}

/* Services & Product listing: product grid + brand filter pills
   (patterns/services-product-grid.php's sibling, services-product-products.php).
   Cards are plain bordered tiles with a brand eyebrow label, name and
   short description - simpler than .service-card, no icon chip overlay. */

/* The pills sit inside a wp:html block (they're not real Gutenberg
   blocks, since the brand list is built from the service_brand
   taxonomy at render time), so there's no blockGap between it and the
   .products-grid sibling below - they were rendering flush against the
   cards with zero space between. margin-bottom adds that spacing back. */
.product-filter-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin-bottom: 40px;
}

.product-filter-pill {
  border: 1px solid #eaeaee;
  border-radius: 999px;
  padding: 5px 20px;
  font-family: inherit;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.56;
  background-color: var(--wp--preset--color--surface-white);
  cursor: pointer;
  color: #45454e;
  transition: background-color var(--transition), border-color var(--transition);
}

.product-filter-pill:not(.is-active):hover {
  border-color: #c9ced6;
}

.product-filter-pill.is-active {
  background-color: #22406f;
  color: var(--wp--preset--color--surface-white);
  border-color: #22406f;
  font-weight: 600;
  letter-spacing: -0.07px;
}

/* Same max-width:none override as .services-grid above, and for the
   same reason - a direct child of an is-layout-constrained wrapper
   otherwise inherits the theme's 700px global content-size default.
   Here that direct child is the wp:html block's own wrapper
   (.wp-block-html), one level further out than .products-grid itself,
   so it needs the same override or .products-grid (width:auto) just
   shrinks to match its still-capped parent. */
.wp-block-html:has(.products-grid) {
  max-width: none;
}

.products-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 40px 25px;
  max-width: none;
}

/* "View all products" under the two visible rows (js/product-filter.js
   points it at the selected brand's products). */
.products-grid-more {
  display: flex;
  justify-content: center;
  margin-top: 40px;
}

.products-grid-more-button {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 13px 18px 13px 24px;
  box-sizing: border-box;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: #2c2c2c;
  text-decoration: none;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid #2c2c2c;
  border-radius: 100px;
  transition: background-color var(--transition);
}

.products-grid-more-button:hover {
  background-color: var(--wp--preset--color--surface-mist);
}

/* Per the Figma "Section 3 - Products" card: four to a row, a white card
   with a hairline border and 20px corners, the product photo centred in a
   rounded panel with an optional tag chip in its corner, then brand and
   name beside a round arrow. flex-grow:0 (not 1) so a partial last row
   doesn't stretch its cards wider than every other row, matching the
   services grid fix above. */
.product-card {
  flex: 0 1 calc(25% - 18.75px);
  min-width: 220px;
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  gap: 24px;
  padding: 16px 8px;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid #eaeaee;
  border-radius: 20px;
  color: inherit;
  text-decoration: none;
  transition: border-color var(--transition), box-shadow var(--transition);
}

.product-card:hover {
  border-color: #d5dbe3;
  box-shadow: 0 12px 32px rgb(28 36 75 / 8%);
}

.product-card-media {
  position: relative;
  height: 290px;
  overflow: hidden;
  border-radius: 15px;
}

/* The whole product, centred in the panel - scaled to fit, never cropped
   (most product images are cut-outs, which cover-cropping clipped). */
.product-card-media img {
  display: block;
  width: 100%;
  height: 100%;
  box-sizing: border-box;
  padding: 24px;
  object-fit: contain;
  object-position: center;
  border-radius: 0;
}

.product-card-tag {
  position: absolute;
  top: 12px;
  left: 12px;
  max-width: calc(100% - 24px);
  box-sizing: border-box;
  padding: 6px 12px;
  overflow: hidden;
  font-size: 12px;
  line-height: 1.56;
  color: #45454e;
  white-space: nowrap;
  text-overflow: ellipsis;
  background-color: #e6f7fd;
  border: 1px solid var(--wp--preset--color--brand-cyan);
  border-radius: 100px;
}

.product-card-body {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 0 6px;
}

.product-card-text {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.product-card-brand {
  margin: 0;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.72px;
  text-transform: uppercase;
  color: #006fdc;
}

/* One line, as in the design - product names vary a lot in length
   ("Panasonic HZ" vs "Mitsubishi Electric Gussuri"), and an ellipsis keeps
   every card in a row the same height. */
.product-card-title {
  margin: 0;
  overflow: hidden;
  font-size: 20px;
  font-weight: 700;
  line-height: 1.56;
  color: #10141b;
  white-space: nowrap;
  text-overflow: ellipsis;
  transition: color var(--transition);
}

.product-card:hover .product-card-title {
  color: #006fdc;
}

.product-card-arrow {
  display: flex;
  flex: 0 0 40px;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  color: var(--wp--preset--color--surface-white);
  background-color: #006fdc;
  border-radius: 50%;
  transition: transform var(--transition);
}

.product-card:hover .product-card-arrow {
  transform: translate(2px, -2px);
}

@media (max-width: 1100px) {
  /* Three to a row: two 25px gaps shared across three cards. */
  .product-card {
    flex-basis: calc(33.333% - 16.67px);
  }
}

@media (max-width: 782px) {
  /* Half of the 25px column gap, so two cards fit per row. */
  .product-card {
    flex: 1 1 calc(50% - 12.5px);
    min-width: 0;
  }

  .product-card-media {
    height: 240px;
  }
}

@media (max-width: 480px) {
  .product-card {
    flex: 1 1 100%;
  }
}

/* Single service page: numbered benefits list (patterns/service-benefits.php).
   Each row's first group (number + label) needs a fixed-ish width so the
   description column lines up across rows, matching the Figma table-like
   layout - space-between alone left the description's start position
   drifting per row based on each label's own text length. */
.service-benefit-row > *:first-child {
  flex: 0 0 340px;
}

/* Dividers between rows. The pattern sets one per row inline, all but the
   last - so a row added by copying the last one (as on Air-to-water) left
   the row above it without a divider. Drawn here instead: under every row
   but the last, however many rows there are. */
.service-benefits-list > .service-benefit-row:not(:last-child) {
  border-bottom: 1px solid #e1e4e8 !important;
}

.service-benefits-list > .service-benefit-row:last-child {
  border-bottom-width: 0 !important;
}

/* A 280px basis, not auto: sized to its full text, a longer description
   (as in Norwegian) didn't fit beside the label and dropped under it on
   desktop, out of line with the other rows. It now wraps its own text and
   only moves under the label when less than 280px is left. */
.service-benefit-row > *:last-child {
  flex: 1 1 280px;
  min-width: 0;
  margin: 0;
}

/* 180px between the label and description columns on desktop, scaling
   down on narrower screens so the description isn't squeezed onto its own
   line early. Only the column gap - the gap between wrapped lines on
   mobile stays as it was. */
.single-service .service-benefit-row {
  column-gap: clamp(40px, 12.5vw, 180px);
}

@media (max-width: 600px) {
  .service-benefit-row > *:first-child {
    flex: 1 1 100%;
  }
}

/* Single service page: FAQ-style accordion (patterns/service-additional-info.php).
   Only one row's answer paragraph is shown at a time; js/service-accordion.js
   toggles the is-open class and the +/- icon per row on click. */
.service-accordion-row {
  border-bottom: 1px solid #e1e4e8;
  padding: 18px 0;
}

.service-accordion-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  background: none;
  border: none;
  padding: 0;
  cursor: pointer;
  gap: 16px;
  text-align: left;
  font-family: inherit;
  font-size: 16px;
  font-weight: 600;
  line-height: 1.4;
  color: var(--wp--preset--color--text-heading);
}

.service-accordion-icon {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  position: relative;
}

.service-accordion-icon::before,
.service-accordion-icon::after {
  content: "";
  position: absolute;
  background-color: var(--wp--preset--color--brand-cyan);
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.service-accordion-icon::before {
  width: 12px;
  height: 2px;
}

.service-accordion-icon::after {
  width: 2px;
  height: 12px;
  transition: transform 0.15s ease;
}

.service-accordion-row.is-open .service-accordion-icon::after {
  transform: translate(-50%, -50%) scaleY(0);
}

.service-accordion-answer {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.2s ease;
}

.service-accordion-row.is-open .service-accordion-answer {
  max-height: 400px;
}

/* .service-accordion-row in the selector outranks .entry-content
   p:first-child, which had set the gap under the title to 0. */
.service-accordion-row .service-accordion-answer p {
  margin: 10px 0 0;
  font-size: 14px;
  line-height: 1.56;
  color: var(--wp--preset--color--text-body);
}

/* Single service page: colored full-bleed sections (Benefits,
   Specifications, Other Services) live inside wp:post-content, which
   single-service.html wraps in its own contentSize:1280px group - so
   their own background can never reach the viewport edge on its own,
   unlike a pattern placed directly in the template (e.g. trust-proof.php
   on the homepage). This breaks a section out to full width while
   its own inner content stays centered at 1280px, the standard
   full-bleed-within-a-constrained-parent technique. */
.service-section-full-bleed {
  width: 100vw;
  margin-left: calc(50% - 50vw);
  margin-right: calc(50% - 50vw);
}

/* The section's own inner contentSize:1280px group has no horizontal
   padding of its own (unlike a normal in-flow section, which inherits
   the site's has-global-padding 16px via its constrained ancestor) -
   below ~1280px + that padding, its content (heading, cards) sits
   flush against the true viewport edge instead of getting the same
   breathing room every other section has. */
.service-section-full-bleed > .wp-block-group {
  padding-left: 16px;
  padding-right: 16px;
}

/* Benefits is the only full-bleed section with visible breathing room
   above it in the design - Specifications and Other Services are meant
   to sit flush against whatever precedes them (Specifications directly
   under the accordion, Other Services flush against Specifications,
   both navy-on-navy). Scoped to a second class rather than the shared
   .service-section-full-bleed so this doesn't reintroduce the gap
   deliberately removed between Specifications and Other Services. */
.service-section-full-bleed-spaced {
  margin-top: 40px;
}

/* In the editor the breakout would push the section past the canvas and
   off-centre, so it stays in the normal content width there. */
.editor-styles-wrapper .service-section-full-bleed {
  width: auto;
  margin-left: 0;
  margin-right: 0;
}

/* Editor-only notes from kw_block_editor_notice() - shown where a dynamic
   block has nothing to render in the editor (e.g. a template with no product
   or partner in context), or above the service cards and product grid to
   say where their content is edited. */
.kw-block-notice {
  display: none;
}

.editor-styles-wrapper .kw-block-notice {
  display: block;
  margin-bottom: 16px;
  padding: 12px 16px;
  font-family: var(--wp--preset--font-family--sans);
  font-size: 13px;
  font-weight: 600;
  line-height: 1.5;
  color: #92400e;
  background-color: #fef3c7;
  border: 1px dashed #d97706;
  border-radius: 6px;
}

/* Widen the block editor's canvas - the theme's 700px contentSize
   (theme.json) is meant for the front end's narrow-measure body copy
   blocks, but the same value caps the editor's own "paper" width for
   post types like "service", making the canvas cramped for editing
   wide, multi-column layouts (hero images, spec cards, etc.). Editor-
   only via .editor-styles-wrapper, so the front end's own contentSize
   is untouched. !important because Gutenberg generates its own
   per-block max-width rule for the root container inline (the same
   mechanism as its wp-container-core-* rules on the front end), which
   this needs to beat regardless of source order. */
.editor-styles-wrapper .is-root-container {
  max-width: 1280px !important;
}

/* Single service page: Technical specifications (patterns/service-specifications.php).
   The 2x2 card grid needs to (a) match the left-hand image's height overall
   and (b) have every card the same height as its row-mate, regardless of
   how much each card's own copy wraps. are-vertically-aligned-stretch on
   the outer columns block only stretches its own direct children to equal
   height (the image column and the cards column) - it doesn't cascade
   into the cards column's own nested rows, so each of those needs
   height:100% explicitly, and each inner cards-row needs flex:1 so the
   two rows split that height evenly between them. */
.service-specs-cards {
  display: flex;
  flex-direction: column;
}

.service-specs-cards-row {
  flex: 1 1 auto;
}

.service-specs-cards-row .wp-block-column {
  display: flex;
}

.service-specs-card {
  height: 100%;
  box-sizing: border-box;
}

/* Stacked (below 782px): each card sat in a display:flex column, so it
   shrank to its own copy's width and the four cards came out ragged; the
   photo likewise stopped short of the column's right edge. Both fill the
   column instead. */
@media (max-width: 781px) {
  .service-specs-card {
    width: 100%;
  }

  .service-specs-media .wp-block-image,
  .service-specs-media .wp-block-image img {
    width: 100%;
  }
}

/* Single service page: wp:post-content applies the theme's default
   block-gap as margin-top between each authored pattern, which also
   leaves a trailing margin-bottom-equivalent gap after the LAST one
   (Technical specifications, a full-bleed navy section) before the
   immediately-following Other Services pattern (also navy) - visible
   as an unwanted sliver of white between two navy sections that should
   sit flush together. Fixing the trailing gap inside wp:post-content
   isn't enough on its own: main's own default block-gap still adds
   margin-top to the Other Services pattern, since it's main's next
   direct child sibling after the wp:post-content wrapper group, not a
   descendant of it - so that margin has to be zeroed separately. */
.wp-block-post-content > *:last-child {
  margin-bottom: 0;
}

main:has(.wp-block-post-content) > .wp-block-group:has(> .wp-block-post-content) + * {
  margin-top: 0;
}

/* ==========================================================================
   Blog - listing (templates/home.html, templates/category.html,
   parts/blog-listing.html) and article (templates/single.html).
   ========================================================================== */

/* The listing and article templates put their sections straight inside
   <main>, whose flow layout would otherwise add 24px between each one. */
.blog-listing-page > *,
.blog-article-page > * {
  margin-block-start: 0;
}

/* The design puts the breadcrumb 16px under the header - drop the 24px
   block gap WordPress adds between the header and <main>. */
.wp-site-blocks > .blog-listing-page,
.wp-site-blocks > .blog-article-page {
  margin-block-start: 0;
}

/* Breadcrumb - every template using .blog-breadcrumb (blog, products,
   product and partner pages, contact). Styled to match the pages'
   .content-page-breadcrumb (small text in text-muted, the current page in
   text-heading), so the trail looks the same on every page. */
.blog-breadcrumb p,
.blog-breadcrumb .wp-block-post-title,
.blog-breadcrumb .wp-block-query-title,
.blog-breadcrumb .product-breadcrumb-brand {
  margin: 0;
  font-size: var(--wp--preset--font-size--small);
  font-weight: 400;
  line-height: 1.56;
  letter-spacing: normal;
  color: var(--wp--preset--color--text-muted);
}

/* Same distance from the header as .content-page-breadcrumb: 56px on
   desktop, 20px on phones. These templates' breadcrumb wrapper sets 16px
   inline. */
body .wp-block-group:has(> .blog-breadcrumb:first-child) {
  padding-top: 56px !important;
}

@media (max-width: 600px) {
  body .wp-block-group:has(> .blog-breadcrumb:first-child) {
    padding-top: 20px !important;
  }

  /* Blog posts wrap it once more, in a section the phone section padding
     also reaches. */
  body main.wp-block-group > .wp-block-group:has(> .wp-block-group > .blog-breadcrumb:first-child) {
    padding-top: 0 !important;
  }
}

.blog-breadcrumb a {
  color: inherit;
  text-decoration: none;
  transition: color 0.2s ease;
}

.blog-breadcrumb a:hover {
  color: var(--wp--preset--color--text-heading);
}

.blog-breadcrumb .blog-breadcrumb-current {
  color: var(--wp--preset--color--text-heading);
}

/* The current page - the trail's last item - in SemiBold (Figma
   Breadcrumbs/M), the earlier items Regular. */
.blog-breadcrumb > :last-child,
.content-page-breadcrumb > :last-child {
  font-weight: 600;
}

/* Breadcrumbs (.blog-breadcrumb and the pages' .content-page-breadcrumb)
   on narrow screens: a flex row wraps each item inside its own column, so a
   long item breaks mid-way and leaves gaps. There the trail flows as one
   line of text instead, breaking at the line's end. */
@media (max-width: 781px) {
  .blog-breadcrumb,
  .content-page-breadcrumb {
    display: block !important;
  }

  .blog-breadcrumb > *,
  .content-page-breadcrumb > * {
    display: inline;
    margin: 0 4px 0 0 !important;
    line-height: 1.6;
  }
}

/* Category filter pills */
.blog-category-filter ul {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 8px 24px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.blog-category-filter a {
  font-size: 16px;
  line-height: 1.56;
  color: var(--wp--preset--color--text-muted);
  text-decoration: none;
  transition: color 0.2s ease;
}

.blog-category-filter a:hover,
.blog-category-filter a.is-active {
  color: var(--wp--preset--color--text-heading);
}

.blog-category-filter a.is-active {
  font-weight: 600;
}

/* Card grid - 3 per row. The first post on each page is the featured
   card spanning the full row. */
.blog-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 40px 25px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.blog-grid > li {
  margin: 0;
}

.blog-card {
  position: relative;
  display: flex;
  flex-direction: column;
  height: 100%;
  overflow: hidden;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid var(--wp--preset--color--border);
  border-radius: 12px;
  transition: box-shadow 0.2s ease;
}

.blog-card:hover {
  box-shadow: 0 8px 24px rgb(16 20 27 / 8%);
}

.blog-card > * {
  margin-block: 0;
}

.blog-card-media {
  margin: 0;
  overflow: hidden;
}

.blog-card-media img {
  display: block;
  width: 100%;
  transition: transform 0.3s ease;
}

.blog-card-body {
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 20px 48px 42px 24px;
}

.blog-card-body > * {
  margin-block: 0;
}

.blog-card-category,
.blog-article-category {
  position: relative;
  z-index: 2;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.72px;
  text-transform: uppercase;
  color: #006fdc;
}

.blog-card-category {
  margin: 0 0 14px;
}

.blog-card-category a,
.blog-article-category a {
  color: inherit;
  text-decoration: none;
}

.blog-card-category a:hover,
.blog-article-category a:hover {
  text-decoration: underline;
}

.blog-card-title {
  margin: 0;
  overflow: hidden;
  font-size: 20px;
  font-weight: 600;
  line-height: 1.35;
  color: #10141b;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.blog-card-title a {
  display: inline;
  color: inherit;
  text-decoration: none;
  transition: color 0.2s ease;
}

/* The title link covers the whole card so the image and white space are
   clickable too; category and "Read more" sit above it at z-index 2. */
.blog-card-title a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}

.blog-card:hover .blog-card-title a {
  color: #006fdc;
}

/* The design reserves a 70px excerpt box so cards stay equal height -
   set on the wrapper, since min-height on the clamped paragraph itself
   exposes the top of a 4th line. */
.blog-card-excerpt {
  min-height: 70px;
}

.blog-card-excerpt p {
  display: -webkit-box;
  margin: 0;
  overflow: hidden;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: #6a727e;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
}

.blog-card-meta,
.blog-card-meta p {
  margin: 0;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.72px;
  color: var(--wp--preset--color--text-muted);
}

.blog-meta-separator {
  margin: 0;
}

.blog-card-read-more {
  display: none;
}

/* Featured card (first post on the page) */
.blog-grid > li:first-child {
  grid-column: 1 / -1;
  margin-bottom: 32px;
}

.blog-grid > li:first-child .blog-card {
  justify-content: flex-end;
  height: 400px;
  border: 0;
}

.blog-grid > li:first-child .blog-card-media {
  position: absolute;
  inset: 0;
  height: 100% !important;
}

.blog-grid > li:first-child .blog-card-media img {
  height: 100% !important;
}

.blog-grid > li:first-child .blog-card:hover .blog-card-media img {
  transform: scale(1.03);
}

.blog-grid > li:first-child .blog-card::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgb(0 0 0 / 0%) 30%, rgb(0 0 0 / 56%) 100%);
  pointer-events: none;
}

.blog-grid > li:first-child .blog-card-body {
  position: relative;
  z-index: 2;
  gap: 20px;
  max-width: 628px;
  padding: 32px 48px;
  pointer-events: none;
}

.blog-grid > li:first-child .blog-card-body a {
  pointer-events: auto;
}

.blog-grid > li:first-child .blog-card-category,
.blog-grid > li:first-child .blog-card-meta {
  display: none;
}

.blog-grid > li:first-child .blog-card-heading {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.blog-grid > li:first-child .blog-card-title {
  font-size: 32px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.16px;
  color: var(--wp--preset--color--surface-white);
  white-space: normal;
}

.blog-grid > li:first-child .blog-card:hover .blog-card-title a {
  color: var(--wp--preset--color--surface-white);
}

.blog-grid > li:first-child .blog-card-excerpt {
  min-height: 0;
  margin-top: -12px;
}

.blog-grid > li:first-child .blog-card-excerpt p {
  font-weight: 400;
  letter-spacing: 0;
  color: var(--wp--preset--color--surface-white);
  -webkit-line-clamp: 2;
}

.blog-grid > li:first-child .blog-card-read-more {
  position: relative;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  align-self: flex-start;
  padding: 11px 18px 11px 24px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: var(--wp--preset--color--text-button);
  text-decoration: none;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid var(--wp--preset--color--text-button);
  border-radius: 100px;
  transition: background-color 0.2s ease;
}

.blog-grid > li:first-child .blog-card-read-more::after {
  content: "";
  width: 16px;
  height: 16px;
  background: url("assets/icons/arrow-right.svg") center / contain no-repeat;
}

.blog-grid > li:first-child .blog-card-read-more:hover {
  background-color: var(--wp--preset--color--surface-mist);
}

/* Pagination */
.blog-pagination {
  gap: 23px;
  margin-top: 40px;
}

.blog-pagination .wp-block-query-pagination-numbers {
  display: flex;
  gap: 4px;
}

.blog-pagination .page-numbers,
.blog-pagination .wp-block-query-pagination-previous,
.blog-pagination .wp-block-query-pagination-next {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  width: 40px;
  height: 40px;
  margin: 0;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  color: #10141b;
  text-decoration: none;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid #eaeaee;
  border-radius: 50%;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}

.blog-pagination a.page-numbers:hover,
.blog-pagination .wp-block-query-pagination-previous:hover,
.blog-pagination .wp-block-query-pagination-next:hover {
  border-color: var(--wp--preset--color--brand-cyan);
}

.blog-pagination .page-numbers.current {
  color: var(--wp--preset--color--text-heading);
  background-color: #e6f6fd;
  border-color: #dadadf;
}

/* Previous/next show only the chevron from the design, keeping core's
   "Previous Page"/"Next Page" text for screen readers. */
.blog-pagination .wp-block-query-pagination-previous,
.blog-pagination .wp-block-query-pagination-next {
  overflow: hidden;
  font-size: 0;
}

.blog-pagination .wp-block-query-pagination-previous::before,
.blog-pagination .wp-block-query-pagination-next::before {
  content: "";
  width: 20px;
  height: 20px;
  background: url("assets/icons/chevron-left.svg") center / contain no-repeat;
}

.blog-pagination .wp-block-query-pagination-next::before {
  transform: scaleX(-1);
}

.blog-no-results {
  color: var(--wp--preset--color--text-muted);
}

/* Article listing with no articles (a category with none yet, in
   parts/blog-listing.html): sized like the featured article card - full
   width, 400px tall (360px on phones), 12px corners, no border, 32px
   below, 32px title - in light blue with a faint cyan inset edge, with an
   icon chip, a heading naming the category (functions.php), a short line
   and "Se alle artikler", centred. */
.blog-empty {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 12px;
  height: 400px;
  margin: 0 0 32px;
  padding: 32px 48px;
  text-align: center;
  background-color: var(--wp--preset--color--surface-mist);
  border-radius: 12px;
  box-shadow: inset 0 0 0 1px rgb(0 174 239 / 20%);
}

.blog-empty::before {
  content: "";
  width: 56px;
  height: 56px;
  margin-bottom: 4px;
  border-radius: 50%;
  background: var(--wp--preset--color--surface-white) url("assets/icons/empty-articles.svg") center / 28px no-repeat;
}

.blog-empty > * {
  margin: 0;
}

.blog-empty .blog-empty-title {
  max-width: 46ch;
  font-size: 32px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.16px;
  color: var(--wp--preset--color--text-heading);
  text-wrap: balance;
}

.blog-empty .blog-empty-text {
  max-width: 46ch;
  font-size: var(--wp--preset--font-size--medium);
  color: var(--wp--preset--color--text-body);
}

.blog-empty .blog-empty-actions {
  justify-content: center;
  margin-top: 8px;
}

@media (max-width: 782px) {
  .blog-empty {
    height: auto;
    min-height: 360px;
    padding: 24px;
  }

  .blog-empty .blog-empty-title {
    font-size: 24px;
  }
}

/* Article - masthead */
.blog-article-top {
  background-color: #f5f6f9;
}

.blog-article-title-block {
  display: flex;
  flex-direction: column;
  gap: 24px;
}

.blog-article-title-block > * {
  margin: 0;
}

.blog-article-title {
  max-width: 940px;
  font-size: 56px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -1.4px;
  color: var(--wp--preset--color--text-heading);
}

.blog-article-standfirst {
  max-width: 820px;
}

.blog-article-standfirst p {
  margin: 0;
  font-size: 18px;
  line-height: 1.56;
  color: #45454e;
}

.blog-article-byline {
  gap: 24px;
  padding-top: 28px;
  border-top: 1px solid #eaeaee;
}

.blog-article-meta,
.blog-article-meta p,
.blog-article-meta .wp-block-post-date {
  margin: 0;
  font-size: 14px;
  line-height: 1.56;
  color: var(--wp--preset--color--text-muted);
}

.blog-article-meta .blog-article-author {
  font-weight: 500;
  letter-spacing: -0.07px;
  color: var(--wp--preset--color--text-heading);
}

.share-links {
  display: flex;
  align-items: center;
  gap: 12px;
}

.share-links-label {
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.72px;
  color: var(--wp--preset--color--text-muted);
}

.share-links-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid #eaeaee;
  border-radius: 10px;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.share-links-button:hover {
  background-color: #e6f6fd;
  border-color: var(--wp--preset--color--brand-cyan);
}

.share-links-button img {
  display: block;
}

.blog-article-hero {
  width: 100%;
  margin: 0;
}

.blog-article-hero img {
  display: block;
  width: 100%;
  height: 100%;
}

/* Article - body: 200px rail + 60px gap + 680px column, left-aligned in
   the 1200px content width. */
.blog-article-layout {
  align-items: flex-start;
}

.blog-article-rail {
  position: sticky;
  top: 32px;
  flex: 0 0 200px;
  width: 200px;
}

.blog-article-column {
  flex: 0 1 680px;
  min-width: 0;
}

.blog-article-column > * {
  margin-block: 0;
}

.blog-toc-label {
  margin: 0 0 20px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.72px;
  text-transform: uppercase;
  color: var(--wp--preset--color--text-muted);
}

.blog-toc-list {
  margin: 0;
  padding: 0;
  list-style: none;
  border-left: 1px solid #eaeaee;
}

.blog-toc-list a {
  display: block;
  margin-left: -1px;
  padding: 11px 0 11px 18px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: var(--wp--preset--color--text-muted);
  text-decoration: none;
  border-left: 1px solid transparent;
  transition: color 0.2s ease, border-color 0.2s ease;
}

.blog-toc-list a:hover {
  color: var(--wp--preset--color--text-heading);
}

.blog-toc-list .is-active a {
  font-weight: 600;
  color: var(--wp--preset--color--text-heading);
  border-left-color: #22406f;
}

/* Article - content typography. Sections are 52px apart, blocks inside a
   section 22px apart. */
.blog-article-content {
  font-size: 18px;
  line-height: 1.56;
  color: #45454e;
}

.blog-article-content > * {
  margin-block: 0;
}

.blog-article-content > * + * {
  margin-block-start: 22px;
}

.blog-article-content > * + h2,
.blog-article-content > * + .wp-block-pullquote,
.blog-article-content > * + .wp-block-image,
.blog-article-content > .wp-block-pullquote + *,
.blog-article-content > .wp-block-image + * {
  margin-block-start: 52px;
}

.blog-article-content > * + .wp-block-columns {
  margin-block-start: 30px;
}

.blog-article-content > p:first-child {
  color: var(--wp--preset--color--text-heading);
}

.blog-article-content h2 {
  font-size: 24px;
  font-weight: 700;
  line-height: 1.28;
  letter-spacing: -0.06px;
  color: var(--wp--preset--color--text-heading);
  scroll-margin-top: 32px;
}

/* Sub-headings in the article text (e.g. each button in "Dette betyr alle
   knappene på fjernkontrollen") match the info cards' headings, a step
   below the 24px section headings instead of the global 24px h3. */
.blog-article-content > h3 {
  font-size: 18px;
  font-weight: 600;
  line-height: 1.56;
  color: var(--wp--preset--color--text-heading);
}

.blog-article-content a {
  color: #006fdc;
}

.blog-article-content > ul,
.blog-article-content > ol {
  padding: 0;
  list-style: none;
  border-top: 1px solid #eaeaee;
}

.blog-article-content > ul > li,
.blog-article-content > ol > li {
  padding: 18px 0;
  color: var(--wp--preset--color--text-heading);
  border-bottom: 1px solid #eaeaee;
}

.blog-article-content .wp-block-pullquote {
  margin-inline: 0;
  padding: 40px 0;
  text-align: left;
  border-top: 1px solid #eaeaee;
  border-bottom: 1px solid #eaeaee;
}

.blog-article-content .wp-block-pullquote blockquote {
  margin: 0;
}

.blog-article-content .wp-block-pullquote p {
  margin: 0;
  font-size: 32px;
  font-weight: 500;
  line-height: 1.2;
  letter-spacing: -0.16px;
  color: var(--wp--preset--color--text-heading);
}

.blog-article-content .wp-block-image img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: 15px;
}

.blog-article-content .wp-block-image figcaption {
  margin: 14px 0 0;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  text-align: left;
  color: var(--wp--preset--color--text-muted);
}

.blog-article-content .wp-block-columns {
  gap: 24px;
  align-items: flex-start;
}

/* "Info card" group style - registered in functions.php so editors can
   apply it to any group, e.g. the two heat-pump types side by side. */
.is-style-blog-info-card {
  padding: 28px;
  background-color: #f5f6f9;
  border-radius: 15px;
}

.is-style-blog-info-card > * {
  margin-block: 0;
}

.is-style-blog-info-card > * + * {
  margin-block-start: 12px;
}

.is-style-blog-info-card h3 {
  font-size: 18px;
  font-weight: 600;
  line-height: 1.56;
  color: var(--wp--preset--color--text-heading);
}

.is-style-blog-info-card p {
  font-size: 16px;
  line-height: 1.56;
  color: #45454e;
}

.blog-article-callout {
  margin-top: 52px !important;
  background-color: #e6f6fd;
  border-radius: 20px;
}

.blog-article-callout > * {
  margin-block: 0;
}

.blog-article-callout > * + * {
  margin-block-start: 28px;
}

.blog-article-callout-text {
  font-size: 20px;
  font-weight: 500;
  line-height: 1.35;
  color: var(--wp--preset--color--text-heading);
}

.blog-article-back {
  margin-top: 52px !important;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
}

.blog-article-back a {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #006fdc;
  text-decoration: none;
}

.blog-article-back a:hover {
  text-decoration: underline;
}

@media (max-width: 1024px) {
  .blog-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .blog-article-title {
    font-size: 44px;
    letter-spacing: -1.1px;
  }

  .blog-article-layout {
    flex-direction: column;
    gap: 40px;
  }

  .blog-article-rail {
    position: static;
    flex-basis: auto;
    width: 100%;
  }

  .blog-article-column {
    flex-basis: auto;
    width: 100%;
  }
}

@media (max-width: 782px) {
  .blog-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .blog-grid > li:first-child .blog-card {
    height: 360px;
  }

  .blog-grid > li:first-child .blog-card-body {
    padding: 24px;
  }

  .blog-grid > li:first-child .blog-card-title {
    font-size: 24px;
  }

  .blog-card-body {
    padding-right: 24px;
  }

  .blog-article-masthead {
    padding-top: 32px !important;
    padding-bottom: 48px !important;
  }

  .blog-article-masthead > .blog-article-byline {
    margin-block-start: 32px;
  }

  .blog-article-title {
    font-size: 36px;
    letter-spacing: -0.9px;
  }

  .blog-article-standfirst p {
    font-size: 16px;
  }

  /* The featured image block sets its own inline height (560px), which
     beat the 100% above and ran the photo 280px past the shorter frame,
     over the "In this article" list below it. */
  .blog-article-hero {
    height: 280px !important;
    overflow: hidden;
  }

  .blog-article-hero img {
    height: 100% !important;
  }

  .blog-article-body {
    padding-top: 48px !important;
    padding-bottom: 48px !important;
  }

  .blog-article-content {
    font-size: 16px;
  }

  .blog-article-content .wp-block-pullquote p {
    font-size: 24px;
  }

  .blog-article-callout {
    padding: 24px !important;
  }

  .blog-article-callout-text {
    font-size: 18px;
  }
}

/* ==========================================================================
   Contact page (templates/page-contact.html, patterns/contact-hero.php,
   patterns/contact-services.php).
   ========================================================================== */

.contact-page > *,
.wp-site-blocks > .contact-page {
  margin-block-start: 0;
}

/* Hero: 483px content column and a 569px form card, space-between in
   the 1200px content width, with the extra 20px the design leaves on
   the right. */
.contact-hero-row {
  padding-right: 20px;
}

/* The row is saved as vertically centred, which left the title and text
   floating halfway down beside the much taller form. Top-aligned, with
   the card's own top padding, the title lines up with "Reach out to us". */
@media (min-width: 1025px) {
  .contact-hero-row {
    align-items: flex-start !important;
  }

  .contact-hero-content {
    padding-top: 30px;
  }
}

.contact-hero-content {
  flex: 0 1 483px;
  min-width: 0;
}

.contact-hero-content * {
  margin-block: 0;
}

.contact-hero-title {
  font-size: 56px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -1.4px;
  color: var(--wp--preset--color--text-heading);
}

.contact-hero-body {
  max-width: 412px;
  line-height: 1.56;
  color: #45454e;
}

.contact-hero-call-label {
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.72px;
  text-transform: uppercase;
  color: var(--wp--preset--color--text-muted);
}

.contact-hero-call-number {
  font-size: 24px;
  font-weight: 700;
  line-height: 1.28;
  letter-spacing: -0.06px;
  color: var(--wp--preset--color--text-heading);
}

.contact-hero-call-number a {
  color: inherit;
  text-decoration: none;
  transition: color 0.2s ease;
}

.contact-hero-call-number a:hover {
  color: var(--wp--preset--color--brand-cyan);
}

.contact-hero-checklist {
  display: flex;
  flex-direction: column;
  gap: 7px;
  padding: 0;
  list-style: none;
}

.contact-hero-checklist li {
  padding-left: 28px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: var(--wp--preset--color--text-muted);
  background: url("assets/icons/tick.svg") 4px center / 12px 9px no-repeat;
}

.contact-form-card {
  flex: 0 0 569px;
  width: 569px;
  border-radius: 20px;
  box-shadow: 0 16px 44px rgb(28 36 75 / 12%);
}

.contact-form-title {
  margin: 0;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.28;
  letter-spacing: -0.06px;
  color: var(--wp--preset--color--text-heading);
}

.contact-form-note {
  margin: 4px 0 0;
  line-height: 1.56;
  color: #45454e;
}

.contact-location {
  background-color: #f5f6f9;
}

@media (max-width: 1024px) {
  .contact-hero-row {
    flex-direction: column;
    align-items: stretch;
    gap: 48px;
    padding-right: 0;
  }

  .contact-hero-content,
  .contact-form-card {
    flex-basis: auto;
    width: 100%;
  }

  .contact-hero-content {
    gap: 40px;
  }
}

@media (max-width: 782px) {
  .contact-hero-title {
    font-size: 40px;
    letter-spacing: -1px;
  }

  .contact-form-card {
    padding: 24px !important;
  }
}

/* ==========================================================================
   Products - archive (templates/archive-product.html) and single product
   (templates/single-product.html). The breadcrumb and pagination reuse the
   blog's .blog-breadcrumb and .blog-pagination styles.
   ========================================================================== */

.product-archive-page > *,
.product-single-page > *,
.wp-site-blocks > .product-archive-page,
.wp-site-blocks > .product-single-page {
  margin-block-start: 0;
}

.product-archive-title {
  margin: 0;
  color: var(--wp--preset--color--text-heading);
}

/* Brand pills - the Products & Services page's .product-filter-pill look,
   as links here (server-side filtering), left-aligned under the heading. */
.product-brand-filter {
  justify-content: flex-start;
  margin-bottom: 0;
}

.product-brand-filter .product-filter-pill {
  text-decoration: none;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}

.product-brand-filter .product-filter-pill:not(.is-active):hover {
  border-color: var(--wp--preset--color--brand-navy);
}

/* Toolbar: result count on the left, sort dropdown on the right. */
.archive-toolbar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 12px 24px;
}

.archive-toolbar-count {
  margin: 0;
  font-size: 14px;
  line-height: 1.56;
  color: var(--wp--preset--color--text-muted);
}

.archive-toolbar-sort select {
  min-width: 220px;
  padding: 11px 44px 11px 16px;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.56;
  color: var(--wp--preset--color--text-heading);
  background: var(--wp--preset--color--surface-white) url("assets/icons/chevron-down.svg") right 16px center / 16px no-repeat;
  border: 1px solid var(--wp--preset--color--border);
  border-radius: 100px;
  cursor: pointer;
  appearance: none;
  transition: border-color 0.2s ease;
}

.archive-toolbar-sort select:hover,
.archive-toolbar-sort select:focus {
  border-color: var(--wp--preset--color--brand-cyan);
  outline: none;
}

/* Grid - 4 per row (3, 2, 1 on smaller screens), each slot holding the
   shared product card (.product-card, as in "Explore our product range"),
   stretched to the full height of its row. */
.product-archive-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 40px 25px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.product-archive-grid > li {
  display: flex;
  margin: 0;
}

.product-archive-grid .product-card {
  flex: 1 1 auto;
  min-width: 0;
}

@media (max-width: 1100px) {
  .product-archive-grid {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

@media (max-width: 782px) {
  .product-archive-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 480px) {
  .archive-toolbar-sort,
  .archive-toolbar-sort select {
    width: 100%;
  }

  .product-archive-grid {
    grid-template-columns: minmax(0, 1fr);
  }
}

/* Single product (templates/single-product.html with blocks/product-detail
   and blocks/product-more) - per the Figma product detail page: a grey hero
   band with gallery and info panel, Overview / Compare variants tabs with
   technical specifications, a contact banner and "Explore more products". */
.product-breadcrumb-band {
  background-color: #f5f6f9;
}

.blog-breadcrumb:not(:has(.product-breadcrumb-brand)) .product-breadcrumb-brand-sep {
  display: none;
}

.product-detail,
.product-more {
  margin: 0;
}

.product-hero {
  padding: 32px 16px 48px;
  background-color: #f5f6f9;
}

.product-hero-inner {
  display: flex;
  align-items: flex-start;
  gap: 42px;
  max-width: 1062px;
  margin: 0 auto;
}

.product-gallery {
  display: flex;
  flex: 0 0 518px;
  gap: 17px;
  min-width: 0;
}

.product-gallery-thumbs {
  display: flex;
  flex: 0 0 48px;
  flex-direction: column;
  gap: 9px;
}

.product-gallery-thumb {
  width: 48px;
  height: 60px;
  padding: 0;
  overflow: hidden;
  cursor: pointer;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid transparent;
}

.product-gallery-thumb.is-active,
.product-gallery-thumb:hover {
  border-color: #0b2234;
}

.product-gallery-thumb img {
  width: 100%;
  height: 100%;
  padding: 0;
  object-fit: contain;
  border-radius: 0;
}

.product-gallery-main {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  aspect-ratio: 453 / 422;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid #eaeaee;
}

.product-gallery-slide {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  margin: 0;
}

.product-gallery-slide[hidden] {
  display: none;
}

.product-gallery-slide img {
  width: 100%;
  height: 100%;
  padding: 24px;
  object-fit: contain;
  border-radius: 0;
}

.product-gallery-arrow {
  position: absolute;
  top: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  color: var(--wp--preset--color--text-heading);
  cursor: pointer;
  background-color: var(--wp--preset--color--surface-white);
  border: 0;
  border-radius: 50%;
  box-shadow: 0 2px 8px rgb(28 36 75 / 14%);
  transform: translateY(-50%);
}

.product-gallery-arrow.is-prev {
  left: 12px;
}

.product-gallery-arrow.is-next {
  right: 12px;
}

.product-hero-info {
  flex: 1 1 502px;
  min-width: 0;
}

.product-hero-brand {
  margin: 0 0 9px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.72px;
  text-transform: uppercase;
  color: #006fdc;
}

.product-hero-title {
  margin: 0;
  font-size: 40px;
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.32px;
  color: #111112;
}

.product-hero-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 16px;
}

.product-hero-subtitle,
.product-hero-description {
  margin: 0;
  font-size: 14px;
  line-height: 1.56;
  color: #45454e;
}

/* The per-model description comes from a rich editor as paragraphs. */
.product-hero-description p {
  margin: 0;
}

.product-hero-description p + p {
  margin-top: 8px;
}

/* The subtitle is the same for every model; a slate-blue tone sets it apart
   from the grey per-model description under it. */
.product-hero-subtitle {
  font-weight: 500;
  color: var(--wp--preset--color--text-body);
}

.product-models {
  padding-top: 28px;
}

.product-models-label {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: #111112;
}

.product-models-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding-top: 12px;
}

.product-model {
  display: flex;
  flex: 1 1 200px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  min-height: 64px;
  padding: 12px 10px;
  font-family: inherit;
  cursor: pointer;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid #e5e9f2;
  border-radius: 16px;
  transition: border-color var(--transition), background-color var(--transition);
}

.product-model:hover {
  border-color: #18b4ec;
}

.product-model.is-active {
  background-color: #e6f6fd;
  border-color: #18b4ec;
}

.product-model-name {
  font-size: 14px;
  font-weight: 700;
  line-height: 1.56;
  color: #111112;
}

.product-model-tagline {
  font-size: 12px;
  line-height: 1.2;
  color: #6f6f78;
}

.product-stats {
  display: flex;
  gap: 8px;
  margin: 26px 0 0;
  padding: 22px 0;
  border-top: 1px solid #e5e9f2;
  border-bottom: 1px solid #e5e9f2;
}

.product-stats[hidden],
.product-overview-model[hidden] {
  display: none;
}

.product-stat {
  display: flex;
  flex: 1 1 0;
  flex-direction: column-reverse;
  align-items: center;
  gap: 2px;
  min-width: 0;
  padding: 0 4px;
  text-align: center;
}

.product-stat dt {
  font-size: 12px;
  line-height: 1.2;
  letter-spacing: 0.48px;
  color: #6f6f78;
}

.product-stat dd {
  margin: 0;
  font-size: 18px;
  font-weight: 800;
  line-height: 1.56;
  color: #111112;
}

.product-hero-buttons {
  display: flex;
  gap: 12px;
  padding-top: 20px;
}

.product-button {
  display: inline-flex;
  flex: 1 1 0;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 48px;
  padding: 13px 18px 13px 24px;
  box-sizing: border-box;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  white-space: nowrap;
  text-decoration: none;
  color: #2c2c2c;
  border: 1px solid transparent;
  border-radius: 100px;
  transition: filter var(--transition), background-color var(--transition);
}

.product-button.is-primary {
  background-color: var(--wp--preset--color--brand-cyan);
}

.product-button.is-primary:hover {
  filter: brightness(0.9);
}

.product-button.is-outline {
  background-color: var(--wp--preset--color--surface-white);
  border-color: #2c2c2c;
}

.product-button.is-outline:hover {
  background-color: var(--wp--preset--color--surface-mist);
}

.product-tabs {
  padding: 0 16px 80px;
}

.product-tabs-inner {
  max-width: 1186px;
  margin: 0 auto;
}

/* No tab bar above the overview (it only ever had the one "Overview"
   tab), so the panel itself sets the space below the hero band. */
.product-panel {
  padding-top: 64px;
}

.product-overview {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  align-items: start;
  gap: 40px;
}

.product-overview.is-specs-only {
  grid-template-columns: minmax(0, 1fr);
}

.product-eyebrow {
  margin: 0 0 8px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.72px;
  text-transform: uppercase;
  color: #006fdc;
}

.product-overview-title {
  margin: 0 0 16px;
  font-size: 32px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.16px;
  color: #111112;
}

.product-overview-copy p {
  margin: 0 0 12px;
  font-size: 15px;
  line-height: 1.6;
  color: #45454e;
}

.product-overview-copy strong {
  font-weight: 600;
  color: #111112;
}

.product-note {
  display: flex;
  gap: 16px;
  margin-top: 24px;
  padding: 20px;
  background-color: #eef7fd;
  border-radius: 12px;
}

.product-note-icon {
  flex: 0 0 24px;
  color: #006fdc;
}

.product-note-title {
  margin: 0 0 4px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.56;
  color: #111112;
}

.product-note-copy p {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: #45454e;
}

.product-note-copy strong {
  font-weight: 600;
  color: #111112;
}

.product-specs {
  padding: 24px;
  background-color: #f5f8fc;
  border-radius: 16px;
}

.product-specs-title {
  margin: 0 0 20px;
  font-size: 24px;
  font-weight: 700;
  line-height: 1.3;
  color: #111112;
}

.product-spec-group {
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid #e5e9f2;
  border-radius: 12px;
}

.product-spec-group + .product-spec-group {
  margin-top: 12px;
}

.product-spec-group summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px 20px;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.56;
  color: #111112;
  cursor: pointer;
  list-style: none;
}

.product-spec-group summary::-webkit-details-marker {
  display: none;
}

.product-spec-group summary::after {
  content: "";
  flex: 0 0 16px;
  height: 16px;
  background: url("assets/icons/chevron-down.svg") center / 12px no-repeat;
  transition: transform var(--transition);
}

.product-spec-group[open] summary::after {
  transform: rotate(180deg);
}

.product-spec-rows {
  margin: 0;
  padding: 0 20px 8px;
}

.product-spec-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 16px;
  padding: 12px 0;
  font-size: 14px;
  line-height: 1.5;
  border-top: 1px solid #eef1f5;
}

.product-spec-row dt {
  color: #45454e;
}

.product-spec-row dd {
  margin: 0;
  color: #111112;
  text-align: right;
}

.product-spec-empty {
  margin: 0;
  padding: 0 20px 16px;
  font-size: 14px;
  line-height: 1.5;
  color: #6f6f78;
}

/* "Which model is right for you?" - under the overview text, where the
   hero's "Compare full specs" button scrolls to (clear of the sticky
   header). */
.product-compare {
  margin-top: 32px;
  padding-top: 28px;
  border-top: 1px solid #e5e9f2;
  scroll-margin-top: 110px;
}

.product-compare-title {
  margin: 0 0 12px;
  font-size: 20px;
  font-weight: 700;
  line-height: 1.35;
  color: #111112;
}

.product-compare-copy p {
  margin: 0 0 12px;
  font-size: 15px;
  line-height: 1.6;
  color: #45454e;
}

.product-compare-copy strong {
  font-weight: 600;
  color: #111112;
}

.product-more {
  padding: 4px 16px 0;
}

.product-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 32px;
  max-width: 1064px;
  margin: 0 auto;
  padding: 40px 56px;
  box-sizing: border-box;
  background: linear-gradient(100deg, #0b1b3a 0%, #104068 100%);
  border-radius: 24px;
}

.product-banner-title {
  margin: 0;
  font-size: 20px;
  font-weight: 700;
  line-height: 1.35;
  color: var(--wp--preset--color--surface-white);
}

.product-banner-copy {
  margin: 6px 0 0;
  font-size: 16px;
  line-height: 1.56;
  color: #b9c4d8;
}

.product-banner .product-button {
  flex: 0 0 auto;
  min-height: 44px;
}

.product-related {
  max-width: 1260px;
  margin: 0 auto;
  padding: 80px 0;
}

.product-related-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.product-related-title {
  margin: 0;
  font-size: 32px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.16px;
  color: #111112;
}

.product-related-all {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: #006fdc;
  text-decoration: none;
}

.product-related-all:hover {
  color: var(--wp--preset--color--brand-navy);
}

/* Product cards here are the shared .products-grid / .product-card ones
   ("Explore our product range"), 56px below the heading row - for both
   "Explore more products" on product pages and the partner pages' range. */
.product-related .products-grid {
  margin-top: 56px;
}

@media (max-width: 1024px) {
  .product-hero-inner {
    flex-direction: column;
    gap: 32px;
  }

  .product-gallery {
    flex-basis: auto;
    width: 100%;
    max-width: 560px;
  }

  .product-hero-info {
    flex-basis: auto;
    width: 100%;
  }

  .product-overview {
    grid-template-columns: minmax(0, 1fr);
  }
}

@media (max-width: 782px) {
  .product-hero-title {
    font-size: 32px;
  }

  .product-panel {
    padding-top: 40px;
  }

  .product-stats {
    flex-wrap: wrap;
    row-gap: 16px;
  }

  .product-stat {
    flex-basis: calc(50% - 4px);
  }

  .product-hero-buttons {
    flex-direction: column;
  }

  .product-overview-title,
  .product-related-title {
    font-size: 26px;
  }

  .product-banner {
    flex-direction: column;
    align-items: flex-start;
    padding: 28px 24px;
  }

  .product-related {
    padding: 56px 0;
  }

  .product-related .products-grid {
    margin-top: 32px;
  }
}

@media (max-width: 600px) {
  .product-gallery-thumbs {
    display: none;
  }

  .product-related-head {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ==========================================================================
   Tables (core/table, site-wide) - a rounded, bordered card with a soft
   header row and hairline row dividers, replacing core's default boxed
   borders and heavy header rule.
   ========================================================================== */

.wp-block-table {
  overflow-x: auto;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid var(--wp--preset--color--border);
  border-radius: 12px;
}

.wp-block-table table {
  width: 100%;
  border-collapse: collapse;
  font-size: 16px;
  line-height: 1.56;
}

.wp-block-table thead {
  border-bottom: 0;
}

.wp-block-table th,
.wp-block-table td {
  padding: 16px 24px;
  text-align: left;
  vertical-align: top;
  border: 0;
  border-bottom: 1px solid #eaeaee;
}

.wp-block-table tbody tr:last-child > * {
  border-bottom: 0;
}

.wp-block-table th {
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.72px;
  text-transform: uppercase;
  color: #0077a4;
  background-color: var(--wp--preset--color--surface-mist);
}

.wp-block-table td {
  color: var(--wp--preset--color--text-heading);
}

.wp-block-table tbody tr {
  transition: background-color 0.2s ease;
}

.wp-block-table tbody tr:hover {
  background-color: #f9fafb;
}

/* Two-column tables are label/value lists (e.g. service / price): the
   value column is right-aligned and a little bolder so it scans easily. */
.wp-block-table table:has(tr > :nth-child(2):last-child) tr > :last-child {
  text-align: right;
}

.wp-block-table table:has(tr > :nth-child(2):last-child) td:last-child {
  font-weight: 600;
  white-space: nowrap;
}

.wp-block-table figcaption {
  margin: 0;
  padding: 12px 24px;
  font-size: 13px;
  color: var(--wp--preset--color--text-muted);
  border-top: 1px solid #eaeaee;
}

@media (max-width: 600px) {
  .wp-block-table table {
    font-size: 14px;
  }

  .wp-block-table th,
  .wp-block-table td {
    padding: 12px 16px;
  }

  .wp-block-table table:has(tr > :nth-child(2):last-child) td:last-child {
    white-space: normal;
  }
}

/* Service pages usually end their content with a full-bleed navy section
   that sits flush against the navy "Explore our other services" band.
   When the content ends with ordinary blocks instead (e.g. Additional
   services' price table and button), give it room before that band. */
.single-service .wp-block-post-content:not(:has(> .service-section-full-bleed:last-child)) {
  padding-bottom: 80px;
}

@media (max-width: 600px) {
  .single-service .wp-block-post-content:not(:has(> .service-section-full-bleed:last-child)) {
    padding-bottom: 40px;
  }
}

/* Article - "More from the blog" (templates/single.html). Cards reuse
   .blog-card from the listing; the grid is its own class so the
   listing's featured-first-card rules don't apply here. */
.blog-related {
  background-color: #f5f6f9;
}

.blog-related-title {
  margin: 0;
  font-size: 32px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.16px;
  color: var(--wp--preset--color--text-heading);
}

.blog-related-link {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  line-height: 1.56;
  letter-spacing: -0.07px;
}

.blog-related-link a {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: #006fdc;
  text-decoration: none;
}

.blog-related-link a::after {
  content: "";
  width: 16px;
  height: 16px;
  background-color: currentcolor;
  mask: url("assets/icons/arrow-right.svg") center / contain no-repeat;
  transition: transform 0.2s ease;
}

.blog-related-link a:hover::after {
  transform: translateX(3px);
}

.blog-related-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.blog-related-grid > li {
  margin: 0;
}

@media (max-width: 1024px) {
  .blog-related-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  .blog-related-grid > li:nth-child(3) {
    display: none;
  }
}

@media (max-width: 782px) {
  .blog-related {
    padding-top: 56px !important;
    padding-bottom: 64px !important;
  }

  .blog-related-title {
    font-size: 26px;
  }

  .blog-related-grid {
    grid-template-columns: minmax(0, 1fr);
  }

  .blog-related-grid > li:nth-child(3) {
    display: block;
  }
}

/* ==========================================================================
   Partner (manufacturer) pages - templates/single-manufacturer.html, the
   partner-* patterns and blocks/partner-range, per the Figma "Manufacturer
   page": hero, light-blue stats band running into the "Why we install"
   section, then the brand's product range.
   ========================================================================== */

.partner-page > *,
.wp-site-blocks > .partner-page,
.partner-content > * {
  margin-block: 0;
}

.partner-hero,
.partner-stats,
.partner-why {
  padding-right: 16px;
  padding-left: 16px;
}

.partner-hero {
  padding-top: 40px;
  padding-bottom: 60px;
}

.partner-hero-row {
  gap: 124px;
  margin: 0;
}

/* Column widths per the design - beats core's own
   .wp-block-columns:not(.is-not-stacked-on-mobile) > .wp-block-column rule. */
.wp-block-columns.partner-hero-row > .wp-block-column.partner-hero-text {
  flex: 0 0 419px;
  padding-top: 24px;
}

.wp-block-columns.partner-hero-row > .wp-block-column.partner-hero-media {
  flex: 1 1 0;
  min-width: 0;
}

.partner-eyebrow {
  margin: 0 0 12px;
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.72px;
  text-transform: uppercase;
  color: #006fdc;
}

.partner-hero-title {
  margin: 0;
  font-size: 56px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -1.4px;
  color: #111112;
}

.partner-hero-body {
  max-width: 385px;
  margin: 24px 0 0;
  font-size: 14px;
  line-height: 1.56;
  color: #45454e;
}

.partner-hero-buttons {
  gap: 16px;
  margin-top: 48px;
}

.partner-hero-buttons .wp-block-button__link {
  padding: 10px 24px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
}

.partner-hero-image {
  margin: 0;
}

.partner-hero-image img {
  width: 100%;
  aspect-ratio: 725 / 500;
  padding: 0;
  object-fit: cover;
  border-radius: 20px;
}

/* Side by side, the text column lines up with the photo like the front
   page hero: the eyebrow/title start at the photo's top edge and the
   buttons sit on its bottom edge, instead of the whole column floating in
   the middle. The partner pages' saved content centres both columns, so
   this overrides that; the 48px gap above the buttons is kept as a minimum.
   Stacked (1024px and below) it is unchanged. */
@media (min-width: 1025px) {
  .wp-block-columns.partner-hero-row {
    align-items: stretch;
  }

  .wp-block-columns.partner-hero-row > .wp-block-column.partner-hero-text {
    display: flex;
    flex-direction: column;
    align-self: stretch;
    padding-top: 0;
  }

  .wp-block-columns.partner-hero-row > .wp-block-column.partner-hero-media {
    align-self: flex-start;
  }

  .partner-hero-text > .partner-hero-buttons {
    margin-top: auto;
    padding-top: 48px;
  }
}

.partner-stats,
.partner-why {
  background-color: #e6f6fd;
}

.partner-stats {
  padding-top: 40px;
  padding-bottom: 40px;
}

.partner-stats-grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 40px;
}

/* Flow layout's block gap would push every stat / reason after the first
   down - the grid and rows set their own spacing. */
.partner-stats-grid > *,
.partner-why-list > *,
.partner-stat > * {
  margin: 0;
}

.partner-stat-value {
  font-size: 32px;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.16px;
  color: #111112;
}

.partner-stat-label {
  margin-top: 8px !important;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: #45454e;
}

.partner-why {
  padding-top: 64px;
  padding-bottom: 80px;
}

.partner-why-row {
  justify-content: space-between;
  gap: 40px;
  margin: 0;
}

.wp-block-columns.partner-why-row > .wp-block-column.partner-why-intro {
  flex: 0 1 436px;
}

.wp-block-columns.partner-why-row > .wp-block-column.partner-why-list {
  flex: 0 1 736px;
  min-width: 0;
}

.partner-why-title {
  margin: 0;
  font-size: 40px;
  font-weight: 700;
  line-height: 1.14;
  letter-spacing: -0.32px;
  color: #111112;
}

.partner-why-body {
  max-width: 324px;
  margin: 20px 0 0;
  font-size: 16px;
  line-height: 1.56;
  color: #45454e;
}

.partner-why-item {
  display: flex;
  justify-content: space-between;
  gap: 40px;
  padding: 28px 0;
  border-top: 1px solid #eaeaee;
}

.partner-why-item:last-child {
  border-bottom: 1px solid #eaeaee;
}

.partner-why-item > * {
  margin: 0;
}

.partner-why-item-title {
  flex: 0 0 282px;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.56;
  color: #111112;
}

.partner-why-item-text {
  flex: 0 1 409px;
  font-size: 16px;
  line-height: 1.56;
  color: #45454e;
}

.partner-range-heading {
  display: flex;
  flex-direction: column;
  gap: 16px;
  max-width: 436px;
}

.partner-range-intro {
  max-width: 368px;
  margin: 0;
  font-size: 16px;
  line-height: 1.56;
  color: #45454e;
}

.partner-range-all.product-button {
  flex: 0 0 auto;
}

@media (max-width: 1024px) {
  .partner-hero-row,
  .partner-why-row {
    flex-direction: column;
    gap: 40px;
  }

  .wp-block-columns.partner-hero-row > .wp-block-column.partner-hero-text,
  .wp-block-columns.partner-why-row > .wp-block-column.partner-why-intro,
  .wp-block-columns.partner-why-row > .wp-block-column.partner-why-list {
    flex-basis: auto;
    width: 100%;
  }

  .partner-stats-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 782px) {
  .partner-hero-title {
    font-size: 40px;
  }

  .partner-why-title {
    font-size: 30px;
  }

  .partner-why-item {
    flex-direction: column;
    gap: 8px;
  }

  .partner-why-item-title,
  .partner-why-item-text {
    flex-basis: auto;
  }

  .partner-range .product-related-head {
    flex-direction: column;
    align-items: flex-start;
  }
}

/* ==========================================================================
   Booking form (blocks/booking-form) - "Book a free inspection". Sits inside
   the final CTA card (.final-cta-form) and the contact page card
   (.contact-form-card); the card itself is styled by each of those.
   ========================================================================== */

.booking-form {
  --booking-error: #c8322b;

  width: 100%;
}

.booking-form-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 0;
}

.booking-form-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Homeowners / Business switch */
.booking-form-audience {
  display: flex;
  gap: 4px;
  margin: 0;
  padding: 4px;
  border: 0;
  border-radius: 15px;
  background: var(--wp--preset--color--surface-paper);
}

.booking-form-audience-option {
  position: relative;
  flex: 1 1 0;
  cursor: pointer;
}

.booking-form-audience-option input {
  position: absolute;
  inset: 0;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.booking-form-audience-option span {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 34px;
  border-radius: 10px;
  font-family: var(--wp--preset--font-family--form);
  font-size: 14px;
  font-weight: 600;
  line-height: 1;
  color: var(--wp--preset--color--text-muted);
  transition: background-color 0.15s ease, color 0.15s ease, box-shadow 0.15s ease;
}

.booking-form-audience-option input:checked + span {
  background: var(--wp--preset--color--surface-white);
  color: #45454e;
  box-shadow: 0 4px 18px rgb(28 36 75 / 10%);
}

.booking-form-audience-option input:focus-visible + span {
  outline: 2px solid var(--wp--preset--color--brand-cyan);
  outline-offset: 1px;
}

/* Small phones: the two tabs had half the width each, so a longer label
   (in English, "Private customers") wrapped onto two lines. Each tab now
   takes the width its label needs, the labels never wrap, and the text
   steps down a little on the narrowest screens. */
@media (max-width: 400px) {
  .booking-form-audience-option {
    flex: 1 1 auto;
  }

  .booking-form-audience-option span {
    padding: 0 8px;
    font-size: 13px;
    white-space: nowrap;
  }
}

@media (max-width: 340px) {
  .booking-form-audience-option span {
    font-size: 12px;
  }
}

/* Fields */
.booking-form-pair {
  display: flex;
  gap: 14px;
}

.booking-form-pair > .booking-form-field {
  flex: 1 1 0;
  min-width: 0;
}

.booking-form-field label,
.booking-form-service label {
  display: block;
  margin-bottom: 4px;
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: var(--wp--preset--color--text-heading);
}

.booking-form input[type="text"],
.booking-form input[type="email"],
.booking-form input[type="tel"],
.booking-form textarea,
.booking-form select {
  box-sizing: border-box;
  width: 100%;
  height: 46px;
  margin: 0;
  padding: 0 16px;
  border: 1px solid var(--wp--preset--color--border-subtle);
  border-radius: 10px;
  background-color: var(--wp--preset--color--surface-paper);
  font-family: var(--wp--preset--font-family--form);
  font-size: 16px;
  line-height: 1.6;
  color: var(--wp--preset--color--text-heading);
  transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

/* Contact form's message */
.booking-form textarea {
  display: block;
  height: auto;
  min-height: 120px;
  padding: 10px 16px;
  resize: vertical;
}

.booking-form input::placeholder {
  color: var(--wp--preset--color--text-muted);
  opacity: 1;
}

.booking-form input:focus,
.booking-form textarea:focus,
.booking-form select:focus {
  outline: none;
  border-color: var(--wp--preset--color--brand-cyan);
  box-shadow: 0 0 0 3px rgb(0 174 239 / 18%);
}

.booking-form input[aria-invalid="true"],
.booking-form textarea[aria-invalid="true"],
.booking-form select[aria-invalid="true"] {
  border-color: var(--booking-error);
}

.booking-form input[aria-invalid="true"]:focus,
.booking-form textarea[aria-invalid="true"]:focus,
.booking-form select[aria-invalid="true"]:focus {
  border-color: var(--booking-error);
  box-shadow: 0 0 0 3px rgb(200 50 43 / 15%);
}

.booking-form select {
  padding-right: 44px;
  appearance: none;
  background-image: url("assets/icons/chevron-down.svg");
  background-position: right 16px center;
  background-size: 18px 18px;
  background-repeat: no-repeat;
  cursor: pointer;
}

.booking-form select:invalid,
.booking-form select:has(option[value=""]:checked) {
  color: var(--wp--preset--color--text-muted);
}

.booking-form select option {
  color: var(--wp--preset--color--text-heading);
}

/* Consent checkbox */
.booking-form-checkbox {
  position: relative;
  display: inline-flex;
  align-items: flex-start;
  gap: 10px;
  cursor: pointer;
}

.booking-form-checkbox input {
  position: absolute;
  top: 0;
  left: 0;
  width: 20px;
  height: 20px;
  margin: 0;
  opacity: 0;
  cursor: pointer;
}

.booking-form-checkbox-box {
  flex: 0 0 20px;
  margin-top: -2px;
  width: 20px;
  height: 20px;
  box-sizing: border-box;
  border: 1px solid var(--wp--preset--color--border-subtle);
  border-radius: 6px;
  background: var(--wp--preset--color--surface-paper) center / 11px 8px no-repeat;
  transition: background-color 0.15s ease, border-color 0.15s ease;
}

.booking-form-checkbox input:checked + .booking-form-checkbox-box {
  border-color: var(--wp--preset--color--brand-cyan);
  background-color: var(--wp--preset--color--brand-cyan);
  background-image: url("assets/icons/white-tick.svg");
}

.booking-form-checkbox input:focus-visible + .booking-form-checkbox-box {
  outline: 2px solid var(--wp--preset--color--brand-cyan);
  outline-offset: 2px;
}

.booking-form-checkbox input[aria-invalid="true"] + .booking-form-checkbox-box {
  border-color: var(--booking-error);
}

.booking-form-checkbox-label {
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--wp--preset--color--text-muted);
}

.booking-form-privacy {
  margin: 8px 0 0 30px;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--wp--preset--color--text-muted);
}

.booking-form-privacy a {
  color: var(--wp--preset--color--text-heading);
  text-decoration: underline;
  text-underline-offset: 2px;
}

.booking-form-privacy a:hover {
  color: var(--wp--preset--color--brand-cyan);
}

.booking-form-required {
  margin-left: 2px;
  color: var(--booking-error);
}

/* Only the dropdown for the chosen audience shows. */
.booking-form-form:has(input[name="audience"][value="homeowner"]:checked) .booking-form-service[data-audience="business"],
.booking-form-form:has(input[name="audience"][value="business"]:checked) .booking-form-service[data-audience="homeowner"] {
  display: none;
}

.booking-form-error {
  margin: 6px 0 0;
  font-size: 13px;
  font-weight: 500;
  line-height: 1.3;
  color: var(--booking-error);
}

.booking-form-error:empty,
.booking-form-message:empty {
  display: none;
}

.booking-form-message {
  margin: 0;
  padding: 10px 14px;
  border-radius: 10px;
  background: rgb(200 50 43 / 8%);
  font-size: 14px;
  line-height: 1.45;
  color: var(--booking-error);
}

/* Submit - same pill-with-arrow as the other CTAs. Full width in the
   booking form; the contact form's is compact (below). */
.booking-form-submit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  width: 100%;
  min-height: 44px;
  margin: 0;
  padding: 6px 6px 6px 32px;
  border: 0;
  border-radius: 100px;
  background: var(--wp--preset--color--brand-cyan);
  font-family: var(--wp--preset--font-family--sans);
  font-size: 14px;
  font-weight: 500;
  line-height: 1.56;
  letter-spacing: -0.07px;
  color: var(--wp--preset--color--text-heading);
  text-align: left;
  cursor: pointer;
  transition: background-color 0.15s ease;
}

/* Contact form: sized to its label and centred, the arrow 16px after the
   label (Figma), not stretched across the form with the arrow at the far
   end. */
.contact-form .booking-form-submit {
  justify-content: flex-start;
  width: fit-content;
  max-width: 100%;
  margin: 0 auto;
}

.booking-form-submit:hover {
  background: #009fd9;
}

.booking-form-submit:focus-visible {
  outline: 2px solid var(--wp--preset--color--brand-navy);
  outline-offset: 2px;
}

.booking-form-submit-icon {
  display: flex;
  flex: 0 0 32px;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--wp--preset--color--surface-white);
  transition: transform 0.15s ease;
}

.booking-form-submit:hover .booking-form-submit-icon {
  transform: translateX(2px);
}

.booking-form-form.is-submitting .booking-form-submit {
  cursor: progress;
  opacity: 0.7;
}

.booking-form-form.is-submitting .booking-form-submit-icon img {
  animation: booking-form-pulse 0.9s ease-in-out infinite alternate;
}

@keyframes booking-form-pulse {
  to {
    opacity: 0.25;
  }
}

/* Thank-you state. The form and the thank-you message swap with the
   hidden attribute - .booking-form-form's display:flex would otherwise keep
   a hidden form on screen. */
.booking-form [hidden] {
  display: none !important;
}

.booking-form-success {
  display: flex;
  flex-direction: column;
  justify-content: center;
  box-sizing: border-box;
  padding: 28px 24px;
  border-radius: 15px;
  background: var(--wp--preset--color--surface-mist);
  text-align: center;
  outline: none;
}

.booking-form-success p {
  margin: 0;
  font-size: 14px;
  line-height: 1.56;
  color: var(--wp--preset--color--text-body);
}

.booking-form-success .booking-form-success-title {
  margin-bottom: 4px;
  font-size: 18px;
  font-weight: 700;
  color: var(--wp--preset--color--text-heading);
}

/* The final CTA card around the form, per the BookingForm frame in Figma
   (its drop shadow is on .final-cta-form above): title and note 4px apart,
   and a little tighter than the design's spacing below. Styled from here
   rather than the pattern because the saved Site Editor copies of the
   templates carry their own frozen markup. */

/* Both cards run 30px padding (Figma: 36px) and a 14px gap to the form -
   a little tighter than the design so the form doesn't set the height of
   the section beside it (stretching the final CTA's background image and
   leaving the left-hand copy floating in space). */
@media (min-width: 783px) {
  .final-cta-form,
  .contact-form-card {
    padding: 30px !important;
  }
}

.final-cta-form > h3 {
  line-height: 1.28;
  letter-spacing: -0.06px;
}

.final-cta-form > h3 + p {
  margin-block-start: 4px;
  line-height: 1.56;
  color: #45454e !important;
}

.final-cta-form > .booking-form,
.contact-form-card > .booking-form {
  margin-block-start: 14px;
}

@media (max-width: 480px) {
  .booking-form-submit {
    padding-left: 20px;
  }

  .booking-form-submit-label {
    white-space: nowrap;
  }

  .booking-form-pair {
    flex-direction: column;
    gap: 18px;
  }

  /* The navy panel's 32-44px sides plus the card's own padding left the
     inputs about 219px wide on a 375px phone. */
  .final-cta-row {
    padding-right: 16px !important;
    padding-left: 16px !important;
  }

  .final-cta-form {
    padding: 20px !important;
  }
}

@media (prefers-reduced-motion: reduce) {
  .booking-form *,
  .booking-form *::before {
    transition: none !important;
    animation: none !important;
  }
}

/* Heat pump housing pages (templates/page-tre-pumpehus.html,
   page-metall-pumpehus.html and their tre-/metall-pumpehus-* patterns).
   The sections sit edge to edge - the intro and cards share one light blue
   band - so main's flow gap between them is taken out. */
.housing-page > * + * {
  margin-block-start: 0;
}

.housing-page p {
  margin: 0;
}

/* Hero: 419px text column and a 725x500 photo, 124px apart. */
.housing-eyebrow {
  font-size: 12px;
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: #006fdc;
}

.housing-hero-title {
  letter-spacing: -0.025em;
}

/* Side by side, the text column is 419px wide, and "Varmepumpehus" at
   56px is a little wider than that. Core's columns set word-break:
   break-word, so the word broke in the middle ("Varmepumpehu / s"). The
   title now only breaks between words, and the column grows to fit its
   longest word, the photo column giving up those few pixels. */
.housing-hero .housing-hero-title {
  overflow-wrap: normal;
  word-break: normal;
}

@media (min-width: 782px) {
  .housing-hero > .wp-block-column:first-child {
    min-width: min-content;
  }
}

/* Phones: the page title follows the phone heading scale (36px, end of
   file), the housing promo's section title (also .housing-hero-title)
   32px. */
@media (max-width: 600px) {
  h1.housing-hero-title {
    font-size: 36px !important;
  }

  h2.housing-hero-title {
    font-size: 32px !important;
  }
}

.housing-standfirst {
  font-weight: 600;
  color: #45454e;
}

.housing-hero-media,
.housing-hero-media img {
  width: 100%;
  margin: 0;
}

/* The photo keeps its own proportions. A fixed 725:500 crop suited the
   wood housing photo but cut the sides off the wider metal one (761x500),
   rounded corners included. */
.housing-hero-media img {
  height: auto;
}

@media (max-width: 1100px) {
  .housing-hero {
    column-gap: 48px !important;
  }
}

/* Intro: a small label on the left, a large statement on the right. */
.housing-intro-label {
  font-weight: 600;
  text-transform: uppercase;
  color: #45454e;
}

.housing-intro-body {
  font-size: 24px;
  font-weight: 500;
  line-height: 1.32;
  letter-spacing: -0.0025em;
  color: var(--wp--preset--color--text-heading);
}

@media (max-width: 1100px) {
  .housing-intro {
    column-gap: 48px !important;
  }
}

@media (max-width: 781px) {
  .housing-intro-body {
    font-size: 20px;
  }
}

/* Benefit cards, on the shared .service-card markup. */
.housing-card-title {
  font-size: 20px;
  font-weight: 600;
  line-height: 1.35;
  color: #10141b;
}

.housing-card-text {
  max-width: 300px;
  color: #6a727e;
}

.housing-cards-wide .housing-card-text {
  max-width: 483px;
}

/* No link to pin to the bottom here, unlike the services grid cards. */
.housing-card .service-card-body {
  justify-content: flex-start;
}

.housing-card .service-card-media .wp-block-image {
  margin: 0;
}

.housing-card .service-card-media img:not(.service-card-icon-chip img) {
  aspect-ratio: 408 / 293;
  object-fit: cover;
}

.housing-cards-wide .service-card-media img:not(.service-card-icon-chip img) {
  aspect-ratio: 618 / 325;
}

.housing-cards-wide .service-card-icon-chip {
  right: 42px;
}

.housing-card .service-card-icon-chip img {
  aspect-ratio: auto;
}

/* Wood page: the cards scroll sideways, three at a time on desktop, with
   previous/next buttons above them (js/housing.js). */
.housing-carousel-nav {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.housing-carousel.is-static .housing-carousel-nav {
  display: none;
}

.housing-carousel-button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--wp--preset--color--text-button);
  border-radius: 50%;
  background: var(--wp--preset--color--surface-white);
  cursor: pointer;
  transition: background-color 0.2s ease, opacity 0.2s ease;
}

.housing-carousel-button:hover:not(:disabled) {
  background: var(--wp--preset--color--surface-mist);
}

/* The benefits carousel sits on surface-mist itself (see the white
   buttons on light-blue sections above). */
.has-surface-mist-background-color .housing-carousel-button:hover:not(:disabled) {
  background: #cceffd;
}

.housing-carousel-button:disabled {
  opacity: 0.4;
  cursor: default;
}

.housing-carousel-button.is-next img {
  transform: scaleX(-1);
}

.housing-carousel-track {
  align-items: stretch !important;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}

.housing-carousel-track::-webkit-scrollbar {
  display: none;
}

.housing-carousel-track > .housing-card {
  flex: 0 0 calc((100% - 50px) / 3);
  height: auto;
  min-height: 489px;
  scroll-snap-align: start;
}

@media (max-width: 1024px) {
  .housing-carousel-track > .housing-card {
    flex-basis: calc((100% - 25px) / 2);
  }
}

@media (max-width: 640px) {
  .housing-carousel-track > .housing-card {
    flex-basis: 85%;
    min-height: 0;
  }
}

/* Sizes / technical specifications: text and a dimensions table on the
   left, a navy card on the right. */
.housing-specs-lead {
  max-width: 403px;
}

@media (max-width: 1100px) {
  .housing-specs {
    column-gap: 48px !important;
  }
}

.housing-swatch {
  align-items: center;
  gap: 10px 6px !important;
}

.housing-swatch[role="radio"] {
  cursor: pointer;
  border-radius: 24px;
}

.housing-swatch[role="radio"]:focus-visible {
  outline: 2px solid var(--wp--preset--color--brand-cyan);
  outline-offset: 4px;
}

.housing-swatch.is-selected .housing-swatch-dot {
  box-shadow: 0 0 0 2px var(--wp--preset--color--surface-white), 0 0 0 4px var(--wp--preset--color--brand-cyan);
}

.housing-swatch-dot {
  flex: 0 0 40px;
  width: 40px;
  height: 40px;
  margin: 4px 8px 4px 4px;
  border: 1px solid #e5e9f2;
  border-radius: 50%;
}

.housing-swatch-name {
  font-size: 14px;
  font-weight: 700;
  color: var(--wp--preset--color--text-heading);
}

.housing-swatch-code {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.06em;
  color: #787878;
}

.housing-spec-table {
  padding: 24px 20px;
  border: 1px solid #eaeaee;
  border-radius: 20px;
  background: var(--wp--preset--color--surface-white);
}

.housing-spec-table > * {
  margin-block-start: 0;
}

.housing-spec-head {
  align-items: center;
  margin-bottom: 16px;
}

.housing-spec-title {
  font-size: 14px;
  font-weight: 600;
  color: #0c9bcf;
}

.housing-spec-title.is-caps {
  font-weight: 700;
  text-transform: uppercase;
}

.housing-spec-row {
  align-items: baseline;
  gap: 16px;
  padding: 12px 0;
  font-size: 14px;
  border-bottom: 1px solid #eaeaee;
}

.housing-spec-row:last-child {
  padding-bottom: 0;
  border-bottom: 0;
}

.housing-spec-head + .housing-spec-row {
  padding-top: 0;
}

.housing-spec-label {
  flex-shrink: 0;
  color: var(--wp--preset--color--text-muted);
}

.housing-spec-value {
  font-weight: 700;
  text-align: right;
  color: var(--wp--preset--color--text-heading);
}

/* Metal page: the dimensions card turns over to the inside measurements.
   Both faces share one grid cell, so the card is as tall as the taller. */
.housing-flip {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  perspective: 1200px;
}

.housing-flip > .housing-flip-face {
  grid-area: 1 / 1;
  margin: 0;
  backface-visibility: hidden;
  transition: transform 0.5s ease;
}

.housing-flip-back {
  transform: rotateY(180deg);
}

.housing-flip.is-flipped .housing-flip-front {
  transform: rotateY(-180deg);
}

.housing-flip.is-flipped .housing-flip-back {
  transform: rotateY(0deg);
}

.housing-flip-toggle {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--wp--preset--color--text-muted);
  cursor: pointer;
  border-radius: 4px;
}

.housing-flip-toggle::after {
  content: "";
  width: 12px;
  height: 12px;
  background: url("assets/icons/flip.svg") center / contain no-repeat;
}

.housing-flip-toggle:hover {
  color: var(--wp--preset--color--text-heading);
}

.housing-flip-toggle:focus-visible {
  outline: 2px solid var(--wp--preset--color--brand-cyan);
  outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
  .housing-flip > .housing-flip-face,
  .housing-color-media > .wp-block-image {
    transition: none;
  }
}

/* Navy card: photo, title, ticked list, and a note under a rule. */
.housing-navy-card > * {
  margin: 0;
}

/* The card photos are PNGs with rounded corners and a transparent strip
   above the photo, so the housing rises over the photo's top edge. The
   card has no top padding - the strip takes its place - and the metal
   card's taller strip is pulled up into the card's top edge (54px at the
   design's 480px image width), leaving the roof just inside the card as
   in the design. The pulled-up strip is transparent, so it lets clicks
   through to whatever it overlaps. */
.housing-navy-card-media img {
  width: 100%;
  height: auto;
}

/* An explicit width: in the card's vertical flex layout the photo's height
   is otherwise worked out at its natural width, before it's stretched -
   so a card wider than the PNG (stacked columns, 600-780px) left the
   scaled-up image hanging over the title and list below it. */
.housing-navy-card > .housing-navy-card-media {
  width: 100%;
}

.housing-navy-card-media.is-popout-tall {
  margin-top: -11.25%;
  pointer-events: none;
}

/* Metal card: one photo per colour, stacked; the chosen swatch's fades in. */
.housing-color-media {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.housing-color-media > .wp-block-image {
  grid-area: 1 / 1;
  margin: 0;
  opacity: 0;
  transition: opacity 0.4s ease;
}

.housing-color-media > .wp-block-image.is-active {
  opacity: 1;
}

.housing-navy-card-title {
  font-size: 18px;
  font-weight: 600;
  line-height: 1.56;
}

.housing-checklist {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 14px;
  color: var(--wp--preset--color--text-on-dark);
}

.housing-checklist li {
  position: relative;
  padding-left: 29px;
}

.housing-checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 3px;
  width: 16px;
  height: 16px;
  background: url("assets/icons/tick.svg") center / 14px auto no-repeat;
}

.housing-navy-card-note {
  padding-top: 16px;
  border-top: 1px solid #3a5c8f;
  color: #b9c8e4;
}

/* Metal page installation: heading and tools card, a full-width photo,
   then four numbered steps. */
.housing-install-lead {
  max-width: 418px;
}

.housing-install-head > .wp-block-column:last-child {
  display: flex;
  justify-content: flex-end;
}

.housing-tools-card {
  width: 100%;
  max-width: 405px;
}

.housing-tools-card-title {
  font-weight: 600;
  color: #0c9bcf;
}

.housing-banner {
  margin: 0;
}

.housing-banner img {
  width: 100%;
  height: 400px;
  object-fit: cover;
}

/* Narrower screens only show the middle of the wide (3.6:1) banner, which
   cut the metal housing - right of centre in the photo - off at the edge.
   The crop follows the housing instead. */
@media (max-width: 781px) {
  .housing-banner img {
    height: 240px;
    object-position: 63% 50%;
  }
}

.housing-steps {
  flex-wrap: wrap !important;
}

.housing-steps > .wp-block-column {
  flex: 1 1 220px !important;
}

.housing-step {
  align-items: flex-start;
  padding: 12px 0;
}

.housing-step-number {
  flex: 0 0 30px;
  width: 30px;
  height: 30px;
  font-size: 14px;
  font-weight: 700;
  line-height: 30px;
  text-align: center;
  color: #006fdc;
  border-radius: 50%;
  background: var(--wp--preset--color--surface-mist);
}

.housing-step-title {
  font-size: 18px;
  font-weight: 700;
  line-height: 1.56;
}

.housing-step-text {
  color: #45454e;
}

/* Heat pump housing promo (patterns/housing-promo.php) on the Heat pumps
   and Accessories service pages: the housing hero layout, with the wood
   and metal photos cross-fading in one frame. */
.housing-promo .housing-hero-title {
  font-size: 56px;
  font-weight: 600;
  line-height: 1;
}


.housing-promo-body {
  max-width: 385px;
  margin: 0;
  color: #45454e;
}

.housing-promo-media {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
}

.housing-promo-media > .wp-block-image {
  grid-area: 1 / 1;
  margin: 0;
}

.housing-promo-media > .wp-block-image + .wp-block-image {
  animation: housing-promo-fade 10s ease-in-out infinite;
}

@keyframes housing-promo-fade {
  0%, 40% { opacity: 0; }
  50%, 90% { opacity: 1; }
  100% { opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .housing-promo-media > .wp-block-image + .wp-block-image {
    display: none;
  }
}

/* Stacked (tablet and phone): the photos lead, above the title and text,
   per the UAT doc. */
@media (max-width: 781px) {
  .housing-promo .housing-hero > .wp-block-column:has(.housing-promo-media) {
    order: -1;
  }
}

/* Heat pump housing pages: stacked (tablet and phone) spacing. */
@media (max-width: 781px) {
  /* Stacked, the metal card sits 40px under the dimensions table: the
     pulled-up transparent strip stays within that gap. */
  .housing-navy-card-media.is-popout-tall {
    margin-top: max(-11.25%, -40px);
  }

  /* Cards are full width once stacked; the desktop wrap widths would
     leave the copy in a narrow strip. */
  .housing-card-text,
  .housing-cards-wide .housing-card-text {
    max-width: none;
  }

  .housing-page .housing-specs-lead,
  .housing-install-lead {
    max-width: none;
  }

  .housing-install-head > .wp-block-column:last-child {
    justify-content: flex-start;
  }

  .housing-tools-card {
    max-width: none;
  }
}

@media (max-width: 600px) {
  /* The hero's own 60px came on top of the 40px every section gets on
     phones (main > .wp-block-group above), leaving 100px under the photo. */
  .housing-hero {
    padding-bottom: 0 !important;
  }

  /* The installation section's inner groups aren't direct children of
     main, so they missed that phone padding cut. */
  .housing-install > .wp-block-group {
    padding-top: 40px !important;
    padding-bottom: 40px !important;
  }

  .housing-install > .wp-block-group:first-child {
    padding-top: 0 !important;
  }

  .housing-steps {
    row-gap: 8px !important;
  }

  .housing-step {
    padding: 4px 0;
  }

  .housing-intro {
    row-gap: 16px !important;
  }
}

/* FAQ page (patterns/faq-questions.php, templates/page-faq.html). Each
   question is a core Details block inside its category group; js/faq.js
   filters by category and keeps one open at a time. The open question
   gets the light-blue panel, the others a divider underneath. */
.faq-intro {
  max-width: 385px;
  margin-inline: auto;
  color: #45454e !important;
}

.faq-filter-pills {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
}

.faq-filter-pills + .faq-list {
  margin-block-start: 32px;
}

.faq-filter-pill {
  border: 1px solid #00aeef;
  border-radius: 100px;
  padding: 6px 20px;
  background-color: rgb(0 174 239 / 8%);
  color: #515152;
  font-family: inherit;
  font-size: 14px;
  font-weight: 400;
  line-height: 1.56;
  cursor: pointer;
}

.faq-filter-pill.is-active {
  background-color: #0e355a;
  border-color: #0e355a;
  color: #17c0fd;
  font-weight: 500;
  letter-spacing: -0.005em;
}

.faq-filter-pill:focus-visible,
.faq-item > summary:focus-visible {
  outline: 2px solid #006fdc;
  outline-offset: 2px;
}

.faq-category > .faq-item {
  margin: 0;
  padding: 28px 24px;
  border-bottom: 1px solid #eaeaee;
  border-radius: 12px 12px 0 0;
}

.faq-category > .faq-item[open] {
  background-color: #eefaff;
  border-bottom-color: transparent;
  border-radius: 12px;
}

.faq-item[hidden],
.faq-category[hidden] {
  display: none;
}

/* The category heading names its pill (functions.php) and is only a label
   for editors - the design shows no heading above the questions. Hidden
   only next to the pills, which exist on the front end alone, so the
   headings stay visible in the editor (style.css is an editor style too). */
.faq-filter-pills + .faq-list .faq-category-name {
  position: absolute !important;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.faq-list > .faq-category {
  margin: 0;
}

.faq-item > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  color: #111112;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.56;
  cursor: pointer;
  list-style: none;
}

.faq-item > summary::-webkit-details-marker {
  display: none;
}

/* Plus / minus in a 36px circle - two 14px bars, the vertical one
   flattened when the question is open. */
.faq-item > summary::after {
  content: "";
  flex-shrink: 0;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background:
    linear-gradient(#006fdc, #006fdc) center / 14px 2px no-repeat,
    linear-gradient(#006fdc, #006fdc) center / 2px 14px no-repeat,
    #e6f6fd;
  margin-block: -2px;
}

.faq-item[open] > summary::after {
  background:
    linear-gradient(#006fdc, #006fdc) center / 14px 2px no-repeat,
    #e6f6fd;
}

.faq-item > p {
  max-width: 722px;
  margin: 16px 0 0;
  color: #45454e;
  font-size: 14px;
  line-height: 1.56;
  opacity: 0.9;
}

.faq-item > summary + p {
  margin-top: 12px;
}

@supports (interpolate-size: allow-keywords) {
  .faq-item {
    interpolate-size: allow-keywords;
  }

  .faq-item::details-content {
    block-size: 0;
    overflow: hidden;
    transition: block-size 0.3s ease, content-visibility 0.3s allow-discrete;
  }

  .faq-item[open]::details-content {
    block-size: auto;
  }
}

@media (prefers-reduced-motion: reduce) {
  .faq-item::details-content {
    transition: none;
  }
}

@media (max-width: 600px) {
  .faq-filter-pills {
    gap: 8px;
  }

  .faq-category > .faq-item {
    padding: 20px 16px;
  }

  .faq-item > summary {
    gap: 16px;
    font-size: 16px;
  }
}

/* ==========================================================================
   Phone heading scale. Per the UAT doc (titles in 2-3 lines, and the same
   size in every section once they get smaller on mobile): page titles are
   36px and section titles 32px on phones. The theme's H1/H2 defaults come
   from the xxx-large/xx-large presets, which only headings use, and many
   section titles set the same 40px (or 56px) inline - both are brought
   down here (page titles to 36px, so the longer hero titles fit in three
   lines). Headings sized smaller on purpose (card titles, the legal
   pages' 24px headings) are left as they are.
   ========================================================================== */
@media (max-width: 600px) {
  :root {
    --wp--preset--font-size--xxx-large: 36px;
    --wp--preset--font-size--xx-large: 32px;
  }

  main h1 {
    font-size: 36px !important;
  }

  main h2[style*="font-size:40px"],
  main h2[style*="font-size:56px"] {
    font-size: 32px !important;
  }
}

/* "Cookie-innstillinger" in the footer's bottom bar (functions.php) - a
   button, as it opens the cookie preferences panel, styled like the links
   next to it. */
.footer-bottom-bar .footer-cookie-settings {
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  letter-spacing: inherit;
  cursor: pointer;
  transition: color 0.2s ease;
}

.footer-bottom-bar .footer-cookie-settings:hover {
  color: var(--wp--preset--color--surface-white);
}

/* The "·" before it: margin rather than spaces, which GTranslate drops when
   it translates the row ("Terms ·Cookie settings"). Matches the width of
   the spaces around the other separators. */
.footer-bottom-bar .footer-cookie-separator {
  margin: 0 0.3em;
}

/* Instagram feed (patterns/socials.php, js/instagram-feed.js): message in
   place of the feed while marketing cookies aren't accepted; a feed that
   doesn't load leaves no empty space. */
.instagram-feed-fallback {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  max-width: 480px;
  margin: 0 auto;
  padding: 24px;
  text-align: center;
  color: var(--wp--preset--color--text-body);
  background-color: var(--wp--preset--color--surface-mist);
  border-radius: 20px;
}

.instagram-feed-fallback[hidden],
.instagram-feed-unavailable {
  display: none;
}

.instagram-feed-fallback p {
  margin: 0;
  font-size: 14px;
  line-height: 1.56;
}

.instagram-feed-fallback-button {
  padding: 10px 24px;
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  color: var(--wp--preset--color--text-button);
  cursor: pointer;
  background-color: var(--wp--preset--color--surface-white);
  border: 1px solid currentcolor;
  border-radius: 100px;
}

/* Search results (templates/search.html) and the 404 page's links. */
.search-page-title {
  margin-bottom: 24px;
  font-size: 40px;
  line-height: 1.14;
  letter-spacing: -0.32px;
}

.search-page-form {
  margin-bottom: 48px;
}

.search-results-list {
  display: flex;
  flex-direction: column;
  gap: 0;
  padding: 0;
  list-style: none;
}

.search-result {
  padding: 24px 0;
  border-top: 1px solid #eaeaee;
}

.search-result-image {
  flex: 0 0 120px;
  margin: 0;
  overflow: hidden;
  border-radius: 12px;
}

.search-result-body > * {
  margin: 0;
}

.search-result-type {
  margin-bottom: 4px;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.72px;
  text-transform: uppercase;
  color: #006fdc;
}

.search-result-title {
  font-size: 20px;
  line-height: 1.3;
}

.search-result-title a {
  color: var(--wp--preset--color--text-heading);
  text-decoration: none;
}

.search-result-excerpt {
  margin-top: 8px;
  font-size: 14px;
  line-height: 1.56;
  color: var(--wp--preset--color--text-body);
}

.search-results-pagination {
  margin-top: 40px;
}

.search-helpful-links {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  padding: 0;
  list-style: none;
}

.search-helpful-links a {
  color: #006fdc;
}

@media (max-width: 600px) {
  .search-page-title {
    font-size: 32px;
  }

  .search-result-image {
    flex-basis: 80px;
  }
}
