@charset "UTF-8";/*!
 * mmenu.js
 * mmenujs.com
 *
 * Copyright (c) Fred Heusschen
 * frebsite.nl
 *
 * License: CC-BY-NC-4.0
 * http://creativecommons.org/licenses/by-nc/4.0/
 */:root{--mm-lineheight:22px}.mm-hidden{display:none!important}.mm-wrapper{overflow-x:hidden;position:relative}.mm-menu,.mm-menu *,.mm-menu :after,.mm-menu :before{-webkit-transition-property:none;-o-transition-property:none;transition-property:none;-webkit-transition-duration:.4s;-o-transition-duration:.4s;transition-duration:.4s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease}:root{--mm-blocker-visibility-delay:0.4s;--mm-blocker-opacity-delay:0s}.mm-blocker{display:block;position:absolute;bottom:100%;top:0;right:0;left:0;z-index:3;opacity:0;background:var(--mm-color-background);-webkit-transition:bottom 0s ease var(--mm-blocker-visibility-delay),width .4s ease,opacity .4s ease var(--mm-blocker-opacity-delay),-webkit-transform .4s ease;transition:bottom 0s ease var(--mm-blocker-visibility-delay),width .4s ease,opacity .4s ease var(--mm-blocker-opacity-delay),-webkit-transform .4s ease;-o-transition:bottom 0s ease var(--mm-blocker-visibility-delay),width .4s ease,opacity .4s ease var(--mm-blocker-opacity-delay),transform .4s ease;transition:bottom 0s ease var(--mm-blocker-visibility-delay),width .4s ease,opacity .4s ease var(--mm-blocker-opacity-delay),transform .4s ease;transition:bottom 0s ease var(--mm-blocker-visibility-delay),width .4s ease,opacity .4s ease var(--mm-blocker-opacity-delay),transform .4s ease,-webkit-transform .4s ease}.mm-blocker:focus-visible{opacity:.75}.mm-btn{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;position:relative;width:50px;padding:0}.mm-btn--next,[dir=rtl] .mm-btn--prev{--mm-btn-rotate:135deg}.mm-btn--prev,[dir=rtl] .mm-btn--next{--mm-btn-rotate:-45deg}.mm-btn--next:after,.mm-btn--prev:before{content:"";display:block;position:absolute;top:0;bottom:0;width:8px;height:8px;margin:auto;-webkit-box-sizing:border-box;box-sizing:border-box;border:2px solid var(--mm-color-icon);border-bottom:none;border-right:none;-webkit-transform:rotate(var(--mm-btn-rotate));-ms-transform:rotate(var(--mm-btn-rotate));transform:rotate(var(--mm-btn-rotate))}.mm-btn--prev:before{inset-inline-start:23px}.mm-btn--next:after{inset-inline-end:23px}.mm-btn--close:before{content:"×";font-size:150%}.mm-btnreset{padding:0;background:0 0;border:none;cursor:pointer}.mm-divider{-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;position:-webkit-sticky;position:sticky;z-index:2;top:0;min-height:var(--mm-lineheight);padding:calc((var(--mm-listitem-size) * .65 - var(--mm-lineheight)) * .5) 20px;font-size:75%;text-transform:uppercase;background:var(--mm-color-background);background-image:-webkit-gradient(linear,left top,left bottom,from(var(--mm-color-background-highlight)),to(var(--mm-color-background-highlight)));background-image:-o-linear-gradient(var(--mm-color-background-highlight),var(--mm-color-background-highlight));background-image:linear-gradient(var(--mm-color-background-highlight),var(--mm-color-background-highlight));opacity:1;-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.mm-navbar:not(.mm-hidden)~.mm-listview .mm-divider{top:var(--mm-navbar-size)}:root{--mm-listitem-size:50px}.mm-listitem{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;position:relative;padding:0;margin:0;color:var(--mm-color-text);border-color:var(--mm-color-border)}.mm-listitem:after{content:"";border-color:inherit;border-bottom-width:1px;border-bottom-style:solid;display:block;position:absolute;inset-inline-start:20px;inset-inline-end:0;bottom:0}.mm-listitem__btn,.mm-listitem__text{padding:calc((var(--mm-listitem-size) - var(--mm-lineheight))/ 2) 0}.mm-listitem__text{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-preferred-size:10%;flex-basis:10%;display:block;padding-left:20px;padding-right:20px;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.mm-listitem__btn{display:block;position:relative;width:auto;-webkit-padding-end:50px;padding-inline-end:50px;border-color:inherit;background:rgba(3,2,1,0)}.mm-listitem__btn:not(.mm-listitem__text){border-left-width:1px;border-left-style:solid}.mm-listitem--selected>.mm-listitem__text{background:var(--mm-color-background-emphasis)}.mm-listitem--opened>.mm-listitem__btn,.mm-listitem--opened>.mm-panel{background:var(--mm-color-background-highlight)}.mm-listview{list-style:none;display:block;padding:0;margin:0}.mm-menu{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;padding:0;margin:0;position:absolute;top:0;right:0;bottom:0;left:0;z-index:0;-ms-scroll-chaining:none;overscroll-behavior:none;background:var(--mm-color-background);border-color:var(--mm-color-border);color:var(--mm-color-text);line-height:var(--mm-lineheight);-webkit-tap-highlight-color:var(--mm-color-background-emphasis);-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.mm-menu ::-webkit-input-placeholder{color:var(--mm-color-text-dimmed)}.mm-menu ::-moz-placeholder{color:var(--mm-color-text-dimmed)}.mm-menu :-ms-input-placeholder{color:var(--mm-color-text-dimmed)}.mm-menu ::-ms-input-placeholder{color:var(--mm-color-text-dimmed)}.mm-menu ::placeholder{color:var(--mm-color-text-dimmed)}.mm-menu,.mm-menu *{-webkit-box-sizing:border-box;box-sizing:border-box}.mm-menu :focus,.mm-menu :focus-visible,.mm-menu:focus,.mm-menu:focus-visible{outline:0}.mm-menu a,.mm-menu button,.mm-menu label{color:inherit}.mm-menu a:focus,.mm-menu button:focus,.mm-menu label:focus{outline:0}.mm-menu a:focus-visible,.mm-menu button:focus-visible,.mm-menu label:focus-visible{outline:2px solid var(--mm-color-focusring);outline-offset:-5px}.mm-menu input:focus,.mm-menu input:focus-visible,.mm-menu select:focus,.mm-menu select:focus-visible,.mm-menu textarea:focus,.mm-menu textarea:focus-visible{outline:2px solid var(--mm-color-focusring);outline-offset:2px}.mm-menu a,.mm-menu a:active,.mm-menu a:hover,.mm-menu a:link,.mm-menu a:visited{text-decoration:none;color:inherit}:root{--mm-navbar-size:50px}.mm-navbar{display:-webkit-box;display:-ms-flexbox;display:flex;position:-webkit-sticky;position:sticky;top:0;z-index:2;min-height:var(--mm-navbar-size);padding-top:env(safe-area-inset-top);color:var(--mm-color-text-dimmed);text-align:center;opacity:1;background:var(--mm-color-background);border-bottom:1px solid var(--mm-color-border);-webkit-transition-property:opacity;-o-transition-property:opacity;transition-property:opacity}.mm-navbar>*{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-box-sizing:border-box;box-sizing:border-box}.mm-navbar__btn{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0}.mm-navbar__title{-webkit-box-flex:1;-ms-flex:1 1 50%;flex:1 1 50%;display:-webkit-box;display:-ms-flexbox;display:flex;padding:0 20px;overflow:hidden}.mm-navbar__title[href="#"]{pointer-events:none}.mm-navbar__title>span{-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.mm-btn.mm-hidden+.mm-navbar__title:not(:last-child){-webkit-padding-start:60px;padding-inline-start:60px;-webkit-padding-end:10px;padding-inline-end:10px}.mm-btn:not(.mm-hidden)+.mm-navbar__title:last-child{-webkit-padding-start:10px;padding-inline-start:10px;-webkit-padding-end:60px;padding-inline-end:60px}.mm-panel{--mm-panel-child-offset:100%;--mm-panel-parent-offset:-30%;position:absolute;left:0;right:0;top:0;bottom:0;z-index:1;-webkit-overflow-scrolling:touch;overflow:hidden;overflow-y:auto;-ms-scroll-chaining:none;overscroll-behavior:contain;color:var(--mm-color-text);border-color:var(--mm-color-border);background:var(--mm-color-background);-webkit-transform:translate3d(var(--mm-panel-child-offset),0,0);transform:translate3d(var(--mm-panel-child-offset),0,0);-webkit-transition-property:inset-inline-start,-webkit-transform;transition-property:inset-inline-start,-webkit-transform;-o-transition-property:transform,inset-inline-start;transition-property:transform,inset-inline-start;transition-property:transform,inset-inline-start,-webkit-transform}[dir=rtl] .mm-panel{--mm-panel-child-offset:-100%;--mm-panel-parent-offset:30%}.mm-panel:after{content:"";display:block;height:var(--mm-listitem-size)}.mm-panel:focus{outline:0}.mm-panel--opened{z-index:2;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);-webkit-transition-delay:0s;-o-transition-delay:0s;transition-delay:0s}.mm-panel--parent{-webkit-transform:translate3d(var(--mm-panel-parent-offset),0,0);transform:translate3d(var(--mm-panel-parent-offset),0,0);z-index:0}.mm-panel--highest{z-index:3}.mm-menu--opened .mm-panel--noanimation{-webkit-transition:none!important;-o-transition:none!important;transition:none!important;-webkit-transition-duration:0s!important;-o-transition-duration:0s!important;transition-duration:0s!important}.mm-panel__content{padding:20px}.mm-panels{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;position:relative;height:100%;overflow:hidden;background:var(--mm-color-background);border-color:var(--mm-color-border);color:var(--mm-color-text)}.mm-panels:focus{outline:0}:root{--mm-toggle-size:34px}.mm-toggle{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-item-align:center;align-self:center;-webkit-box-flex:calc(var(--mm-toggle-size) * 1.75);-ms-flex:calc(var(--mm-toggle-size) * 1.75) 0 0px;flex:calc(var(--mm-toggle-size) * 1.75) 0 0;height:var(--mm-toggle-size);-webkit-margin-end:10px;margin-inline-end:10px;-webkit-appearance:none!important;-moz-appearance:none!important;appearance:none!important;border:none!important;border-radius:var(--mm-toggle-size);border:var(--mm-color-border);background:var(--mm-color-border);cursor:pointer;-webkit-transition-property:background-color;-o-transition-property:background-color;transition-property:background-color}.mm-toggle:before{content:"";aspect-ratio:1;margin:2px;border-radius:100%;background:var(--mm-color-background);-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;-o-transition-property:transform;transition-property:transform;transition-property:transform,-webkit-transform}.mm-toggle:checked{background:#4bd963}.mm-toggle:checked:before{-webkit-transform:translateX(calc(var(--mm-toggle-size) * .75));-ms-transform:translateX(calc(var(--mm-toggle-size) * .75));transform:translateX(calc(var(--mm-toggle-size) * .75))}[dir=rtl] .mm-toggle:checked:before{-webkit-transform:translateX(calc(var(--mm-toggle-size) * -.75));-ms-transform:translateX(calc(var(--mm-toggle-size) * -.75));transform:translateX(calc(var(--mm-toggle-size) * -.75))}.mm-listitem--vertical>.mm-panel{position:static;width:100%;padding:10px 0 10px 20px;-webkit-transform:none!important;-ms-transform:none!important;transform:none!important;-webkit-transition:none!important;-o-transition:none!important;transition:none!important}.mm-listitem--vertical>.mm-panel:after{content:none;display:none}.mm-listitem--vertical:not(.mm-listitem--opened)>.mm-panel{display:none}.mm-listitem--vertical>.mm-listitem__btn{height:var(--mm-listitem-size);bottom:auto}.mm-listitem--vertical .mm-listitem:last-child:after{border-color:transparent}.mm-listitem--opened>.mm-listitem__btn:after{-webkit-transform:rotate(225deg);-ms-transform:rotate(225deg);transform:rotate(225deg);right:19px}:root{--mm-size:80%;--mm-min-size:240px;--mm-max-size:440px}.mm-menu--offcanvas{position:fixed;z-index:0}.mm-page{-webkit-box-sizing:border-box;box-sizing:border-box;min-height:100vh;background:inherit}:where(.mm-slideout){position:relative;z-index:1;width:100%;-webkit-transition-duration:.4s;-o-transition-duration:.4s;transition-duration:.4s;-webkit-transition-timing-function:ease;-o-transition-timing-function:ease;transition-timing-function:ease;-webkit-transition-property:width,-webkit-transform;transition-property:width,-webkit-transform;-o-transition-property:width,transform;transition-property:width,transform;transition-property:width,transform,-webkit-transform}.mm-wrapper--opened,.mm-wrapper--opened body{overflow:hidden}.mm-wrapper__blocker{background:rgba(0,0,0,.4)}.mm-wrapper--opened .mm-wrapper__blocker{--mm-blocker-visibility-delay:0s;--mm-blocker-opacity-delay:0.4s;bottom:0;opacity:.5}.mm-menu{--mm-translate-horizontal:0;--mm-translate-vertical:0}.mm-menu--position-left,.mm-menu--position-left-front{right:auto}.mm-menu--position-right,.mm-menu--position-right-front{left:auto}.mm-menu--position-left,.mm-menu--position-left-front,.mm-menu--position-right,.mm-menu--position-right-front{width:clamp(var(--mm-min-size),var(--mm-size),var(--mm-max-size))}.mm-menu--position-left-front{--mm-translate-horizontal:-100%}.mm-menu--position-right-front{--mm-translate-horizontal:100%}.mm-menu--position-top{bottom:auto}.mm-menu--position-bottom{top:auto}.mm-menu--position-bottom,.mm-menu--position-top{width:100%;height:clamp(var(--mm-min-size),var(--mm-size),var(--mm-max-size))}.mm-menu--position-top{--mm-translate-vertical:-100%}.mm-menu--position-bottom{--mm-translate-vertical:100%}.mm-menu--position-bottom,.mm-menu--position-left-front,.mm-menu--position-right-front,.mm-menu--position-top{z-index:2;-webkit-transform:translate3d(var(--mm-translate-horizontal),var(--mm-translate-vertical),0);transform:translate3d(var(--mm-translate-horizontal),var(--mm-translate-vertical),0);-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;-o-transition-property:transform;transition-property:transform;transition-property:transform,-webkit-transform}.mm-menu--position-bottom.mm-menu--opened,.mm-menu--position-left-front.mm-menu--opened,.mm-menu--position-right-front.mm-menu--opened,.mm-menu--position-top.mm-menu--opened{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.mm-wrapper--position-left{--mm-translate-horizontal:clamp(
      var(--mm-min-size),
      var(--mm-size),
      var(--mm-max-size)
  )}.mm-wrapper--position-right{--mm-translate-horizontal:clamp(
      calc(-1 * var(--mm-max-size)),
      calc(-1 * var(--mm-size)),
      calc(-1 * var(--mm-min-size))
  )}.mm-wrapper--position-left .mm-slideout,.mm-wrapper--position-right .mm-slideout{-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0)}.mm-wrapper--position-left.mm-wrapper--opened .mm-slideout,.mm-wrapper--position-right.mm-wrapper--opened .mm-slideout{-webkit-transform:translate3d(var(--mm-translate-horizontal),0,0);transform:translate3d(var(--mm-translate-horizontal),0,0)}.mm-wrapper--position-bottom .mm-wrapper__blocker,.mm-wrapper--position-left-front .mm-wrapper__blocker,.mm-wrapper--position-right-front .mm-wrapper__blocker,.mm-wrapper--position-top .mm-wrapper__blocker{z-index:1}.mm-menu--theme-light{--mm-color-background:#f3f3f3;--mm-color-border:rgb(0 0 0 / 0.15);--mm-color-icon:rgb(0 0 0 / 0.4);--mm-color-text:rgb(0 0 0 / 0.8);--mm-color-text-dimmed:rgb(0 0 0 / 0.4);--mm-color-background-highlight:rgb(0 0 0 / 0.05);--mm-color-background-emphasis:rgb(255 255 255 / 0.75);--mm-color-focusring:#06c}.mm-menu--theme-light-contrast{--mm-color-background:#f3f3f3;--mm-color-border:rgb(0 0 0 / 0.5);--mm-color-icon:rgb(0 0 0 / 0.5);--mm-color-text:#000;--mm-color-text-dimmed:rgb(0 0 0 / 0.7);--mm-color-background-highlight:rgb(0 0 0 / 0.05);--mm-color-background-emphasis:rgb(255 255 255 / 0.9);--mm-color-focusring:#06c}.mm-menu--theme-dark{--mm-color-background:#333;--mm-color-border:rgb(0, 0, 0, 0.4);--mm-color-icon:rgb(255, 255, 255, 0.4);--mm-color-text:rgb(255, 255, 255, 0.8);--mm-color-text-dimmed:rgb(255, 255, 255, 0.4);--mm-color-background-highlight:rgb(255, 255, 255, 0.08);--mm-color-background-emphasis:rgb(0, 0, 0, 0.1);--mm-color-focusring:#06c}.mm-menu--theme-dark-contrast{--mm-color-background:#333;--mm-color-border:rgb(255 255 255 / 0.5);--mm-color-icon:rgb(255 255 255 / 0.5);--mm-color-text:#fff;--mm-color-text-dimmed:rgb(255 255 255 / 0.7);--mm-color-background-highlight:rgb(255 255 255 / 0.1);--mm-color-background-emphasis:rgb(0 0 0 / 0.3);--mm-color-focusring:#06c}.mm-menu--theme-white{--mm-color-background:#fff;--mm-color-border:rgb(0 0 0 / 0.15);--mm-color-icon:rgb(0 0 0 / 0.3);--mm-color-text:rgb(0 0 0 / 0.8);--mm-color-text-dimmed:rgb(0 0 0 / 0.3);--mm-color-background-highlight:rgb(0 0 0 / 0.06);--mm-color-background-emphasis:rgb(0 0 0 / 0.03);--mm-color-focusring:#06c}.mm-menu--theme-white-contrast{--mm-color-background:#fff;--mm-color-border:rgb(0 0 0 / 0.5);--mm-color-icon:rgb(0 0 0 / 0.5);--mm-color-text:#000;--mm-color-text-dimmed:rgb(0 0 0 / 0.7);--mm-color-background-highlight:rgb(0 0 0 / 0.07);--mm-color-background-emphasis:rgb(0 0 0 / 0.035);--mm-color-focusring:#06c}.mm-menu--theme-black{--mm-color-background:#000;--mm-color-border:rgb(255 255 255 / 0.2);--mm-color-icon:rgb(255 255 255 / 0.4);--mm-color-text:rgb(255 255 255 / 0.7);--mm-color-text-dimmed:rgb(255 255 255 / 0.4);--mm-color-background-highlight:rgb(255 255 255 / 0.1);--mm-color-background-emphasis:rgb(255 255 255 / 0.06);--mm-color-focusring:#06c}.mm-menu--theme-black-contrast{--mm-color-background:#000;--mm-color-border:rgb(255 255 255 / 0.5);--mm-color-icon:rgb(255 255 255 / 0.5);--mm-color-text:#fff;--mm-color-text-dimmed:rgb(255 255 255 / 0.6);--mm-color-background-highlight:rgb(255 255 255 / 0.125);--mm-color-background-emphasis:rgb(255 255 255 / 0.1);--mm-color-focusring:#06c}.mm-counter{display:block;-webkit-padding-start:20px;padding-inline-start:20px;float:right;color:var(--mm-color-text-dimmed)}[dir=rtl] .mm-counter{float:left}:root{--mm-iconbar-size:50px}.mm-menu--iconbar-left .mm-navbars,.mm-menu--iconbar-left .mm-panels{margin-left:var(--mm-iconbar-size)}.mm-menu--iconbar-right .mm-navbars,.mm-menu--iconbar-right .mm-panels{margin-right:var(--mm-iconbar-size)}.mm-iconbar{display:none;position:absolute;top:0;bottom:0;z-index:2;width:var(--mm-iconbar-size);overflow:hidden;-webkit-box-sizing:border-box;box-sizing:border-box;border:0 solid;border-color:var(--mm-color-border);background:var(--mm-color-background);color:var(--mm-color-text-dimmed);text-align:center}.mm-menu--iconbar-left .mm-iconbar,.mm-menu--iconbar-right .mm-iconbar{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.mm-menu--iconbar-left .mm-iconbar{border-right-width:1px;left:0}.mm-menu--iconbar-right .mm-iconbar{border-left-width:1px;right:0}.mm-iconbar__bottom,.mm-iconbar__top{width:100%;-webkit-overflow-scrolling:touch;overflow:hidden;overflow-y:auto;-ms-scroll-chaining:none;overscroll-behavior:contain}.mm-iconbar__bottom>*,.mm-iconbar__top>*{-webkit-box-sizing:border-box;box-sizing:border-box;display:block;padding:calc((var(--mm-iconbar-size) - var(--mm-lineheight))/ 2) 0}.mm-iconbar__bottom a,.mm-iconbar__bottom a:hover,.mm-iconbar__top a,.mm-iconbar__top a:hover{text-decoration:none}.mm-iconbar__tab--selected{background:var(--mm-color-background-emphasis)}:root{--mm-iconpanel-size:50px}.mm-panel--iconpanel-0{inset-inline-start:calc(0 * var(--mm-iconpanel-size))}.mm-panel--iconpanel-1{inset-inline-start:calc(1 * var(--mm-iconpanel-size))}.mm-panel--iconpanel-2{inset-inline-start:calc(2 * var(--mm-iconpanel-size))}.mm-panel--iconpanel-3{inset-inline-start:calc(3 * var(--mm-iconpanel-size))}.mm-panel--iconpanel-4{inset-inline-start:calc(4 * var(--mm-iconpanel-size))}.mm-panel--iconpanel-first~.mm-panel{inset-inline-start:var(--mm-iconpanel-size)}.mm-menu--iconpanel .mm-panel--parent .mm-divider,.mm-menu--iconpanel .mm-panel--parent .mm-navbar{opacity:0}.mm-menu--iconpanel .mm-panels>.mm-panel--parent{overflow-y:hidden;-webkit-transform:unset;-ms-transform:unset;transform:unset}.mm-menu--iconpanel .mm-panels>.mm-panel:not(.mm-panel--iconpanel-first):not(.mm-panel--iconpanel-0){border-inline-start-width:1px;border-inline-start-style:solid}.mm-navbars{-ms-flex-negative:0;flex-shrink:0}.mm-navbars .mm-navbar{position:relative;padding-top:0;border-bottom:none}.mm-navbars--top{border-bottom:1px solid var(--mm-color-border)}.mm-navbars--top .mm-navbar:first-child{padding-top:env(safe-area-inset-top)}.mm-navbars--bottom{border-top:1px solid var(--mm-color-border)}.mm-navbars--bottom .mm-navbar:last-child{padding-bottom:env(safe-area-inset-bottom)}.mm-navbar__breadcrumbs{-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;-webkit-box-flex:1;-ms-flex:1 1 50%;flex:1 1 50%;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;padding:0 20px;overflow-x:auto;-webkit-overflow-scrolling:touch}.mm-navbar__breadcrumbs>*{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;-webkit-padding-end:6px;padding-inline-end:6px}.mm-navbar__breadcrumbs>a{text-decoration:underline}.mm-navbar__breadcrumbs:not(:last-child){-webkit-padding-end:0;padding-inline-end:0}.mm-btn:not(.mm-hidden)+.mm-navbar__breadcrumbs{-webkit-padding-start:0;padding-inline-start:0}.mm-navbar__tab{padding:0 10px;border:1px solid transparent}.mm-navbar__tab--selected{background:var(--mm-color-background)}.mm-navbar__tab--selected:not(:first-child){border-inline-start-color:var(--mm-color-border)}.mm-navbar__tab--selected:not(:last-child){border-inline-end-color:var(--mm-color-border)}.mm-navbars--top.mm-navbars--has-tabs{border-bottom:none}.mm-navbars--top.mm-navbars--has-tabs .mm-navbar{background:var(--mm-color-background-emphasis)}.mm-navbars--top.mm-navbars--has-tabs .mm-navbar--tabs~.mm-navbar{background:var(--mm-color-background)}.mm-navbars--top.mm-navbars--has-tabs .mm-navbar:not(.mm-navbar--tabs):last-child{border-bottom:1px solid var(--mm-color-border)}.mm-navbars--top .mm-navbar__tab{border-bottom-color:var(--mm-color-border)}.mm-navbars--top .mm-navbar__tab--selected{border-top-color:var(--mm-color-border);border-bottom-color:transparent}.mm-navbars--bottom.mm-navbar--has-tabs{border-top:none}.mm-navbars--bottom.mm-navbar--has-tabs .mm-navbar{background:var(--mm-color-background)}.mm-navbars--bottom.mm-navbar--has-tabs .mm-navbar--tabs,.mm-navbars--bottom.mm-navbar--has-tabs .mm-navbar--tabs~.mm-navbar{background:var(--mm-color-background-emphasis)}.mm-navbars--bottom .mm-navbar__tab{border-top-color:var(--mm-color-border)}.mm-navbars--bottom .mm-navbar__tab--selected{border-bottom-color:var(--mm-color-border);border-top-color:transparent}.mm-searchfield{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;height:var(--mm-navbar-size);padding:0;overflow:hidden}.mm-searchfield__input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-align:center;-ms-flex-align:center;align-items:center;position:relative;width:100%;max-width:100%;padding:0 10px;-webkit-box-sizing:border-box;box-sizing:border-box}.mm-searchfield__input input{display:block;width:100%;max-width:100%;height:calc(var(--mm-navbar-size) * .7);min-height:auto;max-height:auto;margin:0;padding:0 10px;-webkit-box-sizing:border-box;box-sizing:border-box;border:none;border-radius:4px;line-height:calc(var(--mm-navbar-size) * .7);font:inherit;font-size:inherit}.mm-searchfield__input input,.mm-searchfield__input input:focus,.mm-searchfield__input input:hover{background:var(--mm-color-background-highlight);color:var(--mm-color-text)}.mm-menu[class*=-contrast] .mm-searchfield__input input{border:1px solid var(--mm-color-border)}.mm-searchfield__input input::-ms-clear{display:none}.mm-searchfield__btn{display:none;position:absolute;inset-inline-end:0;top:0;bottom:0}.mm-searchfield--searching .mm-searchfield__btn{display:block}.mm-searchfield__cancel{display:block;position:relative;-webkit-margin-end:-100px;margin-inline-end:-100px;-webkit-padding-start:5px;padding-inline-start:5px;-webkit-padding-end:20px;padding-inline-end:20px;visibility:hidden;line-height:var(--mm-navbar-size);text-decoration:none;-webkit-transition-property:visibility,margin;-o-transition-property:visibility,margin;transition-property:visibility,margin}.mm-searchfield--cancelable .mm-searchfield__cancel{visibility:visible;-webkit-margin-end:0;margin-inline-end:0}.mm-panel--search{left:0!important;right:0!important;width:100%!important;border:none!important}.mm-panel__splash{padding:20px}.mm-panel--searching .mm-panel__splash{display:none}.mm-panel__noresults{display:none;padding:40px 20px;color:var(--mm-color-text-dimmed);text-align:center;font-size:150%;line-height:1.4}.mm-panel--noresults .mm-panel__noresults{display:block}:root{--mm-sectionindexer-size:20px}.mm-sectionindexer{background:inherit;text-align:center;font-size:12px;-webkit-box-sizing:border-box;box-sizing:border-box;width:var(--mm-sectionindexer-size);position:absolute;top:0;bottom:0;inset-inline-end:calc(-1 * var(--mm-sectionindexer-size));z-index:5;-webkit-transition-property:inset-inline-end;-o-transition-property:inset-inline-end;transition-property:inset-inline-end;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-pack:space-evenly;-ms-flex-pack:space-evenly;justify-content:space-evenly}.mm-sectionindexer a{color:var(--mm-color-text-dimmed);line-height:1;text-decoration:none;display:block}.mm-sectionindexer~.mm-panel{-webkit-padding-end:0;padding-inline-end:0}.mm-sectionindexer--active{right:0}.mm-sectionindexer--active~.mm-panel{-webkit-padding-end:var(--mm-sectionindexer-size);padding-inline-end:var(--mm-sectionindexer-size)}.mm-menu--selected-hover .mm-listitem__btn,.mm-menu--selected-hover .mm-listitem__text,.mm-menu--selected-parent .mm-listitem__btn,.mm-menu--selected-parent .mm-listitem__text{-webkit-transition-property:background-color;-o-transition-property:background-color;transition-property:background-color}@media (hover:hover){.mm-menu--selected-hover .mm-listview:hover>.mm-listitem--selected:not(:hover)>.mm-listitem__text{background:0 0}.mm-menu--selected-hover .mm-listitem__btn:hover,.mm-menu--selected-hover .mm-listitem__text:hover{background:var(--mm-color-background-emphasis)}}.mm-menu--selected-parent .mm-listitem__btn,.mm-menu--selected-parent .mm-listitem__text{-webkit-transition-delay:.2s;-o-transition-delay:.2s;transition-delay:.2s}@media (hover:hover){.mm-menu--selected-parent .mm-listitem__btn:hover,.mm-menu--selected-parent .mm-listitem__text:hover{-webkit-transition-delay:0s;-o-transition-delay:0s;transition-delay:0s}}.mm-menu--selected-parent .mm-panel--parent .mm-listitem:not(.mm-listitem--selected-parent)>.mm-listitem__text{background:0 0}.mm-menu--selected-parent .mm-listitem--selected-parent>.mm-listitem__btn,.mm-menu--selected-parent .mm-listitem--selected-parent>.mm-listitem__text{background:var(--mm-color-background-emphasis)}:root{--mm-sidebar-collapsed-size:50px;--mm-sidebar-expanded-size:var(--mm-max-size)}.mm-wrapper--sidebar-collapsed .mm-slideout{width:calc(100% - var(--mm-sidebar-collapsed-size));-webkit-transform:translate3d(var(--mm-sidebar-collapsed-size),0,0);transform:translate3d(var(--mm-sidebar-collapsed-size),0,0)}[dir=rtl] .mm-wrapper--sidebar-collapsed .mm-slideout{-webkit-transform:none;-ms-transform:none;transform:none}.mm-wrapper--sidebar-collapsed:not(.mm-wrapper--opened) .mm-menu--sidebar-collapsed .mm-divider,.mm-wrapper--sidebar-collapsed:not(.mm-wrapper--opened) .mm-menu--sidebar-collapsed .mm-navbar{opacity:0}.mm-wrapper--sidebar-expanded .mm-menu--sidebar-expanded{width:var(--mm-sidebar-expanded-size);border-right-width:1px;border-right-style:solid}.mm-wrapper--sidebar-expanded.mm-wrapper--opened{overflow:auto}.mm-wrapper--sidebar-expanded.mm-wrapper--opened .mm-wrapper__blocker{display:none}.mm-wrapper--sidebar-expanded.mm-wrapper--opened .mm-slideout{width:calc(100% - var(--mm-sidebar-expanded-size));-webkit-transform:translate3d(var(--mm-sidebar-expanded-size),0,0);transform:translate3d(var(--mm-sidebar-expanded-size),0,0)}[dir=rtl] .mm-wrapper--sidebar-expanded.mm-wrapper--opened .mm-slideout{-webkit-transform:none;-ms-transform:none;transform:none}
/* ======================================================================
   Bright Cloud Studio Layout Utility Framework (Pure CSS)
   DESKTOP-FIRST • max-width media queries
   ====================================================================== */

/* ======================================================================
   PROJECT TOKENS — EDIT THESE PER SITE
   ====================================================================== */
:root {
  /* Page gutters (site margins) */
  --page-gutter: clamp(16px, 4vw, 60px);

  /* Max content width — the single dial for page width. Everything that
     caps content reads this: the .container utility, and the site shell's
     .container_inside rule in website_structure.css. */
  --container-max: 1920px;   /* Cornerstone: 1800px of content (the boards' x300–2100)
                               + the 60px gutter each side */

/* ======================================================================
   GUTTER SCALE (PROJECT-CONFIGURABLE)
   ======================================================================

   The single source of truth for every gutter value. The .gap-* and
   .pxc-* utilities, the row defaults, and the responsive overrides all
   read from these — so changing a value here retunes the whole site
   without touching a single class name.

   As with the spacing scale, the numbers in class names are STEPS, not
   promises: set --gutter-40 to 32px and .gap-40 becomes 32px.

   NOTE — deliberately SEPARATE from the --space-* scale below.
   The space steps are fluid (--space-40 is clamp(24px, 3vw, 40px)),
   while the fixed gutters are fixed on purpose, so that .gap-40 can
   match a comp exactly. Wiring them together would quietly make every
   fixed gutter fluid and erase the point of the .gap-fluid-* tier.

   Every value must carry a unit — a bare 0 invalidates the column
   calc() that consumes it and the column silently loses its width.
====================================================================== */

  /* Fixed steps */
  --gutter-0:  0px;
  --gutter-16: 16px;
  --gutter-24: 24px;
  --gutter-40: 40px;
  --gutter-60: 60px;

  /* Fluid steps — scale smoothly with the viewport */
  --gutter-fluid-sm: clamp(8px, 1.5vw, 16px);
  --gutter-fluid-md: clamp(12px, 2vw, 32px);
  --gutter-fluid-lg: clamp(24px, 4vw, 64px);

  /* Single-axis fluid (used by .gap-x-fluid / .gap-y-fluid) */
  --gutter-fluid-axis: clamp(12px, 2vw, 40px);

  /* Column inner padding, fluid tier — a SEPARATE scale from the gutters
     above. Inner padding runs wider than a gutter at the top end, so these
     keep their own ceilings (60/80px) rather than the gutter's 64px. */
  --col-pad-fluid-sm: clamp(8px, 1.5vw, 24px);
  --col-pad-fluid:    clamp(16px, 3vw, 60px);
  --col-pad-fluid-lg: clamp(24px, 4vw, 80px);

  /* Default row spacing (desktop) — points at the scale above */
  --row-gap-x: var(--gutter-40);
  --row-gap-y: var(--gutter-40);

  /* Default column inner padding (desktop) — edit per site if needed */
  --row-col-pad-x: var(--gutter-0);

/* ======================================================================
   SPACING SCALE (PROJECT-CONFIGURABLE)
   ======================================================================

   IMPORTANT:
   The numbers in spacing utility class names (mb-40, mt-24, etc.)
   represent spacing STEPS, not fixed pixel values.

   Changing the --space-* values below will update spacing globally
   without changing class names.

   Do NOT assume mb-40 always equals 40px.

   BY DESIGN — FLUID STEPS CONVERGE ON SMALL SCREENS
   -------------------------------------------------
   The larger steps (40/60/80) are fluid clamp() values whose lower bounds
   intentionally overlap the fixed steps below them. Consequence:

     • On narrow viewports (~≤800px) --space-40 sits at its 24px floor, so
       mb-40 and mb-24 render identically. The steps only visibly separate
       on wider screens.

   This is intentional: spacing tightens on mobile and opens up on desktop.
   If you need steps that stay distinct at EVERY width, raise the clamp
   floors (e.g. --space-40: clamp(28px, 3vw, 40px)) — see audit note C7.
====================================================================== */
  --space-0: 0;
  --space-8: 8px;
  --space-12: 12px;
  --space-16: 16px;
  --space-24: 24px;
  --space-40: clamp(24px, 3vw, 40px);
  --space-60: clamp(32px, 5vw, 60px);
  --space-80: clamp(40px, 7vw, 80px);

  /* Major section separation (responsive) */
  --space-section: clamp(48px, 6vw, 96px);   /* the boards' section padding: 96 (28 of 57 sections) */
    
    
/* ======================================================================
   SINGLE-COLUMN MAX WIDTH TOKENS (EDIT PER SITE)
   ======================================================================

   Used to constrain one-column rows without affecting global containers.
   Ideal for editorial content, long-form copy, and focused sections.
====================================================================== */

--single-sm: 720px;   /* readable text width */
--single-md: 880px;   /* default content column */
--single-lg: 1040px;  /* wide single-column layouts */


}

/* End tokens ======================================================================
=================================================================================== */

/* ======================================================================
   BOX SIZING RESET — REQUIRED BY THE CONTAINER / COLUMN MATH
   ======================================================================

   Padding must be included in declared widths, or max-width and
   padding-inline compound: .container / #main > .inside would render
   (--container-max + 2 × --page-gutter) wide instead of --container-max,
   and percentage columns would overflow once padding is added.

====================================================================== */
html {
  box-sizing: border-box;
}

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


/* ======================================================================
   CONTAINERS — SAFE TO REUSE ACROSS PROJECTS
   ====================================================================== */
.container {
  margin-inline: auto;
  padding-inline: var(--page-gutter);
  max-width: var(--container-max);
}

.container-fluid {
  width: 100%;
  padding-inline: var(--page-gutter);
}


/* ======================================================================
   THE PAGE CONTAINER LIVES IN THE SITE STYLESHEET — NOT HERE
   ======================================================================

   This framework is CMS-agnostic: it owns containers, rows, columns and
   spacing utilities, but it does NOT claim any CMS-specific selector.

   In the "article = .row" model each article renders into the CMS's main
   content column, and THAT column is what carries the site's max-width,
   centring and page gutter. In Contao that is .container_inside — which
   wraps #main and the left/right columns — and the rule belongs in the
   site shell stylesheet (website_structure.css), alongside the matching
   rules for the header, prefooter and footer.

   ⚠ One owner only. Two selectors at identical specificity (1,1,0) would
   let whichever stylesheet loads last decide the site's content width.

   Nothing here depends on it: with the gap engine rows use no negative
   margins, so they can never overflow their parent. Without a container
   rule, rows simply run the full width of whatever contains them.
====================================================================== */




/* AUDIT NOTE — .bleed-x
   .bleed-x applies negative margins to break out of container gutters.
   Use it for full-bleed backgrounds/sections.

   Avoid putting .bleed-x on elements inside components that already have
   their own padding (cards, modals) unless you intend for it to escape. */

/* Full-bleed helper — breaks out of the container GUTTER only. Use inside a
   full-width parent, or when --container-max ≈ the viewport. */
.bleed-x {
  margin-inline: calc(-1 * var(--page-gutter));
  padding-inline: 0;
}

/* Viewport-wide bleed — breaks out all the way to the screen edges, even when
   the content column (--container-max) is narrower than the viewport. Use it
   for full-width COLOUR BANDS, then put an inner `.container` back inside to
   re-cap the content. Relies on html { overflow-x: clip } (website_structure)
   so the 100vw never introduces a horizontal scrollbar.

     <section class="mod_article hero hero--photo bleed-full">
       <div class="container"> … </div>
     </section> */
.bleed-full {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
}

/* Full-width colour BAND with self-capping content. Put it on a section/article
   that carries a background: the band itself spans the viewport, and each of
   its DIRECT children is re-capped to the content column and gutter-padded —
   so no inner `.container` wrapper (or element group) is needed. This is what
   the native-content-element sections use: article = .band, children = the
   headline / text / image / element-group content elements. */
.band {
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  padding-inline: 0;
}
.band > * {
  box-sizing: border-box;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--page-gutter);
}

/* Bleeding a COLUMN needs two corrections:

   1. padding — plain .bleed-x ties with .row > * and loses on source
      order, so the gutter padding has to be dropped at higher specificity.

   2. width — a flex item's percentage basis resolves against the row's
      content box, and margins sit OUTSIDE that box. So negative margins
      do not widen the item, they shrink its margin box to (100% - 2×gutter)
      and, because flex-grow is 0 and justify-content is flex-start, the
      whole box simply shifts left: correct bleed on the left, but two
      gutters short on the right. Paying for both margins in the basis
      makes the margin box exactly 100% again, so the band lands flush on
      both edges.

   Only full-width bleeds make sense here; .bleed-x on a fractional
   column is unsupported. */
.row > *.bleed-x {
  flex: 0 0 calc(100% + var(--page-gutter) * 2);
  padding-inline: 0;
}



/* ======================================================================
   HOW GUTTERS WORK — REAL gap + SELF-COMPENSATING COLUMNS
   ======================================================================

   THE PROBLEM WITH NAIVE gap
   --------------------------
   A plain `gap` adds space ON TOP of percentage columns:

     .col-2-3 (66.666%) + .col-1-3 (33.333%) + gap > 100%   → wraps

   THE FIX — COLUMNS PAY FOR THE GUTTER
   ------------------------------------
   Each column subtracts its own fair share of the gutter from its width:

     width = P% - gap × (1 - P)        where P is the column's fraction

   Worked example — 75/25 on a 1200px row with a 40px gap:

     .col-3-4 → 75% of 1200 - 40 × 0.25  =  900 - 10  =  890px
     .col-1-4 → 25% of 1200 - 40 × 0.75  =  300 - 30  =  270px
                                    890 + 40 + 270  =  1200px  ✓

   Any set of fractions summing to 100% fills the row exactly, and the
   leftover gutter is billed to each column in proportion to how much
   width it gives up — which is why the arithmetic always closes.

   WHY THIS BEATS THE OLD NEGATIVE-MARGIN TECHNIQUE
   ------------------------------------------------
     • Real empty space between columns, so column backgrounds, borders
       and cards actually separate (padding gutters cannot do this).
     • No negative margins, so a row can never overflow its parent and
       needs no padded container to sit in.
     • flex-basis stays a real width, so flex-wrap still works: .col-1-1
       claims its own line and N-up grids wrap naturally.
     • .trim becomes unnecessary (kept as a no-op for old markup).

   Vertical spacing between wrapped lines uses the same gap's row axis.
====================================================================== */


/* ======================================================================
   ROW ENGINE — CORE (LEAVE ALONE)
   ====================================================================== */
.row {
    display: flex;
    flex-wrap: wrap;
    /* Row-level spacing defaults (from project tokens) */
    --gap-x: var(--row-gap-x);   /* horizontal gutter between columns */
    --gap-y: var(--row-gap-y);   /* vertical gap between wrapped rows */
    --col-pad-x: var(--row-col-pad-x); /* optional inner padding inside each column */
    /* A REAL gap — genuine empty space between columns.
    Columns give the gutter back out of their own width (see the
    calc() bases below), so percentages never sum past 100%. */
    gap: var(--gap-y) var(--gap-x);

    /* Optional inner padding, applied INSIDE the column's declared width.
       box-sizing:border-box means this insets content without changing the
       column's outer width — so no .trim compensation is ever needed. */
    /* flex-basis 100% is a FALLBACK: a row child with no col-* class (Contao emits
       several of its own — .syndication, .back, and any unclassed element) would
       otherwise shrink-wrap to its content instead of taking a line. Every .col-*
       rule is later in source at equal specificity, so real columns still win. */
    > * {
      flex: 0 1 100%;
      padding-inline: var(--col-pad-x);
      min-width: 0;
      box-sizing: border-box;
    }

    /* Contao emits a <script> straight after a form (and after some modules). As a
       flex child it is a zero-width COLUMN, so the row's gap gets applied one extra
       time and every real column loses that space. It has no box to lay out. */
    > script { display: none; }

    /* ----------------------------------------------------------------------
       CONTENT CONTAINMENT
       ----------------------------------------------------------------------
       `.row > *` sets min-width: 0 so columns can shrink below their content's
       intrinsic width — that is what keeps percentage columns honest. The
       side effect is that anything wider than the column (an uploaded image,
       an embed, an unbroken URL) will overflow it and can force horizontal
       scroll on the whole page.

       Scoped to the framework's own boxes: the layout engine created this
       exposure, so it contains it. A site-wide `img { max-width: 100% }`
       baseline, if wanted, belongs in the theme/base layer.
    ---------------------------------------------------------------------- */

    > * img, > * svg, > * video, > * canvas, > * iframe, > * embed, > * object { max-width: 100%; }

    /* Preserve aspect ratio once max-width starts constraining the element */
    > * img, > * svg, > * video { height: auto; }

    /* Long unbroken strings (URLs, tokens) wrap instead of pushing the column open */
    > * { overflow-wrap: break-word; }

    /* DEPRECATED — .trim existed to cancel the old negative row margins.
       The gap engine has no negative margins, so this is now a no-op.
       Kept so existing markup does not break. Safe to delete later. */
    &.trim { margin-inline: 0; }
}


/* ======================================================================
   COLUMN WIDTH UTILITIES — HOW flex: 0 0 X% WORKS
   ======================================================================

   flex is shorthand for:
     flex-grow | flex-shrink | flex-basis

   Example:
     flex: 0 0 50%;

   Means:
     - flex-grow:   0  → do NOT grow larger than the base size
     - flex-shrink: 0  → do NOT shrink smaller than the base size
     - flex-basis:  50% → base width is 50% of the row

   Why we use this:
     - Guarantees predictable column widths
     - Prevents stretching or squishing
     - Works cleanly with flex-wrap, gaps, and .trim
     - Avoids layout drift when spacing changes

   IMPORTANT:
     These classes control WIDTH ONLY.
     Prefer controlling spacing at the ROW level (gap utilities).
     Optional inner padding is available via the .pxc-* utilities.

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


/* ======================================================================
   COLUMN WIDTHS
   ====================================================================== */

/* AUDIT NOTE — WHY THESE ARE calc() AND NOT PLAIN PERCENTAGES
   Each column subtracts its own share of the gutter, so a set of
   fractions summing to 100% fits the row EXACTLY with the gap included.
   Plain percentages would sum to 100% + gap and wrap the last column.

   The multiplier is always (1 - P). Adding a new width means adding its
   pair: e.g. a 10% column → calc(10% - var(--gap-x) * 0.9).

   --gap-x must always carry a unit (0px, never 0) or the whole calc()
   is invalid and the column silently loses its width.
   ====================================================================== */
/* Each basis is  P% - gap × (1 - P)  — the column's own share of the
   gutter, subtracted from its width. See the gutter explainer above. */
/* .col divides whatever space is left between however many there are, so
   it behaves like a fraction and stacks with them at 600 (see below).
   .col-auto is an explicit opt-out — "size me to my content" — so it is
   deliberately left OUT of every stacking rule. An icon or a button beside
   a heading should stay beside it on a phone; if you want it to stack,
   use a fraction instead. */
.col { flex: 1 1 0; }
.col-auto { flex: 0 0 auto; }
.col-1-1 { flex: 0 0 100%; }                                    /* full width — takes its own line */
.col-3-4 { flex: 0 0 calc(75%     - var(--gap-x, 0px) * 0.25);  }
.col-2-3 { flex: 0 0 calc(200% / 3 - var(--gap-x, 0px) / 3);     }
.col-3-5 { flex: 0 0 calc(60%     - var(--gap-x, 0px) * 0.4);   }
.col-1-2 { flex: 0 0 calc(50%     - var(--gap-x, 0px) * 0.5);   }
.col-2-5 { flex: 0 0 calc(40%     - var(--gap-x, 0px) * 0.6);   }
.col-1-3 { flex: 0 0 calc(100% / 3 - var(--gap-x, 0px) * 2 / 3); }
.col-30 { flex: 0 0 calc(30%     - var(--gap-x, 0px) * 0.7);   }
.col-1-4 { flex: 0 0 calc(25%     - var(--gap-x, 0px) * 0.75);  }
.col-20 { flex: 0 0 calc(20%     - var(--gap-x, 0px) * 0.8);   }

/* Fixed ma-widths */

.single-sm,
.single-md,
.single-lg {
  max-width: var(--single-md); /* overridden per class */
  width: 100%;
}

.single-sm { max-width: var(--single-sm); }
.single-md { max-width: var(--single-md); }
.single-lg { max-width: var(--single-lg); }


/* ======================================================================
   GAP DECISION GUIDE (READ THIS BEFORE ADDING NEW SPACING)
   ======================================================================

   Use this guide to choose the RIGHT gap utility.
   Do not invent new gap values unless absolutely necessary.

   DEFAULT (most sections):
     gap-fluid
     → Responsive, balanced spacing across all screen sizes

   TIGHT / DENSE LAYOUTS:
     gap-fluid-sm  OR  gap-16
     → Icon grids, specs, compact UI sections

   SPACIOUS / PREMIUM SECTIONS:
     gap-fluid-lg  OR  gap-40 / gap-60
     → Hero sections, editorial layouts, feature showcases

   AXIS-SPECIFIC CONTROL:
     gap-x-0/16/24/40/60/fluid  and  gap-y-0/16/24/40/60/fluid
     → When horizontal and vertical rhythm should differ. Combine with a
       gap-* class: `row gap-24 gap-y-60` is 24 across, 60 down.

   PRECISION / MATCHING DESIGNS:
     gap-16 / gap-24 / gap-40
     → When spacing must match comps exactly

   RULE OF THUMB:
     If unsure, use `gap-fluid`.

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


/* ======================================================================
   GAP UTILITIES — EDIT AVAILABLE SIZES AS NEEDED
   ====================================================================== */
.gap-0 { --gap-x: var(--gutter-0);  --gap-y: var(--gutter-0); }
.gap-16 { --gap-x: var(--gutter-16); --gap-y: var(--gutter-16); }
.gap-24 { --gap-x: var(--gutter-24); --gap-y: var(--gutter-24); }
.gap-40 { --gap-x: var(--gutter-40); --gap-y: var(--gutter-40); }
.gap-60 { --gap-x: var(--gutter-60); --gap-y: var(--gutter-60); }

/* ======================================================================
   FLUID GAP UTILITIES (CLAMP-BASED)
   ======================================================================

   Use these when spacing should scale smoothly across screen sizes.
   Prefer these for marketing and editorial layouts.

   Tiers:
     - sm: tight, dense layouts
     - md: most sections  (.gap-fluid and .gap-fluid-md are the same thing)
     - lg: spacious, premium layouts
*/

.gap-fluid-sm {
  --gap-x: var(--gutter-fluid-sm);
  --gap-y: var(--gutter-fluid-sm);
}

/* .gap-fluid is the original name; .gap-fluid-md is an alias so the three
   tiers read consistently (sm / md / lg). Both are supported — existing
   markup using .gap-fluid keeps working. */
.gap-fluid,
.gap-fluid-md {
  --gap-x: var(--gutter-fluid-md);
  --gap-y: var(--gutter-fluid-md);
}

.gap-fluid-lg {
  --gap-x: var(--gutter-fluid-lg);
  --gap-y: var(--gutter-fluid-lg);
}

/* ======================================================================
   SINGLE-AXIS GAPS
   ======================================================================

   Use these when horizontal and vertical rhythm should differ — a card
   grid often wants tight gutters between columns but more separation
   between wrapped rows. Combine with a .gap-* class, or use alone.

     <div class="row gap-24 gap-y-60">   24 across, 60 down

   THE TWO AXES ARE NOT EQUIVALENT — worth understanding before reaching
   for gap-x-*:

     --gap-y  affects ONLY the space between wrapped lines. Nothing else
              reads it, so it can never disturb a column's width.

     --gap-x  is read TWICE: by the row's gap, and by every column's width
              calc (flex-basis: P% - gap × (1-P)). Changing it therefore
              resizes the columns to compensate — which is exactly what
              keeps a row summing to 100% — but it is the bigger lever.

   Both are safe; gap-y-* is simply the more contained of the two.
====================================================================== */

/* Horizontal only — the space between columns on a line */
.gap-x-0 { --gap-x: var(--gutter-0); }
.gap-x-16 { --gap-x: var(--gutter-16); }
.gap-x-24 { --gap-x: var(--gutter-24); }
.gap-x-40 { --gap-x: var(--gutter-40); }
.gap-x-60 { --gap-x: var(--gutter-60); }
.gap-x-fluid { --gap-x: var(--gutter-fluid-axis); }

/* Vertical only — the space between wrapped lines */
.gap-y-0 { --gap-y: var(--gutter-0); }
.gap-y-16 { --gap-y: var(--gutter-16); }
.gap-y-24 { --gap-y: var(--gutter-24); }
.gap-y-40 { --gap-y: var(--gutter-40); }
.gap-y-60 { --gap-y: var(--gutter-60); }
.gap-y-fluid { --gap-y: var(--gutter-fluid-axis); }


/* ======================================================================
   COLUMN INNER PADDING UTILITIES (optional inner inset)
   ====================================================================== */

.pxc-0 { --col-pad-x: var(--gutter-0); }
.pxc-16 { --col-pad-x: var(--gutter-16); }
.pxc-24 { --col-pad-x: var(--gutter-24); }
.pxc-40 { --col-pad-x: var(--gutter-40); }
.pxc-60 { --col-pad-x: var(--gutter-60); }

/* Fluid column padding (default) */
.pxc-fluid {
  --col-pad-x: var(--col-pad-fluid);
}

/* Fluid column padding — SMALL */
.pxc-fluid-sm {
  --col-pad-x: var(--col-pad-fluid-sm);
}

/* Fluid column padding — LARGE (optional) */
.pxc-fluid-lg {
  --col-pad-x: var(--col-pad-fluid-lg);
}


/* ======================================================================
   RESPONSIVE OVERRIDES — DESKTOP FIRST (MAX-WIDTH) • SIMPLIFIED
   ======================================================================

   SIMPLIFIED RESPONSIVE MODEL (CMS-FRIENDLY)
   -----------------------------------------
   We auto-stack fraction columns on smaller screens.

   - Desktop: .col-1-2, .col-2-3, etc. behave as expected
   - Tablet and down: fraction columns become full width (stacked)
   - No md:* / sm:* classes required

   ESCAPE HATCH
   ------------
   If you need a row to KEEP columns side-by-side on tablet/mobile,
   add .no-stack to the row:

     <div class="row no-stack">...</div>

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

/* Tablet and down: stack fraction columns by default */
@media (max-width: 992px) {

  /* Default behavior: stack, unless the row opts out */
  .row:not(.no-stack) > .col-2-3,
  .row:not(.no-stack) > .col-3-4,
  .row:not(.no-stack) > .col-3-5,
  .row:not(.no-stack) > .col-2-5 {
    flex: 0 0 100%;
  }
  /* NOTE: .col-1-2, .col-1-4, .col-1-3, .col-30 and .col-20 are intentionally
     NOT in this list. Each steps down through an intermediate count before it
     stacks — see "COLUMNS THAT STEP DOWN BEFORE STACKING" below. The four
     classes left here are the MAJOR half of an unequal pair (75 / 66 / 60 / 40
     %); on their own they have nowhere to step to, so they go straight to full
     width, and when they appear WITH their partner the mixed-pair rules below
     out-specify this and equalise them first.
     Use .no-stack to keep any row side-by-side at every width. */
}


/* ======================================================================
   MIXED-RATIO PAIRS — EQUALIZE BEFORE STACKING
   ======================================================================

   Unequal two-column pairs (75/25, 66/33, 60/40) shouldn't jump straight
   from their ratio to a full stack — the minor column gets uncomfortably
   narrow on tablet. Instead they step through an even 50/50 (still 2-up)
   before stacking:

     ratio (desktop)  →  50/50 (≤992)  →  stacked (≤600)

   Detection is automatic via :has(): a row is treated as a mixed pair
   ONLY when it holds BOTH partners, so a 3-up of .col-1-3 or a 4-up of
   .col-1-4 is unaffected. Specificity (5 classes) beats the auto-stacker
   above (3), and the :not(.no-stack) guard keeps the escape hatch working.

   These target two-column pairs; adding a third column to the same row is
   unsupported (both partner selectors would still apply at 50%).
====================================================================== */

/* Tablet: equalize the pair to 50/50 (still side-by-side) */
@media (max-width: 992px) {
  .row:not(.no-stack):has(> .col-3-4):has(> .col-1-4) > .col-3-4,
  .row:not(.no-stack):has(> .col-3-4):has(> .col-1-4) > .col-1-4,
  .row:not(.no-stack):has(> .col-2-3):has(> .col-1-3) > .col-2-3,
  .row:not(.no-stack):has(> .col-2-3):has(> .col-1-3) > .col-1-3,
  .row:not(.no-stack):has(> .col-3-5):has(> .col-2-5) > .col-3-5,
  .row:not(.no-stack):has(> .col-3-5):has(> .col-2-5) > .col-2-5 {
    flex: 0 0 calc(50% - var(--gap-x, 0px) * 0.5);
  }
}

/* Mobile: now stack the pair to full width */
@media (max-width: 600px) {
  .row:not(.no-stack):has(> .col-3-4):has(> .col-1-4) > .col-3-4,
  .row:not(.no-stack):has(> .col-3-4):has(> .col-1-4) > .col-1-4,
  .row:not(.no-stack):has(> .col-2-3):has(> .col-1-3) > .col-2-3,
  .row:not(.no-stack):has(> .col-2-3):has(> .col-1-3) > .col-1-3,
  .row:not(.no-stack):has(> .col-3-5):has(> .col-2-5) > .col-3-5,
  .row:not(.no-stack):has(> .col-3-5):has(> .col-2-5) > .col-2-5 {
    flex: 0 0 100%;
  }
}

/* ======================================================================
   TYPOGRAPHY IS NOT THIS FILE'S JOB
   ======================================================================

   THE BOUNDARY
   ------------
   This framework owns LAYOUT: containers, rows, columns, gutters, and the
   spacing UTILITIES you apply to blocks (mb-*, mt-*, section-space).

   It does NOT own type. Paragraph, list, blockquote and heading rhythm —
   margins, line-height, size — belong to the site's typography layer
   (website.scss), which already defines them.

   ⚠ NEVER add an element reset here. A bare `p` selector ties (0,0,1) with
   the type layer's own `p`, so load order would decide the winner — the same
   markup could space correctly on one site and collapse on another. To zero a
   margin, do it in the type layer or use a spacing utility on a wrapper.
====================================================================== */


/* ----------------------------------------------------------------------
   THE ONE TYPE-ADJACENT RULE THAT IS GENUINELY LAYOUT
   ----------------------------------------------------------------------

   A trailing bottom margin on the last element inside a column adds
   phantom space below the content but INSIDE the column box. That is
   invisible on plain text, but obvious once a column has a background
   or border (cards), where it reads as uneven padding.

   Scoped to this framework's own boxes rather than resetting elements
   globally, so the type layer keeps full control of rhythm everywhere
   else. (Same approach Bootstrap uses for card bodies.)
---------------------------------------------------------------------- */

/* Contao wraps rich text in a .rte div, so the column's own :last-child is that
   wrapper — whose trailing <p> keeps its margin. Reach one level further so the
   reset lands on the element that actually carries it. */
.row > * > :last-child,
.row > * > :last-child > :last-child {
  margin-bottom: 0;
}


/* ----------------------------------------------------------------------
   OPTIONAL FLOW VARIANTS
   ----------------------------------------------------------------------

   Opt-in rhythm overrides for rich-text wrappers. These are arguably
   typography too and are candidates to move to the type layer — kept
   here for now because existing markup may reference them.
---------------------------------------------------------------------- */

.rte-tight > * + * {
  margin-top: 0.75em;
}

.rte-loose > * + * {
  margin-top: 1.5em;
}


/* ----------------------------------------------------------------------
   GUIDANCE FOR THE TEAM
   ----------------------------------------------------------------------

   - Do NOT put margin utilities (mb-*, mt-*) on <p> tags — paragraph
     rhythm comes from the type layer.
   - DO use margin utilities on SECTIONS, BLOCKS and columns.

   Example (correct):

     <div class="mb-40">
       <p>Paragraph one</p>
       <p>Paragraph two</p>
     </div>

   Example (avoid):

     <p class="mb-24">Paragraph one</p>
     <p class="mb-24">Paragraph two</p>

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

/* Margin bottom */
.mb-0 { margin-bottom: var(--space-0); }
.mb-8 { margin-bottom: var(--space-8); }
.mb-12 { margin-bottom: var(--space-12); }
.mb-16 { margin-bottom: var(--space-16); }
.mb-24 { margin-bottom: var(--space-24); }
.mb-40 { margin-bottom: var(--space-40); }
.mb-60 { margin-bottom: var(--space-60); }
.mb-80 { margin-bottom: var(--space-80); }

/* Margin top */
.mt-0 { margin-top: var(--space-0); }
.mt-8 { margin-top: var(--space-8); }
.mt-12 { margin-top: var(--space-12); }
.mt-16 { margin-top: var(--space-16); }
.mt-24 { margin-top: var(--space-24); }
.mt-40 { margin-top: var(--space-40); }
.mt-60 { margin-top: var(--space-60); }
.mt-80 { margin-top: var(--space-80); }

/* Optional: margin block (top + bottom together) */
.my-24 { margin-block: var(--space-24); }
.my-60 { margin-block: var(--space-60); }


/* Use for consistent spacing between major sections */
.section-space { margin-block: var(--space-section); }
.section-space-top { margin-top: var(--space-section); }
.section-space-bottom { margin-bottom: var(--space-section); }


/* Optional: tighten default spacing on smaller screens (global)
   NOTE: Because we use clamp() utilities, you may not need these.
   Keep these only if your team wants more predictable rhythm. */
   
/* centering */
.center_text {
    text-align: center;
}

/* margin-INLINE only. The `margin: auto` shorthand also set the block axis,
   which silently zeroed every bottom/top margin utility on the same element
   (auto resolves to 0 in normal flow) and, on a flex column, opted the item
   out of cross-axis stretch so it no longer matched its siblings in height. */
.center_element {
    margin-inline: auto;
}

.hor_center {
    justify-content: center;
}


.vert_center {
    align-items: center;
}

.vert_top {
    align-items: flex-start;
}

.vert_bottom {
    align-items: flex-end;
}


/* Element / text alignment (Toolbox: align-left / align-right) */
.align-left,
.align-left img {
    text-align: left;
    margin-inline: 0 auto;
}

.align-right,
.align-right img {
    text-align: right;
    margin-inline: auto 0;
}


@media (max-width: 768px) {
  :root {
    --row-gap-x: var(--gutter-24);
    --row-gap-y: var(--gutter-24);
  }
}

/* ----------------------------------------------------------------------
   MOBILE COLUMN ORDER
   ----------------------------------------------------------------------
   Rows read left-to-right on desktop but top-to-bottom once stacked, so a
   "text beside image" row can end up with the wrong one first on a phone.
   .mobile_col_reverse flips the stacking order without touching the desktop
   layout or the source order (which stays correct for screen readers).
---------------------------------------------------------------------- */
.mobile_col_reverse {
  flex-direction: row;
}

@media (max-width: 600px) {
  .mobile_col_reverse {
    flex-direction: column-reverse;
  }
}


@media (max-width: 480px) {
  :root {
    --row-gap-x: var(--gutter-16);
    --row-gap-y: var(--gutter-16);
  }
}


/* ======================================================================
   COLUMNS THAT STEP DOWN BEFORE STACKING
   ======================================================================

   EVERY multi-column layout steps down through the intermediate counts
   instead of jumping from its full ratio straight to a stack:

     .col-1-2 pair   2-up   (> 992)  →  2-up   (≤ 992)  →  1-up  (≤ 600)
     75/25 pair      75/25  (> 992)  →  50/50  (≤ 992)  →  1-up  (≤ 600)
     66/33 pair      66/33  (> 992)  →  50/50  (≤ 992)  →  1-up  (≤ 600)
     60/40 pair      60/40  (> 992)  →  50/50  (≤ 992)  →  1-up  (≤ 600)
     .col-1-3 grid   3-up   (> 992)  →  2-up   (≤ 992)  →  1-up  (≤ 600)
     .col-30 grid    3-up   (> 992)  →  2-up   (≤ 992)  →  1-up  (≤ 600)
     .col-1-4 grid   4-up   (> 992)  →  2-up   (≤ 992)  →  1-up  (≤ 600)
     .col-20 grid    5-up   (> 992)  →  3-up   (≤ 992)  →  2-up  (≤ 600)
                                                        →  1-up  (≤ 480)

   Thirds ramp 3 → 2 → 1 and accept the trailing orphan, which is what every
   major framework does (Bootstrap's `col-lg-4 col-md-6 col-12`, Tailwind's
   `grid-cols-1 md:grid-cols-2 lg:grid-cols-3`): one wide card beside a gap
   still reads as a grid, three full-bleed cards read as three sections.
   .col-30 joins it; .col-20 goes 5 → 3 → 2 → 1, since a fifth at 2-up on a
   phone is only ~150px. A 50/50 pair holds 2-up to 600 like the rest — it
   must not collapse sooner than a 75/25.

   The :not(.no-stack) guard keeps the escape hatch working: a .row.no-stack
   holds its columns side-by-side at every width.

   ⚠ A component that draws dividers BETWEEN cells has to track these
   breakpoints, because "every cell but the first" is only right while the
   cells share a line — see the divider block in stats.css.
====================================================================== */
@media (max-width: 992px) {
  /* A quarter promotes to a half on tablet — UNLESS the row also holds a
     .col-1-2, which is already 50%. Three 50% items fill one line exactly
     and orphan the third at half width, so those rows stack instead. */
  .row:not(.no-stack):not(:has(> .col-1-2)) > .col-1-4 {
    flex: 0 0 calc(50% - var(--gap-x, 0px) * 0.5);
  }
  .row:not(.no-stack):has(> .col-1-2) > .col-1-4,
  .row:not(.no-stack):has(> .col-1-4) > .col-1-2 { flex: 0 0 100%; }

  /* A third and a 30% promote to a half. When a third appears WITH its
     .col-2-3 partner the mixed-pair rule above already says 50% — same
     answer, so no guard is needed. */
  .row:not(.no-stack) > .col-1-3,
  .row:not(.no-stack) > .col-30 {
    flex: 0 0 calc(50% - var(--gap-x, 0px) * 0.5);
  }

  /* A fifth promotes to a third — 5-up → 3-up reads as 3 + 2. */
  .row:not(.no-stack) > .col-20 {
    flex: 0 0 calc(100% / 3 - var(--gap-x, 0px) * 2 / 3);
  }
}

@media (max-width: 600px) {
  .row:not(.no-stack) > .col-1-2,
  .row:not(.no-stack) > .col-1-3,
  .row:not(.no-stack) > .col-30,
  .row:not(.no-stack) > .col { flex: 0 0 100%; }

  /* A quarter needs the SAME shape as its 992 promotion above, or it never
     stacks: `.row:not(.no-stack):not(:has(> .col-1-2)) > .col-1-4` is four
     class-level selectors and a plain `.row:not(.no-stack) > .col-1-4` is
     three, so the promotion won the cascade at every width below 992 and a
     4-up grid sat at 2-up right down to 390px. Measured on Our Story's values
     row: 171px cells on a phone, with the dividers already switched off
     because stats.css correctly believed they had stacked. */
  .row:not(.no-stack):not(:has(> .col-1-2)) > .col-1-4,
  .row:not(.no-stack):has(> .col-1-2) > .col-1-4 { flex: 0 0 100%; }

  /* ...and a fifth to a half, one step behind everything else. */
  .row:not(.no-stack) > .col-20 {
    flex: 0 0 calc(50% - var(--gap-x, 0px) * 0.5);
  }
}

@media (max-width: 480px) {
  .row:not(.no-stack) > .col-20 { flex: 0 0 100%; }
}

/* box-sizing lives in framework_v3.css (an inherit-based reset, so components
   can opt out) — do not add a universal border-box rule here, it would load
   later and defeat it.

   ⚠ Do not set overflow-x: hidden on body either. website_structure.css
   already clips on html, and `hidden` on one axis forces the other to `auto`,
   which turns body into a scroll container and breaks position: sticky for
   everything inside it. `clip` has no such effect. */

#header .background,
#header .background_image {
    overflow-x: hidden;
}

html {scroll-behavior: smooth; }

/* Moved here from framework_v3.css, which must own no CMS-specific
   selector. .content-image is Contao markup. */
.content-image.center_element img {
    margin-inline: auto;
}

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

body,
form,
fieldset,
h1,
h2,
h3,
h4,
h5,
h6,
figure,
p.active,
p.confirm {

    margin: 0;
    padding: 0;
}

a img { border-bottom: 0; }

header,
footer,
nav,
section,
aside,
article,
figure,
figcaption,
.custom,
.tableless label,
.checkbox_container span,
.radio_container span {
    display: block;
}

/* Controls do not inherit type by default. max() keeps the page's own size on
   desktop and never drops below 16px — under 16px, iOS Safari zooms the page
   whenever a field is focused. */
select,
input,
textarea {
    font-family: inherit;
    font-size: max(16px, 1em);
}

/* .block is a float-clearing relic. Contao puts it on EVERY article, and in
   the layout framework an article is a .row — so an unscoped `overflow:
   hidden` here silently clips any .bleed-x inside a row (and creates a new
   block formatting context on every row). Excluding .row keeps the legacy
   clearing behaviour everywhere it is still wanted.

   `overflow: clip` clips exactly as `hidden` did, without creating a
   scrollport (which would break position: sticky inside).

   ⚠ `display` MUST NOT be set here. `.block:not(.row)` is (0,2,0), specific
   enough to beat any single-class component rule, and Contao puts `.block` on
   every article AND every content element — so a `display` here overrides the
   layout of anything needing a non-block display. `display: flow-root` once
   collapsed `.ins-grid { display: grid }` (0,1,0) and the Insights list went
   from three columns to one. Float containment is handled where floats can
   actually occur — see the `.media--left/right` rule below.

   The reason the split matters: `overflow: hidden` also makes the element a
   SCROLL CONTAINER, and `animation-timeline: view()` binds to the nearest
   scrollport ancestor. Since Contao puts `.block` on every article, EVERY
   article was a scrollport that never scrolls — so every scroll-driven
   animation on the site resolved its ViewTimeline against a zero-range
   scroller, `currentTime` stayed null, and the animation sat frozen at its
   `both` end state. That is why the Switching timeline and the For Advisors
   phone tree "didn't run": the CSS was correct all along. `overflow: clip`
   clips without creating a scroll container, so `view()` now resolves past the
   article to the real page scroller. */
.block:not(.row) {
    overflow: clip;
}

/* Visually hidden but still announced. The previous version used zero
   dimensions and left:-1000px; zero-size elements are skipped by some
   screen readers, and off-screen positioning can cause horizontal scroll
   in RTL. Contao uses this for real assistive text, e.g.
   <span class="invisible">Mandatory field</span>. */
.invisible {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* The "Skip navigation" links are .invisible until a keyboard user reaches them:
   then they show, top left, so the focus is never on something unseen
   (WCAG 2.4.7; 8 Oct). */
a.invisible:focus-visible {
    position: fixed;
    top: 12px;
    left: 12px;
    z-index: 10000;
    width: auto;
    height: auto;
    margin: 0;
    padding: 0.6em 1em;
    overflow: visible;
    clip-path: none;
    white-space: nowrap;
    background: #fff;
    color: var(--prime);
    font-weight: 600;
    border-radius: 6px;
    box-shadow: 0 4px 16px rgba(4, 32, 63, 0.25);
}

/* A visible focus indicator is required (WCAG 2.4.7). This replaces an
   `outline: none` that removed it with no substitute, which left keyboard
   users unable to tell which control they were in — the site search box
   included. :focus-visible keeps it off for mouse users. */
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
button:focus-visible,
a:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--prime);
    outline-offset: 2px;
}

textarea { min-height: 150px; }

fieldset {
    border: 0;
    margin-inline: 0;
    padding-inline: 0;
    padding-block: 0;
}

fieldset table,
input.text,
input.email,
textarea {
    width: 100%;
}

input.captcha {
    width: 50px;
}

input.checkbox,
.tableless .checkbox_container label,
.checkbox_container span.mandatory,
input.radio,
.tableless .radio_container label,
.radio_container span.mandatory,
.tableless span label,
address,
.pdf_link img,
.content-download img,
.content-downloads img,
.enclosure img {
    display: inline;
}

/* Strip the platform's native control chrome. */
input.text,
input.submit,
.textarea,
textarea,
input.captcha,
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
    -webkit-appearance: none;
    appearance: none;
}

/* --second matches forms.css, so the required-field asterisk is one colour
   whether the form is a content element or a module. */
.error,
span.mandatory {
    color: var(--second);
}

.confirm {
    color: var(--prime);
}

p.error {
    margin: 0;
    padding-top: 10px;
}

.content-download img,
.content-downloads img,
.enclosure img {
    vertical-align: top;
}

.content-downloads p,
.enclosure p,
p.error {
    padding-bottom: 0;
}

.enclosure { padding-top: 20px; }
/* Table styling lives in tables.css. This stays as a bare reset for
   any table outside a .content-table element. */
table { border-spacing: 0; }
address { font-style: normal; }

/* IMAGE POSITION IN A TEXT ELEMENT
   --------------------------------
   These are FLOATS, deliberately, not flex.

   The editor's choice is literally "floating: left/right", and what that
   means is that the text WRAPS around the image and then continues full
   width beneath it. Flex cannot do that — it produces two rigid columns,
   so a short paragraph beside a tall image leaves a large empty gap and
   the text never flows underneath.

   `display: flow-root` on the parent contains the float, so the image can
   never escape the bottom of its content element. It is the modern
   replacement for a clearfix pseudo-element or `overflow: hidden`, and
   unlike overflow it creates no scroll container and no clipping. */

.content-text.media { display: flow-root; }

/* SPACING AROUND A FLOATED IMAGE
   The gap between the image and the text beside it is a GUTTER — the same
   idea as the space between two columns — so it uses the gutter scale
   rather than a hardcoded value.

   --row-gap-x already steps down at the framework's breakpoints
   (40 -> 24 -> 16), so the float gap tightens on smaller screens in step
   with every column gutter on the site. Retuning --gutter-40 moves both.

   The space BELOW the image is block rhythm, not a gutter, so it comes
   from the spacing scale instead. */

/* A plain `max-width: 50%` keeps scaling with the container, so on a wide
   site the image reaches ~900px and dominates the composition. The pixel
   cap stops it growing once there is plenty of room, which keeps the text
   column reading like a column rather than a narrow strip beside a poster.

   min() takes whichever is smaller, so narrow screens still get the 50%
   behaviour and wide screens settle at a sensible fixed size. */
.content-text.media--left figure,
.content-text.media--right figure {
    max-width: min(50%, 480px);
}

.content-text.media--left figure {
    float: left;
    margin: 0 var(--row-gap-x) var(--space-24) 0;
}

.content-text.media--right figure {
    float: right;
    margin: 0 0 var(--space-24) var(--row-gap-x);
}

/* above / below simply stack. The figure is first in the DOM, so `below`
   needs the order reversed. */
.content-text.media.media--above figure { margin-bottom: var(--space-24); }

.content-text.media.media--below {
    display: flex;
    flex-direction: column-reverse;
}

.content-text.media.media--below figure { margin-top: var(--space-24); }

/* Too narrow to wrap around: let the image take its own line.

   TUNING NOTE — the awkward zone is roughly 601-768px.
   In that range the image is still taking ~50% while the gutter is still
   at its desktop 40px, so the text column can drop to around 350px and
   the wrap goes ragged. Measured at an 820px viewport: 754px container,
   361px image, 353px of text.

   If a particular site's images or copy make that look bad, raise this
   breakpoint to 768px so the image unfloats before the column gets tight:

       @media (max-width: 768px) { ... }

   Left at 600px by default because it keeps the wrap on small tablets,
   which suits shorter captions and portrait images. Change per site
   rather than globally — it depends on the imagery. */
@media (max-width: 600px) {
    .content-text.media--left figure,
    .content-text.media--right figure {
        float: none;
        max-width: none;
        margin: 0 0 var(--space-24);
    }
}

/* Legacy float utilities, still available for hand-written content. */
.float_left { float: left; }
.float_right figure { float: right; }

.float_clear,
.center,
.clear,
#clear {
    clear: both;
}

/* --------------------------------------------------------------------------
   VIDEO EMBEDS — YouTube and Vimeo
   --------------------------------------------------------------------------
   Contao renders the player as <iframe width="640" height="360">. Those are
   HTML attributes rather than CSS, but they still size the element — so
   overriding only the width makes the embed scale sideways while its height
   stays locked at 360px. It also explains why aspect-ratio alone did nothing
   here: with BOTH dimensions definite, aspect-ratio is ignored outright.

   `height: auto` is what releases it. Once the height is auto the ratio has
   something to drive, and the embed scales on both axes.

   The framework gives .row > * img/svg/video a height: auto but deliberately
   skips iframe, because a bare iframe — a map, an external form — has to
   keep its attribute height; with no ratio to work from it would collapse to
   the 150px default size. So the release happens HERE instead, scoped to the
   players, where a ratio is guaranteed by the rule below.
   -------------------------------------------------------------------------- */

.content-youtube,
.content-vimeo,
.content-youtube iframe,
.content-vimeo iframe {
    width: 100%;
}

.content-youtube iframe,
.content-vimeo iframe {
    height: auto;

    /* The ratio dropdown is optional — Contao ships a blank option — so a
       default is required or an embed with nothing chosen would collapse.
       16/9 is exactly what Contao's own 640x360 attributes describe, so the
       unset case keeps the shape it was already rendering, just fluid.

       Using playerSize for a non-16:9 embed without picking a ratio? Set
       --video-ratio on that element rather than hardcoding a pixel size. */
    aspect-ratio: var(--video-ratio, 16 / 9);

    /* block removes the inline descender gap beneath the player; the auto
       margins centre the tall ratios once max-width starts constraining. */
    display: block;
    margin-inline: auto;
}

/* Every ratio Contao offers. The class is literally `aspect--16:9`, so the
   colon has to be escaped. */
.content-youtube .aspect--16\:9 iframe,
.content-vimeo .aspect--16\:9 iframe {
    aspect-ratio: 16 / 9;
}

.content-youtube .aspect--16\:10 iframe,
.content-vimeo .aspect--16\:10 iframe {
    aspect-ratio: 16 / 10;
}

.content-youtube .aspect--21\:9 iframe,
.content-vimeo .aspect--21\:9 iframe {
    aspect-ratio: 21 / 9;
}

.content-youtube .aspect--4\:3 iframe,
.content-vimeo .aspect--4\:3 iframe {
    aspect-ratio: 4 / 3;
}

.content-youtube .aspect--3\:2 iframe,
.content-vimeo .aspect--3\:2 iframe {
    aspect-ratio: 3 / 2;
}

/* Portrait and square are the two ratios that can run away: in a full-width
   1800px container a 9:16 player works out over 3000px tall. Both are capped
   by WIDTH rather than height — with the width pinned at 100%, a max-height
   would letterbox inside the player instead of resizing it. */
.content-youtube .aspect--9\:16 iframe,
.content-vimeo .aspect--9\:16 iframe {
    aspect-ratio: 9 / 16;
    max-width: calc(var(--video-tall-max, 80vh) * 9 / 16);
}

.content-youtube .aspect--1\:1 iframe,
.content-vimeo .aspect--1\:1 iframe {
    aspect-ratio: 1 / 1;
    max-width: var(--video-tall-max, 80vh);
}


/* --------------------------------------------------------------------------
   SELF-HOSTED PLAYER — the "player" content element
   --------------------------------------------------------------------------
   Same element for both: Contao renders <video> or <audio> depending on the
   file's mime type, wrapped in the figure component so a caption becomes a
   <figcaption>.

   The width/height fields in the back end become HTML ATTRIBUTES on the
   media element, exactly as they do on the YouTube iframe above. The
   difference is that <video> has an intrinsic size, so no ratio needs to be
   invented here: browsers already derive aspect-ratio from those attributes
   the way they do for <img>. Setting an explicit ratio would be actively
   wrong — it would force a 4:3 clip into 16:9.

   So the whole job is releasing the pinned width. Left alone, a video with
   width="640" sits at 640px inside a wider column, and one with no size set
   at all falls back to the 300x150 default for a replaced element.
   -------------------------------------------------------------------------- */

/* Bounded on BOTH axes rather than stretched to the column width. A <video>
   carries an intrinsic ratio, so a max-width and a max-height together are
   enough: the browser shrinks it to satisfy whichever bites first and keeps
   the ratio itself. No ratio has to be declared, and none should be.

   The height ceiling is what makes portrait usable. Measured with a real
   2160x3840 clip: at width 100% it rendered 639x1135 — 1.17x the viewport
   height, and about 3200px tall in a full-width container. With the ceiling
   it settles to roughly 435x774 and stays on screen.

   Trade-off worth knowing: width is `auto`, not 100%, so a video whose
   intrinsic width is SMALLER than the column renders at its own size instead
   of being upscaled. That is deliberate — upscaled video looks soft — but if
   a small clip must fill the column, set the width in the element's player
   size field. */
.content-player {
    video {
        display: block;
        width: auto;
        height: auto;
        max-width: 100%;
        max-height: var(--video-tall-max, 80vh);
        margin-inline: auto;
    }

    /* Audio has no picture, so it has a fixed control height and only the width
       is worth touching. Full width because a centred 300px control bar in a
       wide column reads as broken rather than deliberate. */
    audio {
        display: block;
        width: 100%;
    }

    figure { margin: 0; }

    figcaption {
        margin-top: var(--space-8);
        font-size: 0.875em;
        color: var(--grey-dark);
    }
}

/* --------------------------------------------------------------------------
   PASTED EMBEDS — raw <iframe> in a text or HTML element
   --------------------------------------------------------------------------
   Clients often skip the video content element and paste YouTube's embed
   code straight into the rich text editor. That markup carries no `aspect`
   class and no .content-youtube wrapper, so none of the rules above reach
   it — it arrives as a bare <iframe width="560" height="315">.

   The ratio is genuinely unknown to CSS: it exists only in those two HTML
   attributes, and until recently no CSS could read them. So this works in
   three layers, cheapest first.

   Note a pasted embed is NOT distorted the way a stretched image would be —
   an iframe re-lays out its contents rather than scaling them. A too-narrow
   player letterboxes internally. So the failure mode for anything missed
   here is mild, which is why the rules stay conservative.

   Two places a pasted embed can land, and they are structurally different:

     .rte              inside a text element — a normal descendant
     .mod_article >    the HTML and unfiltered HTML elements emit their
                       markup with NO wrapper div at all, so the embed
                       becomes a DIRECT CHILD of the article

   The second case is the one that surprises. There is no .content-* box to
   hook onto, and a column class set in the back end is silently dropped
   because there is nothing to put it on — which also means the embed becomes
   a flex item of the row and needs to be told to take its own line.
   -------------------------------------------------------------------------- */

/* 1. Nothing pasted may break out of its column, whatever it is. */
.rte :is(iframe, embed, object, video),
.mod_article > :is(iframe, embed, object, video) {
    max-width: 100%;
}

/* An unwrapped embed is a flex item of the row. Give it a full line so it
   does not sit alongside the real columns as if it were one. */
.mod_article > :is(iframe, embed, object, video, .embed-fluid) {
    flex: 0 0 100%;
}

/* 2. Known video hosts get the fluid treatment, with 16:9 assumed — right
      for essentially every player embed code in circulation.

      Deliberately scoped by src rather than applied to every iframe: a map,
      a Spotify player (152px tall), a booking widget or a form embed would
      be wrecked by being forced into 16:9. Matching on host means those keep
      their own height and only video is treated as video.

      Add a host by extending this list. */
:is(.rte iframe, .mod_article > iframe):is(
    [src*="youtube.com"], [src*="youtube-nocookie.com"], [src*="youtu.be"],
    [src*="player.vimeo.com"], [src*="loom.com"], [src*="wistia.net"],
    [src*="dailymotion.com"], [src*="videopress.com"]),
.embed-fluid iframe {
    width: 100%;
    height: auto;                             /* release the attribute height */
    aspect-ratio: var(--video-ratio, 16 / 9);
    display: block;
}

/* 3. Where the browser can read typed attr(), take the REAL ratio from the
      embed's own width/height instead of assuming. This is what makes a
      pasted 4:3 or portrait embed correct rather than merely contained.

      Progressive enhancement only — browsers without it keep the 16:9 above,
      which is why layer 2 is not written as a fallback inside this block.
      [width][height] is required in the selector so the function always has
      both attributes to read. */
@supports (aspect-ratio: attr(width type(<number>)) / attr(height type(<number>))) {
    :is(.rte iframe, .mod_article > iframe)[width][height]:is(
        [src*="youtube.com"], [src*="youtube-nocookie.com"], [src*="youtu.be"],
        [src*="player.vimeo.com"], [src*="loom.com"], [src*="wistia.net"],
        [src*="dailymotion.com"], [src*="videopress.com"]),
    .embed-fluid iframe[width][height] {
        aspect-ratio: attr(width type(<number>), 16) / attr(height type(<number>), 9);

        /* Same 80vh ceiling the 9:16 and 1:1 elements get, for the same
           reason: a pasted portrait embed measured 777x1381 without it.
           Capping WIDTH keeps the ratio true — the width that produces a
           full-height box is height-limit x (w/h). Landscape embeds are far
           from the ceiling at any normal width, so this only ever bites on
           tall ones. */
        max-width: calc(var(--video-tall-max, 80vh)
                        * attr(width type(<number>), 16)
                        / attr(height type(<number>), 9));
        margin-inline: auto;
    }
}

/* TUNING
     --video-ratio      fallback ratio when the editor picks none, and the
                        assumed ratio for a pasted embed. 16/9.
     --video-tall-max   height ceiling for 9:16 and 1:1. 80vh leaves the
                        page furniture visible around a portrait embed.

   An embed from a host not listed above keeps its own size. To make one
   fluid, wrap it in <div class="embed-fluid"> in the editor's source view;
   add style="--video-ratio: 4/3" to that div if it is not 16:9. */

iframe { border: 0; }

/* ==========================================================================
   IMAGE RATIOS — crop a photo to a frame with a Theme Toolbox class
   ==========================================================================
   A class on an image element (ratio-3x2 …) crops the photo to that frame
   with object-fit, so an editor can drop in any photo. Faces: set
   --ratio-focus (e.g. 50% 20%) on the element. Crops belong here, in CSS —
   every image uses the "Webp Convert" size (original dimensions, as WebP). */
:is(.ratio-1x1, .ratio-4x3, .ratio-3x2, .ratio-16x9, .ratio-21x9) img {
    width: 100%;
    height: auto;
    object-fit: cover;
    object-position: var(--ratio-focus, 50% 50%);
}
.ratio-1x1 img  { aspect-ratio: 1 / 1; }
.ratio-4x3 img  { aspect-ratio: 4 / 3; }
.ratio-3x2 img  { aspect-ratio: 3 / 2; }
.ratio-16x9 img { aspect-ratio: 16 / 9; }
.ratio-21x9 img { aspect-ratio: 21 / 9; }

html { overflow-x: clip; }
/* mmenu puts `overflow-x: hidden` on body (.mm-wrapper). With html clipped, that
   no longer passes to the viewport: body becomes a scroll container that never
   scrolls, and every position: sticky inside it (the legal pages' "On this
   page", the style guide's sub menu) stops sticking. `clip` hides the same
   overflow without making a scroll container. */
body.mm-wrapper { overflow-x: clip; }

#header .inside,
#hero .ce_text,
#hero .content-text {
    width: 100%;
}

/* THE PAGE CONTAINER — one owner per region.
   fe_page nests .container_inside > #main > .inside, so both cannot carry
   the container: with border-box the gutter is subtracted twice and body
   content ends up inset from the header and footer by a full gutter on
   each side (60px at desktop). .container_inside is the right owner
   because it wraps #main AND the left/right columns; putting it on
   #main > .inside would leave the sidebars outside the container.

   Using a stock fe_page with no .container_inside? Move that selector to
   `#main > .inside` — but keep exactly one of them. */
#header .inside,
#prefooter .inside,
#footer .inside,
.container_inside {
    max-width: var(--container-max);
    width: 100%;
    margin-inline: auto;
    padding-inline: var(--page-gutter);
}

#container {
    padding-top: 60px;
    background-color: var(--background);
    position: relative;
}
.container_inside { padding-bottom: 120px; }

#wrapper { overflow: clip; }

/* ==========================================================================
   BRAND TOKENS — colours and type for this site
   ==========================================================================
   Native CSS custom properties, so every other stylesheet can use them with
   no @import. They are resolved by the browser at runtime, which means load
   order does not matter — any stylesheet may reference these even if it is
   served before this one.

   Requirement: this stylesheet must be present in the layout, since it is
   the only place these are defined.
   ========================================================================== */
:root {
  /* Standard colours — rarely changed */
  --black: #000;
  --white: #fff;

  /* Brand colours — change these per site */
  --text: var(--black);
  --prime: #0A417C;   /* Penpot: brand → color.blue.700 */
  --second: #AD1E22;  /* Penpot: accent → color.red.600 */

  /* Page background. Wired to #container in website_structure.css, so
     changing it here changes the page. White by default; a soft grey such
     as #F1F1F1 is the usual alternative. */
  --background: var(--white);

  /* Borders and rules. A COLOUR, not a shorthand, so each component picks
     its own width and style — 1px solid for form fields, 2px for a table
     header, and so on. Do not put "1px solid" in here: the usage sites
     already supply it, and doing so invalidates every border that reads it. */
  --stroke: #DFE4EA;  /* Penpot: border → color.neutral.200 */

  /* OPTIONAL — uncomment if the brand has a third colour.
     Nothing reads it by default, so it costs nothing to leave commented.
     --third: #000A46; */

  /* Derived shades. These were SCSS lighten() calls, which cannot operate on
     custom properties — so the exact resulting values are named here instead.
     (color-mix() could re-derive them at runtime if you ever want that.) */
  --grey-dark: #404040;    /* was lighten($black, 25%) */
  --grey-light: #ededed;   /* was lighten($black, 93)  */
  --prime-light: #235E97;  /* Penpot: color.blue.600 (was lighten($prime, 20%)) */

  /* Dark brand surfaces — bands and callout cards. */
  --ink:  #04203F;   /* Penpot: color.blue.950 — deep navy (bands, callout cards) */
  --navy: #083C6F;   /* Penpot: color.blue.800 — closing CTA band */

  /* Heading colour (deep navy) vs body text (slate grey) — from the design. */
  --heading: #072F5A;   /* Penpot: text.primary / color.blue.900 */
  --body:    #4A545F;   /* Penpot: color.neutral.600 */
  --red-700: #93191D;   /* Penpot: color.red.700 — deep accent (pull quotes, phone tree) */
  --red-800: #7C181B;   /* Penpot: color.red.800 — the eyebrow label */
  --text-on-dark-dim: #C4CCD6;   /* body copy and eyebrows on the dark bands */
  --text-muted: #636E7B;   /* a shade darker than the board's #6B7683: 4.5:1 on cream (WCAG AA, 8 Oct) */
  --text-muted-board: #6B7683;         /* Penpot: color.neutral.500 — captions, dates, stat labels */

  /* The type scale the boards use more than once (px at the 2400 board). */
  --fs-hero-h1: clamp(2.4rem, 5.2vw, 4.6875rem);   /* 75 — every hero headline */
  --fs-h2: clamp(1.9rem, 3.2vw, 2.8rem);           /* 45 — section headings */

  /* Off-white section band (hero + soft light sections). */
  --cream: #FBFAF9;

  /* Hairlines — the thin brand rules that frame the hero and feature rows. */
  --hairline:         var(--prime);    /* the boards draw every rule 1px solid #0A417C */
  --hairline-on-dark: var(--stroke);   /* …and #DFE4EA on the dark bands */

  /* Muted grey — placeholder text, and the quiet captions on a dark card.
     The designs use this one value for every "not yet filled in" string. */
  --placeholder: #9AA5B3;   /* Penpot: color.neutral.400 */

  /* Role tokens — what framework3's shared components (cards, notch, def-list,
     legal, the style guide) read. Mapped onto this palette; nothing here
     changes an existing rule. */
  --accent: var(--second);
  --text-body: var(--body);
  --text-muted: #636E7B;   /* WCAG AA on cream, see above */              /* Penpot: color.neutral.500 — dates, captions */
  --text-on-dark: var(--white);
  --text-on-dark-dim: #C4CCD6;        /* Penpot: body copy on the dark bands */
  --prime-deep: var(--ink);
  --surface-soft: var(--cream);
  --grad-cta: var(--navy);

  /* The fixed header's height — what sticky things (the guide's sub menu, the
     legal pages' aside) sit under. The nav runs two lines above the 900px
     switch to the mobile menu, hence 104. */
  --header-h: 56px;

  /* Soft decorative blobs behind the hero (radial gradient stops). */
  --blob-cyan: #A6DDEA;   /* Penpot: color.blue.300 */
  --blob-pink: #ECB9B9;   /* Penpot: hero pink wash */

  /* Display heading gradient */
  --heading-gradient-from: #04203F;  /* Penpot: color.blue.950 */
  --heading-gradient-to: #0A417C;    /* Penpot: brand → color.blue.700 */

  /* Hero band gradient — the dark brand wash behind hero copy. Change per site.
     Penpot "Gradiant Blue" stops (#04203F deep navy → #0A417C brand).
     DIRECTION: deepest in the TOP-RIGHT corner, lightest in the BOTTOM-LEFT —
     a deliberate departure from the boards' top-to-bottom, so it reads the
     same on every surface using this token (Contact card, .hero--text). */
  --grad-hero: linear-gradient(to bottom left, var(--heading-gradient-from) 0%, var(--prime) 100%);

  /* Type — change these per site (Penpot: font.body Rubik, font.display Literata) */
  --type-body: Rubik, sans-serif;
  --type-display: Literata, serif;
}
@media (min-width: 1120px) { :root { --header-h: 104px; } }   /* the full bar; below it the menu (header.css) */

body {
    font-size: clamp(1rem, 1.2vw, 1.1875rem);   /* up to 19px, per the design */
    font-family: var(--type-body);
    color: var(--body);
    font-weight: 400;
    font-style: normal;
    margin: 0;
    padding: 0;
    line-height: 1.55;
    min-height: 100vh;
    width: 100%;
    /* No overflow-x here: website_structure.css already clips on html, and
       `hidden` on body forces the other axis to `auto`, which makes body a
       scroll container and breaks position: sticky inside it. */
}

/* Headings — deep navy, Literata (display), 700. Solid colour, not a gradient
   text-clip. */
h1, h2, h3, h4, h5, h6 {
    font-family: var(--type-display);
    font-weight: 700;
    color: var(--heading);
    line-height: 1.14;
    /* Even out the line lengths so a headline never leaves one orphaned word
       on the last line. Progressive enhancement — a browser without it just
       wraps normally, and the cap on balanced lines makes it a no-op on long
       text, so it only ever affects the short strings headings actually are. */
    text-wrap: balance;
}

/* A heading is already 700, so `<strong>` inside one has to go FURTHER to read
   as emphasis — the boards set the emphasised sentence to 800 against the
   heading's 700 (Penpot reports those two shapes' weight as "mixed", every
   other heading as a flat 700). Two headings use this: For Financial Advisors'
   "It isn't, because we do it for you." and Switching's "Almost none. That's
   the point." Needs Literata 800, which fe_page.html.twig now requests. */
:is(h1, h2, h3, h4, h5, h6) strong,
:is(h1, h2, h3, h4, h5, h6) b { font-weight: 800; }

h1 {
    font-size: clamp(2.2rem, 4vw, 3rem);
    line-height: 1.06;
    margin-bottom: 0.5em;
}
h1.small { font-size: clamp(1.9rem, 3.4vw, 2.6rem); }

h2 {
    margin-bottom: 0.6em;
    font-size: var(--fs-h2);
}
.small h2 { font-size: clamp(1.25rem, 1.6vw, 1.65rem); }

h3 {
    margin: 0 0 0.55em;
    font-weight: 500;   /* the boards' 27px card/feature heading (66 uses on 11 pages) */
    font-size: clamp(1.35rem, 2vw, 1.7rem);    /* Penpot H3 27px */
}

h4 {
    margin: 0 0 0.55em;
    font-size: clamp(1.2rem, 1.6vw, 1.4rem);   /* Penpot LG 22px */
}

h5 { margin: 0 0 0.5em; font-size: 1.125rem; }
h6 { margin: 0 0 0.5em; font-size: 1rem; }

a {
    border-bottom: 1px solid var(--prime);
    text-decoration: none;
    color: var(--prime);
    transition: all 0.2s ease;
    &:hover {
        border-bottom: 1px solid var(--second);
        color: var(--second);
    }
}

h1 a,
h3 a,
h2 a,
h1 a:hover,
h3 a:hover,
h2 a:hover {
    border-bottom: 0;
}

hr {
    margin-top: var(--space-60);
    margin-bottom: var(--space-60);
    border: 0;
    position: relative;
    border-top: 1px solid var(--prime);
}

p { margin: 0 0 1.5em; }

/* LISTS
   Here rather than in a component file because the list content element and
   a list typed into the rich text editor emit the SAME markup — plain
   <ul>/<li> and <dl>/<dt>/<dd>, with only the wrapper div differing. Two
   files styling one <li> would race at similar specificity, and the two
   would drift apart visually; one owner means they cannot.

   Not website_standard.css either: that file exists for Contao's quirks,
   and indent, spacing and markers are brand decisions.

   Left on UA defaults these run at a 40px indent, which is far wider than
   the type scale wants. padding-inline-start rather than padding-left so a
   right-to-left site mirrors correctly. */
ul,
ol {
    margin: 0 0 1em;
    padding-inline-start: 1.25em;
}

li {
    margin-bottom: 0.5em;

    /* The list's own bottom margin already provides the gap after the last item;
       without this the two stack up. */
    &:last-child { margin-bottom: 0; }

    /* A nested list belongs to its parent item, so it gets the item's spacing
       above it and none below. */
    > ul, > ol { margin-block: 0.5em 0; }
}

dl { margin: 0 0 1em; }

dt {
    font-weight: 600;
}

/* Browsers indent <dd> by 40px and give it nothing else, which reads as a
   stray indent rather than a definition. Reset and spaced instead. */
dd {
    margin: 0 0 0.75em;
    &:last-child { margin-bottom: 0; }
}

/* TUNING
   Markers are deliberately left at the text colour. Colouring them
   (`ul > li::marker { color: var(--prime); }`) suits some brands, but it
   costs legibility on ordered lists where the number carries meaning. */

/* BUTTONS
   The three rules below (base, hover, small screens) must list the SAME
   selectors. They had drifted: .layout_latest p.more a had a hover but no
   base styling, plain `button` had base styling but only [type=submit]
   got a hover, and the download link appeared in two lists out of three.
   .ce_download is dropped — Contao 5 emits .content-download.

   These name INTENTS, not the button element. A bare `button` selector was
   here and it matched the tag, which means "interactive control" rather than
   "brand call to action" — so it caught every button any third-party
   component renders. Counted across this build it styled ONE button it
   should (the contact form submit) and eleven it should not: four cookie bar,
   three accordion headers, four Colorbox controls. Overriding it was the
   normal case, not the exception, and three stylesheets were each undoing it.
   It is also why a <button> used for correct semantics in a header or footer
   had to be un-styled by hand.

   [type="submit"] separates them cleanly because an attribute selector only
   matches an attribute that is PRESENT: submit is the spec default for
   <button>, but third-party controls either set type="button" or omit it, so
   they are not matched. Contao also puts class="submit" on form submits.

   Consequence worth knowing: a hand-written <button> no longer gets the brand
   styling for free. Add .btn to it.

   The cookie bar is deliberately NOT in this list: that bundle is
   token-driven, so cookiebar.css brands it by setting its own --ccb-*
   properties instead of imposing the site button on its layout. */
.btn a,
a.btn,
button[type="submit"],
input[type="submit"],
.submit,
.content-download .download-element a,
.layout_latest p.more a {
    display: inline-block;
    margin-bottom: 1.5em;
    padding: 13px 28px;
    text-align: center;
    background-color: var(--second);
    border-radius: 30px;
    color: var(--white);
    font-weight: 600;
    cursor: pointer;
    border: 0;
    line-height: 1.2;
    margin-right: 1em;
    font-size: 0.9375rem;   /* Penpot button 15px */
}

.btn a:hover,
a.btn:hover,
button[type="submit"]:hover,
input[type="submit"]:hover,
.submit:hover,
.content-download .download-element a:hover,
.layout_latest p.more a:hover {
    background-color: var(--prime);
}

/* BUTTON VARIANTS
   Modifiers layered onto .btn — add the class on the SAME element, e.g.
   <a class="btn alt">, <a class="btn outline">, <a class="btn alt outline">.
   The base .btn is solid --second (hover --prime); these only change colour:
     .alt          solid, colours swapped — --prime (hover --second)
     .outline      transparent with a --prime edge, fills --prime on hover
     .alt.outline  transparent with a --second edge, fills --second on hover
   Borders inset (box-sizing: border-box is global), so an outline button keeps
   the same footprint as a solid one. */

/* .alt — inverse solid: --prime, hover --second */
.btn.alt a,
a.btn.alt,
button[type="submit"].alt,
input[type="submit"].alt,
.submit.alt {
    background-color: var(--prime);
}
.btn.alt a:hover,
a.btn.alt:hover,
button[type="submit"].alt:hover,
input[type="submit"].alt:hover,
.submit.alt:hover {
    background-color: var(--second);
}

/* .outline — transparent with a --prime edge; fills --prime on hover */
.btn.outline a,
a.btn.outline,
button[type="submit"].outline,
input[type="submit"].outline,
.submit.outline {
    background-color: transparent;
    border: 2px solid var(--prime);
    color: var(--prime);
}
.btn.outline a:hover,
a.btn.outline:hover,
button[type="submit"].outline:hover,
input[type="submit"].outline:hover,
.submit.outline:hover {
    background-color: var(--prime);
    color: var(--white);
}

/* .alt.outline — transparent with a --second edge; fills --second on hover.
   Inherits the transparent background and border width from .outline; the
   three-class selector outranks .alt (solid) and .outline so its colours win. */
.btn.alt.outline a,
a.btn.alt.outline,
button[type="submit"].alt.outline,
input[type="submit"].alt.outline,
.submit.alt.outline {
    background-color: transparent;
    border-color: var(--second);
    color: var(--second);
}
.btn.alt.outline a:hover,
a.btn.alt.outline:hover,
button[type="submit"].alt.outline:hover,
input[type="submit"].alt.outline:hover,
.submit.alt.outline:hover {
    background-color: var(--second);
    color: var(--white);
}

/* .light — white pill, prime text: the button treatment for dark bands
   (media-split, callouts). The closing CTA band paints its own; this is the
   reusable class for any dark surface. */
a.btn.light,
.btn.light a,
button[type="submit"].light,
input[type="submit"].light,
.submit.light {
    background-color: var(--white);
    color: var(--prime);
}
a.btn.light:hover,
.btn.light a:hover,
button[type="submit"].light:hover,
input[type="submit"].light:hover,
.submit.light:hover {
    background-color: var(--second);
    color: var(--white);
}

.small,
.small p {
    font-size: clamp(0.75em, 1.35vw, 1.125em);
}

.small p {
    margin-bottom: 0.875em;
}

.small a, a.small {
    display: inline-block;
}

.small li {
    margin-bottom:0;
}

a.download-element:after {
    display: inline-block;
    padding: 0 0 0 .25em;
    border: 0;
    font-family: "Font Awesome 5 Pro";
    text-transform: none;
    content: "\f019";
    font-weight: 900;
}

a.download-element {
    margin-right: .25em;
    margin-left: .25em;
    padding: 0;
    font-weight: bold;
}

.download-element .size {
    display: none;
}


/* EYEBROW
   The small tracked, uppercase label above a section heading. Its own element,
   class="eyebrow". Accent colour on light; add .on-dark for white-on-dark bands.
   (No leading em-dash — the Cornerstone design sets the label plain.) */
.eyebrow {
    display: block;
    margin: 0 0 0.6em;
    font-family: var(--type-body);
    font-size: 0.8rem;
    font-weight: 600;
    letter-spacing: 0.12em;   /* the boards: 12px, 1.4px tracking */
    text-transform: uppercase;
    color: var(--red-800);
    text-wrap: balance;
}
.eyebrow.on-dark { color: var(--text-on-dark-dim); }


/* FONT AWESOME (SVG + JS kit)
   The kit swaps <i> for an <svg class="svg-inline--fa">. Its own CSS that caps
   the icon to 1em does not always inject before paint, which leaves icons at
   their intrinsic viewBox size (hundreds of px). Cap them here so inline icons
   always track the surrounding font-size. */
.svg-inline--fa,
.row > * .svg-inline--fa {          /* beat framework_v3 .row > * svg containment */
    display: inline-block;
    height: 1em;
    width: auto;
    max-width: none;
    overflow: visible;
    vertical-align: -0.125em;
}


blockquote {
    padding: 0;
    margin: 0;
    
    p { margin-bottom: 0; }
    
    em {
        font-weight: 600;
        color: var(--prime);
    }
    
    em:after { content: " "; }
}

/* ==========================================================================
   BACKGROUND BANDS
   ==========================================================================
   Replaces .full_width, which conflated two separate jobs: breaking out of
   the page container AND painting a grey background. Those are now split,
   because either is useful without the other:

     .bleed-x    break out of the container   (framework — layout)
     .bg-*       paint a background           (here — brand)

   A full-width grey band is both together:  <div class="bleed-x bg-light">

   .full_width also used two 9999em pseudo-elements to fake the breakout,
   which needed `overflow: visible !important` on the element to work. The
   gap engine's .bleed-x does it with margins and needs no override.
   ========================================================================== */

.bg-light { background-color: var(--grey-light); }
.bg-cream { background-color: var(--cream); }
.bg-white { background-color: var(--white); }
.bg-dark { background-color: var(--grey-dark); color: var(--white); }
.bg-prime { background-color: var(--prime);      color: var(--white); }
.bg-ink { background-color: var(--ink);        color: var(--white); }
.bg-navy { background-color: var(--navy);       color: var(--white); }

/* A band needs breathing room, or the text sits on the colour's edge. */
.bg-light,
.bg-cream,
.bg-white,
.bg-dark,
.bg-prime,
.bg-ink,
.bg-navy {
    padding-block: var(--space-40);
    padding-inline: var(--page-gutter);
}

/* A .band already spans the viewport AND re-caps its own children. When a band
   also paints a bg-* colour, drop the band's own inline padding so it doesn't
   fight `.band > *` (which supplies the child gutter) and shift content. */
.band.bg-light,
.band.bg-cream,
.band.bg-white,
.band.bg-dark,
.band.bg-prime,
.band.bg-ink,
.band.bg-navy { padding-inline: 0; }

/* Section vertical rhythm — ONE value for every band on the site, the boards'
   96px (--space-section). A band that differs is a component with its own
   padding (hero, logo strip), never a per-page class. Placed after the bg-*
   block, which pads non-band boxes, so it wins the (0,1,0) tie on order. */
.band { padding-block: var(--space-section); }
/* Theme Toolbox: compact section spacing (Home's logo strip) */
.section-space-50 { margin-block: clamp(20px, 4vw, 50px); }

/* Copy on a dark band is the boards' muted #C4CCD6; headings stay white (below). */
:is(.bg-dark, .bg-prime, .bg-ink, .bg-navy) :is(p, li) { color: var(--text-on-dark-dim); }
:is(.bg-dark, .bg-prime, .bg-ink, .bg-navy) .eyebrow { color: var(--text-on-dark-dim); }

/* On dark bands the headings must not stay --prime (unreadable on navy):
   h1-h4 carry an explicit dark colour, so re-assert white here. The h1 text
   gradient (background-clip) is also cleared so it doesn't vanish. */
.bg-dark  :is(h1, h2, h3, h4),
.bg-prime :is(h1, h2, h3, h4),
.bg-ink   :is(h1, h2, h3, h4),
.bg-navy  :is(h1, h2, h3, h4) {
    color: var(--white);
    background: none;
    -webkit-text-fill-color: currentColor;
}

.full_img_background {
    position: relative;
    padding-bottom: 180px;
    margin-bottom: -120px;
    margin-inline: calc(-1 * var(--page-gutter));
    .content-image { position: absolute; }
}

.all_corners img {
    border-radius: 20px;
}

/* Narrow screens trim the button's HORIZONTAL padding only: space is tight,
   but a touch target must not get smaller than a mouse one. Vertical padding
   and 15px type hold, and `min-height` guards the 44px WCAG 2.5.5 / Apple HIG
   minimum if a variant ever changes the padding. `inline-flex` (not
   `inline-block`) is what lets `min-height` centre the label. */
@media only screen and (max-width: 1050px) {
    .btn a,
    a.btn,
    button[type="submit"],
    input[type="submit"],
    .submit,
    .content-download .download-element a,
    .layout_latest p.more a {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-height: 44px;
        padding: 13px 22px;
        font-size: 0.9375rem;      /* hold the design's 15px */
    }
}

/* ==========================================================================
   HEADER — Cornerstone bar   (global, per-site active file)
   ==========================================================================
   Fixed, transparent over the hero; turns white (.shrink) on scroll.
   Markup: #header .inside > .logo · .navigation · .contact(social + CTA) · a.menu
   ========================================================================== */

/* Fixed transparent header overlays the page, so remove the container offset. */
#container { padding-top: 0; }
.container_inside { padding-bottom: 0; }

/* The bar ------------------------------------------------------------------ */
#header {
    position: fixed;
    inset-block-start: 0;
    width: 100%;
    z-index: 1000;
    background-color: transparent;
    transition: background-color 0.2s ease, box-shadow 0.2s ease;
}
.shrink #header {
    background-color: #fff;     /* from 230px of scroll (j_shrink.html5); no rule under it (Bob, 10 Oct 2026) */
}
#header {
    .inside {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;
        gap: clamp(10px, 1.2vw, 28px);
        padding-block: clamp(10px, 1.4vw, 18px);
        transition: padding 0.2s ease;
    }

    /* Logo --------------------------------------------------------------------- */
    .logo a { display: block; border-bottom: 0; }
    /* as large as the bar allows with the nav on one line (Bob, 13 Oct): 41px at
       1280, the board's 46 from 1366; each step below sets its own */
    .logo img { display: block; height: clamp(41px, calc(5.8vw - 33.2px), 46px); width: auto; object-fit: contain; object-position: left center; }   /* squeezed on a small phone, it scales rather than stretches */

    /* Navigation --------------------------------------------------------------- */
    .navigation { margin-left: auto; }
    /* Horizontal padding is HALF the gap; 22px → ~45px between links, clamped down. */
    .navigation a, .navigation strong {
        color: #04203F;                          /* Penpot blue 950 */
        font-family: var(--type-body);
        font-weight: 500;                        /* the board's 15px / 500, in caps (Bob, 10 Oct 2026) */
        text-transform: uppercase;
        font-size: clamp(0.78rem, 0.95vw, 0.95rem);
        /* 22px at the board's width, 6px on a laptop, so the caps stay on one line */
        padding-inline: clamp(6px, calc(1.6vw - 13px), 22px);
        padding-block: 0.4rem;
    }
    /* Down arrow on items that have a submenu (Unicode ▾).
       The selector has to cover `strong` and `span`, not just `a`: Contao renders
       the CURRENT page's nav item as `<strong class="active submenu">` rather than
       a link (and `<span class="active submenu">` in the mobile copy), so an
       `a`-only selector silently dropped the arrow from whichever item you were
       on — which is exactly the "on active, the down arrow goes away" report. */
    .navigation .submenu > a::after, .navigation .submenu > strong::after, .navigation .submenu > span:not(.nav-for)::after {
        content: "\25BE";
        font-size: 0.72em;
        margin-inline-start: 0.35em;
        position: relative;
        top: -0.1em;
        display: inline-block;
    }
    /* Hover + open submenu: white background, red text. */
    .navigation li:hover > a, .navigation li:focus-within > a, .navigation a:hover {
        background-color: #fff;
        color: var(--second);
    }
    .navigation .level_2 { background: #fff; box-shadow: 0 8px 24px rgba(4, 32, 63, 0.14); }
    .navigation .level_2 a { color: #04203F; }
    .navigation .level_2 :is(a, strong) { text-transform: none; letter-spacing: 0; }   /* caps on the bar only */
    .navigation .level_2 li:hover > a, .navigation .level_2 a:hover { background: #fff; color: var(--second); }

    /* Actions: social icons + CTA ---------------------------------------------- */
    /* 15px between the social icons (Bob, 10 Oct 2026; the board draws 10) */
    .contact {
        display: flex;
        align-items: center;
        gap: 15px;
    }
    .contact .social {
        display: inline-flex;
        align-items: center;
        justify-content: center;
        min-width: 24px;                         /* the WCAG 2.2 target size */
        min-height: 24px;
        border-bottom: 0;                        /* no underline on the icon links */
        border-radius: 6px;
        background: transparent;                      /* Penpot blue 700 */
        color: #0A417CFF;
        font-size: clamp(0.95rem, 1.1vw, 1.1rem);
    }
    .contact .social svg { height:20px;   }
    .contact .social:hover { color: var(--second); }
    .contact a.btn {
        margin: 0 0 0 clamp(0px, calc(1.6vw - 10px), 13px);
        white-space: nowrap;
        padding: clamp(8px, 0.8vw, 12px) clamp(12px, 1.2vw, 24px);
        font-size: clamp(0.78rem, 0.95vw, 0.95rem);
    }

    /* Mobile toggle ------------------------------------------------------------ */
    .menu {
        display: none;
        align-items: center;
        border-bottom: 0;
        color: var(--prime);
        font-size: 24px;
    }
}

/* 40px above the bar while it sits over the hero (Bob, 10 Oct 2026); back to
   the slim bar once it turns white */
@media only screen and (min-width: 1120px) {
    #header .inside { padding-top: 40px; }
    .shrink #header .inside { padding-top: clamp(10px, 1.4vw, 18px); }
}

/* Responsive --------------------------------------------------------------- */
/* The nav never wraps to two lines and stays a nav as long as it can (Bob,
   13 Oct). The links need ~702px with their "For", ~600 without:
     1280 up     the full labels
     1150-1279   "For" drops (nav_default.html5 wraps it in .nav-for; the
                 page names keep it)
     1120-1149   and the bar tightens
     1119 down   the menu
   Each step was checked one line wide with the letters 3% wider than here,
   for fonts that render fatter. */
@media only screen and (max-width: 1279px) {
    #header .nav-for { display: none; }
    #header .logo img { height: clamp(34px, calc(9.3vw - 73px), 46px); }
}
@media only screen and (max-width: 1149px) {
    #header {
        .inside { gap: 10px; }
        .logo img { height: 35px; }
        .navigation :is(a, strong) { padding-inline: 5px; }
        .contact { gap: 10px; }
        .contact a.btn { margin-left: 0; padding: 8px 12px; font-size: 0.78rem; }
    }
}
/* The menu: the bar reads logo · menu · LinkedIn · "Start a Conversation", so
   contacting them is one tap away (as on TPA Stack). */
@media only screen and (max-width: 1119px) {
    #header .navigation { display: none; }
    #header .menu { display: inline-flex; margin-left: auto; }
    #header .logo img { height: clamp(30px, 5vw, 40px); }   /* the menu bar has room for it */
    #header .contact { gap: 12px; }
    #header .contact a.btn { margin: 0; padding: 8px 14px; font-size: 0.8rem; }
}
@media only screen and (max-width: 420px) {
    #header .inside { gap: 10px; }
    #header .logo img { height: 28px; }
    #header .contact { gap: 10px; }
    #header .contact a.btn { padding: 7px 10px; font-size: 0.72rem; }   /* room for the logo beside the LinkedIn icon */
}

/* The mobile menu also ends with the button (templates/base-theme/mod_mmenu.html5). */
.mm-menu .menu-cta {
    padding: 24px 20px;
    &::after { content: none; }
    a.btn {
        flex: 0 0 auto;
        margin: 0;
        padding: 14px 28px;
        color: var(--white);   /* mmenu's own link colour outranks .btn here */
    }
}

.mod_navigation, .mod_navigation.block {
  overflow: visible;
}

.mod_navigation {
    ul, li {
      list-style: none;
      margin: 0;
      padding: 0;
    }

    li { position: relative; }

    > ul.level_1 > li { display: inline-block; }

    a, strong {
      display: block;
      padding: 0.33rem 2rem;
      text-decoration: none;
      border-bottom:none;
    }

    /*li:hover > a, li:focus-within > a { background-color: var(--black); }*/

    .level_2 {
      display: block;
      opacity: 0;
      visibility: hidden;
      transform: translateY(-10px);
      position: absolute;
      top: 100%;
      left: -1px;
      /*background: var(--black);*/
      min-width: 180px;
      z-index: 1000;
      transition: opacity 0.3s ease, transform 0.3s ease;
      pointer-events: none;
      border: 1px solid var(--prime);
      border-top: 0;
    }

    li:hover > .level_2, li:focus-within > .level_2 {
      opacity: 1;
      visibility: visible;
      transform: translateY(0);
      pointer-events: auto;
    }

    .level_2 li a { white-space: nowrap; }

    /*.level_2 li a:hover { background-color: var(--grey-dark); }*/

    /* CONTRAST ON DARK NAV SURFACES
       The hover/focus states below set a dark background but previously left the
       link colour alone, so text stayed --prime (#001078) on black — about 1.3:1,
       effectively unreadable. Every dark surface now sets its foreground too.

       The focus ring is overridden to white for the same reason: the site-wide
       ring is --prime, which disappears against a black dropdown. */
    li:hover > a, li:focus-within > a, .level_2 a, .level_2 li a:hover {
        color: var(--white);
        border-bottom-color: transparent;
    }
    
    li.sibling:hover {
      outline: 1px solid var(--prime);
      border-bottom: 0;
    }

    a:focus-visible { outline-color: var(--white); }
}

/* ==========================================================================
   FOOTER — Cornerstone dark: brand + 5 nav columns + offices + credits
   ==========================================================================
   Active per-site footer. Markup: module 9 (html) → #footer .inside.
   ========================================================================== */

#footer {
    position: relative;
    overflow: clip;
    background-color: var(--ink);
    color: rgba(255, 255, 255, 0.72);
    .inside { padding-block: var(--space-60) var(--space-40); }
    a { border-bottom: 0; }

    /* ---- Top: brand + nav columns ------------------------------------------ */
    .footer_top { align-items: start; }
}
/* `nowrap` is scoped to DESKTOP, in a min-width query, rather than being
   switched off later by a max-width one — and at the FRAMEWORK's own
   breakpoint, not a number of its own.

   The bug that caused: these two were unconditionally `nowrap` and were only
   restored to `wrap` at max-width 900. But framework_v3's column ramp steps at
   992 — `.col-2-3` drops to 50% and `.col-20` to 33.3% there. So between 901
   and 992 the five nav columns had already been re-sized for a 3-up layout
   while wrapping was still disabled, which put all five on one line inside a
   half-width parent: columns 4 and 5 ran off the right of the page (at 960 the
   container ends at 930 and the last column's right edge was 1232).

   Matching 992 means the wrap turns on in the same step that makes the columns
   narrow, so there is no window where the two disagree. */
@media only screen and (min-width: 993px) {
    #footer .footer_top,
    #footer .footer-cols { flex-wrap: nowrap; }
}
#footer {
    .footer_top img { display: block; height: auto; margin-bottom: 1.1em; }

    /* Brand column */
    /* The tagline runs the column's width (it wrapped at 24em with room to
       spare); weights as the board: both lines 400 (Bob, 10 Oct 2026). */
    .footer-brand p { color: rgba(255, 255, 255, 0.72); font-size: 0.9rem; margin: 0 0 0.8em; text-wrap: balance; }
    .footer-brand .foundation { font-weight: 400; color: rgba(255, 255, 255, 0.92); }
    .footer-social { display: inline-flex; gap: 15px; }
    .social {
        display: inline-flex;
        align-items: center;
        /*justify-content: center;*/
        width: 2.3rem; height: 2rem;
        border-radius: 6px;
        background: transparent;                      /* Penpot blue 700, like the header */
        color: #fff;
        font-size: 1.1rem;
    }
    .social svg { height:20px;   }
    .social:hover { background: transparent; color: var(--second); }

    /* Column headings — caps, white, linked; the board's 14px / 600, 0.8px
       tracking (Bob, 10 Oct 2026: font weights). */
    .footer-col-head {
        font-family: var(--type-body);
        font-size: 0.875rem;
        font-weight: 600;
        letter-spacing: 0.057em;
        text-transform: uppercase;
        margin: 0 0 0.9em;
        line-height: 1.3;
    }
    .footer-col-head a { color: var(--white); }
    .footer-col-head a:hover { color: var(--second); }

    /* Nav lists */
    .mod_customnav ul { margin: 0; padding: 0; list-style: none; }
    .mod_customnav li { display: block; margin-bottom: 0.55em; }
    /* the current page is a <strong class="active">: same size, a touch brighter */
    .mod_customnav :is(a, strong) { display: inline-block; padding: 0; color: rgba(255, 255, 255, 0.72); font-size: 0.9rem; font-weight: 400; text-wrap: balance; }
    .mod_customnav a:hover { color: var(--second); }
    .mod_customnav strong.active { color: var(--white); }

    /* ---- Offices (with dividers between) ----------------------------------- */
    .footer_offices {
        margin-top: var(--space-40);
        padding-top: var(--space-40);
        border-top: 1px solid rgba(255, 255, 255, 0.14);
        align-items: stretch;
    }
    /* Divider sits centred in the column gap (gap-40 → 20px each side), not hard
       against the next column's text. */
    .footer_offices > * + * { position: relative; }
    .footer_offices > * + *::before {
        content: "";
        position: absolute;
        top: 0; bottom: 0;
        left: -20px;
        border-left: 1px solid rgba(255, 255, 255, 0.14);
    }
    .footer_offices h4 {
        color: var(--white);
        font-family: var(--type-body);
        font-size: 0.875rem; font-weight: 600;          /* the board's 14px / 600, 1.2px tracking */
        letter-spacing: 0.086em; text-transform: uppercase;
        margin: 0 0 0.7em;
    }
    .footer_offices p { color: rgba(255, 255, 255, 0.72); font-size: 0.9rem; line-height: 1.6; margin: 0 0 0.9em; text-wrap: balance; }
    .footer_offices a { color: rgba(255, 255, 255, 0.72); }
    .footer_offices a:hover { color: var(--second); }
    /* Get in touch CTA: white, red on hover. */
    .footer_offices a.btn, .footer_offices a.btn:link { background-color: #fff; color: var(--prime); margin: 0.3em 0 0; }
    .footer_offices a.btn:hover { background-color: var(--second); color: #fff; }

    /* ---- Bottom: panda + credits + associations (one row) ------------------ */
    .footer_bottom {
        position: relative;
        margin-top: var(--space-40);
        padding-top: var(--space-24);
        border-top: 1px solid rgba(255, 255, 255, 0.14);
    }
    /* Panda sits on the top border of the credits bar. */
    .footer-panda {
        position: absolute;
        right: clamp(16px, 4vw, 90px);
        bottom: 100%;
        margin-bottom: 0;
        width: clamp(56px, 7vw, 104px);
        height: auto;
        pointer-events: none;
    }
    .footer_bottom .bottom_line {
        display: flex;
        flex-wrap: wrap;
        align-items: center;
        justify-content: space-between;
        gap: 0.6em 1.5em;
        color: rgba(255, 255, 255, 0.5);
        font-size: 0.8125rem;
    }
    .footer_bottom .credits, .footer_bottom .credits a { color: rgba(255, 255, 255, 1); }
    /* the credits line up with the legal links: no paragraph margin (it made the
       row centre a taller box and lifted the text 9px), the links' line height (John, 8 Oct) */
    .footer_bottom .credits { margin: 0; line-height: 1.4; }
    .footer_bottom .bottom-footer-nav ul { display: flex; flex-wrap: wrap; gap: 0.6em 1.5em; margin: 0; padding: 0; list-style: none; }
    /* The legal links and "Cookie settings" read as ONE row (John, 8 Oct): same
       size, weight and line height, the same 1.5em apart (the row's own gap),
       centred on one line. The current page is white, not bold. */
    .footer_bottom .bottom-footer-nav { display: flex; align-items: center; margin-left: auto; }
    /* the row spreads its items (space-between): auto margins keep "Cookie
       settings" next to the legal links, the gap between them the row's 1.5em */
    .footer_bottom .cookie-settings { margin-right: auto; display: flex; align-items: center; }
    .footer_bottom .bottom-footer-nav ul { align-items: center; }
    .footer_bottom .bottom-footer-nav li { display: flex; margin: 0; padding: 0; }
    .footer_bottom .bottom-footer-nav .mod_customnav { margin: 0; padding: 0; }
    .footer_bottom :is(.bottom-footer-nav, .cookie-settings) :is(a, strong) {
        font-size: 0.8125rem; font-weight: 400; line-height: 1.4;
        display: block;   /* one 18px box each, so the row centres them all alike */
    }
    .footer_bottom .bottom-footer-nav strong.active { color: rgba(255, 255, 255, 0.9); }
    .footer_bottom a { color: rgba(255, 255, 255, 0.5); }
    .footer_bottom a:hover { color: var(--second); }
    /* Association logos: a small white tile, inline in the credits row. */
    .footer-associations {
        display: inline-flex;
        align-items: center;
        gap: clamp(14px, 1.6vw, 26px);
        background: #fff;
        border-radius: 8px;
        padding: 14px 22px;      /* even room above and below the logos (Bob, 10 Oct 2026) */
    }
    .footer-associations img { height: clamp(22px, 2.4vw, 30px); width: auto; display: block; }
}

@media only screen and (max-width: 900px) {
    #footer .footer-panda { display: none; }
    #footer .footer_bottom .credits { justify-content: flex-start; }
}

/* ---- Tablet and phone (Bob, 13 Oct) ----------------------------------------
   992: the brand gets its own centred line, the nav columns the full width
   (3-up), with dividers between them like the offices'.
   700: offices and nav columns go 2-up (the framework's step is 600).
   480: one column, everything centred.
   A divider sits in the middle of the gap and goes wherever a cell starts a line. */
#footer .footer-cols > * + * { position: relative; }
@media only screen and (max-width: 992px) {
    #footer {
        .footer_top > .footer-brand {
            flex: 0 0 100%;
            text-align: center;
            img { margin-inline: auto; }
        }
        /* full width, the offices' 40px column gap and a rule on top, so the nav
           columns and the offices read as one system (Bob, 13 Oct) */
        .footer_top > .footer-cols {
            flex: 0 0 100%;
            --gap-x: var(--gutter-40);
            border-top: 1px solid rgba(255, 255, 255, 0.14);
            padding-top: var(--space-40);
        }
        .footer-cols > * + *::before {
            content: "";
            position: absolute;
            top: 0; bottom: 0;
            left: calc(var(--gap-x, 0px) / -2);
            border-left: 1px solid rgba(255, 255, 255, 0.14);
        }
        .footer-cols > :nth-child(3n + 1)::before { content: none; }
        .footer_offices > .col-1-3 { flex: 0 0 calc(100% / 3 - var(--gap-x, 0px) * 2 / 3); }
    }
}
@media only screen and (max-width: 700px) {
    #footer {
        .footer-cols > .col-20,
        .footer_offices > .col-1-3 { flex: 0 0 calc(50% - var(--gap-x, 0px) * 0.5); }
        .footer-cols > :nth-child(3n + 1)::before { content: ""; }
        :is(.footer-cols, .footer_offices) > :nth-child(odd)::before { content: none; }
    }
}
@media only screen and (max-width: 480px) {
    #footer {
        .footer-cols > .col-20,
        .footer_offices > .col-1-3 { flex: 0 0 100%; }
        :is(.footer-cols, .footer_offices) > :nth-child(n)::before { content: none; }
        :is(.footer-cols, .footer_offices) { text-align: center; }
    }
}

/* WCAG 2.2 target size (2.5.8): the footer's phone links are at least 24px tall (8 Oct). */
#footer a[href^="tel:"] { display: inline-block; min-height: 24px; line-height: 24px; }   /* own 24px line each, so phone and fax don't overlap */

/* ==========================================================================
   FORMS
   ==========================================================================
   Two parts, kept separate on purpose:

     PART 1 — LAYOUT   how form fields sit in the column framework
     PART 2 — BRAND    how they look

   Change Part 2 per site. Part 1 should rarely need touching.

   SCOPE: `.formbody`, not `.ce_form .formbody`. Contao uses the same wrapper
   for the form CONTENT ELEMENT and for every member module — login, lost
   password, change password, personal data, registration. They render the
   same .widget markup, so scoping to .ce_form left every member form
   completely unstyled while the contact form looked finished.

   Two files would have been the wrong fix: they would race to style one
   .widget at equal specificity and drift apart, which is the same reasoning
   that keeps list typography in one place.
   ========================================================================== */


/* ==========================================================================
   PART 1 — LAYOUT
   ==========================================================================
   Contao renders form fields as .widget divs inside .formbody. This makes
   .formbody behave as a framework row, so a `col-*` class on a form field
   works exactly as it does on a content element inside an article — same
   widths, same gutter, same stacking.

   Editors set the width through the Theme Toolbox, which already offers the
   column options on every form field type. No template override is needed;
   this is done entirely in CSS.

   The column WIDTHS come from framework_v3 — they are plain flex-basis
   values and apply to any flex child. Only the row behaviour and the
   stacking are repeated here, because those are scoped to `.row` in the
   framework and .formbody is markup we do not control.
   ========================================================================== */

.formbody {
  display: flex;
  flex-wrap: wrap;

  /* Same tokens the framework's rows use, so form gutters match page
     gutters and respond to the same per-site dial. */
  --gap-x: var(--row-gap-x);
  --gap-y: var(--row-gap-y);
  gap: var(--gap-y) var(--gap-x);
}

/* Default every child to a full line, so a field with no col-* class takes
   its own row and Contao's own children (error messages) behave.

   :where() keeps this at ZERO specificity on purpose — the col-* classes
   must win, and this file loads after the framework, so a normal selector
   here would beat them on source order and flatten every column. */
:where(.formbody) > * {
  flex: 0 1 100%;
  min-width: 0;
}

/* Row gaps handle the spacing between fields, so widgets carry no margin
   of their own — otherwise the two would compound. */
.formbody > .widget {
  margin: 0;
}

/* Stacking, mirroring the framework's own breakpoints. Higher specificity
   than the col-* widths, so these win below the breakpoint.
   `.no-stack` on the form opts out, exactly as it does on a row. */
@media (max-width: 992px) {
  form:not(.no-stack) .formbody > .col-2-3,
  form:not(.no-stack) .formbody > .col-3-4,
  form:not(.no-stack) .formbody > .col-3-5,
  form:not(.no-stack) .formbody > .col-2-5 {
    flex-basis: 100%;
  }

  /* Quarters, thirds and 30% step down to a half before stacking, and fifths
     to a third — exactly the ramp framework_v3 gives a .row. Kept in step by
     hand because .formbody is markup we do not control, so it cannot simply
     carry .row. */
  form:not(.no-stack) .formbody > .col-1-4,
  form:not(.no-stack) .formbody > .col-1-3,
  form:not(.no-stack) .formbody > .col-30 {
    flex-basis: calc(50% - var(--gap-x, 0px) * 0.5);
  }
  form:not(.no-stack) .formbody > .col-20 {
    flex-basis: calc(100% / 3 - var(--gap-x, 0px) * 2 / 3);
  }
}

@media (max-width: 600px) {
  form:not(.no-stack) .formbody > .col-1-2,
  form:not(.no-stack) .formbody > .col-1-4,
  form:not(.no-stack) .formbody > .col-1-3,
  form:not(.no-stack) .formbody > .col-30 {
    flex-basis: 100%;
  }
  form:not(.no-stack) .formbody > .col-20 {
    flex-basis: calc(50% - var(--gap-x, 0px) * 0.5);
  }
}

@media (max-width: 480px) {
  form:not(.no-stack) .formbody > .col-20 { flex-basis: 100%; }
}

/* The label sits above its control. */
.formbody {
    label { display: block; }

    /* Controls fill their column. Without this an input keeps its browser
       default size (roughly 20 characters) and ignores the column entirely. */
    input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]), select, textarea {
      width: 100%;
      max-width: 100%;
    }

    textarea {
      display: block;
      resize: vertical;      /* horizontal resizing would break the column */
    }

    /* Checkbox and radio groups: the control sits beside its label. */
    .checkbox_container label, .radio_container label { display: inline-block; }

    /* ==========================================================================
       PART 2 — BRAND
       ==========================================================================
       Colours come from the tokens in website.css. Adjust the values here per
       site; the layout above is unaffected by anything in this section.
       ========================================================================== */

    input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]), select, textarea {
      /* Cornerstone: a 2px navy hairline and a 6px radius, per the Contact design,
         on the design's 48px control height. Type is pinned to 1rem so the height
         doesn't drift with the surrounding band's font-size. */
      box-sizing: border-box;
      min-height: 48px;
      padding: 10px 16px;
      border: 2px solid var(--heading);
      border-radius: 6px;
      background-color: var(--white);
      color: var(--heading);
      font: inherit;         /* controls do not inherit type by default */
      /* AFTER the `font` shorthand — it resets font-size, so setting the size above
         it silently does nothing. Pinned so the control keeps the design's 48px
         height whatever the surrounding band's type size is. */
      font-size: 1rem;
      line-height: 1.5;
    }
    textarea { min-height: 130px; }
    /* the design's message box */

    /* FOCUS — deliberately explicit.
       website_standard.css sets `outline: none` on form fields and replaces it
       with nothing, which leaves keyboard users unable to see where they are
       (WCAG 2.4.7). This restores a visible focus ring. Do not remove it
       without providing another visible indicator. */
    input:focus-visible, select:focus-visible, textarea:focus-visible {
      outline: 2px solid var(--prime);
      outline-offset: 2px;
      border-color: var(--prime);
    }

    label {
      margin-bottom: var(--space-8);
      /* Cornerstone: the design labels fields in semibold body at full size, not
         the smaller default. #333B44 is the design's own label grey (no token). */
      font-family: var(--type-body);
      font-size: 1rem;
      font-weight: 600;
      color: #333B44;
    }

    /* The asterisk on a required field. */
    span.mandatory { color: var(--second); }

    /* Placeholder text is the designs' own muted grey, not body grey — at
       --grey-dark (#404040) a placeholder read as a filled-in answer. A select
       showing its prompt option is a placeholder too, so it gets the same colour
       while nothing real is chosen. */
    ::placeholder {
      color: var(--placeholder);
      opacity: 1;            /* Firefox dims placeholders by default */
    }
    select:has(option[value=""]:checked) { color: var(--text-muted); }   /* the prompt is read as text: WCAG AA (8 Oct) */
    select option { color: var(--heading); }
    /* the real options stay dark */

    /* Validation messages. */
    p.error, .widget .error {
      color: var(--second);
      font-size: 0.875em;
    }

    .widget.error input, .widget.error select, .widget.error textarea { border-color: var(--second); }

    /* Buttons use the site's .btn rules in website.css — only the
       form-specific spacing is set here. */
    .widget-submit button { margin-bottom: 0; }

    /* ==========================================================================
       ALTCHA ("I'm not a robot") — no control chrome
       ==========================================================================
       The spam-protection widget ships as a bordered, boxed control. It is not a
       field the visitor fills in and the designs don't draw it at all, so it
       reads as a quiet checkbox line rather than another input. The widget sets
       its own look through custom properties, and it renders in the normal DOM
       (no shadow root), so `.altcha` — the box that actually carries the border —
       can be reached directly.
       ========================================================================== */
    .widget-altcha {
      --altcha-border-width: 0;
      --altcha-border-radius: 0;
      --altcha-color-border: transparent;
      --altcha-max-width: none;
    }
    .widget-altcha .altcha {
      border: 0;
      border-radius: 0;
      background: none;
      padding-inline: 0;
      max-width: none;
    }
}

/* ==========================================================================
   GALLERY
   ==========================================================================
   Two parts, same split as forms.css:

     PART 1 — LAYOUT   how the tiles are arranged
     PART 2 — BRAND    how they look

   HOW TO SET IT UP IN CONTAO
   Put every image in a SINGLE row in the gallery element — set "images per
   row" to the total number of images. Contao then renders one flat list and
   the grid below decides how many fit per line. Do not use the per-row
   setting to control the layout; it cannot respond to screen width.
   ========================================================================== */


/* ==========================================================================
   PART 1 — LAYOUT
   ==========================================================================
   `repeat(auto-fit, minmax(...))` is intrinsically responsive: the browser
   fits as many tracks of at least --gallery-min as the container allows and
   distributes the remainder evenly. Columns are added and dropped purely on
   available width, so there are no breakpoints to maintain and it behaves
   correctly inside a narrow column as well as at full width.

   This replaces a flex layout with a percentage width per --cols-N class
   and three media queries.
   ========================================================================== */

.content-gallery {
    ul {
        display: grid;
        /* min(…, 100%) lets the single track collapse to the container instead
           of overflowing it — a bare minmax floor is a hard minimum, so a
           gallery inside a narrow column would spill past its edge. */
        grid-template-columns: repeat(auto-fit, minmax(min(var(--gallery-min, 220px), 100%), 1fr));
        gap: var(--gallery-gap, var(--gutter-24));

        margin: 0;
        padding: 0;
        list-style: none;
    }

    /* The gap provides all the spacing, so the items carry none of their own. */
    ul li {
        margin: 0;
        padding: 0;
        min-width: 0;        /* let a tile shrink below its image's intrinsic width */
    }

    figure {
        margin: 0;
        height: 100%;
    }

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

/* Single-image galleries should not stretch one tile across the full width. */
.content-gallery--cols-1 ul {
    grid-template-columns: 1fr;
}


/* --------------------------------------------------------------------------
   OPTIONAL — uniform tiles
   --------------------------------------------------------------------------
   By default tiles keep each image's own aspect ratio, so rows can vary in
   height and nothing is cropped. If a site wants a strict grid of identical
   tiles instead, add .gallery-crop to the element and every image is cropped
   to a common ratio.
   -------------------------------------------------------------------------- */

.gallery-crop img {
    aspect-ratio: var(--gallery-ratio, 1);
    height: 100%;
    object-fit: cover;
}


/* ==========================================================================
   PART 2 — BRAND
   ==========================================================================
   Adjust per site. Nothing here affects the arrangement above.
   ========================================================================== */

.content-gallery {
    img { border-radius: 2px; }

    figcaption {
        margin-top: var(--space-8);
        font-size: 0.875em;
        text-align: center;
    }
}


/* --------------------------------------------------------------------------
   TUNING
   --------------------------------------------------------------------------
   Both dials can be set globally in website.css or per element via the
   CSS class field:

     --gallery-min   smallest a tile may get before a column is dropped.
                     Lower = more columns. 220px suits thumbnails; use
                     ~300px for larger feature images.
     --gallery-gap   space between tiles. Defaults to the gutter scale.

   Example, a coarser gallery on one element:
     .gallery-large { --gallery-min: 320px; }
   -------------------------------------------------------------------------- */

/* ==========================================================================
   TABLES
   ==========================================================================
   Two parts, same split as forms.css and gallery.css:

     PART 1 — LAYOUT   how a table behaves when it does not fit
     PART 2 — BRAND    how it looks

   Change Part 2 per site. Part 1 should rarely need touching.
   ========================================================================== */


/* ==========================================================================
   PART 1 — LAYOUT
   ==========================================================================
   A table is the one content element that cannot reflow. Columns have a
   hard minimum width, so a wide table in a narrow column does not wrap or
   stack — it overflows.

   That matters here because html and #wrapper use `overflow: clip`, which
   has no scrollbar: an overflowing table would be silently CUT OFF and the
   hidden columns unreachable. Making the element itself scrollable keeps
   the content available without letting it break the page.

   Contao renders no wrapper around <table>, so the scroll lives on
   .content-table, the content element's own div.
   ========================================================================== */

.content-table {
    overflow-x: auto;
    /* Room for the scrollbar so it does not sit on top of the last row. */
    padding-bottom: 2px;

    table {
        width: 100%;
        border-collapse: collapse;

        /* Without this the table shrinks to fit and the text becomes unreadable
           instead of scrolling. Cells stay legible and the container scrolls. */
        min-width: var(--table-min, 32rem);
    }

    /* Cells must not collapse to one word per line. */
    th, td {
        text-align: left;
        vertical-align: top;
    }

    /* ==========================================================================
       PART 2 — BRAND
       ==========================================================================
       Colours come from the tokens in website.css.
       ========================================================================== */

    th, td {
        padding: 0.75em 1em;
        border-bottom: 1px solid var(--stroke);
    }

    thead th {
        border-bottom: 2px solid var(--prime);
        font-weight: 700;
        color: var(--prime);
    }

    tfoot td {
        border-top: 2px solid var(--stroke);
        border-bottom: 0;
        font-weight: 600;
    }

    /* Last row needs no rule under it — the container edge reads as the end. */
    tbody tr:last-child td { border-bottom: 0; }

    caption {
        margin-bottom: var(--space-8);
        font-size: 0.875em;
        text-align: left;
        color: var(--grey-dark);
    }
}


/* --------------------------------------------------------------------------
   OPTIONAL — zebra striping
   --------------------------------------------------------------------------
   Add .table-striped to the element. Useful for long numeric tables where
   the eye needs help tracking a row across.
   -------------------------------------------------------------------------- */

.table-striped tbody tr:nth-child(even) {
    background-color: var(--grey-light);
}


/* --------------------------------------------------------------------------
   TUNING
   --------------------------------------------------------------------------
     --table-min   width below which the table scrolls instead of squeezing.
                   32rem suits 3–4 columns; raise it for wider tables so
                   they scroll sooner rather than cramming.

   ACCESSIBILITY NOTE
   A scrollable region should be reachable by keyboard. Browsers are
   inconsistent about focusing scroll containers automatically, so if tables
   are common on a site, add tabindex="0" and an accessible name to the
   scrolling element in the template rather than relying on the browser.
   -------------------------------------------------------------------------- */

/* ==========================================================================
   COOKIE BAR — brand layer for oveleon/contao-cookiebar
   ==========================================================================
   The bundle is token-driven: its own stylesheet reads --ccb-* custom
   properties for every colour. So branding it means SETTING THOSE TOKENS
   rather than overriding its rules.

   That matters. Fighting the bundle's selectors means re-specifying
   padding, radius and width to stop half-overridden buttons looking wrong,
   and it breaks on every bundle update. Setting its tokens uses the API it
   deliberately exposes, and its layout keeps working.

   For the same reason the site's .btn rules are NOT applied here. The
   bundle stacks equal-width full-bleed buttons on mobile and rows them
   above 768px; imposing the site button on top produced a full-width pill
   sitting oddly beside the others.

   Tokens the bundle exposes (defaults in its own stylesheet):
     --ccb-btn-bg / -bdr / -clr / -bg-hvr    buttons
     --ccb-focus-clr                          focus ring
     --ccb-checked-bg / -clr                  toggle, on
     --ccb-unchecked-bg / -clr                toggle, off
     --ccb-disabled-bg / -clr                 toggle, locked
     --ccb-backdrop                           overlay behind the bar
     --ccb-anim-duration                      open/close timing
   ========================================================================== */

.contao-cookiebar {
	/* Secondary buttons — deny, save, details. Outlined, so they do not
	   compete with accept. */
	--ccb-btn-bg: transparent;
	--ccb-btn-bdr: var(--stroke);
	--ccb-btn-clr: var(--text);
	--ccb-btn-bg-hvr: var(--grey-light);

	/* The bundle already ships a correct :focus-visible ring and only asks
	   for the colour, so this is all that is needed — no competing outline. */
	--ccb-focus-clr: var(--prime);

	/* Toggles */
	--ccb-checked-bg: var(--grey-light);
	--ccb-checked-clr: var(--prime);
	--ccb-unchecked-bg: var(--white);
	--ccb-unchecked-clr: var(--grey-dark);
	--ccb-disabled-bg: var(--grey-light);
	--ccb-disabled-clr: var(--grey-dark);
}

/* Accept — the primary action, so it takes the site's button colours
   (--second, hovering to --prime) exactly as .btn does elsewhere.
   .highlight is the bundle's "emphasise accept" backend option; covering
   both means the branding holds whichever variant is configured. */
.contao-cookiebar .cc-btn.success,
.contao-cookiebar .highlight .success {
	--ccb-btn-bg: var(--second);
	--ccb-btn-bdr: var(--second);
	--ccb-btn-clr: var(--white);
	--ccb-btn-bg-hvr: var(--prime);
}


/* --------------------------------------------------------------------------
   TYPE
   --------------------------------------------------------------------------
   The bundle sets its own font-size in px. Inheriting keeps the bar on the
   site's type scale instead of a fixed 15px.
   -------------------------------------------------------------------------- */
.contao-cookiebar,
.contao-cookiebar .cc-btn {
	font-family: inherit;
}

.contao-cookiebar {
    p, a {	margin-bottom: 0; }

    /* Links must stay distinguishable from surrounding copy — colour alone is
       not sufficient (WCAG 1.4.1), so the underline is kept. */
    a:not(.cc-btn) {
    	color: var(--prime);
    	border-bottom: 1px solid var(--prime);
    }

    a:not(.cc-btn):hover {
    	color: var(--second);
    	border-bottom-color: var(--second);
    }

    /* --------------------------------------------------------------------------
       BUTTON LAYOUT
       --------------------------------------------------------------------------
       The bundle stacks all three buttons full-width, then lets them size to
       their text above 768px. This gives them an explicit hierarchy instead:

           Accept all          full width, on its own line
           Deny all  |  Privacy settings     half each, sharing the next line

       Accept and Deny stay one click apart on the first layer — both are
       equally reachable, which is what consent has to be. Accept is only
       visually dominant, which is a normal hierarchy and not a dark pattern.

       .cc-footer also contains the collapsible .cc-groups panel, so it is
       pushed to its own full-width line below the buttons.

       `flex: 1 1 0` rather than `width: 50%` on purpose: with a zero basis the
       two share whatever is left after the gap, so they are exactly equal and
       never overflow — a 50% width plus a gap would.
       -------------------------------------------------------------------------- */

    .cc-footer {
    	display: flex;
    	flex-wrap: wrap;
    	gap: 8px;
    }

    /* Beat the bundle's own sizing at both breakpoints. All margins are zeroed,
       not just the bottom: it also sets margin-right: 15px for its inline row,
       which would add to the flex gap and clip 15px off the full-width button. */
    .cc-footer .cc-btn {
    	width: auto;
    	margin: 0;
    }

    .cc-footer .cc-btn.success {	flex: 1 1 100%; }

    .cc-footer .cc-btn.deny, .cc-footer .cc-btn.info {	flex: 1 1 0; }

    /* The settings panel is a sibling of the buttons — keep it on its own row. */
    .cc-footer .cc-groups {	flex: 1 1 100%; }
}

/* The banner's description (the bundle's #868686, 3.6:1) in the body colour: WCAG AA (8 Oct). */
#cookiebar-desc, #cookiebar-desc p { color: var(--body, #4A545F); }

/* ==========================================================================
   PAGINATION
   ==========================================================================
   Shared by every list that can run to a second page — news, events, FAQ,
   search results, comments and the listing bundle — so it lives in its own
   file rather than inside any one of them. It is the first thing to appear
   the moment a site has more items than fit on a page, which is why it is
   worth having before those bundles are styled at all.

   Contao's markup is already sound, and this file deliberately does not
   fight it:

       <nav class="pagination" role="navigation" aria-label="Pagination">
         <p>Page 2 of 3</p>
         <ul>
           <li class="previous"><a class="previous">Previous</a></li>
           <li><a class="link" aria-label="Go to page 1">1</a></li>
           <li><strong class="active" aria-current="page">2</strong></li>
           <li class="next"><a class="next">Next</a></li>
         </ul>
       </nav>

   The current page is a <strong> carrying aria-current, not a link — so it
   is announced correctly and cannot be clicked. Numbered links carry
   "Go to page N" labels. First/previous and next/last are rendered only when
   they apply, so the row's item count changes from page to page.
   ========================================================================== */


/* --------------------------------------------------------------------------
   FRAME
   -------------------------------------------------------------------------- */

.pagination {
    margin-top: var(--space-40);

    /* The "Page 2 of 3" summary. Kept visible rather than hidden: it is the only
       thing that states the total, and on a long list that is the useful part. */
    p {
        margin: 0 0 var(--space-8);
        font-size: 0.875em;
        color: var(--grey-dark);
        text-align: center;
    }

    /* --------------------------------------------------------------------------
       THE ROW
       --------------------------------------------------------------------------
       website.css styles ul/li globally, because the list and description-list
       elements share their markup with the rich text editor. A list used as
       INTERFACE therefore has to opt out — the same reset the header nav and
       gallery files make, for the same reason. Without it the page numbers carry
       bullets and a 1.25em indent.
       -------------------------------------------------------------------------- */

    ul {
        display: flex;
        flex-wrap: wrap;
        justify-content: center;
        gap: var(--space-8);
        margin: 0;
        padding: 0;
        list-style: none;
    }

    li { margin: 0; }

    /* --------------------------------------------------------------------------
       TARGETS
       --------------------------------------------------------------------------
       44px minimum on both axes. WCAG 2.5.8 asks 24, but page numbers are small
       glyphs that get tapped on phones, and a bare digit is otherwise a very
       small target. The word links (Previous, Next) grow past it naturally.
       -------------------------------------------------------------------------- */

    a, strong {
        display: flex;
        align-items: center;
        justify-content: center;
        min-width: 44px;
        min-height: 44px;
        padding-inline: var(--space-8);
        border: 1px solid var(--stroke);
        font-weight: 500;
        line-height: 1;
        text-decoration: none;
        color: var(--text);
    }

    a:hover {
        background-color: var(--grey-light);
        border-color: var(--text);
    }

    a:focus-visible {
        outline: 2px solid var(--prime);
        outline-offset: 2px;
    }

    /* The current page. Distinguished by weight AND fill, not by colour alone
       (WCAG 1.4.1) — and it is already a <strong> rather than a link, so the
       difference survives with styles off. */
    strong.active {
        background-color: var(--prime);
        border-color: var(--prime);
        color: var(--white);
        font-weight: 700;
        cursor: default;
    }
}


/* --------------------------------------------------------------------------
   NARROW SCREENS
   --------------------------------------------------------------------------
   With first/previous/next/last as words, a long run of pages wraps to
   several lines on a phone. Dropping the outermost jumps keeps it to one or
   two: next/previous still step through, and the numbers still jump directly.
   -------------------------------------------------------------------------- */

@media (max-width: 600px) {
    .pagination li.first,
    .pagination li.last {
        display: none;
    }
}


/* TUNING
   Numbers are squared off. For pills, add `border-radius: 22px` to the
   shared a/strong rule — half of the 44px minimum, so it stays a circle for
   single digits and a lozenge for the word links. */

/* ==========================================================================
   HERO — the first band of every page
   ==========================================================================
   The hero article goes in the layout's Hero section (article "Display in:
   Hero"), so #hero is the hook. The article carries only its variant class:

     hero--light   cream band, navy copy. A statement (`hero__frame`) or
                   columns (`hero__intro`: copy | divider | stat rail or card)
     hero--split   Home: headline | divider | copy + buttons, stats row below
     hero--text    dark gradient, white copy

   Decor sits in a first text element `hero-decor`: `.hero-wash` (light
   heroes) or `.hero-blobs` (Home).
   ========================================================================== */

/* Each child of the hero is held to the content column. `:where()` keeps the
   id's weight out, so the variant and page rules below override it. */
:where(#hero) .mod_article {
    > * {
        box-sizing: border-box;
        max-width: var(--container-max);
        margin-inline: auto;
        padding-inline: var(--page-gutter);
    }
    a.btn { margin-top: 0.5rem; }
    p { text-wrap: balance; }      /* even lines, no one-word last line (John, 14 Oct) */
}

/* The decor layer spans the whole band, behind the copy */
:is(.hero--light, .hero--split) .hero-decor {
    position: absolute;
    inset: 0;
    z-index: 0;
    margin: 0;
    max-width: none;
    padding-inline: 0;
    pointer-events: none;
}

/* ---- Light -------------------------------------------------------------- */
.hero--light {
    --hero-h1-gap: clamp(0.875rem, 1vw, 1.5rem);   /* H1 → lead */
    position: relative;
    overflow: clip;
    background: var(--cream);
    color: var(--body);
    padding-top: clamp(128px, 17vw, 300px);        /* clears the fixed header */
    padding-bottom: clamp(48px, 7vw, 104px);
    > * { position: relative; z-index: 1; }
    h1 {
        color: var(--heading);
        background: none;                 /* no h1 text-gradient */
        -webkit-text-fill-color: currentColor;
        font-family: var(--type-display);
        font-weight: 700;
        font-size: var(--fs-hero-h1);
        line-height: 1.04;
        margin: 0 0 var(--hero-h1-gap);
    }

    /* the eyebrow sits above the top rule */
    .hero-eyebrow { margin: 0 auto clamp(0.9rem, 1.6vw, 1.4rem); }

    /* Intro: copy | divider | rail or card, with rules above and below.
       The rules are pseudo-elements inset by the gutter: a border would
       overshoot the text. */
    .hero__intro {
        --hero-h1-gap: clamp(1.25rem, 1.85vw, 2.75rem);
        position: relative;
        padding-block: clamp(1.75rem, 3vw, 2.75rem);
        align-items: start;

        .rte {
            padding-right: 30px;
        }
    }
    .hero__intro::before, .hero__intro::after {
        content: "";
        position: absolute;
        left: var(--page-gutter);
        right: var(--page-gutter);
        height: 0;
        border-top: 1px solid var(--hairline);
        pointer-events: none;
    }
    .hero__intro::before { top: 0; }
    .hero__intro::after { bottom: 0; }
    .hero__intro > *:first-child p {
        color: var(--heading);
        font-size: clamp(1.05rem, 1.35vw, 1.25rem);
        line-height: 1.55;
        max-width: var(--hero-intro-measure, none);   /* the column is the measure */
        margin: 0 0 1.25rem;
    }
    .hero__intro a.btn { margin-top: 0.25rem; margin-bottom: 0; }

    /* Statement: rules above and below; the copy's width is a per-page dial
       (`--hero-frame-max`, set as body.page-<alias> .hero__frame in the page's
       own file). The board's gaps: 32px above the H1, 42px below. */
    .hero__frame {
        --hero-frame-max: 62%;
        position: relative;
        padding-block: clamp(1.25rem, 2.2vw, 2rem) clamp(1.5rem, 2.8vw, 2.625rem);
    }
    .hero__frame::before, .hero__frame::after {
        content: "";
        position: absolute;
        left: var(--page-gutter);
        right: var(--page-gutter);
        height: 0;
        border-top: 1px solid var(--hairline);
        pointer-events: none;
    }
    .hero__frame::before { top: 0; }
    .hero__frame::after { bottom: 0; }
    .hero__frame > * { max-width: var(--hero-frame-max); }
    .hero__frame h1 { margin: 0 0 var(--hero-h1-gap); }
    /* the frame's padding alone sets the gap to the bottom rule */
    .hero__frame :last-child { margin-bottom: 0; }
    .hero__frame p {
        color: var(--body);
        font-size: clamp(1.05rem, 1.25vw, 1.1875rem);
        line-height: 1.55;
        margin: 0;
    }
}

/* Divider between the intro's columns: desktop only, so a padded card in the
   second column (Plan Explainers' .pe-card) keeps its own padding below */
@media only screen and (min-width: 993px) {
    .hero--light .hero__intro > *:nth-child(2) {
        border-left: 1px solid var(--hairline);
        padding-left: clamp(1.75rem, 3.5vw, 3.5rem);
    }
    .hero--light .hero__intro > *:nth-child(2):not(.pe-card) { align-self: stretch; }
}

/* Stat rail: metric + caption, a hairline between each */
.hero-rail {
    display: flex; flex-direction: column;
    .stat { padding-block: clamp(1rem, 1.8vw, 1.6rem); }
    .stat:first-child { padding-top: 0; }
    .stat + .stat { border-top: 1px solid var(--hairline); }
    .num {
        display: block;
        font-family: var(--type-display);
        font-weight: 700;
        color: var(--prime);
        font-size: clamp(1.35rem, 1.9vw, 1.625rem);
        line-height: 1.1;
        margin-bottom: 0.35em;
    }
}
.hero--light .hero-rail p {
    margin: 0;
    color: var(--text-muted);
    font-size: 0.875rem;
    line-height: 1.4;
    max-width: none;
}

/* The intro stacks at 992 instead of halving: half a tablet is too narrow for
   a rail or a card. `:has()` lifts these above the framework's mixed-pair rule. */
@media only screen and (max-width: 992px) {
    .hero--light .hero__intro.row:not(.no-stack):has(> .col-2-5) > :is(.col-3-5, .col-2-5) {
        flex: 0 0 100%;
    }
    .hero--light .hero__intro > *:nth-child(2) { margin-top: clamp(1.5rem, 3vw, 2rem); }
}
@media only screen and (max-width: 760px) {
    .hero--light .hero__frame > * { max-width: none; }
}

/* ---- The wash: soft cyan and pink masses behind a light hero -------------
   Markup: <div class="hero-wash"><i class="hw hw1"></i>…hw4</div>. Placed in
   a centred 2400px box (the board width) so it tracks the page column.
   Per-page dials: --wash-strength (opacity), --wash-speed (duration),
   --wash-y (shift), --wash-core (how far the colour holds before fading),
   --wash-travel (distance). */
.hero-wash {
    position: absolute;
    inset: 0;
    max-width: 2400px;
    margin-inline: auto;
    pointer-events: none;
    --wash-strength: 1;
    --wash-speed: 1;
    --wash-y: 0%;
    --wash-core: 38%;
    --wash-travel: 2.5;
    .hw {
        position: absolute;
        border-radius: 50%;
        will-change: transform;
        translate: 0 var(--wash-y);
    }
    .hw1 {   /* cyan, upper left */
        left: -20%;
        top: -14%;
        width: 64%;
        aspect-ratio: 1063 / 620;
        background: radial-gradient(closest-side,
            var(--blob-cyan) 0%, var(--blob-cyan) var(--wash-core), transparent 100%);
        opacity: calc(0.95 * var(--wash-strength));
        animation: washSink calc(16s * var(--wash-speed)) ease-in-out -7s infinite;
    }
    .hw2 {   /* pink, upper right */
        left: 34%;
        top: -18%;
        width: 78%;
        aspect-ratio: 1326 / 768;
        background: radial-gradient(closest-side,
            var(--blob-pink) 0%, var(--blob-pink) var(--wash-core), transparent 100%);
        opacity: calc(1 * var(--wash-strength));
        animation: washDrift calc(21s * var(--wash-speed)) ease-in-out -19s infinite;
    }
    .hw3 {   /* cyan, lower left */
        left: 2%;
        top: 44%;
        width: 52%;
        aspect-ratio: 1 / 0.72;
        background: radial-gradient(closest-side,
            var(--blob-cyan) 0%, var(--blob-cyan) calc(var(--wash-core) * 0.8), transparent 100%);
        opacity: calc(0.82 * var(--wash-strength));
        animation: washRise calc(18s * var(--wash-speed)) ease-in-out -23s infinite;
    }
    .hw4 {   /* pink, lower right */
        left: 52%;
        top: 38%;
        width: 66%;
        aspect-ratio: 1 / 0.62;
        background: radial-gradient(closest-side,
            var(--blob-pink) 0%, var(--blob-pink) calc(var(--wash-core) * 0.8), transparent 100%);
        opacity: calc(0.88 * var(--wash-strength));
        animation: washCircle calc(23s * var(--wash-speed)) ease-in-out -11s infinite;
    }
}
/* `translate` on .hw carries --wash-y, so these use `transform` and compose */
@keyframes washSink {
    0%   { transform: translate3d(0, 0, 0) scale(1); }
    15%  { transform: translate3d(calc(4% * var(--wash-travel)), calc(8% * var(--wash-travel)), 0) scale(1.16); }
    30%  { transform: translate3d(calc(10% * var(--wash-travel)), calc(18% * var(--wash-travel)), 0) scale(0.92); }
    45%  { transform: translate3d(calc(2% * var(--wash-travel)), calc(27% * var(--wash-travel)), 0) scale(1.18); }
    60%  { transform: translate3d(calc(-8% * var(--wash-travel)), calc(20% * var(--wash-travel)), 0) scale(0.9); }
    80%  { transform: translate3d(calc(-13% * var(--wash-travel)), calc(8% * var(--wash-travel)), 0) scale(1.12); }
    100% { transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes washDrift {
    0%   { transform: translate3d(0, 0, 0) scale(1); }
    18%  { transform: translate3d(calc(-10% * var(--wash-travel)), calc(9% * var(--wash-travel)), 0) scale(1.2); }
    36%  { transform: translate3d(calc(-22% * var(--wash-travel)), calc(16% * var(--wash-travel)), 0) scale(0.88); }
    54%  { transform: translate3d(calc(-30% * var(--wash-travel)), calc(-4% * var(--wash-travel)), 0) scale(1.18); }
    72%  { transform: translate3d(calc(-18% * var(--wash-travel)), calc(-16% * var(--wash-travel)), 0) scale(0.9); }
    88%  { transform: translate3d(calc(-6% * var(--wash-travel)), calc(-10% * var(--wash-travel)), 0) scale(1.1); }
    100% { transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes washRise {
    0%   { transform: translate3d(0, 0, 0) scale(1); }
    20%  { transform: translate3d(calc(8% * var(--wash-travel)), calc(-12% * var(--wash-travel)), 0) scale(1.22); }
    40%  { transform: translate3d(calc(17% * var(--wash-travel)), calc(-25% * var(--wash-travel)), 0) scale(0.88); }
    58%  { transform: translate3d(calc(2% * var(--wash-travel)), calc(-35% * var(--wash-travel)), 0) scale(1.18); }
    78%  { transform: translate3d(calc(-13% * var(--wash-travel)), calc(-22% * var(--wash-travel)), 0) scale(0.9); }
    100% { transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes washCircle {
    0%   { transform: translate3d(0, 0, 0) scale(1); }
    16%  { transform: translate3d(calc(11% * var(--wash-travel)), calc(-9% * var(--wash-travel)), 0) scale(1.15); }
    33%  { transform: translate3d(calc(22% * var(--wash-travel)), calc(2% * var(--wash-travel)), 0) scale(0.9); }
    50%  { transform: translate3d(calc(26% * var(--wash-travel)), calc(16% * var(--wash-travel)), 0) scale(1.2); }
    66%  { transform: translate3d(calc(8% * var(--wash-travel)), calc(24% * var(--wash-travel)), 0) scale(0.92); }
    83%  { transform: translate3d(calc(-9% * var(--wash-travel)), calc(14% * var(--wash-travel)), 0) scale(1.12); }
    100% { transform: translate3d(0, 0, 0) scale(1); }
}

/* ---- Split (Home) --------------------------------------------------------- */
/* Spacing is the board's, in proportion below 2400: 32px from the top rule to
   the headline, 63px from the headline to the stats, the copy 91px right of
   the divider. */
.hero--split {
    --hs-pad: clamp(1.25rem, 1.333vw, 2rem);         /* top rule → headline */
    --hs-gap: clamp(1.75rem, 2.625vw, 3.9375rem);    /* headline → stats rule */
    position: relative;
    overflow: clip;
    background: #FBFAF9;
    color: var(--text);
    padding-top: clamp(150px, 21vw, 400px);          /* clears the fixed header */
    padding-bottom: clamp(60px, 8vw, 120px);
    h1, h3 { color: var(--heading); }
    > * { position: relative; z-index: 1; }
    h1 {
        font-family: var(--type-display);
        font-weight: 700;
        font-size: clamp(2.1rem, 3.125vw, 4.6875rem);   /* 75 at 2400, in proportion */
        line-height: 1.15;
        margin: 0;
        background: none;
        -webkit-text-fill-color: currentColor;
    }
    h1 em { font-style: normal; font-size: 1.2em; }  /* the enlarged word */

    .hero__intro {
        position: relative;
        padding-top: var(--hs-pad);
        align-items: start;
    }
    .hero__intro::before {
        content: "";
        position: absolute;
        top: 0;
        left: var(--page-gutter);
        right: var(--page-gutter);
        height: 0;
        border-top: 1px solid var(--hairline);
        pointer-events: none;
    }
    /* The copy column stretches so its divider runs from the top rule to the
       stats rule; the copy centres on the headline */
    .hero__intro > *:nth-child(2) {
        position: relative;
        overflow: visible;
        padding-left: clamp(1.5rem, 3.8vw, 5.6875rem);
        align-self: stretch;
        display: flex;
        flex-direction: column;
        justify-content: center;
    }
    .hero__intro > *:nth-child(2)::before {
        content: "";
        position: absolute;
        left: 0;
        top: calc(-1 * var(--hs-pad));
        bottom: calc(-1 * var(--hs-gap));
        border-left: 1px solid var(--hairline);
        pointer-events: none;
    }
    .hero__intro p { color: var(--heading); }
    .hero__intro a.btn { margin-top: 0.5rem; margin-bottom: 0; }

    /* Stats: rules above and below, dividers between cells */
    .hero__stats {
        position: relative;
        align-items: center;
        margin-top: var(--hs-gap);
        padding-block: clamp(1rem, 1.3vw, 1.9375rem);
    }
    .hero__stats::before, .hero__stats::after {
        content: "";
        position: absolute;
        left: var(--page-gutter);
        right: var(--page-gutter);
        height: 0;
        border-top: 1px solid var(--hairline);
        pointer-events: none;
    }
    .hero__stats::before { top: 0; }
    .hero__stats::after { bottom: 0; }
    .hero__stats > * {
        position: relative;
        text-align: center;
        padding-inline: clamp(0.5rem, 1.5vw, 1.25rem);
    }
    .hero__stats > * + * { border-left: 1px solid var(--hairline); }
    .hero__stats h3 {
        display: block;
        font-family: var(--type-display);
        font-weight: 700;
        font-size: clamp(1.1rem, 1.9vw, 1.625rem);
        line-height: 1.1;
        margin: 0 0 0.3em;
    }
    .hero__stats p {
        margin: 0;
        color: var(--text-muted);
        font-size: 0.85rem;
        line-height: 1.35;
    }
}
@media only screen and (max-width: 900px) {
    .hero--split h1 { margin-bottom: 1.25rem; }
    .hero--split .hero__intro > *:nth-child(2) { padding-left: 0; }
    .hero--split .hero__intro > *:nth-child(2)::before { content: none; }
}
/* The stats' dividers follow the cells' step-down (2-up at 992, stacked at
   600): the cell that starts a line has none (John, 16 Oct) */
@media only screen and (max-width: 992px) {
    .hero--split .hero__stats > :nth-child(odd) { border-left: 0; }
}
@media only screen and (max-width: 600px) {
    .hero--split .hero__stats > * + * { border-left: 0; }
}

/* Home's drifting blobs (the design's ellipses). --blob-speed scales the
   cycle, --blob-travel the path: set to move about as fast as the other
   heroes' wash (For Financial Advisors), John 14 Oct. */
.hero-blobs {
    position: absolute; inset: 0; pointer-events: none;
    --blob-speed: 0.6;
    --blob-travel: 2.2;
    .hb { position: absolute; height: auto; will-change: transform; }
    .hb5 { left: -8%;  top: -18%; width: 42vw; animation: heroBlobA calc(18s * var(--blob-speed)) ease-in-out infinite; }
    .hb3 { left: -16%; top: 6%;   width: 38vw; animation: heroBlobB calc(22s * var(--blob-speed)) ease-in-out infinite; }
    .hb1 { left: 20%;  top: -12%; width: 54vw; animation: heroBlobC calc(20s * var(--blob-speed)) ease-in-out infinite; }
    .hb2 { left: 44%;  top: 0%;   width: 54vw; animation: heroBlobA calc(24s * var(--blob-speed)) ease-in-out infinite; }
    .hb4 { left: 36%;  top: 18%;  width: 52vw; animation: heroBlobB calc(17s * var(--blob-speed)) ease-in-out infinite reverse; }
}
@keyframes heroBlobA {
    0%   { transform: translate(0, 0) scale(1); }
    25%  { transform: translate(calc(7% * var(--blob-travel)), calc(-6% * var(--blob-travel))) scale(1.12); }
    50%  { transform: translate(calc(-5% * var(--blob-travel)), calc(5% * var(--blob-travel))) scale(0.9); }
    75%  { transform: translate(calc(6% * var(--blob-travel)), calc(7% * var(--blob-travel))) scale(1.08); }
    100% { transform: translate(0, 0) scale(1); }
}
@keyframes heroBlobB {
    0%   { transform: translate(0, 0) scale(1); }
    25%  { transform: translate(calc(-7% * var(--blob-travel)), calc(5% * var(--blob-travel))) scale(0.88); }
    50%  { transform: translate(calc(6% * var(--blob-travel)), calc(-7% * var(--blob-travel))) scale(1.15); }
    75%  { transform: translate(calc(-5% * var(--blob-travel)), calc(-6% * var(--blob-travel))) scale(1.04); }
    100% { transform: translate(0, 0) scale(1); }
}
@keyframes heroBlobC {
    0%   { transform: translate(0, 0) scale(1); }
    33%  { transform: translate(calc(-6% * var(--blob-travel)), calc(-6% * var(--blob-travel))) scale(1.1); }
    66%  { transform: translate(calc(7% * var(--blob-travel)), calc(4% * var(--blob-travel))) scale(0.92); }
    100% { transform: translate(0, 0) scale(1); }
}

/* ---- Text (dark) ---------------------------------------------------------- */
.hero--text {
    position: relative;
    overflow: clip;
    background: var(--grad-hero);
    color: var(--white);
    padding-block: clamp(48px, 7vw, 88px);
    h1 {
        color: var(--white);
        margin: 0 0 0.4em;
        font-weight: 200;
        font-size: clamp(2.5rem, 5vw, 3.75rem);
        line-height: 1.05;
        max-width: 18ch;
    }
    p { color: rgba(255, 255, 255, 0.82); max-width: 44em; }
    .eyebrow.on-dark { margin-bottom: 0.9em; }
}

@media (prefers-reduced-motion: reduce) {
    .hero-wash .hw, .hero-blobs .hb { animation: none; }
}

/* Lead copy wraps balanced */
.hero__intro p { text-wrap: balance; }

/* ==========================================================================
   STATS ROW — a strip of headline metrics   (visual only)
   ==========================================================================
   A short row of "big number + caption" stats under a heading. A single
   hairline rule runs across the TOP of the row and vertical hairlines divide
   the cells (per the Cornerstone "record behind the promise" design). The
   metric is a Literata navy heading; the caption is small grey body.

   Build: element_group `row stats` with N children `col-1-3` (or `col-1-4`),
   each a `text` element holding:
       <h3>No audit failures.</h3>
       <p>Across every plan we administer.</p>

   Styled BY TAG inside `.stats` (Contao's rich-text editor strips inner
   classes): the first heading is the metric, the paragraph is the caption.
   ========================================================================== */
.stats {
    --stats-rule: var(--hairline);       /* a modifier may go solid; see below */
    position: relative;
    padding-top: clamp(1.25rem, 2.4vw, 2rem);
    align-items: start;
    /* THE TOP RULE IS AN INSET PSEUDO-ELEMENT, NOT A BORDER. A stats row is an
       element_group, which is a `.block` and so carries `padding-inline:
       var(--page-gutter)`; a border-top therefore ran a full gutter past the text
       at each end. Every board draws this rule at exactly the container width
       (Our Story's values rule: x302, w1800 of the 2400 board), flush with the
       copy above it. Same treatment as the hero's framing rules. */
    &::before {
        content: "";
        position: absolute;
        top: 0;
        left: var(--page-gutter);
        right: var(--page-gutter);
        height: 0;
        border-top: 1px solid var(--stats-rule);
        pointer-events: none;
    }
    > * { position: relative; }
    /* cells above the rule */
    > * + * {
        border-left: 1px solid var(--stats-rule);
        padding-left: clamp(1.5rem, 3vw, 3rem);
    }
}

.stats {
    h3 {
        font-family: var(--type-display);
        font-weight: 700;
        font-size: clamp(1.35rem, 1.9vw, 1.6875rem);   /* ~27px */
        line-height: 1.15;
        color: var(--prime);
        margin: 0 0 0.5em;
    }
    p {
        margin: 0;
        color: var(--body);
        font-size: clamp(0.9rem, 1vw, 0.9375rem);       /* ~15px */
        line-height: 1.45;
    }
}

/* On a dark band: light rule/divider, white metric, muted caption. */
.bg-ink .stats,
.bg-dark .stats,
.bg-prime .stats { --stats-rule: var(--hairline-on-dark); }
.bg-ink .stats h3,
.bg-dark .stats h3,
.bg-prime .stats h3 { color: var(--white); }
.bg-ink .stats p,
.bg-dark .stats p,
.bg-prime .stats p { color: rgba(255, 255, 255, 0.8); }

/* --------------------------------------------------------------------------
   DIVIDERS MUST VANISH EXACTLY WHEN THE COLUMNS STOP SITTING SIDE BY SIDE
   --------------------------------------------------------------------------
   A divider is drawn on "every cell but the first", which is only right while
   the cells share ONE LINE. So every breakpoint in framework_v3's step-down
   ramp needs a matching rule here, and "off" is not the only answer — at a
   2-up or 3-up the cell that STARTS each line loses its divider and the rest
   keep theirs.

   Tracking framework_v3's ramp (see "COLUMNS THAT STEP DOWN BEFORE STACKING"):
     .col-1-3 / .col-30   3-up → 2-up (992) → 1-up (600)
     .col-1-4 / .col-1-2  4-up → 2-up (992) → 1-up (600)
     .col-20              5-up → 3-up (992) → 2-up (600) → 1-up (480)
     major halves alone   → 1-up (992)

   `.stats--split` inherits all of this through the same selectors.
   -------------------------------------------------------------------------- */
@media only screen and (max-width: 992px) {
    /* The major half of an unequal pair, on its own, goes straight to 1-up. */
    .stats > .col-2-3 + .col-2-3,
    .stats > .col-3-4 + .col-3-4,
    .stats > .col-3-5 + .col-3-5,
    .stats > .col-2-5 + .col-2-5 {
        border-left: 0;
        padding-left: 0;
        padding-top: 1.25rem;
    }
    /* 2-up: only the cell that starts a line loses its divider. */
    .stats > .col-1-3:nth-child(odd),
    .stats > .col-30:nth-child(odd),
    .stats > .col-1-4:nth-child(odd),
    .stats > .col-1-2:nth-child(odd) {
        border-left: 0;
        padding-left: 0;
    }
    .stats > .col-1-3:nth-child(n + 3),
    .stats > .col-30:nth-child(n + 3),
    .stats > .col-1-4:nth-child(n + 3),
    .stats > .col-1-2:nth-child(n + 3) { padding-top: 1.25rem; }

    /* 3-up: every third cell starts a line. */
    .stats > .col-20:nth-child(3n + 1) {
        border-left: 0;
        padding-left: 0;
    }
    .stats > .col-20:nth-child(n + 4) { padding-top: 1.25rem; }
}
@media only screen and (max-width: 600px) {
    /* Everything but a fifth is now fully stacked. */
    .stats > * + * { border-left: 0; padding-left: 0; padding-top: 1.25rem; }

    /* A fifth is 2-up here, so the second of each pair keeps its divider. */
    .stats > .col-20:nth-child(even) {
        border-left: 1px solid var(--stats-rule);
        padding-left: clamp(1.5rem, 3vw, 3rem);
        padding-top: 0;
    }
    .stats > .col-20:nth-child(-n + 2) { padding-top: 0; }
}
@media only screen and (max-width: 480px) {
    .stats > .col-20 + .col-20 {
        border-left: 0;
        padding-left: 0;
        padding-top: 1.25rem;
    }
}

/* ==========================================================================
   FIXED-HEIGHT DIVIDERS  `stats--split`
   ==========================================================================
   The base component divides cells with a border, so the divider is as tall as
   its own cell — ragged when the cells hold different amounts of copy. Where
   the design draws a divider of ONE fixed height, centred in the gutter (the
   Cornerstone milestone + values rows), use this instead: the border comes off
   and each cell after the first draws its own short rule, pulled half a gutter
   left so it sits in the middle of the gap. `--gap-x` comes from `.row`.
   ========================================================================== */
.stats--split {
    > * + * {
        border-left: 0;
        padding-left: 0;
        position: relative;
    }
    > * + *::before {
        content: "";
        position: absolute;
        top: 0;
        left: calc(-1 * var(--gap-x, 0px) / 2);
        width: 1px;
        height: var(--stats-divider, 140px);
        background: var(--stats-rule);
    }
}

/* ==========================================================================
   MILESTONE ROW  `stats stats--split stats--milestones`
   ==========================================================================
   A dated history strip: "2014 / 2016 / ~100 clients / Merger / Today". Same
   bones as a metric row, but the label is grey body colour rather than the
   navy metric, the caption is a touch larger, and the LAST cell is the present
   day so its label goes brand-navy. No top rule of its own — it's designed to
   hang under the hero's bottom framing rule.

   Build: element_group `row stats stats--split stats--milestones` with N
   children `col-20` (= a fifth; or col-1-4 for four), each a `text`:
       <h3>2016</h3>
       <p>Cornerstone founded from scratch…</p>
   ========================================================================== */
.stats--milestones {
    --stats-rule: var(--heading);
    --gap-x: clamp(2.5rem, 5.75vw, 138px);   /* the board's 138 of 2400, divider centred */
    padding-top: clamp(1.75rem, 2.6vw, 2.5rem);
    &::before { content: none; }
    /* hangs under the hero's own rule */
    h3 { color: var(--body); }
    > *:last-child h3 { color: var(--prime); }
    p { font-size: clamp(0.9rem, 1.05vw, 1rem); }
}   /* ~16px */

/* ==========================================================================
   VALUES ROW  `stats stats--split stats--values`
   ==========================================================================
   Short "how we work" statements under a solid hairline: a Literata title at
   medium weight (a statement, not a metric, so it isn't bolded to 700) over a
   line of body copy.

   Build: element_group `row stats stats--split stats--values` with N children
   `col-1-4`, each a `text`:  <h3>Tell the truth.</h3><p>…</p>
   ========================================================================== */
.stats--values {
    --stats-rule: var(--heading);
    --stats-divider: 134px;
    --gap-x: clamp(2.5rem, 7.5vw, 181px);    /* the board's 181 of 2400 */
    padding-top: clamp(1.75rem, 2.6vw, 2.25rem);
    h3 {
        font-weight: 500;
        color: var(--heading);
    }
    p { font-size: clamp(1rem, 1.25vw, 1.1875rem); }
}    /* ~19px */

/* The fixed-height divider follows the same ramp — see the block above. The
   `.stats--split` divider is a pseudo-element, so it is switched off with
   `content: none` rather than a zeroed border. */
@media only screen and (max-width: 992px) {
    .stats--split > .col-2-3 + .col-2-3::before,
    .stats--split > .col-3-4 + .col-3-4::before,
    .stats--split > .col-2-5 + .col-2-5::before,
    .stats--split > .col-3-5 + .col-3-5::before,
    .stats--split > .col-1-3:nth-child(odd)::before,
    .stats--split > .col-30:nth-child(odd)::before,
    .stats--split > .col-1-4:nth-child(odd)::before,
    .stats--split > .col-1-2:nth-child(odd)::before,
    .stats--split > .col-20:nth-child(3n + 1)::before { content: none; }
}
@media only screen and (max-width: 600px) {
    .stats--split > * + *::before { content: none; }
    .stats--split > .col-20:nth-child(even)::before { content: ""; }
}
@media only screen and (max-width: 480px) {
    .stats--split > .col-20 + .col-20::before { content: none; }
}

/* While side by side, the first cell sits in from the rule (the boards' 28-32
   of 2400). Stacked (2-up and below), a split row's dividers run the cell's
   full height with the row gap between them, and a fully stacked cell gets a
   rule above it instead, with the same space either side (Bob, 13 Oct). */
@media only screen and (min-width: 993px) {
    .stats--split > :first-child { padding-left: clamp(0px, 1.3vw, 32px); }
}
@media only screen and (max-width: 992px) {
    .stats.stats--split > :nth-child(n) { padding-top: 0; }
    .stats--split > * + *::before { height: 100%; }
}
@media only screen and (max-width: 600px) {
    .stats--split { --stack-gap: 1.5rem; row-gap: var(--stack-gap); }
    /* the base row's 2-up border would double the split row's own divider */
    .stats.stats--split > .col-20:nth-child(even) { border-left: 0; padding-left: 0; }
    .stats.stats--split > :not(.col-20):nth-child(n + 2) {
        border-top: 1px solid var(--stats-rule);
        padding-top: var(--stack-gap);
    }
}
@media only screen and (max-width: 480px) {
    .stats.stats--split > .col-20:nth-child(n + 2) {
        border-top: 1px solid var(--stats-rule);
        padding-top: var(--stack-gap);
    }
}

/* ==========================================================================
   LOGO STRIP — a row of partner / platform logos   (visual only)
   ==========================================================================
   Grayscale logos on a light band, e.g. "works with these platforms", built
   on Contao's NATIVE slider markup — a `slider` content element whose children
   are `image` elements. Contao emits `.content-slider > .slider-wrapper > …`,
   which is what the rules below style; there is no made-up wrapper class.

   Two earlier hand-rolled approaches lived here and are gone: a `.logo-strip`
   flex row and a `.logo-strip-img` single pre-composed image. Neither was used
   on any page once the carousel landed — three mechanisms for one job.
   ========================================================================== */

/* ---- Logo carousel (native slider): 11 visible, advances 1 at a time ----- */
.slider-control { display: none !important; }   /* no arrows, no dots */
.content-slider {
    overflow: hidden;
    .slider-wrapper { display: flex; align-items: center; will-change: transform; }
    .slider-wrapper > * {
               /* each slide = one logo */
        flex: 0 0 calc(100% / 11);
        box-sizing: border-box;
        padding-inline: clamp(10px, 1.4vw, 26px);
    }
    .slider-wrapper figure { margin: 0; }
    .slider-wrapper img {
        display: block;
        margin: 0 auto;
        max-height: 40px;
        width: auto;
        max-width: 100%;
        filter: grayscale(1);
        opacity: 0.85;          /* darker grey than the 0.6 it was (Bob, 10 Oct 2026) */
    }
}
@media only screen and (max-width: 900px) { .content-slider .slider-wrapper > * { flex-basis: calc(100% / 5); } }
@media only screen and (max-width: 560px) { .content-slider .slider-wrapper > * { flex-basis: calc(100% / 3); } }

/* ==========================================================================
   TESTIMONIAL — deep-red pull quote + advisor photo   (visual only)
   ==========================================================================
   Cornerstone design: a large deep-red serif quote on the left, an advisor
   photo filling the right. Big decorative quote mark; red attribution.

   Build: element_group `row testimonial` →
       text  `col-1-2`  (blockquote: quote <p> + `.cite` attribution <p>, then a.btn)
       image `col-1-2`  (advisor photo — fills the column)
   ========================================================================== */
.testimonial {
    --quote-red: #93191D;
    /* Penpot red-700; layout = .testimonial-band (home.css) */

    blockquote { position: relative; margin: 0; }

    /* The quote at the board's 45px / 600 (in proportion below 2400). Its marks
       are drawn, not typed into the copy, in the same type and size as the
       text; the opening one hangs outside the text's left edge so every line
       starts flush (Bob, 10 Oct 2026). */
    blockquote > p:first-of-type {
        position: relative;
        font-family: var(--type-display);
        font-weight: 600;
        font-size: clamp(1.5rem, 1.875vw, 2.8125rem);
        line-height: 1.4;
        color: var(--quote-red);
        margin: 0 0 1em;
    }
    blockquote > p:first-of-type::before {
        content: "\201C";
        position: absolute;
        right: 100%;
        padding-right: 0.08em;
    }
    blockquote > p:first-of-type::after { content: "\201D"; }
    blockquote .cite, blockquote > p:last-child {
        font-family: var(--type-body);
        font-weight: 600;
        font-size: 0.9rem;
        color: var(--quote-red);
        margin: 0;
    }
    blockquote strong { font-weight: 700; }

    a.btn { margin-top: 1.5rem; margin-bottom: 0; }
}

/* ==========================================================================
   CALLOUT — a dark navy feature card   (visual only)
   ==========================================================================
   A self-contained dark card for a highlighted message (e.g. the SECURE 2.0
   box): eyebrow, optional oversized numeral, heading, body, and links.

   Build: element_group `callout` (usually a `col-1-2` inside a `row`) → a
   `text` element:
        <p class="eyebrow on-dark">SECURE 2.0</p>
        <h2 class="numeral">2.0</h2>
        <h3>The small-plan market is booming…</h3>
        <p>SECURE 2.0 incentives and state mandates…</p>
        <p><a href="…">Download the flyer (PDF)</a></p>

   Colours come from --ink; text/heading are forced white here.
   ========================================================================== */
.callout {
    background: var(--ink);
    color: rgba(255, 255, 255, 0.82);
    padding: clamp(24px, 3vw, 44px);
    border-radius: 8px;
    height: 100%;

    .eyebrow.on-dark { margin-bottom: 0.6em; }

    /* Oversized brand numeral (echoes the eyebrow). `.numeral` is authored on the
       heading, so it survives the editor; falls back to a plain h2 if stripped. */
    .numeral, h2 {
        font-family: var(--type-display);
        font-size: clamp(2.5rem, 6vw, 4rem);
        line-height: 0.95;
        color: var(--white);
        margin: 0 0 0.15em;
    }
    h3 {
        color: var(--white);
        font-size: clamp(1.25rem, 2.2vw, 1.6rem);
        line-height: 1.2;
        margin: 0 0 0.6em;
    }
    p { color: var(--text-on-dark-dim); }

    a {
        color: var(--white);
        text-decoration: underline;
        text-underline-offset: 3px;
    }
    a:hover { text-decoration-thickness: 2px; }
}

/* ---- Outline variant — a light bordered "deliverable" card -------------- */
/* White fill, 1px prime border, square corners: a quiet card for a short
   promise (Plan Administration "what reaches you"). Literata heading + grey
   body. Stack two or more and they space themselves. */
.callout--outline {
    background: #ffffff;
    color: var(--body);
    border: 1px solid var(--prime);
    border-radius: 10px;   /* rounded like the site's other cards (John, 8 Oct) */
    height: auto;
    padding: clamp(20px, 2.4vw, 28px) clamp(22px, 2.6vw, 30px);
    + .callout--outline { margin-top: clamp(16px, 1.8vw, 20px); }
    h3 {
        font-family: var(--type-display);
        font-weight: 500;                 /* the boards' outline cards: 27px / 500 */
        color: var(--heading);
        font-size: clamp(1.3rem, 1.9vw, 1.6875rem);   /* ~27px */
        line-height: 1.2;
        margin: 0 0 0.4em;
    }
    p {
        color: var(--body);
        font-size: clamp(0.9rem, 1.05vw, 0.9375rem);   /* ~15px */
        line-height: 1.5;
        margin: 0;
    }
}

/* ==========================================================================
   CTA BAND — full-width closing call-to-action   (visual only)
   ==========================================================================
   A centred heading + sub + button on a full-width brand band.

   Build: an ARTICLE (or element_group) carrying `cta-band bleed-x bg-navy`
   with three text/link children:
        <h2>It takes one conversation…</h2>       (text)
        <p>No pitch decks. No obligation…</p>      (text)
        <a class="btn">Start a Conversation</a>     (in a text element)

   `bleed-x bg-navy` spans the viewport and paints the band; this file only
   handles the centred, capped content. Heading white comes from the bg-navy
   heading rule in website.css.
   ========================================================================== */
.cta-band {
    --cta-max: calc(1200px + 2 * var(--page-gutter));
    padding-block: clamp(48px, 5.5vw, 88px);   /* every board: 88, not the 96 section rhythm */
    text-align: center;
    /* The content element (text) caps and centres; the heading and copy fill that
       width rather than carrying their own max-widths. The cap is a DIAL because
       the boards do not use one value.

       MEASURED (24 Sep) — the `cta inner` board is **1200 wide at x600** on Plan
       Administration, For CPAs, Advisor Partnership, Case Studies and What We Do,
       and 1156 on Complex Plan Design. That is 66.7% of the 1800 container, not the
       50% this was capped at, which is exactly why John reported the band as too
       narrow on four separate pages. Switching is a deliberate outlier at 900 (its
       H2 is set to wrap onto two lines at 760) and sets its own value.

       Rhythm, identical on every board: 88px of section padding, H2 fs45 centred,
       24px from the H2's descender to whatever follows, 24px from a sub-line to the
       button, button 197x46. */
    /* The board's 1200 is the CONTENT width, and this element also carries
       `padding-inline: var(--page-gutter)` from `.band > *` — so the cap has to add
       the gutter back or the text lands 1088 wide at a 1400 viewport. Same
       `calc(Npx + 2 * gutter)` convention as contact.css and why-cornerstone.css. */
    > * {
        max-width: var(--cta-max);
        margin-inline: auto;
    }
    h2 {
        margin-top: 0;
        margin-bottom: 24px;          /* board: H2 descender -> next element */
    }
    p {
        color: var(--text-on-dark-dim);
        margin-bottom: 24px;          /* board: sub-line -> button */
    }
    a.btn { margin-top: 0; margin-bottom: 0; }
    p:last-child { margin-bottom: 0; }   /* the button's own <p>: the band's padding is the only space below it */

    /* On the blue band the button is a white pill with navy text; red on hover. */
    a.btn, a.btn:link {
        background-color: var(--white);
        color: var(--prime);
    }
    a.btn:hover { background-color: var(--second); color: var(--white); }
}

/* ==========================================================================
   FEATURE COLUMNS — icon (left) + heading + body, rule-divided  (visual only)
   ==========================================================================
   A row of equal columns, each led by a Font Awesome icon to the LEFT of the
   text, separated by hairline rules, with a rule UNDER the row. Works on light
   or dark bands (rule/icon colour follows the band).

   Build: element_group `row feature-cols` with N children `col-1-3`, each a
   `text` element shaped icon-left:
       <i class="fa-light fa-gear-complex-code"></i>
       <div class="ft"><h3>We do the complex work.</h3><p>Targeted cash…</p></div>
   ========================================================================== */
/* ---- The rules are INSET pseudo-elements, not borders ------------------- */
/* This group is a DIRECT child of a `.band` article, and `.band > *` supplies
   `padding-inline: var(--page-gutter)`. A border-top/bottom therefore paints
   across that padding and runs a full gutter (56px at 1400) past the text on
   BOTH sides — which is what John reported on Advisor Partnership's "What you
   can expect. Every time." and on Case Studies. Every board draws these rules
   at exactly x300–2100, i.e. exactly the 1800 container, so the design never
   overshoots; this was ours.

   `--rule-inset` is the dial, defaulting to the page gutter because that is the
   padding a band child carries. Used somewhere with no gutter padding, set
   `--rule-inset: 0` on the group or any ancestor. Same fix already applied to `.hero__intro`, `.hero__frame` and
   `.stats`. */
.feature-cols {
    --fc-rule: var(--hairline);
    --fc-rule-gap: clamp(1.4rem, 2.6vw, 2.3125rem);   /* rule -> content, 37px */
    position: relative;
    margin-top: clamp(1.75rem, 4vw, 3.5rem);       /* more gap below the heading */
    padding-bottom: clamp(1.5rem, 3vw, 2.25rem);
    align-items: stretch;
    &::before, &::after {
        content: "";
        position: absolute;
        left: var(--rule-inset, var(--page-gutter));
        right: var(--rule-inset, var(--page-gutter));
        height: 0;
        border-top: 1px solid var(--fc-rule);
        pointer-events: none;
    }
    &::before { content: none; top: 0; }
    /* opted into by --top */
    &::after { bottom: 0; }
    /* the rule under the row */
    > * + * {
        border-left: 1px solid var(--fc-rule);
        padding-left: clamp(1.25rem, 2.5vw, 2rem);
    }

    /* icon-left layout: the rich-text wrapper becomes the flex row. */
    .rte { display: flex; gap: 1rem; align-items: flex-start; }
    .ft { flex: 1 1 auto; min-width: 0; }
    i, .svg-inline--fa {
        flex: 0 0 auto;
        font-size: clamp(2.1rem, 2.6vw, 3.875rem);   /* the boards' icons are 62px */
        line-height: 1;
        color: var(--second);
        margin-top: 0.15rem;
    }
    h3 { margin: 0 0 0.5em; }   /* the base h3: 27px / 500, as the boards set it */
    p { margin: 0; }
}

/* On a dark band: light rules, white icons, muted body. */
:is(.bg-ink, .bg-dark, .bg-prime) .feature-cols { --fc-rule: var(--hairline-on-dark); }
.bg-ink .feature-cols i,   .bg-ink .feature-cols .svg-inline--fa,
.bg-dark .feature-cols i,  .bg-dark .feature-cols .svg-inline--fa,
.bg-prime .feature-cols i, .bg-prime .feature-cols .svg-inline--fa { color: var(--white); opacity: 0.92; }
.bg-ink .feature-cols p,
.bg-dark .feature-cols p,
.bg-prime .feature-cols p { color: var(--text-on-dark-dim); }

/* ---- Headings sub-variant (no icon, big Literata heading, no bottom rule) */
/* For a "value" grid where the heading IS the feature (e.g. For CPAs "The value
   has to make sense"). Keeps the vertical dividers + dark-band treatment; drops
   the icon flex-row and the bottom rule. Use `feature-cols feature-cols--headings`
   with `col-1-4` children that are just <h3> + <p> (no <i>, no .ft). */
.feature-cols--headings {
    padding-bottom: 0;
    &::after { content: none; }
    .rte { display: block; }
    h3 {
        font-family: var(--type-display);
        font-size: clamp(1.2rem, 1.8vw, 1.6875rem);   /* 27px / 500 — the base h3 weight */
        line-height: 1.15;
        margin: 0 0 0.5em;
    }
}

/* ---- Rule-ABOVE sub-variant (stacked rows, rule over each row) ---------- */
/* For a multi-row grid where each row carries a full-width rule above it and
   none below (e.g. Advisor Partnership "What you can expect"). Pair with
   `--headings`; the base bottom rule is already dropped by `--headings`. */
/* Rhythm off the board (Advisor Partnership "What you can expect. Every time.",
   Service standards y1082-1669): heading descender -> first rule 48px, then
   rule -> items 37px, and items -> the NEXT row's rule 48px again. The two 48s
   are the same gap, which is why one margin-top serves both. The clamp maxima
   land on those numbers at >=1400. */
.feature-cols--top {
    padding-top: var(--fc-rule-gap);
    margin-top: clamp(1.75rem, 3.4vw, 3rem);        /* 48px */
    &::before { content: ""; }
}
/* The section heading brings its own margin-bottom, which stacked on top of
   that 48px and pushed the first rule down. The board measures 48 from the
   descender to the rule, full stop. */
.content-text:has(+ .feature-cols--top) :is(h2, h3):last-child { margin-bottom: 0; }

/* ---- Rule-BELOW sub-variant (closes a stacked grid with a bottom rule) --- */
/* For the last row of a multi-row grid that carries a full-width rule under it
   (e.g. Complex Plan Design "The designs that need an actuary"). On the
   difference band the base bottom rule is stripped, so restore it here with a
   selector specific enough to win. */
.feature-cols--btm,
.difference .feature-cols.feature-cols--btm {
    padding-bottom: var(--fc-rule-gap);   /* the same space as above a rule */
}
.feature-cols--btm::after,
.difference .feature-cols.feature-cols--btm::after { content: ""; }

/* The dividers are the columns' left borders, so they are as tall as the tallest
   column. Where a board draws them taller than the text, a page sets
   `--fc-rule-h` (the board's height, in vw of the 2400 board, capped at it) on
   the row. Only while the columns sit side by side. */
@media only screen and (min-width: 601px) {
    .feature-cols > * { min-height: var(--fc-rule-h, 0); }
}

/* The dividers track framework_v3's step-down (3/4-up -> 2-up at 992 -> 1-up
   at 600), as stats.css does: at 2-up the cell that starts a line loses its
   divider; stacked, a rule runs between the cells instead, with the same
   space above and below it. */
@media only screen and (max-width: 992px) {
    .feature-cols > :is(.col-1-3, .col-30, .col-1-4, .col-1-2):nth-child(odd) { border-left: 0; padding-left: 0; }
}
@media only screen and (max-width: 600px) {
    .feature-cols { row-gap: 0; }
    .feature-cols > * + * {
        border-left: 0;
        padding-left: 0;
        border-top: 1px solid var(--fc-rule);
        margin-top: var(--fc-rule-gap);
        padding-top: var(--fc-rule-gap);
    }
}

/* ==========================================================================
   DECOR — soft background blobs for sections   (visual only)
   ==========================================================================
   Reusable decorative gradient blobs, echoing the hero. Add `decor` (sets the
   clip + stacking context) plus a variant on a section/article/group:
     .decor-cyan   one soft cyan blob, top-left (light sections, e.g. quote)
     .decor-red    a soft red wash off the right edge
   The hero draws its own blobs; this is for the other sections.
   ========================================================================== */
.decor {
    position: relative; overflow: clip; isolation: isolate;
    > * { position: relative; z-index: 1; }
    &::before, &::after { content: ""; position: absolute; z-index: 0; pointer-events: none; border-radius: 50%; }
}


/* Light section: a single soft cyan blob off the LEFT, vertically centred on
   the section and slowly drifting. Centred rather than pinned to the top so it
   sits behind the content on a tall row instead of hugging the corner.

   `translate` rather than `transform: translateY(-50%)`, so the centring
   composes with the drift animation's `transform` instead of being
   overwritten by it. */
.decor-cyan::before {
    left: -14%;
    top: 50%;
    translate: 0 -50%;
    width: 44vw; height: 38vw; max-width: 760px; max-height: 650px;
    background: radial-gradient(closest-side, var(--blob-cyan) 0%, transparent 78%);
    opacity: 0.55;
    animation: cyanDrift 42s ease-in-out -9s infinite;
}
@keyframes cyanDrift {
    0%   { transform: translate(0, 0) scale(1); }
    33%  { transform: translate(5%, -6%) scale(1.09); }
    66%  { transform: translate(-4%, 5%) scale(0.94); }
    100% { transform: translate(0, 0) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
    .decor-cyan::before { animation: none; }
}

/* Light section: a soft red/pink wash bleeding off the RIGHT edge.
   Measured off the Home board's SECURE 2.0 column (the light half of the split
   band): an ellipse 1326 x 768, radial `#ecb9b9` at offset 0.07 fading to the
   band's own `#fbfaf9` at offset 1, start (0.5, 0.5) to end (0.5, 1) so the
   radius is half the height. Against the 1200-wide half it sits left 42% and
   1320 wide, i.e. it hangs 624 (52% of the half) off the right edge and is
   vertically centred on the section.

   Those proportions are the defaults below, exposed as dials because the same
   motif appears on full-width bands too (Complex Plan Design's "Built to hold
   up", Consulting & Actuarial's "Actuaries on staff"), where the section is
   1800 rather than 1200 and the wash wants to be correspondingly smaller a
   share of it. `--decor-red-w` is its width as a share of the section and
   `--decor-red-out` how far it hangs off the right.

   The gradient ends at `transparent`, not at the band colour: fading to
   transparent is visually identical over any light band and does not paint an
   opaque rectangle over whatever is behind it. */
.decor-red {
    --decor-red-w: 110%;
    --decor-red-out: -52%;
    --decor-red-strength: 1;
    &::before {
        right: var(--decor-red-out);
        top: 50%;
        translate: 0 -50%;
        width: var(--decor-red-w);
        height: auto;
        aspect-ratio: 1326 / 768;
        background: radial-gradient(closest-side, var(--blob-pink) 7%, transparent 100%);
        opacity: var(--decor-red-strength);
    }
}

/* ---- Swirl decor (shared dark "difference" band) ------------------------ */
/* Two large organic swirl arcs bleeding off a dark band's lower corners, drawn
   from the shared brand SVGs. Add `decor decor-swirls` to a `.bg-ink`/
   `.bg-dark` band. `.decor` supplies the clip + stacking context.

   ⚠ THE PENPOT SVG EXPORTS ARE MOSTLY EMPTY CANVAS. Measured by rasterising
   each file and scanning for non-transparent pixels:

     swirl-shape.svg    art fills 30.5% × 49%   of the canvas, centred
     swirl-shape-2.svg  art fills 51%   × 54.5% of the canvas, centred

   So `background-size: contain` drew the arc at a THIRD of the box and the
   rest as transparent padding — which is why these read as "missing" on every
   band that asked for them, not just the one that got reported. The file is
   fine; the canvas is padded. `background-size` now scales each file until its
   art exactly fills the element (100 / 30.5 = 328%, 100 / 51 = 196%), and
   because the art is centred in its canvas, `center` is all the positioning
   that is needed. The element's own box therefore IS the arc: its width and
   aspect-ratio are the arc's, straight off the board.

   PLACEMENT IS BY EYE, not off the board. The two exported files don't
   correspond 1:1 to the board's swirl groups — their ids trace back to the
   Home board, and each group carries a rotation in its clip-path that the flat
   export doesn't preserve — so reproducing the board's coordinates put the arc
   98% off the left edge. What the comp shows is the impression: one large arc
   bleeding off the LOWER LEFT and one off the LOWER RIGHT, each roughly a
   third of the band wide, cut off by the band's bottom edge. That is what
   these values draw. (Earlier they were hung off the TOP corners, which is
   wrong in any reading of the comp.)

   Recolouring is not needed and not possible from here: each file carries its
   own paint (a #135380 → #00335c gradient at 37% opacity, clipped to the arc).
   Do NOT reach for `mask-image` to tint them — masking a box this size while
   animating it froze the renderer outright. */
.decor-swirls {
    /* The arc alone carries the SVG's own 37% opacity, which over #04203F is
    a ~6-point lift — real, but close to invisible on a compressed screen.
    A soft radial bloom sits UNDER each arc to lift its corner the way the
    comp does, and this is the dial for both: raise it to make the swirls
    more present, set it to `transparent` for the arc on its own.
    ⚠ The bloom MUST fade to transparent inside its own box:
    `farthest-side … transparent 78%` at `100% 100%`. With `closest-side` at
    `150% 150%` the transparent point falls beyond the element's edge, the
    rectangle cuts the fade off, and because these pseudo-elements carry
    `border-radius: 0` for the arc you get a hard-edged lighter rectangle on
    the navy band — visible as a "background" that is the bloom's box, not the
    swirl. */
    --swirl-bloom: rgba(255, 255, 255, 0.10);
    &::before, &::after {
        content: "";
        position: absolute;
        z-index: 0;
        pointer-events: none;
        border-radius: 0;              /* .decor::before/::after default to 50% */
        background-repeat: no-repeat;
        background-position: center;
    }
    &::before {
        left: -12%;
        bottom: -12%;
        width: 34%;
        aspect-ratio: 417 / 670;
        background-image:
            url("/files/structure/images/swirl-shape.svg"),
            radial-gradient(farthest-side, var(--swirl-bloom) 0%, transparent 78%);
        background-size: 328% auto, 100% 100%;
    }
    &::after {
        left: 74%;
        bottom: -12%;
        width: 34%;
        aspect-ratio: 698 / 746;
        background-image:
            url("/files/structure/images/swirl-shape-2.svg"),
            radial-gradient(farthest-side, var(--swirl-bloom) 0%, transparent 78%);
        background-size: 196% auto, 100% 100%;
    }
}
/* The swirls stand still: they used to turn and drift (Bob, 10 Oct 2026: "stop
   spinning backgrounds"). */


/* ==========================================================================
   SPLIT BAND — full-width two-colour split   (visual only)
   ==========================================================================
   A viewport-wide band divided into two halves, each a solid colour, with the
   inner content aligned to the page column. Cornerstone home: dark navy left
   (icon + heading + body + accent CTA), light right (big numeral + eyebrow +
   heading + body + CTA + links).

   Build: element_group `split-band` with exactly TWO `text` children
   (left, then right). No col-* — the grid handles the halves.
     left  : <i class="fa-light fa-user-plus"></i><h2>…</h2><p>…</p><p><a class="btn">…</a></p>
     right : <h2 class="numeral">2.0</h2><p class="eyebrow">SECURE 2.0</p><h3>…</h3><p>…</p>…
   ========================================================================== */
/* The article carries framework `.bleed-full`; this grid splits it edge-to-edge
   and aligns each half's content to the page column. */
.split-band {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 100%;
    /* Outer padding aligns inner content to the page container; inner padding is
       the gap between the two halves. */
    > * {
        padding-block: clamp(40px, 5vw, 72px);
        box-sizing: border-box;
    }
    > *:first-child {
        background: var(--ink);
        color: rgba(255, 255, 255, 0.85);
        padding-left: max(var(--page-gutter), calc(50vw - var(--container-max) / 2 + var(--page-gutter)));
        padding-right: clamp(24px, 4vw, 60px);
    }
    > *:last-child {
        background: #FBFAF9;
        padding-right: max(var(--page-gutter), calc(50vw - var(--container-max) / 2 + var(--page-gutter)));
        padding-left: clamp(24px, 4vw, 60px);
        /* The board hangs a soft red wash off this half's right edge (see
           `.decor-red` in decor.css for the measurement). Clipped and isolated
           here rather than by adding `.decor` in the spec, because this half is a
           grid item whose background is part of the component. */
        position: relative;
        overflow: clip;
        isolation: isolate;
    }
    > *:last-child > * { position: relative; z-index: 1; }
    > *:last-child::before {
        content: "";
        position: absolute;
        z-index: 0;
        pointer-events: none;
        right: -52%;
        top: 50%;
        translate: 0 -50%;
        width: 110%;
        aspect-ratio: 1326 / 768;
        border-radius: 50%;
        background: radial-gradient(closest-side, var(--blob-pink) 7%, transparent 100%);
    }

    /* Icon / numeral sit inline to the LEFT of the copy (like the feature columns). */
    > * .rte { display: flex; gap: clamp(16px, 1.8vw, 28px); align-items: flex-start; }
    > * .ft { flex: 1 1 auto; min-width: 0; }

    /* ---- Left (dark) -------------------------------------------------------- */
    > *:first-child i, > *:first-child .svg-inline--fa {
        flex: 0 0 auto;
        font-size: 2.3rem; line-height: 1;
        color: var(--white); opacity: 0.92;
        margin-top: 0.15rem;
    }
    > *:first-child h2 {
        color: var(--white);
        font-size: var(--fs-h2);                     /* the boards: the 45px section heading */
        line-height: 1.2; margin: 0 0 0.7em;
    }
    > *:first-child p { color: var(--text-on-dark-dim); }
    > *:first-child a.btn { margin-bottom: 0; }

    /* ---- Right (light) ------------------------------------------------------ */
    /* Big red numeral sits inline to the left of the copy. */
    > *:last-child .numeral {
        flex: 0 0 auto;
        font-family: var(--type-display);
        font-weight: 700;
        font-size: clamp(2.75rem, 5.5vw, 3.75rem);   /* Penpot 60px */
        line-height: 0.85;
        color: #93191D;                              /* Penpot red-700 */
    }
    > *:last-child .eyebrow { margin: 0 0 0.4em; }
    > *:last-child .eyebrow::before { content: ""; }
    > *:last-child h3 {
        color: var(--heading);
        font-weight: 700;                 /* the board's "small-plan market" heading */
        font-size: var(--fs-h2);          /* 45, set as an h3 */
        line-height: 1.2; margin: 0 0 0.6em;
    }
    > *:last-child a.btn { margin-bottom: 0.5rem; }
}
.split-band__links a,
.split-band > *:last-child p:last-child a {
    color: var(--prime);
    font-weight: 600;
    text-decoration: underline;
    text-underline-offset: 3px;
    border-bottom: 0;          /* the site's link border drew a second underline (Bob, 10 Oct 2026) */
    margin-right: 1.25rem;
}

/* Home: the board's padding (Bob, 10 Oct 2026), in proportion below 2400 —
   ~110px above and below each half's copy, 95px between the light half's edge
   and its numeral. */
body.page-index .split-band > * { padding-block: clamp(48px, 4.583vw, 110px); }
@media only screen and (min-width: 761px) {
    body.page-index .split-band > *:last-child { padding-left: clamp(24px, 3.958vw, 95px); }
}

@media only screen and (max-width: 760px) {
    .split-band { grid-template-columns: 1fr; }
    .split-band > * { padding-inline: var(--page-gutter); }
}

/* ==========================================================================
   HOME   body.page-index
   ==========================================================================
   Sections by id: #difference (the dark band), #testimonial. Site asset paths
   (files/content/home/*) live here, not in component files.
   ========================================================================== */

/* The dark band: the board's 80px above the copy and 55px under the closing
   rule, 84px under "A partner built for advisors…", 296px column dividers,
   balanced feature copy. The swirls are black SVG paths that read as darker
   navy; `.decor` supplies the clip and stacking. */
#difference {
    padding-block: clamp(48px, 3.333vw, 80px) clamp(36px, 2.292vw, 55px);
    .content-text:has(+ .feature-cols) { margin-bottom: clamp(2.5rem, 3.5vw, 5.25rem); }
    .content-text:has(+ .feature-cols) h2 { margin-bottom: 0; }
    .feature-cols { --fc-rule-h: min(12.333vw, 296px); }
    .feature-cols :is(h3, p) { text-wrap: balance; }

    &::before, &::after {
        content: "";
        position: absolute;
        z-index: 0;
        pointer-events: none;
        background-repeat: no-repeat;
        background-size: contain;
        background-position: center;
        opacity: 1;
    }
    &::before {
        top: -22%; left: -20%;
        width: 46vw; height: 46vw; max-width: 720px; max-height: 720px;
        background-image: url("/files/content/home/swirl.svg");
    }
    &::after {
        top: -16%; right: -16%;
        width: 48vw; height: 48vw; max-width: 760px; max-height: 760px;
        background-image: url("/files/content/home/swirl-2.svg");
    }
}

/* Testimonial: a full-bleed split; the copy aligns to the container column */
#testimonial .testimonial {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 100%;
    align-items: center;

    > *:first-child {
        padding-block: clamp(40px, 5vw, 72px);
        padding-left: max(var(--page-gutter), calc(50vw - var(--container-max) / 2 + var(--page-gutter)));
        padding-right: clamp(24px, 4vw, 60px);
    }
    > *:last-child { align-self: stretch; }

    figure { margin: 0; height: 100%; }
    img { display: block; width: 100%; height: 100%; min-height: 440px; object-fit: cover; }

    blockquote {
        margin: 0;
        p + p.cite { margin-top: 1.1rem; }
        & + p { margin: clamp(1.75rem, 3vw, 2.5rem) 0 0; }
    }
    a.btn { margin-bottom: 0; }
}
@media only screen and (max-width: 760px) {
    #testimonial .testimonial {
        grid-template-columns: 1fr;
        > *:first-child { padding-inline: var(--page-gutter); }
        img { min-height: 280px; }
    }
}

/* The composed user+plus icon (the Penpot group, not a Font Awesome name),
   drawn as a mask so it takes `color` like the fa-light icons */
.cs-icon {
    display: inline-block;
    flex: 0 0 auto;
    width: 1em;
    height: 1em;
    background-color: currentColor;
    -webkit-mask: var(--cs-icon) center / contain no-repeat;
            mask: var(--cs-icon) center / contain no-repeat;
}
.cs-icon--user-plus { --cs-icon: url("/files/content/home/icon-user-plus.svg"); }
.split-band > *:first-child .cs-icon {
    width: clamp(56px, 6.2vw, 89px);
    height: clamp(56px, 6.2vw, 89px);
    margin-top: 0.1rem;
}

/* ==========================================================================
   MEDIA SPLIT — content one side, full-bleed image the other  (visual only)
   ==========================================================================
   Generalises home.css's `.testimonial-band`: a viewport-wide split where the
   copy aligns to the page column on one side and a photo bleeds to the edge on
   the other. Works light or, with `bg-ink`, as a dark band (Cornerstone For
   Advisors → "Yes. We do the complex work.").

   Build: an ARTICLE carrying framework `.bleed-full`; inside, an element_group
   `media-split` (add `bg-ink` for the dark treatment) with exactly TWO children
   in visual order:
       text   — eyebrow + h2 + body + chips + a.btn        (the content half)
       image  — the photo                                   (bleeds to the edge)
   ========================================================================== */
.media-split {
    display: grid;
    grid-template-columns: 1fr 1fr;
    width: 100%;
    align-items: center;
    padding-inline: 0;   /* it sits in a .bleed-full article; drop the element_group gutter so both halves reach the viewport edge */
    /* Content half: padded out to the page column on the left, gap on the right. */
    > *:first-child {
        padding-block: clamp(48px, 6vw, 96px);
        padding-left: max(var(--page-gutter), calc(50vw - var(--container-max) / 2 + var(--page-gutter)));
        padding-right: clamp(24px, 4vw, 64px);
        box-sizing: border-box;
    }
    /* Image half: fills its cell edge-to-edge. */
    > *:last-child { align-self: stretch; }
    figure { margin: 0; height: 100%; }
    img {
        display: block;
        width: 100%; height: 100%;
        min-height: 460px;
        object-fit: cover;
    }

    /* ---- Dark treatment ----------------------------------------------------- */
    /* Drop the bg-* vertical padding so the photo fills the band top-to-bottom;
       the content half supplies its own padding-block. */
    &.bg-ink { padding-block: 0; }
    /* The content half deliberately has NO background of its own. `.bg-ink` on the
       group already paints the whole band, so an opaque `background: var(--ink)`
       here was redundant — and because `.decor > *` lifts both halves above the
       band's decorative pseudo-elements, that opaque panel sat on top of the
       swirls and hid them completely. Our Story's "Why Cornerstone exists." band
       asked for `decor decor-swirls` and appeared to ignore it for exactly this
       reason. Anything that needs a different colour behind the copy half should
       set it on the GROUP, not on this child. */
    &.bg-ink a.btn { margin-top: 0.5rem; margin-bottom: 0; }
}

@media only screen and (max-width: 760px) {
    .media-split { grid-template-columns: 1fr; }
    .media-split > *:first-child { padding-inline: var(--page-gutter); }
    .media-split img { min-height: 300px; }
}

/* ==========================================================================
   CHIPS — pill tags for a list of capabilities / topics   (visual only)
   ==========================================================================
   A wrapping row of outlined pills. Neutral by default; on a dark band the
   border/label lighten automatically.

   Build: a `<div class="chips">` with `<span class="chip">…</span>` children,
   placed inside a rich-text `text` element (e.g. the media-split content half).
   ========================================================================== */
.chips {
    display: flex;
    flex-wrap: wrap;
    gap: clamp(8px, 1vw, 14px);
    margin: clamp(1rem, 2vw, 1.75rem) 0;
}
.chip {
    display: inline-flex;
    align-items: center;
    padding: 12px 24px;
    border-radius: 999px;
    border: 1px solid var(--hairline);
    background: transparent;
    font-family: var(--type-body);
    font-weight: 600;
    font-size: 0.9375rem;
    line-height: 1;
    color: var(--heading);
}

/* On any dark band: subtle white fill + light border + muted label. */
.bg-ink .chip,
.bg-dark .chip,
.bg-prime .chip {
    background: #ffffff14;
    border-color: rgba(255, 255, 255, 0.28);
    color: var(--text-on-dark-dim);
}

/* ---- Muted variant (light capability list) ----------------------------- */
/* A quieter, denser pill for a long capability list on a light band: white
   fill, hairline border, grey body label, a touch smaller (Plan Administration
   "a lot goes on…"). */
.chips--muted { gap: clamp(7px, 0.9vw, 12px);
    .chip {
        background: #ffffff;
        border-color: var(--hairline);
        color: var(--body);
        font-weight: 400;             /* the boards' capability chips */
        font-size: 0.875rem;          /* 14px */
        padding: 9px 18px;
    }
}

/* ==========================================================================
   TESTIMONIAL GRID — avatar + short pull-quote, N-up   (visual only)
   ==========================================================================
   A centred row of client quotes, each led by a round initial-badge avatar,
   with a short deep-red serif quote below. Pairs with a centred section
   heading and a centred CTA (`.cta-center`).

   Build: element_group `row testimonial-grid` with N children `col-1-4`, each a
   `text` element:
       <span class="tavatar">RB</span>
       <blockquote><p>They tell it to you straight…</p></blockquote>
   ========================================================================== */
.testimonial-grid {
    margin-top: clamp(1.75rem, 3.5vw, 3.5rem);
    align-items: start;
    > * {
        display: flex;
        flex-direction: column;
        align-items: flex-start;
        text-align: left;
    }
}

/* Round initial badge. */
.tavatar {
    display: flex;
    align-items: center;
    justify-content: center;
    width: clamp(72px, 6.5vw, 110px);
    height: clamp(72px, 6.5vw, 110px);
    border-radius: 50%;
    background: var(--prime);
    color: var(--white);
    font-family: var(--type-display);
    font-weight: 700;
    font-size: clamp(1.5rem, 1.9vw, 2.8125rem);   /* 45px initials */
    line-height: 1;
    margin-bottom: clamp(1rem, 1.6vw, 1.5rem);
    margin-inline: auto;          /* centre the avatar; the quote below stays left-aligned */
}

.testimonial-grid {
    blockquote { margin: 0; }
    blockquote p {
        margin: 0;
        font-family: var(--type-display);
        font-weight: 400;
        font-size: clamp(1.25rem, 1.46vw, 2.1875rem);   /* the board: 35px / 400 */
        line-height: 1.3;
        color: var(--red-700);
    }
}

/* Centred CTA under a centred block (heading / grid). */
.cta-center { text-align: center; margin-top: clamp(1.5rem, 3vw, 2.75rem);
    a.btn { margin-bottom: 0; }
}

@media only screen and (max-width: 700px) {
    .testimonial-grid > * + * { margin-top: 2rem; }
}

/* ==========================================================================
   ORG COMPARE — two side-by-side diagrams (before / after)   (visual only)
   ==========================================================================
   A two-column comparison framed by a rule across the top and a hairline down
   the middle that runs the full height, to the next section. Cornerstone For
   Advisors: a chaotic phone-tree (left) vs a clean Concierge org chart (right).

   Build the diagram as an ARTICLE `band bg-cream oc-section` → element_group
   `org-compare` with two `text` children (left, right), each = <h3>Title</h3>
   [<p class="oc-sub">…</p>] then the `.oc-tree`.
   ========================================================================== */

/* Rebuilt 8 Oct from the board's own geometry (For Financial Advisors, "Most
   TPAs When you Call" / "Cornerstone"). Every size is in BOARD PIXELS through
   one unit, `--u`: a board px scaled to the column the tree sits in, so the
   boxes, gaps and connectors keep the board's proportions at any width (a
   container query unit: `cqi` = 1% of the tree's width).
     columns  left 300–1080 (780) │ 200 gap, the divider at its middle (x1180) │
              right 1280–2100 (820), on the 1800 content column
     title → first box 56; the phone tree 278 / 362 / 223 / 306 wide, 72 / 61
     tall, 3px red connectors; the Concierge 268×64, 342×78, four 186×68 boxes
     22 apart, a 4px spine in and 2px lines out (both navy on the board) */

/* The article: cream band. The centre rule runs through the bottom padding to
   meet the next (dark) section, as on the board. */
.band.oc-section { padding-top: var(--space-80); padding-bottom: 120px; }

.org-compare {
    position: relative;
    display: grid;
    grid-template-columns: 780fr 820fr;
    column-gap: 11.111%;                                /* 200 of 1800 */
    padding-top: clamp(2rem, 2.7vw, 4.0625rem);         /* rule → title: 65 */
    margin-top: 0;
    /* Top rule, inset to the page gutter (this group is a `.band` child, so
       `.band > *` pads it by the gutter). */
    &::before {
        content: "";
        position: absolute;
        top: 0;
        left: var(--rule-inset, var(--page-gutter));
        right: var(--rule-inset, var(--page-gutter));
        height: 0;
        border-top: 1px solid var(--hairline);
        pointer-events: none;
    }
    /* Centre rule: from the titles down through the bottom padding. */
    &::after {
        content: "";
        position: absolute;
        top: calc(clamp(2rem, 2.7vw, 4.0625rem) - 6px);
        bottom: -120px;
        left: calc(var(--page-gutter) + (100% - 2 * var(--page-gutter)) * 0.48889);   /* x1180 */
        border-left: 1px solid var(--hairline);
    }
    > * { container-type: inline-size; min-width: 0; }
    > *:first-child { --u: calc(100cqi / 780); }
    > *:last-child  { --u: calc(100cqi / 820); }

    h3 {
        font-family: var(--type-display);
        font-weight: 500;
        font-size: clamp(1.2rem, 1.9vw, 1.6875rem);     /* 27 */
        line-height: 1.25;
        color: var(--prime);
        text-align: center;
        margin: 0 0 calc(56 * var(--u));
    }
    /* "You never have to navigate the org chart.": 24 under the title, 35 above the tree */
    h3:has(+ .oc-sub) { margin-bottom: calc(24 * var(--u)); }
    .oc-sub { text-align: center; color: #333B44; margin: 0 0 calc(35 * var(--u)); font-size: clamp(0.95rem, 0.8vw + 0.3rem, 1.1875rem); }
    .oc-note {
        display: block; text-align: center;
        color: var(--heading); font-weight: 500;
        font-size: clamp(0.75rem, calc(13 * var(--u)), 0.8125rem);
        margin-top: calc(37 * var(--u));
    }
}

/* ---- The trees ------------------------------------------------------------ */
.oc-tree { display: flex; flex-direction: column; align-items: center; }
.oc-tree--red { color: var(--red-700); --oc-w: max(2px, calc(3 * var(--u))); }
.oc-tree--navy { color: #083C6F; --oc-w: max(1.5px, calc(2 * var(--u))); }

.oc-box {
    display: flex; align-items: center; justify-content: center;
    text-align: center;
    box-sizing: border-box;
    padding: calc(6 * var(--u)) calc(10 * var(--u));
    border-radius: 8px;
    font-family: var(--type-body);
    font-weight: 500;
    line-height: 1.2;
    flex: none;
    hyphens: auto; overflow-wrap: anywhere;   /* "administration" in a phone-width box */
}
/* Phone tree: white boxes, a 12-on / 10-off dashed red outline (a CSS dashed
   border can't set its dash, so the outline is drawn) */
.oc-box--dash {
    color: #083C6F; background-color: #fff;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100%25' height='100%25'%3E%3Crect width='100%25' height='100%25' fill='none' rx='8' ry='8' stroke='%2393191D' stroke-width='3' stroke-dasharray='12 10'/%3E%3C/svg%3E");
    font-size: clamp(0.75rem, calc(18 * var(--u)), 1.125rem);     /* 18 */
    width: calc(223 * var(--u)); min-height: calc(61 * var(--u));
}
.oc-tree--red > .oc-box:first-child { width: calc(278 * var(--u)); min-height: calc(72 * var(--u)); }       /* Advisor */
.oc-tree--red > .oc-link + .oc-box { width: calc(362 * var(--u)); min-height: calc(72 * var(--u)); }        /* Automated menu */
.oc-tree--red .oc-branch > :nth-child(2) > .oc-box:last-child { width: calc(306 * var(--u)); }             /* Transferred again */

/* Concierge: the pink "needing support" node, the navy Concierge, four outlined services */
.oc-tree--navy .oc-box { font-size: clamp(0.75rem, calc(16 * var(--u)), 1rem); color: #1F262D; }    /* 16 */
.oc-box--rose {
    background: radial-gradient(farthest-corner at 50% 50%, #FF8D8D 0%, #FBBAB9 100%);
    width: calc(268 * var(--u)); min-height: calc(64 * var(--u));
}
.oc-tree--navy .oc-box--nav {
    background: var(--prime); color: #fff; font-weight: 600;
    width: calc(342 * var(--u)); min-height: calc(78 * var(--u));
}
.oc-box--line {
    background: #fff; border: max(1px, calc(1.22 * var(--u))) solid var(--prime);
    width: calc(186 * var(--u)); min-height: calc(68 * var(--u));
}

/* The connector between the two top boxes: the phone tree's 39, the
   Concierge's 4px spine IN (49). The stem down to the branch is the branch's. */
.oc-link { width: 0; height: calc(39 * var(--u)); border-left: var(--oc-w) solid currentColor; }
.oc-tree--navy > .oc-link { height: calc(49 * var(--u)); border-left: max(2px, calc(4 * var(--u))) solid #0A417C; }

/* Branch: a bus from the first column's centre to the last's, a drop into each */
.oc-branch {
    --col: 223; --gap: 55; --drop: 28; --stem: 30;
    position: relative; display: flex; justify-content: center; align-items: flex-start;
    gap: calc(var(--gap) * var(--u));
    margin-top: calc(var(--stem) * var(--u));
    padding-top: calc(var(--drop) * var(--u));
}
.oc-tree--navy .oc-branch { --col: 186; --gap: 22; --drop: 32; --stem: 44; }
/* the stem from the box above down to the bus */
.oc-branch::after {
    content: ""; position: absolute; left: 50%; transform: translateX(-50%);
    top: calc(-1 * var(--stem) * var(--u)); height: calc(var(--stem) * var(--u));
    border-left: var(--oc-w) solid currentColor;
}
.oc-branch::before {
    content: ""; position: absolute; top: 0;
    left: calc(var(--col) / 2 * var(--u)); right: calc(var(--col) / 2 * var(--u));
    border-top: var(--oc-w) solid currentColor;
}
.oc-branch > * { position: relative; flex: none; width: calc(var(--col) * var(--u)); display: flex; flex-direction: column; align-items: center;
    &::before {
        content: ""; position: absolute; top: calc(-1 * var(--drop) * var(--u)); left: 50%;
        height: calc(var(--drop) * var(--u)); border-left: var(--oc-w) solid currentColor; transform: translateX(-50%);
    }
}
.oc-drop { width: 0; height: calc(31 * var(--u)); border-left: var(--oc-w) solid currentColor; margin: 0 auto; }

/* ---- Narrow: stack the two sides; drop the centre rule ------------------- */
@media only screen and (max-width: 760px) {
    .org-compare { grid-template-columns: 1fr; row-gap: 2.5rem; }
    .org-compare::after { display: none; }
    .org-compare > *:first-child { border-bottom: 1px solid var(--hairline); padding-bottom: 2.5rem; }
    /* a phone is narrower than either tree: the unit stops shrinking at 0.42 of
       the board, and the boxes' text wraps inside them */
    .org-compare > *:first-child { --u: max(calc(100cqi / 780), 0.42px); }
    .org-compare > *:last-child  { --u: max(calc(100cqi / 820), 0.42px); }
}

/* ---- Scroll-in reveal ----------------------------------------------------
   The design's note: "on scroll-in the phone tree draws first, then collapses
   into the Concierge model. One loop, then rest. Both sides stay visible if
   motion is cut."

   So the LEFT column draws node by node, top to bottom, the way you would
   actually walk a phone tree — each node and its connector arriving in turn,
   which is what makes the length of it land. Only once the left has finished
   does the RIGHT column resolve, as a single quick settle rather than another
   node-by-node crawl: that contrast IS the point being made. One pass, no
   repeat, no reverse on scroll-up.

   Both directions keep the weights the design asks for — outbound stays the
   thin grey connector, inbound the single accent line — because this only
   animates opacity and position, never colour or width.

   Gated on `.js-reveal` (see fe_page.html.twig), so with JS off or reduced
   motion both columns render complete and static. */
.js-reveal {
    .org-compare :is(.oc-box, .oc-link, .oc-drop),
    .org-compare .oc-branch::before, .org-compare .oc-branch::after,
    .org-compare .oc-branch > *::before { opacity: 0; }
    .org-compare.is-in :is(.oc-box, .oc-link, .oc-drop),
    .org-compare.is-in .oc-branch::before, .org-compare.is-in .oc-branch::after,
    .org-compare.is-in .oc-branch > *::before { animation: ocReveal 0.45s ease both; }

    /* Left column — the phone tree, walked one level at a time. */
    .org-compare.is-in > *:first-child {
        .oc-tree > .oc-box:first-child { animation-delay: 0.05s; }
        .oc-tree > .oc-link, .oc-tree > .oc-link + .oc-box { animation-delay: 0.35s; }
        .oc-branch::after, .oc-branch::before, .oc-branch > *::before,
        .oc-branch > * > .oc-box:first-child { animation-delay: 0.65s; }
        .oc-branch > * > .oc-box:first-child ~ * { animation-delay: 0.95s; }
        .oc-branch > :nth-child(2) > :nth-last-child(-n + 2) { animation-delay: 1.25s; }   /* → Transferred again */
    }

    /* Right column — the Concierge model, AFTER the tree has finished, as one
       settle rather than a crawl. */
    .org-compare.is-in > *:last-child {
        :is(.oc-box, .oc-link, .oc-drop), .oc-branch::before, .oc-branch::after, .oc-branch > *::before {
            animation-duration: 0.6s; animation-delay: 1.6s;
        }
        .oc-box--nav { animation-delay: 1.75s; }
    }
}

@keyframes ocReveal {
    from { opacity: 0; transform: translateY(10px) scale(0.98); }
    to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   FOR FINANCIAL ADVISORS   body.page-for-financial-advisors
   ==========================================================================
   Section by id: #concierge. The hero H1 follows its column (no dial).
   ========================================================================== */

body.page-for-financial-advisors {
    .difference .feature-cols { --fc-rule-h: min(12.333vw, 296px); }   /* the board's 296px dividers */
}
/* The complex cases: text 60%, photo 40%; stacked below 760 */
@media only screen and (min-width: 761px) {
    body.page-for-financial-advisors .media-split { grid-template-columns: 3fr 2fr; }
}

/* Concierge intro: 45px H2 → button, and a soft red ellipse off the right edge
   (a page asset, so it lives here, not in decor.css) */
#concierge {
    position: relative;
    overflow: clip;
    isolation: isolate;
    > * { position: relative; z-index: 1; }
    .col-2-5 {
        h2 { margin-bottom: 45px; }
        p  { margin-top: 0; }
    }
    &::after {
        content: "";
        position: absolute;
        z-index: 0;
        pointer-events: none;
        right: -6%;
        top: 50%;
        transform: translateY(-50%);
        width: 46vw;
        max-width: 900px;
        aspect-ratio: 1814 / 1283;
        background: url("/files/content/for-financial-advisors/blob-red.svg") no-repeat center / contain;
    }
}
@media only screen and (max-width: 760px) {
    #concierge::after { opacity: 0.5; right: -20%; }
}

/* ==========================================================================
   DIFFERENCE BAND — the shared "why us" dark section   (visual only)
   ==========================================================================
   A dark navy band: an intro heading (optionally a two-column problem/answer)
   then a row of icon-led feature columns, over soft brand swirls. This is the
   SAME section on Home ("The Cornerstone difference") and For Advisors ("The
   problem"), and the service pages reuse it too — build it from here rather
   than re-inventing per page.

   Build (ARTICLE):
     class: `band bg-ink difference decor decor-swirls`
     ├ text  <h2>…</h2>                              (intro heading)
     └ element_group `row feature-cols`
         └ N × text  <i class="fa-light fa-…"></i><div class="ft"><h3>…</h3><p>…</p></div>

   `bg-ink` paints the band (the band's own padding is the site rhythm),
   `decor decor-swirls` (decor.css) adds the swirls, `feature-cols` lays out the
   icon columns. This file only tunes the shared bits.
   ========================================================================== */

/* No rule under the feature row on the difference band (the design has none). */
.difference {
    .feature-cols { padding-bottom: 0; margin-top: clamp(1.75rem, 3.5vw, 5.25rem); }   /* heading → row: 84 */
    .feature-cols::after { content: none; }

    /* Intro heading breathes above the columns. */
    > h2, > .content-text:first-child h2 { margin-bottom: 0; }
}

/* WHAT WE DO   body.page-what-we-do — everything else is a shared component */
body.page-what-we-do .hero__frame { --hero-frame-max: 59.0%; }   /* the board's 1062 of 1800 */

/* ==========================================================================
   STEPS — numbered process timeline   (visual only)
   ==========================================================================
   A horizontal connector line with numbered dots sitting on it; each dot has a
   heading + short body below. Cornerstone "How a referral works" (For CPAs) and
   the switching flow. Reads left-to-right on desktop; on narrow screens it
   folds to a vertical spine down the left with the dots on it.

   Build: element_group `steps` with N children `text.step`, each:
       <span class="step__dot">1</span><h3>Introduce us.</h3><p>A two-line email is plenty.</p>

   The connector is drawn per-step (each dot draws a segment to the next), so it
   aligns whether or not the container carries the page gutter.
   ========================================================================== */
.steps {
    --steps-gap: clamp(1.5rem, 3vw, 3rem);
    position: relative;
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    column-gap: var(--steps-gap);
    margin-top: clamp(1.75rem, 3.5vw, 2.75rem);
}

.step {
    position: relative;
    container-type: inline-size;       /* the heading sizes to its column */
    /* connector: from this dot's centre (21px = half of the 43px dot) across the
       gap to the next dot. The last step draws a short tail to the band edge. */
    &::before {
        content: "";
        position: absolute; z-index: 0;
        top: 21px; left: 21px;
        right: calc(-1 * var(--steps-gap));
        border-top: 1px solid var(--prime);
        pointer-events: none;
    }
    &:last-child::before { right: 0; }
}

.step__dot {
    display: flex; align-items: center; justify-content: center;
    width: 43px; height: 43px; border-radius: 50%;
    background: var(--prime); color: var(--white);
    font-family: var(--type-body); font-weight: 600;   /* every board: 20px / 600 */
    font-size: 1.25rem; line-height: 1;
    position: relative; z-index: 1;    /* over the connector line */
}
.step {
    h3 {
        font-family: var(--type-display);
        /* 27px / 500, smaller as the columns narrow, so a two-word heading
           doesn't break a word per line (Switching's five steps, Bob 13 Oct) */
        font-size: clamp(1.05rem, 10cqi, 1.6875rem);
        color: #11161B; line-height: 1.15;
        margin: clamp(1.2rem, 2.2vw, 1.6rem) 0 0.35em;
    }
    p {
        margin: 0; color: var(--body);
        font-size: clamp(0.875rem, 8.5cqi, 1.1875rem);    /* 19px, less in a narrow column */
        line-height: 1.5;
    }
}

/* On a dark band the heading + line flip to on-dark. */
.bg-ink .step::before, .bg-dark .step::before, .bg-prime .step::before { border-top-color: var(--hairline-on-dark); }
.bg-ink .step h3, .bg-dark .step h3, .bg-prime .step h3 { color: var(--white); }
.bg-ink .step p,  .bg-dark .step p,  .bg-prime .step p { color: rgba(255, 255, 255, 0.8); }

/* ---- Mobile: vertical spine on the left ------------------------------- */
@media only screen and (max-width: 700px) {
    .steps { grid-auto-flow: row; grid-auto-columns: auto; row-gap: var(--steps-gap); }
    .step { padding-left: 68px; min-height: 43px; }
    .step__dot { position: absolute; left: 0; top: 0; }
    .step::before {                 /* vertical connector down to the next dot */
        top: 21px; left: 21px; right: auto;
        bottom: calc(-1 * var(--steps-gap));
        width: 0; border-top: 0;
        border-left: 1px solid var(--prime);
    }
    .step:last-child::before { display: none; }
    .step h3 { margin-top: 0.15rem; font-size: 1.35rem; }
    .step p { font-size: 1.05rem; }
}

/* ---- Scroll-in: number, then text, then the line on to the next number ---
   The design reads the timeline left to right. Each step: its NUMBER fades in,
   then its heading and copy, then ITS connector draws rightward, and the
   moment that line arrives at the next dot, the next number fades in (John,
   8 Oct: "fade the number in first, then the text, then continue the line").
   One pass; no replay or reverse on scroll-up.

   The connector belongs to the step BEHIND it — `.step::before` runs from this
   dot's centre across the gap to the next dot — so step N's line starts after
   its number AND its text have faded in: `--step-in + 2 × fade`.

   Timing is three variables. `--step-pitch` is the beat from one number to
   the next and must equal 2 × fade + line, or the arrival drifts out of sync.

   Driven by `is-in` from fe_page.html.twig's observer and gated on
   `.js-reveal`, so with JS off or reduced motion every step renders complete
   and static. */
.js-reveal {
    .steps {
        --step-fade: 0.4s;
        --step-line: 0.35s;
        --step-pitch: 1.15s;          /* = number + text + line (John, 8 Oct) */
    }
    .steps .step__dot, .steps .step h3, .steps .step p { opacity: 0; }
    .steps .step::before {
        transform: scaleX(0);
        transform-origin: left center;
    }
    /* each step: the number fades in, then its text, then its line runs on to
       the next number (John, 8 Oct) */
    .steps.is-in .step__dot {
        animation: stepFadeIn var(--step-fade) ease both;
        animation-delay: var(--step-in);
    }
    .steps.is-in .step h3, .steps.is-in .step p {
        animation: stepFadeIn var(--step-fade) ease both;
        animation-delay: calc(var(--step-in) + var(--step-fade));
    }
    .steps.is-in .step::before {
        animation: stepLineDraw var(--step-line) linear both;
        animation-delay: var(--step-draw);
    }

    /* One beat per step. `--step-in` is when this dot appears; `--step-draw` is
       when its outgoing line starts, which is the instant the dot has landed. */
    .steps.is-in .step:nth-child(1) { --step-in: calc(0 * var(--step-pitch)); }
    .steps.is-in .step:nth-child(2) { --step-in: calc(1 * var(--step-pitch)); }
    .steps.is-in .step:nth-child(3) { --step-in: calc(2 * var(--step-pitch)); }
    .steps.is-in .step:nth-child(4) { --step-in: calc(3 * var(--step-pitch)); }
    .steps.is-in .step:nth-child(5) { --step-in: calc(4 * var(--step-pitch)); }
    .steps.is-in .step:nth-child(6) { --step-in: calc(5 * var(--step-pitch)); }
    .steps.is-in .step { --step-draw: calc(var(--step-in) + 2 * var(--step-fade)); }
}

@keyframes stepFadeIn {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: none; }
}
@keyframes stepLineDraw {
    from { transform: scaleX(0); }
    to   { transform: scaleX(1); }
}

@keyframes stepLineDrawY {
    from { transform: scaleY(0); }
    to   { transform: scaleY(1); }
}
/* Mobile folds the connector to a vertical spine, so it draws downward. A
   SECOND keyframe name rather than redefining `stepLineDraw` inside the query:
   a media-scoped `@keyframes` override is legal but relies on the engine
   scoping it correctly, and switching animation-name cannot be misread. */
@media only screen and (max-width: 700px) {
    .js-reveal .steps .step::before {
        transform: scaleY(0);
        transform-origin: top center;
    }
    .js-reveal .steps.is-in .step::before { animation-name: stepLineDrawY; }
}

/* ==========================================================================
   ADVISOR PARTNERSHIP   body.page-advisor-partnership
   ==========================================================================
   Sections by id: #one-way (one-way referrals), #fit (fit / not-fit lists).
   ========================================================================== */

body.page-advisor-partnership .hero__frame { --hero-frame-max: 68.6%; }   /* the board's 1234 of 1800 */

/* One-way referrals: flush left in the container, the copy capped at the
   board's 1100px; 26px eyebrow → H2 → copy */
#one-way {
    .eyebrow { margin: 0 0 26px; }
    h2 { margin: 0 0 26px; max-width: 1100px; }
    p:not(.eyebrow) { margin: 0; max-width: 1100px; }
}

/* Fit / not-fit: two checklists, the second muted */
#fit {
    h2 {
        margin: 0 0 1.4rem;
        padding-bottom: 0.6rem;
        border-bottom: 1px solid var(--prime);
    }
    ul {
        list-style: none;
        margin: 0;
        padding: 0;
    }
    li {
        position: relative;
        padding-left: 2rem;
        margin: 0 0 1.25rem;
        color: var(--body);
        line-height: 1.5;
        max-width: 42ch;
        &:last-child { margin-bottom: 0; }
        &::before {
            position: absolute;
            left: 0; top: 0.05em;
            font-weight: 600;
            content: "\2713";             /* ✓ */
            color: var(--heading);
        }
    }
    .row > :last-child {
        h2 { color: var(--text-muted); border-bottom-color: #4A545F; }
        li::before { content: "\2014"; color: #9AA5B3; font-weight: 400; }   /* — */
    }
}

/* ==========================================================================
   BAR COMPARE — true-scale bar charts   (visual only)
   ==========================================================================
   Two related chart shapes, one file:

   A) .bar-compare — multi-row comparison. Each .bc-row = a head (label left /
      value right) over a proportional bar. Hairline rules between rows; the
      "winning" row (.bc-row--hi) is heading-navy with a prime->ink gradient bar.
      Optional 12px grey .bc-note caption.

   B) .bar-stack — one rail split into segments (grey -> grey -> navy gradient),
      pill ends, a swatch legend below, and a 19px body .bs-note caption.

   Both are a single `text` content element (all <div>/<span>/<p> — no inline
   <svg>, so Contao output keeps it). Bar widths are true-scale, set per-bar as
   inline `style="width:N%"`. The component takes the width of its column.

   Build: drop the markup (see cornerstone.bar-compare.spec.md) into a text CE
   inside any light band (`band bg-cream section-80` / `bg-white`).
   ========================================================================== */

:root {
    /* Grey ramp for the "lesser" bars/segments (per Penpot). */
    --bc-g1: #C4CCD6;   /* lightest */
    --bc-g2: #9AA5B3;   /* mid grey */
    /* Highlight fill: prime -> ink, light on the left, dark on the right.
       Verified against Case Study A's board bar, whose gradient is
       #0a417c -> #04203f running start(0.007, 0.467) to end(1.001, 0.488). */
    --bc-hi: linear-gradient(90deg, var(--prime) 0%, var(--ink) 100%);
    --bc-radius: 0;     /* square ends, like the column charts (Bob, 13 Oct) */
}

/* ---- On a DARK band the whole scale re-keys ------------------------------
   A navy-on-navy bar is invisible, so the board uses different paint on the
   ink bands. Case Study D (#04203f) draws the lesser bar as a solid mid blue
   rather than the light grey, and runs the highlight gradient the OTHER WAY —
   Penpot: #9cb0ec at start(1, 0.5) to #0a417c at end(0, 0.5), i.e. deep navy at
   the root brightening to periwinkle at the tip. That inversion is what John
   reported as the wrong colour/gradient on the "Safe harbor match only" /
   "With cash balance combo" spans. The light-band values above are correct and
   unchanged. */
.bg-ink .bar-compare,
.bg-dark .bar-compare {
    --bc-g1: #4D7FB0;
    --bc-g2: #4D7FB0;
    --bc-hi: linear-gradient(90deg, var(--prime) 0%, #9CB0EC 100%);
}

/* ==========================================================================
   A) MULTI-ROW COMPARISON
   ========================================================================== */
.bar-compare { display: flex; flex-direction: column; }

.bc-row { padding: 0.75rem 0 1rem; }
.bc-row + .bc-row,
.bar-compare .bc-note { border-top: 1px solid var(--hairline); }
.bc-row:first-child { padding-top: 0.25rem; }

/* Head: label left, value right, aligned on their baseline. */
.bc-head {
    display: flex; align-items: baseline; justify-content: space-between;
    gap: 1rem; margin-bottom: 0.7rem;
}
.bc-label {
    font-family: var(--type-body); font-weight: 500;
    font-size: clamp(1rem, 1.15vw, 1.1875rem);   /* 19px */
    color: var(--body); line-height: 1.2;
}
.bc-val {
    font-family: var(--type-body); font-weight: 700;
    font-size: clamp(1.35rem, 1.7vw, 1.6875rem);  /* 27px */
    color: var(--body); white-space: nowrap; line-height: 1;
}

/* Track + fill. Track is the full available width; fill is true-scale. */
.bc-track { width: 100%; }
.bc-fill {
    display: block; height: 30px; width: 0;
    border-radius: var(--bc-radius);
    background: var(--bc-g2);
}
.bc-fill--g1 { background: var(--bc-g1); }
.bc-fill--g2 { background: var(--bc-g2); }
.bc-fill--hi { background: var(--bc-hi); height: 35px; }

/* Highlight row: heading-navy text; value a touch smaller (per Penpot). */
.bc-row--hi {
    .bc-label { color: var(--heading); }
    .bc-val { color: var(--heading); font-size: clamp(1.25rem, 1.5vw, 1.5rem); }
} /* 24px */

/* Caption. */
.bc-note {
    margin: 0; padding-top: 0.9rem;
    font-family: var(--type-body);
    font-size: 0.75rem; color: var(--text-muted); line-height: 1.4;
}

/* ==========================================================================
   B) STACKED BAR + LEGEND
   ========================================================================== */
.bar-stack { display: flex; flex-direction: column; }

.bs-track {
    display: flex; align-items: stretch; gap: 3px;
    width: 100%; height: 61px;
}
.bs-seg {
    display: block; height: 100%; min-width: 2px;
    background: var(--bc-g2);
}
.bs-seg--g1 { background: var(--bc-g1); }
.bs-seg--g2 { background: var(--bc-g2); }
.bs-seg--hi { background: var(--bc-hi); }
.bs-seg:first-child { border-radius: var(--bc-radius) 0 0 var(--bc-radius); }
.bs-seg:last-child { border-radius: 0 var(--bc-radius) var(--bc-radius) 0; }

/* Legend. */
.bs-legend {
    display: flex; flex-wrap: wrap; align-items: center;
    gap: 0.5rem 2rem; margin-top: 1.25rem;
    font-family: var(--type-body);
    font-size: clamp(0.95rem, 1.05vw, 1.0625rem);
    color: var(--body);
}
.bs-key { display: inline-flex; align-items: center; gap: 0.55rem; white-space: nowrap;
    b { color: var(--heading); font-weight: 600; }
}
.bs-dot {
    flex: none; width: 14px; height: 14px; border-radius: 4px;
    background: var(--bc-g2);
}
.bs-dot--g1 { background: var(--bc-g1); }
.bs-dot--g2 { background: var(--bc-g2); }
.bs-dot--hi { background: var(--bc-hi); }

/* Stack caption is body-size (19px), not the small scenario note. */
.bs-note {
    margin: 1.25rem 0 0;
    font-family: var(--type-body);
    font-size: clamp(1rem, 1.15vw, 1.1875rem);
    color: var(--body); line-height: 1.45;
}

/* ==========================================================================
   SHARED — chart title (sits above a .bar-stack / .bar-col)
   ========================================================================== */
/* Literata navy caption, ~26px (per Penpot: hero "How a combo design stacks up"
   and §"Maximum tax-deductible… by age"). */
.chart-title {
    font-family: var(--type-display);
    font-weight: 700;
    font-size: clamp(1.25rem, 1.6vw, 1.625rem);   /* the boards: 26px / 700, five pages */
    line-height: 1.2;
    color: #083C6F;
    margin: 0 0 clamp(1rem, 1.6vw, 1.5rem);
}
/* In a hero the chart title sits on a navy rule across the chart's column,
   19px under the text (Complex Plan Design, Consulting: board x1352 y409 w748;
   John, 8 Oct). The age chart further down Complex Plan Design has none. */
#hero .chart-title {
    padding-bottom: clamp(0.75rem, 0.8vw, 1.1875rem);
    border-bottom: 1px solid var(--prime);
}

/* ==========================================================================
   C) COLUMN CHART — vertical bars, value over bar, category under
   ==========================================================================
   Single `text` element (all <div>/<span>/<b> — survives Contao output).
   Bars are true-scale: each .bcx carries `--h` = bar height as a % of the plot
   track (Penpot: bar px / 266). Lesser bars grey (--bc-g1); the highlight column
   (.bcx--hi) is solid --prime with navy labels. Markup (see the page spec):
     <div class="bar-col"><div class="bc-plot">
        <div class="bcx" style="--h:30%"><span class="bcx-col">
            <b class="bcx-val">$220k</b><span class="bcx-bar"></span>
        </span><span class="bcx-lab">Age 45</span></div> …
     </div></div>
     <p class="bar-col-note">…</p>
   ========================================================================== */
.bar-col { width: 100%; }
.bc-plot {
    display: flex;
    align-items: flex-start;     /* columns top-aligned: the bar areas are one fixed height, so the bars
                                    share a baseline even when a label wraps to two lines (Bob, 13 Oct) */
    gap: 0;                                     /* bars touch, as on the boards and the printed case studies */
    border-bottom: 1px solid var(--ink);        /* axis baseline — board #04203f */
}
.bcx { flex: 1 1 0; min-width: 0; }
/* fixed bar area; value + bar bottom-aligned so bars meet the axis and each
   value label hugs its bar top (headroom above the tallest bar = 100% − 90%). */
.bcx-col {
    height: clamp(220px, 26vw, 280px);
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
}
.bcx-val {
    display: block;
    text-align: center;
    font-family: var(--type-body);
    font-weight: 600;
    font-size: clamp(0.9rem, 1.05vw, 1.125rem);   /* ~18px */
    color: var(--body);
    margin-bottom: 0.4rem;
    line-height: 1;
}
/* The board ramps these columns by VALUE rather than painting them all one
   grey — Complex Plan Design's age chart runs #EEF1F5, #DFE4EA, #9AA5B3,
   var(--text-muted), then back DOWN to #9AA5B3 where the $500k column dips, and only the
   highlight is navy. So the fill is per-column data, supplied inline next to
   `--h` in the spec, exactly the way the height already is. `--bc-g1` stays the
   fallback for a chart that does not ramp.
   Bars are square-topped on the board (radius 0), not rounded. */
.bcx-bar {
    display: block;
    height: var(--h, 0%);
    background: var(--bcx-fill, var(--bc-g1));
    transform-origin: bottom center;
}
.bcx-lab {
    display: block;
    text-align: center;
    font-family: var(--type-body);
    font-weight: 600;
    font-size: clamp(0.9rem, 1.05vw, 1.125rem);   /* 18px / 600 */
    color: #1f262d;
    padding: 0.7rem 0.2rem 0;           /* the bars touch; their labels don't */
    line-height: 1;
}
/* The highlight column is a VERTICAL gradient, dark at the top:
   Penpot #04203f -> #0a417c, s(0.5, 0) to e(0.5, 1). */
.bcx--hi {
    .bcx-bar { background: linear-gradient(180deg, var(--ink) 0%, var(--prime) 100%); }
    .bcx-val, .bcx-lab { color: var(--prime); }
}

.bar-col-note {
    margin: 1.1rem 0 0;
    font-family: var(--type-body);
    font-size: clamp(0.78rem, 0.95vw, 0.8125rem);   /* 13px / 500 */
    font-weight: 500;
    color: #333B44;
    line-height: 1.45;
}

/* ==========================================================================
   MOBILE
   ========================================================================== */
@media only screen and (max-width: 760px) {
    .bc-head { flex-direction: column; gap: 0.15rem; }
    .bc-val, .bc-row--hi .bc-val { font-size: 1.375rem; }
    .bs-track { height: 48px; }
    .bs-legend { gap: 0.5rem 1.25rem; }
    .bcx-col { height: clamp(160px, 42vw, 220px); }
    .bcx-val, .bcx-lab { font-size: 0.8125rem; }
}

/* ==========================================================================
   SCROLL-IN REVEAL — bars fill the first time the chart enters view
   ==========================================================================
   Driven by `is-in`, added once by fe_page.html.twig's IntersectionObserver.
   Gated on `.js-reveal`, which only exists while that observer is running, so
   with JS off or reduced motion requested every bar renders at its authored
   width immediately. One pass; it does not reverse on scroll-up.

   The reveal is a `clip-path` wipe, NOT `transform: scaleX()`. A scaled fill
   squashes its own 10px pill ends for the length of the animation and they
   only settle at the last frame; a clip wipe uncovers the bar at its true
   geometry, so the rounded cap looks right the whole way across. It also means
   the bar's inline `style="width:N%"` stays the single source of truth for
   length — nothing here has to know the value.

   The highlight bar lands a beat after the comparison bar so the pair reads as
   "this much... versus THIS much" rather than both arriving together.
   ========================================================================== */
.js-reveal {
    .bar-compare .bc-fill, .bar-stack .bs-seg { clip-path: inset(0 100% 0 0); }
    .bar-compare.is-in .bc-fill { animation: bcWipe 0.85s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
    .bar-compare.is-in .bc-row:nth-child(2) .bc-fill { animation-delay: 0.18s; }
    .bar-compare.is-in .bc-row:nth-child(3) .bc-fill { animation-delay: 0.36s; }
    .bar-compare.is-in .bc-row--hi .bc-fill { animation-delay: 0.42s; }

    /* ---- The cumulative rail fills STRICTLY one segment at a time -----------
       `.bar-stack` is a single rail split into segments that add up to one total,
       so overlapping them read as one blurry sweep. Each segment now waits for the
       one before it to finish — light grey fills and stops, then the mid grey, then
       the navy — which is what makes the rail read as an accumulation rather than a
       bar. `--bs-step` is both the per-segment duration and the beat, so they stay
       butted together by construction. */
    .bar-stack { --bs-step: 0.5s; }
    .bar-stack.is-in .bs-seg { animation: bcWipe var(--bs-step) ease-out both; }
    .bar-stack.is-in .bs-seg:nth-child(1) { animation-delay: calc(0 * var(--bs-step)); }
    .bar-stack.is-in .bs-seg:nth-child(2) { animation-delay: calc(1 * var(--bs-step)); }
    .bar-stack.is-in .bs-seg:nth-child(3) { animation-delay: calc(2 * var(--bs-step)); }
    .bar-stack.is-in .bs-seg:nth-child(4) { animation-delay: calc(3 * var(--bs-step)); }
    .bar-stack.is-in .bs-seg:nth-child(5) { animation-delay: calc(4 * var(--bs-step)); }
}

@keyframes bcWipe {
    from { clip-path: inset(0 100% 0 0); }
    to   { clip-path: inset(0 0 0 0); }
}

/* Column charts grow UP from the axis; a vertical clip keeps the bar's own
   top radius intact the same way. */
.js-reveal {
    .bc-plot .bcx-bar { clip-path: inset(100% 0 0 0); }
    .bc-plot.is-in .bcx-bar { animation: bcxGrow 0.8s cubic-bezier(0.22, 0.61, 0.36, 1) both; }
    .bc-plot.is-in .bcx:nth-child(2) .bcx-bar { animation-delay: 0.12s; }
    .bc-plot.is-in .bcx:nth-child(3) .bcx-bar { animation-delay: 0.24s; }
    .bc-plot.is-in .bcx:nth-child(4) .bcx-bar { animation-delay: 0.36s; }
    .bc-plot.is-in .bcx:nth-child(5) .bcx-bar { animation-delay: 0.48s; }
    .bc-plot.is-in .bcx:nth-child(6) .bcx-bar { animation-delay: 0.60s; }
    .bc-plot.is-in .bcx--hi .bcx-bar { animation-delay: 0.72s; }
}

@keyframes bcxGrow {
    from { clip-path: inset(100% 0 0 0); }
    to   { clip-path: inset(0 0 0 0); }
}

/* ==========================================================================
   PLAN ADMINISTRATION & COMPLIANCE   body.page-plan-administration-compliance
   ==========================================================================
   The hero's second row: capability chips (left) | "what reaches you" cards
   (right), a hairline between them and a rule under both (inset pseudo-
   elements: the row carries the gutter, so a border would overshoot).
   ========================================================================== */

body.page-plan-administration-compliance {
    .hero__frame { --hero-frame-max: 72.2%; }

    #hero .mod_article > .row {
        position: relative;
        align-items: start;
        padding-top: clamp(1.5rem, 2.6vw, 2.25rem);
        padding-bottom: clamp(1.75rem, 3vw, 2.75rem);
        &::after {
            content: "";
            position: absolute;
            left: var(--page-gutter);
            right: var(--page-gutter);
            bottom: 0;
            height: 0;
            border-top: 1px solid var(--hairline);
            pointer-events: none;
        }
        > *:nth-child(2) {
            border-left: 1px solid var(--hairline);
            padding-left: clamp(1.75rem, 3.5vw, 3.5rem);
        }
    }

    /* 12px uppercase labels: navy, the right column's in brand blue */
    .pa-label {
        margin: 0 0 clamp(1rem, 1.6vw, 1.4rem);
        font-family: var(--type-body);
        font-weight: 600;
        font-size: 0.75rem;
        letter-spacing: 0.12em;
        text-transform: uppercase;
        color: var(--heading);
    }
    .pa-label--prime { color: var(--prime); }
    .pa-note {
        margin: clamp(0.75rem, 1.4vw, 1.1rem) 0 0;
        font-size: 0.8125rem;
        color: var(--text-muted);
    }
    .pa-foot {
        margin: clamp(1rem, 1.8vw, 1.4rem) 0 0;
        font-family: var(--type-display);
        font-size: clamp(0.95rem, 1.1vw, 0.9375rem);
        color: #11161b;
    }
}
/* Stacks at 1200, not 992 (the board splits it 58.9 / 36.7), and the divider
   goes with it */
@media only screen and (max-width: 1200px) {
    body.page-plan-administration-compliance #hero .mod_article > .row {
        > * { flex: 0 0 100%; }
        > *:nth-child(2) { border-left: 0; padding-left: 0; padding-top: 1.75rem; }
    }
}

/* ==========================================================================
   NUM LABEL — grey numbered section label   (visual only)
   ==========================================================================
   The small grey "NN · SECTION" label that leads a numbered two-column
   editorial band (What We Do service bands, Resources category bands). Pairs
   with a `row gap-60` → col-2-5 (this label + h2) | col-3-5 (body + a.btn alt).

   Build: a `<p class="num-label">01 &middot; PLAN EXPLAINERS</p>` above the h2.
   (Promoted 2026-09-19 from the page-scoped `.wwd-num`.)
   ========================================================================== */
.num-label {
    margin: 0 0 0.9rem;
    font-family: var(--type-body);
    font-weight: 600;
    font-size: 0.6875rem;          /* 11px */
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-muted);   /* was #9AA5B3: 2.4:1 on cream, under WCAG AA (8 Oct) */
}

/* ==========================================================================
   SWITCHING TO CORNERSTONE   body.page-switching-to-cornerstone
   ==========================================================================
   Sections by id: #one-meeting, #scales, #independent, #moments, #closing.
   Everything else is a shared component (hero__frame, steps, bar-col,
   cta-band).
   ========================================================================== */

body.page-switching-to-cornerstone .hero__frame {
    --hero-frame-max: 94.6%;            /* the board's 1702 of 1800 */
    &::after { content: none; }         /* the steps' line is the only rule */
}

/* "One meeting per client": the CTA band at 98.2% of the container; 16px
   eyebrow → H2, 24px H2 → button, 70px below */
#one-meeting {
    --cta-max: 98.2%;
    padding-bottom: 70px;
    .eyebrow { color: var(--white); margin-bottom: 16px; }
    h2 { margin: 0 0 24px; }
    a.btn { margin-top: 0; }
}

/* The process scales: navy eyebrow; blue columns (the 100% one keeps its navy);
   a caption line under each column label; no line under the chart */
#scales {
    .eyebrow { color: var(--heading); }
    .bcx:not(.bcx--hi) .bcx-bar { background: #6E9AC4; }
    .bc-plot { border-bottom: 0; }
    .bcx-lab > span {
        display: block;
        font-weight: 400;
        color: var(--text-muted);
        font-size: clamp(0.85rem, 1vw, 1rem);
        line-height: 1.3;
        padding-top: 0.35rem;
    }
}

/* the copy and the chart stack at 992, not 600: half a tablet is too narrow
   for three labelled columns (Bob, 13 Oct) */
@media only screen and (max-width: 992px) {
    #scales .row > * { flex: 0 0 100%; }
}

/* Independent. For life.: the closing line larger and white; the button
   column has a divider on its inner edge. The space either side of the divider
   is the board's (168 | 190 of 2400), so no column gap (Bob, 13 Oct) */
#independent {
    .row { --gap-x: 0px; }
    .col-3-5 { padding-right: clamp(1.5rem, 7vw, 10.5rem); }
    p > strong { color: var(--white); }
    .col-3-5 p:last-child {
        font-size: clamp(1.25rem, 1.8vw, 1.5rem);
        font-weight: 500;
        color: var(--white);
        margin-bottom: 0;
    }
    .col-2-5 {
        display: flex;
        align-items: center;
        justify-content: flex-start;
        min-height: 100%;
        border-left: 1px solid var(--hairline-on-dark);
        padding-left: clamp(1.5rem, 7.9vw, 11.875rem);
        a.btn { margin: 0; }
    }
}
@media (max-width: 992px) {                 /* the columns stack here */
    #independent {
        .col-3-5 { padding-right: 0; }
        .col-2-5 { border-left: 0; padding-left: 0; min-height: 0; margin-top: 0; justify-content: center; }   /* no divider: the button centres (Bob, 13 Oct) */
    }
}

/* Moments like these: six quote cards, 2-up; 44px above and below the grid */
#moments {
    .row { margin-top: 44px; }
    .row + * { margin-top: 44px; }
    .row > * {
        background: var(--white);
        border: 1px solid #C4CCD6;
        border-radius: 10px;
        padding: 24px;
    }
    .row p {
        margin: 0;
        font-family: var(--type-body);
        font-weight: 500;
        font-size: clamp(1.05rem, 1.25vw, 1.25rem);
        line-height: 1.45;
        color: #083C6F;
    }
}

/* The closing CTA is 900 wide here (1200 elsewhere) */
#closing { --cta-max: calc(900px + 2 * var(--page-gutter)); }

/* ==========================================================================
   CASE STUDIES   body.page-case-studies
   ==========================================================================
   Four bands, #case-a…#case-d (cream / ink alternating): a .cs-head over a
   `row split`, copy (.cs-col) left, the proof right — A and D a bar-compare,
   B a "what changed" list, C before/after panels. Then #testimonials.
   ========================================================================== */

body.page-case-studies {
    .hero__frame { --hero-frame-max: 77.8%; }

    /* Heading block with a rule under it, inset by the gutter (a border would
       overshoot the text) */
    .cs-head {
        position: relative;
        padding-bottom: 44px;
        margin-bottom: 45px;
        h2 { margin: 0; }
        &::after {
            content: "";
            position: absolute;
            bottom: 0;
            left: var(--rule-inset, var(--page-gutter));
            right: var(--rule-inset, var(--page-gutter));
            height: 0;
            border-top: 1px solid var(--hairline);
            pointer-events: none;
        }
    }

    /* Left column: labels, copy, a red note, the visual's label, the closing
       caption and the Download button */
    .cs-lbl {
        font-family: var(--type-body);
        font-weight: 700;
        font-size: clamp(1.05rem, 1.25vw, 1.1875rem);
        color: var(--heading);
        line-height: 1.3;
        margin: clamp(1.5rem, 2.6vw, 2.25rem) 0 6px;
        &:first-child { margin-top: 0; }
    }
    .cs-col p { margin: 0; color: var(--body); }
    .cs-note { margin: 0.8rem 0 0; font-size: 0.75rem; font-weight: 500; color: var(--red-800); line-height: 1.4; }
    .cs-vlabel { color: var(--heading); }
    .cs-cap { margin: 1.1rem 0 0; font-size: clamp(1rem, 1.1vw, 1.0625rem); font-weight: 600; color: #11161B; }
    .cs-dl { margin: clamp(1.5rem, 2.4vw, 2.5rem) 0 0; }

    /* the bar charts' closing line has no rule above it */
    .bar-compare .bc-note { border-top: 0; }
}

/* Bar labels are 700 on the light bands, 500 on the ink ones */
:is(#case-a, #case-c) .bc-label { font-weight: 700; }

/* The ink bands (B, D) invert the colours */
:is(#case-b, #case-d) {
    .cs-head::after { border-top-color: var(--hairline-on-dark); }
    .cs-head .eyebrow { color: var(--text-on-dark-dim); }
    .cs-lbl { color: #FFFFFF; }
    .cs-col p { color: var(--text-on-dark-dim); }
    .cs-vlabel { color: #9AA5B3; }
    .cs-cap { color: #FFFFFF; }
    .bar-compare {
        .bc-label,
        .bc-row--hi .bc-label,
        .bc-val,
        .bc-row--hi .bc-val { color: #FFFFFF; }
        .bc-row + .bc-row { border-top-color: var(--hairline-on-dark); }
        .bc-note { color: var(--text-on-dark-dim); }
    }
}

/* B: "what changed", a stacked list with a rule under its label */
#case-b {
    .cs-vlabel:has(+ .cs-changed) {
        padding-bottom: clamp(0.85rem, 1.4vw, 1.15rem);
        margin-bottom: clamp(0.85rem, 1.4vw, 1.15rem);
        border-bottom: 1px solid var(--hairline-on-dark);
    }
    .cs-changed {
        display: flex;
        flex-direction: column;
        .cs-item {
            padding: clamp(0.85rem, 1.4vw, 1.15rem) 0;
            & + .cs-item { border-top: 1px solid var(--hairline-on-dark); }
            &:first-child { padding-top: 0; }
        }
        h4 {
            font-family: var(--type-display); font-weight: 600;
            font-size: clamp(1.2rem, 1.5vw, 1.375rem);
            color: #FFFFFF; margin: 0 0 0.3em; line-height: 1.15;
        }
        p { margin: 0; font-size: 0.9375rem; color: var(--text-on-dark-dim); line-height: 1.5; }
    }
}

/* C: before/after plan-health panels */
#case-c {
    .cs-ba { display: flex; gap: clamp(0.9rem, 1.6vw, 1.4rem); align-items: start; }
    .cs-panel {
        flex: 1 1 0; min-width: 0;
        background: #FFFFFF;
        border: 1px solid var(--hairline);
        border-radius: 10px;
        padding: clamp(1rem, 1.6vw, 1.4rem);
    }
    .cs-ph {
        margin: 0 0 0.8rem;
        font-family: var(--type-body); font-weight: 600;
        font-size: 0.6875rem; letter-spacing: 0.09em; text-transform: uppercase;
    }
    .cs-row {
        display: flex; justify-content: space-between; gap: 0.75rem;
        padding: 0.5rem 0; font-size: 0.875rem; line-height: 1.3;
        & + .cs-row { border-top: 1px solid var(--hairline); }
    }
    .cs-k { color: var(--text-muted); }
    .cs-v { font-weight: 600; text-align: right; white-space: nowrap; }
    /* Before reads lighter than After (both above WCAG AA) */
    .cs-panel--before :is(.cs-ph, .cs-v) { color: var(--text-muted); }
    .cs-panel--after {
        border-color: var(--prime);
        .cs-ph { color: var(--prime); }
        .cs-k { color: #072F5A; }
        .cs-v { color: #11161B; }
    }
}
@media only screen and (max-width: 600px) { #case-c .cs-ba { flex-direction: column; } }

/* In their words: photo avatars, left-aligned, a navy rule above each */
#testimonials {
    .tavatar { margin-inline: 0; }
    .tavatar--photo {
        padding: 0; background: none; overflow: hidden;
        img { width: 100%; height: 100%; object-fit: cover; display: block; }
    }
    .tname {
        margin: 0 0 0.5rem;
        font-family: var(--type-body); font-weight: 600;
        font-size: clamp(1.05rem, 1.2vw, 1.25rem);
        color: var(--red-800); line-height: 1.3;
    }
    blockquote p { font-size: clamp(0.95rem, 1.05vw, 1rem); }
    .testimonial-grid > * {
        border-top: 1px solid var(--prime);
        padding-top: clamp(1rem, 1.2vw, 1.4375rem);
    }
}

/* ==========================================================================
   WHY "CORNERSTONE"   body.page-why-cornerstone
   ==========================================================================
   One centred ~1064px editorial column in the hero (the site's only page off
   the 1800 container): the statement, then .wc-prose with a lead paragraph
   (.wc-lead) and a bordered pull-quote (.wc-quote).
   ========================================================================== */

body.page-why-cornerstone {
    /* the hero's children centre; the cap includes their gutter padding */
    .hero--light {
        > .hero-eyebrow,
        > .hero__frame,
        > .wc-prose { max-width: calc(1064px + 2 * var(--page-gutter)); }
        .hero__frame > * { max-width: none; }   /* the column is the measure */
        > .wc-prose { margin-top: clamp(1.25rem, 2.2vw, 2.1875rem); }
    }

    .wc-prose {
        p {
            color: #333B44;
            font-family: var(--type-body);
            font-size: clamp(1.05rem, 1.25vw, 1.25rem);
            line-height: 1.6;
            margin: 0 0 1.25rem;
        }
        .wc-lead {
            font-family: var(--type-display);
            font-weight: 500;
            font-size: clamp(1.5rem, 2.4vw, 2rem);
            line-height: 1.35;
            color: var(--heading);
            margin: 0 0 clamp(1.75rem, 3.5vw, 2.75rem);
        }
        .wc-quote {
            margin: clamp(1.5rem, 3vw, 2.25rem) 0;
            padding-left: clamp(1.25rem, 2vw, 1.75rem);
            padding-block: clamp(0.25rem, 0.42vw, 0.625rem);   /* the bar runs 10px past the text */
            border-left: 3px solid var(--prime);
            p {
                color: var(--heading);
                font-family: var(--type-display);
                font-weight: 600;
                font-size: clamp(1.25rem, 1.8vw, 1.5rem);
                line-height: 1.4;
                margin: 0;
                max-width: 54rem;   /* the board's 865px measure */
            }
        }
    }
}

/* ==========================================================================
   PLAN EXPLAINERS   body.page-plan-explainers
   ==========================================================================
   An intro hero with a sample explainer card (.pe-card, reusing bar-compare),
   then #launch-set, the grid of explainers.
   ========================================================================== */

body.page-plan-explainers {
    /* The card has its own border: no divider beside it. Desktop: it floats
       over the hero's two rules, 106px above the top one and 127px below the
       bottom (at 2400), as on the board. Stacked below 993. */
    .hero__intro > .pe-card {
        border-left: 0;
        padding-left: clamp(1.25rem, 2vw, 1.9rem);
    }

    .pe-card {
        background: var(--white);
        border: 1px solid #E3E7EC;
        border-radius: 12px;
        padding: clamp(1.25rem, 2vw, 1.9rem);
        box-shadow: 0 18px 40px -24px rgba(4, 32, 63, 0.25);

        h3 {
            font-family: var(--type-display);
            font-size: clamp(1.2rem, 1.5vw, 1.5rem); color: var(--heading);
            margin: 0 0 0.75rem; padding-bottom: 0.75rem;
            border-bottom: 1px solid var(--hairline); line-height: 1.2;
        }
        .pe-body { margin: 0; color: var(--body); font-size: 0.9375rem; line-height: 1.5; }
        .pe-step {
            display: block; margin: 1.1rem 0 0.4rem;
            font-family: var(--type-body); font-weight: 700;
            font-size: 0.625rem; letter-spacing: 0.1em; text-transform: uppercase;
            color: var(--prime);
        }
        .pe-check { display: flex; gap: 0.5rem; align-items: flex-start; margin: 0.35rem 0; color: var(--body); font-size: 0.9375rem; line-height: 1.4; }
        .pe-tick { color: var(--prime); font-weight: 700; flex: none; }
        .pe-tax {
            margin: 0.75rem 0 0; text-align: right;
            font-family: var(--type-body); font-weight: 700;
            font-size: 0.875rem; color: var(--heading);
        }

        /* the bar-compare, compacted; no rule between its two bars */
        .bar-compare { margin-top: 0.25rem; }
        .bc-row { padding: 0.4rem 0 0.55rem; }
        .bc-row + .bc-row { border-top: 0; }
        .bc-label { font-size: 0.875rem; }
        .bc-val,
        .bc-row--hi .bc-val { font-size: 1rem; }
        .bc-fill { height: 16px; }
        .bc-fill--hi { height: 18px; }
    }
}
@media only screen and (min-width: 993px) {
    body.page-plan-explainers .hero__intro > .pe-card {
        position: relative; z-index: 1;
        margin-top: calc(-1 * clamp(1.75rem, 3vw, 2.75rem) - clamp(2rem, 4.42vw, 6.625rem));
        margin-bottom: calc(-1 * clamp(1.75rem, 3vw, 2.75rem) - clamp(2rem, 5.29vw, 7.9375rem));
    }
}

/* The launch set: a rule above each explainer */
#launch-set .row > * {
    border-top: 2px solid var(--hairline);
    padding-top: clamp(1rem, 1.6vw, 1.4rem);

    h3 {
        font-family: var(--type-display);
        font-size: clamp(1.2rem, 1.5vw, 1.5rem); color: var(--heading);
        margin: 0 0 0.5rem; line-height: 1.2;
    }
    p { margin: 0 0 1.1rem; color: var(--body); font-size: 0.9375rem; line-height: 1.5; }
    p:last-child { margin-bottom: 0; }
    a.btn { margin: 0; }
}

/* ==========================================================================
   TEAM GRID — headshot cards + an optional "and the rest of us" panel
   ==========================================================================
   A row of people: a cropped portrait, then the name, the role, and a bio.
   Used on an "Our Story & Team" page; the panel variant fills the leftover
   columns with a single dark statement instead of a person (e.g. a role still
   being hired for, or "and 30 more of us").

   Build: element_group `row team-grid gap-24`, then per person an
   element_group `col-1-3 team-card` holding an `image` element + a `text`:
       <h3>Daniel Jock</h3>
       <p>Enrolled Actuary, President</p>
       <p>Bio…</p>
   and, to fill the rest of a short row, a `text` `col-2-3 team-note`:
       <p>Roughly 30 more of us.</p>

   Styled BY TAG (same convention as `stats`): the h3 is the name, the FIRST
   paragraph is the role, the rest is bio. So a card carries no inner classes
   and can't drift.
   ========================================================================== */
.team-grid { align-items: start; }

/* The portrait. A fixed aspect keeps every card's text starting on the same
   line no matter how tall the source photo is, and `cover` + a high focal
   point suits headshots (faces sit in the upper middle). The grey shows while
   a photo loads, and matches the design's empty-slot fill. */
.team-card {
    figure { margin: 0; }
    img {
        display: block;
        width: 100%;
        aspect-ratio: 583 / 698;
        object-fit: cover;
        object-position: 50% 22%;
        background: #B1B2B5;               /* design's placeholder grey — no token */
    }

    h3 {
        font-family: var(--type-display);
        font-weight: 500;
        font-size: clamp(1.35rem, 1.9vw, 1.6875rem);   /* ~27px */
        line-height: 1.25;
        color: var(--heading);
        margin: clamp(1rem, 1.6vw, 1.5rem) 0 0.15em;
    }
    p {
        color: var(--body);
        font-size: clamp(0.9rem, 1.05vw, 1rem);        /* ~16px */
        line-height: 1.55;
        margin: 0 0 0.9em;
    }
    p:first-of-type {
                            /* the role */
        color: var(--heading);
        margin-bottom: clamp(0.9rem, 1.4vw, 1.25rem);
    }
    p:last-child { margin-bottom: 0; }
}

/* The panel that fills out a short row. Sized to the portrait band so its
   bottom edge lines up with the photos beside it, not with their text. */
.team-note {
    display: grid;
    place-items: center;
    aspect-ratio: 1186 / 698;
    padding: clamp(1.5rem, 4vw, 3.5rem);
    background: var(--heading);
    text-align: center;
    p {
        margin: 0;
        max-width: 22em;
        color: var(--white);
        font-family: var(--type-display);
        font-weight: 600;
        font-size: clamp(1.25rem, 1.95vw, 1.75rem);    /* ~28px */
        line-height: 1.35;
    }
}

@media only screen and (max-width: 900px) {
    /* Two columns of cards; the panel spans the pair and gives up its aspect
       so it doesn't become a tall empty box. */
    .team-note { aspect-ratio: auto; min-height: 14rem; }
}

/* ==========================================================================
   OUR STORY & TEAM   body.page-our-story-team
   ==========================================================================
   Section by id: #values. Everything else is a shared component.
   ========================================================================== */

body.page-our-story-team {
    .hero__frame { --hero-frame-max: 69.1%; }   /* the board's 1243 of 1800 */
    /* the team cards' names, roles and bios in black, as the board draws them */
    .team-card :is(h3, p, p:first-of-type) { color: #000; }
}

/* Values: the heading left, the "read more" button right, on one baseline,
   above the values row's top rule */
#values > :first-child {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: clamp(1rem, 2vw, 1.5rem);
    margin-bottom: clamp(1.75rem, 2.125vw, 3.1875rem);   /* heading -> rule: the board's 51 */
    > *, p, .btn { margin: 0; }      /* the button's own margins held it high */
    h2 {
        margin: 0;
        color: var(--prime);
        font-size: clamp(1.6rem, 2.6vw, 2.375rem);
    }
}

/* ==========================================================================
   ACCORDION — brand layer for Contao's accordion element
   ==========================================================================
   REQUIRES contao-components/handorgel:

       composer require contao-components/handorgel

   Contao's accordion element emits handorgel__* markup and pulls that
   component's JS and base CSS from assets/handorgel. The component is NOT a
   core dependency, so without it both files 404 and the element renders as
   dead buttons with every panel expanded — it fails loudly and permanently,
   not gracefully.

   The base stylesheet is functional, not decorative: it owns the
   display/height/opacity transitions that make a panel open at all. So this
   file BRANDS it rather than replacing it — the same approach cookiebar.css
   takes, and for the same reason. Rewriting its layout means re-solving the
   open/close animation and re-breaking it on every component update.

   Every selector is scoped under .content-accordion. handorgel's own rules
   are single-class (0,1,0), so scoping puts these at 0,2,0 and they win
   regardless of which stylesheet the page happens to load last — worth doing
   because Contao injects the component CSS itself and the order is not ours
   to control.
   ========================================================================== */


/* --------------------------------------------------------------------------
   FRAME hi
   -------------------------------------------------------------------------- */

.content-accordion {
    border-bottom: 1px solid var(--stroke);
    margin-bottom: var(--space-24);

    /* --------------------------------------------------------------------------
       HEADER BUTTON
       --------------------------------------------------------------------------
       The header tag (h2–h6) is the editor's choice, so font-size is left to
       inherit from the heading rather than pinned here.

       Padding-right leaves room for the marker below. It is expressed against
       the same token as the horizontal padding so the two stay in step.
       -------------------------------------------------------------------------- */

    .handorgel__header { margin: 0; }

    .handorgel__header__button {
        position: relative;
        border-top: 1px solid var(--stroke);
        background-color: transparent;
        padding: var(--space-16) calc(var(--space-24) * 2.2) var(--space-16) var(--space-24);
        font-family: inherit;
        font-weight: 600;
        color: var(--text);
        transition: background-color .2s ease;
    }

    .handorgel__header__button:hover { background-color: var(--grey-light); }

    /* A button that cannot be seen when focused is a WCAG 2.4.7 failure, and
       handorgel's base CSS strips the UA outline without replacing it. Inset so
       the ring stays visible on a full-bleed button rather than being clipped. */
    .handorgel__header__button:focus-visible {
        outline: 2px solid var(--prime);
        outline-offset: -2px;
    }

    /* --------------------------------------------------------------------------
       OPEN / CLOSED MARKER
       --------------------------------------------------------------------------
       handorgel keeps aria-expanded in step on the button, so the marker is
       driven off that rather than off a state class: the visual and the
       accessible state then cannot disagree, because they read the same source.

       It also means open/closed is not signalled by colour alone (WCAG 1.4.1) —
       the chevron changes direction, which does not depend on seeing colour.
       -------------------------------------------------------------------------- */

    .handorgel__header__button::after {
        content: "";
        position: absolute;
        right: var(--space-24);
        top: 50%;
        width: .5em;
        height: .5em;
        border-right: 2px solid currentColor;
        border-bottom: 2px solid currentColor;
        transform: translateY(-70%) rotate(45deg);
        transition: transform .2s ease;
    }

    .handorgel__header__button[aria-expanded="true"]::after { transform: translateY(-20%) rotate(-135deg); }

    /* --------------------------------------------------------------------------
       PANEL
       -------------------------------------------------------------------------- */

    .handorgel__content {
        background-color: transparent;
        border-top: 0;
    }

    .handorgel__content__inner { padding: 0 var(--space-24) var(--space-24); }

    /* The panel's last child would otherwise add its margin to the padding. */
    .handorgel__content__inner > :last-child, .handorgel__content__inner > :last-child > :last-child { margin-bottom: 0; }
}


/* --------------------------------------------------------------------------
   REDUCED MOTION
   --------------------------------------------------------------------------
   Deliberately NOT `transition: none` on .handorgel__content. handorgel
   binds a transitionend listener on that element and applies its
   --opened class from the callback, so removing the transition means the
   event never fires and the panel never finishes opening. Collapsing the
   duration instead keeps the event and drops the animation.

   The button and its marker have no JS depending on them, so those can be
   turned off outright.
   -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
    .content-accordion .handorgel__content,
    .content-accordion .handorgel__content__inner {
        transition-duration: 1ms;
    }

    .content-accordion .handorgel__header__button,
    .content-accordion .handorgel__header__button::after {
        transition: none;
    }
}


/* TUNING
     Panels are separated by a single rule in --stroke, with the frame closed
     by a matching line at the bottom. For a card-style accordion instead,
     give .content-accordion a border and radius and drop the border-top on
     the button for the first panel. */


/* ==========================================================================
   FAQ VARIANT  `accordion--faq`  (on the accordion element's cssID)
   ==========================================================================
   The editorial FAQ treatment: the question is a Literata statement flush with
   the container edge (no box, no indent), rules run the full width above every
   row and below the last, and the marker is a + / − rather than a caret. The
   answer is body copy capped to a comfortable measure rather than the full
   width of the question.

   Contao's accordion element takes each nested element's **sectionHeadline**
   as the toggle text (not `headline` — that renders an empty button), and
   leaves the FIRST panel open unless `closeSections` is set.

   Build: a `accordion` element with cssID `accordion--faq`, whose children are
   the panels — each a `text` with `sectionHeadline` = the question.
   ========================================================================== */
/* The closing rule is an INSET pseudo-element. The accordion element is a direct
   child of the band article, so `.band > *` gives it
   `padding-inline: var(--page-gutter)` and a border-bottom painted a full gutter
   past the questions on both sides. (The PANEL BUTTONS' own `border-top` is
   fine: a button's box is the accordion's CONTENT box, already the container,
   and its 42px right padding is where the +/- marker sits — the board draws
   that marker at the container's right edge, x2083 of x300-2100.) */
.content-accordion.accordion--faq {
    position: relative;
    border-bottom: 0;          /* the base frame's rule; redrawn inset below */
    margin-bottom: 0;
    &::after {
        content: "";
        position: absolute;
        bottom: 0;
        left: var(--rule-inset, var(--page-gutter));
        right: var(--rule-inset, var(--page-gutter));
        height: 0;
        border-top: 1px solid var(--prime);
        pointer-events: none;
    }

    .handorgel__header__button {
        /* flush with the container: the question sits on the same left edge as the
           group heading above it, so only the marker gets reserved space */
        padding: var(--space-24) calc(var(--space-24) * 1.75) var(--space-24) 0;
        border-top: 1px solid var(--prime);
        font-family: var(--type-display);
        font-weight: 500;
        font-size: clamp(1.15rem, 1.9vw, 1.6875rem);      /* ~27px */
        line-height: 1.25;
        color: var(--heading);
    }
    .handorgel__header__button:hover {
        background-color: transparent;
        color: var(--prime);
    }

    /* + / − marker, drawn as two rules so it needs no glyph or icon font. */
    .handorgel__header__button::after {
        content: "";
        right: 0;
        width: 0.62em;
        height: 0.62em;
        border: 0;
        transform: none;
        background:
            linear-gradient(var(--prime), var(--prime)) center / 100% 2px no-repeat,
            linear-gradient(var(--prime), var(--prime)) center / 2px 100% no-repeat;
        transition: background-size 0.2s ease, transform 0.2s ease;
    }
    /* open: the vertical stroke collapses, leaving a minus */
    .handorgel__header__button[aria-expanded="true"]::after {
        transform: none;
        background:
            linear-gradient(var(--prime), var(--prime)) center / 100% 2px no-repeat,
            linear-gradient(var(--prime), var(--prime)) center / 2px 0 no-repeat;
    }

    .handorgel__content__inner { padding: 0 0 var(--space-24); }
    .handorgel__content__inner p {
        max-width: 50ch;            /* the design caps the answer at half the row */
        color: var(--body);
        font-size: clamp(1rem, 1.25vw, 1.1875rem);        /* ~19px */
        line-height: 1.6;
    }
}

/* ==========================================================================
   FAQ   body.page-faq
   ==========================================================================
   A hero, four accordion groups (accordion--faq) and the CTA.
   ========================================================================== */

body.page-faq {
    /* the headline runs the full container */
    .hero__frame > * { max-width: none; }
    /* the heading above each group */
    .faq-group {
        margin: 0 0 var(--space-24);
        font-size: clamp(1.4rem, 2.2vw, 2rem);
    }
}

/* ==========================================================================
   ARTICLE CARDS — news list, featured article, filter pills, reader
   ==========================================================================
   The `ins-*` family (insight/article). Everything here styles Contao NEWS
   module output, so the markup lives in Twig templates rather than in a page
   spec:
     news_latest.html.twig           → .ins-card          (grid cell)
     news_latest_featured.html.twig  → .ins-featured      (featured block)
     news_latest_related.html.twig   → .ins-related__item (reader sidebar)
     news_full.html.twig             → .ins-article*      (reader)
     nav_newscategories.html5        → .ins-filters       (filter pills)

   Because a news module renders one template per item, the GRID is applied to
   the module wrapper, not to the items: `.ins-grid` goes on the content
   element's cssID and lays its children out three-up.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Shared meta line — "6 Feb 2026 · 4 min read"
   -------------------------------------------------------------------------- */
.ins-meta {
    margin: 0;
    color: var(--text-muted);
    font-size: 0.75rem;                              /* ~12px */
    line-height: 1.5;
}

/* --------------------------------------------------------------------------
   GRID  `.ins-grid` on the news-list element; cards are its children
   -------------------------------------------------------------------------- */
.ins-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    column-gap: 24px;
    row-gap: 48px;
    /* Contao's news list wraps all items in `.layout_wrapper`, which would be the
       grid's only child. `display: contents` lifts the cards back out so they are
       the grid items — and the grid stays defined in exactly one place whether the
       wrapper is there or not. */
    .layout_wrapper { display: contents; }
}
@media only screen and (max-width: 992px) {
    .ins-grid { grid-template-columns: repeat(2, 1fr); }
}
@media only screen and (max-width: 600px) {
    .ins-grid { grid-template-columns: 1fr; row-gap: 32px; }
}

/* --------------------------------------------------------------------------
   CARD — a 2px navy rule across the top, then category / title / teaser / meta
   -------------------------------------------------------------------------- */
.ins-card {
    border-top: 2px solid var(--prime);
    padding-top: var(--space-24);
}
.ins-card__cat {
    margin: 0 0 0.9em;
    color: var(--prime);
    font-size: 0.75rem;                              /* ~12px */
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}
.ins-card__title {
    margin: 0 0 0.6em;
    font-family: var(--type-display);
    font-weight: 500;
    font-size: clamp(1.15rem, 1.7vw, 1.5rem);        /* ~24px */
    line-height: 1.3;
    color: var(--heading);
    a { color: inherit; border-bottom: 0; }
    a:hover { color: var(--prime); }
}
.ins-card__teaser {
    margin-bottom: 0.9em;
    color: var(--body);
    font-size: 1rem;                                 /* ~16px */
    line-height: 1.55;
    p { margin: 0; }
}

/* --------------------------------------------------------------------------
   FEATURED — copy column + a dark pull-quote panel
   --------------------------------------------------------------------------
   The design's panel is 17px taller than the white card and overhangs it; not
   reproduced (see the capture note) — both columns are equal height here.
   -------------------------------------------------------------------------- */
.ins-featured {
    display: grid;
    grid-template-columns: minmax(0, 936fr) minmax(0, 916fr);
    background: var(--white);
}
.ins-featured__copy {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    padding: clamp(1.75rem, 3vw, 3rem);
}
.ins-card__cat--featured { color: var(--red-700); }
.ins-featured__title {
    margin: 0 0 0.5em;
    font-family: var(--type-display);
    font-weight: 700;
    font-size: clamp(1.75rem, 3vw, 2.8125rem);       /* ~45px */
    line-height: 1.15;
    color: var(--heading);
    a { color: inherit; border-bottom: 0; }
    a:hover { color: var(--prime); }
}
.ins-featured__teaser {
    color: var(--body);
    font-size: clamp(1rem, 1.25vw, 1.1875rem);       /* ~19px */
    line-height: 1.55;
    p { margin: 0; }
}
.ins-featured__cta { margin: clamp(1.25rem, 2.4vw, 2rem) 0 clamp(1.5rem, 3vw, 2.5rem); }
/* the meta line sits at the bottom of the copy column */
.ins-featured__copy .ins-meta { margin-top: auto; }

.ins-featured__panel {
    display: grid;
    place-items: center;
    padding: clamp(2rem, 4vw, 3.75rem);
    background: var(--ink);
    blockquote { margin: 0; }
    p {
        margin: 0;
        color: var(--white);
        font-family: var(--type-display);
        font-weight: 600;
        font-size: clamp(1.25rem, 1.95vw, 1.75rem);      /* ~28px */
        line-height: 1.35;
    }
}
/* Image variant: the photo fills the right panel instead of the quote (the
   designer's note on the Insights board — "if image template uses image").
   Same cell, so the card's proportions don't change between the two. */
.ins-featured__media {
    margin: 0;
    display: grid;
    background: var(--ink);
    img {
        display: block;
        width: 100%;
        height: 100%;
        object-fit: cover;
    }
}

@media only screen and (max-width: 860px) {
    .ins-featured { grid-template-columns: 1fr; }
    /* stacked, the right side (the quote panel or the photo) goes on top (John, 16 Oct) */
    :is(.ins-featured__panel, .ins-featured__media) { order: -1; }
    /* keep the photo from becoming a tall band once stacked */
    .ins-featured__media { aspect-ratio: 916 / 437; }
}

/* --------------------------------------------------------------------------
   FILTER PILLS — the extension's reset item is the design's "All"
   --------------------------------------------------------------------------
   The active item is rendered as <strong>, the rest as <a>, so both are styled.
   -------------------------------------------------------------------------- */
.ins-filters {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin: 0;
    padding: 0;
    list-style: none;
}
.ins-filters__item { margin: 0; }
.ins-filter {
    display: inline-flex;
    align-items: center;
    min-height: 39px;
    padding: 0 1.25rem;
    border: 1px solid #C4CCD6;
    border-radius: 24px;
    background: var(--white);
    color: var(--body);
    font-size: 0.875rem;                             /* ~14px */
    line-height: 1;
    text-decoration: none;
}
a.ins-filter:hover {
    border-color: var(--prime);
    color: var(--prime);
}
.ins-filter.is-active {
    border-color: var(--prime);
    background: var(--prime);
    color: var(--white);
    font-weight: 600;
}
/* 39px is the board's pill height and is fine for a mouse, but these are real
   controls — the only way to filter the list — so on touch they take the same
   44px minimum as a button (WCAG 2.5.5). Desktop keeps the design's height. */
@media only screen and (max-width: 1050px) {
    .ins-filter { min-height: 44px; }
}

/* --------------------------------------------------------------------------
   READER
   -------------------------------------------------------------------------- */
/* board: eyebrow -> rule 31px of 2400 */
.ins-article__eyebrow { margin: 0 0 clamp(0.9rem, 1.3vw, 1.9375rem); }
.ins-article__head {
    border-top: 1px solid var(--prime);
    border-bottom: 1px solid var(--prime);
    padding-block: clamp(1.5rem, 3vw, 2rem);
    margin-bottom: clamp(2rem, 4vw, 3.75rem);
    h1 {
        margin: 0 0 0.35em;
        max-width: 1400px;
    }
}
.ins-article__lead {
    max-width: 1400px;
    color: var(--body);
    font-size: clamp(1.1rem, 1.5vw, 1.375rem);       /* ~22px */
    line-height: 1.5;
    p { margin: 0 0 0.5em; }
}
.ins-article__byline {
    margin: clamp(1rem, 2vw, 1.5rem) 0 0;
    color: var(--text-muted);
    font-size: 0.875rem;                             /* ~14px */
}

/* body column + sidebar: 1132 | 380 of 1800 */
.ins-article__body {
    display: grid;
    grid-template-columns: minmax(0, 1132fr) minmax(0, 380fr);
    column-gap: clamp(2.5rem, 8vw, 143px);
    align-items: start;
}
.ins-article__main {
    max-width: 1132px;
    p {
        color: #333B44;
        font-size: clamp(1.0625rem, 1.4vw, 1.25rem);     /* ~20px */
        line-height: 1.75;
    }
    /* the design opens the article on a bolder paragraph */
    .ins-lead p { font-weight: 700; }
    h2 {
        margin: 2em 0 0.8em;
        font-family: var(--type-display);
        font-weight: 600;
        font-size: clamp(1.4rem, 2.2vw, 2rem);           /* ~32px */
        color: var(--heading);
    }
    /* pull quote: a 3px navy rule on the left, text inset from it */
    .ins-pull {
        margin: clamp(1.75rem, 3vw, 2.5rem) 0;
        border-left: 3px solid var(--prime);
        padding-left: clamp(1.25rem, 2.2vw, 2.1875rem);
        padding-block: clamp(0.25rem, 0.42vw, 0.625rem);   /* the bar runs 10px past the text (board) */
    }
    .ins-pull p {
        margin: 0;
        max-width: 54rem;   /* the board's 865px measure */
        color: var(--heading);
        font-family: var(--type-display);
        font-weight: 600;
        font-size: clamp(1.25rem, 1.95vw, 1.75rem);      /* ~28px */
        line-height: 1.35;
    }
}

/* sidebar blocks: a small caps label over a hairline */
.ins-aside__block + .ins-aside__block { margin-top: clamp(1.5rem, 3vw, 2rem); }
.ins-aside__label {
    margin: 0 0 0.75rem;
    padding-bottom: 0.75rem;
    border-bottom: 1px solid var(--prime);
    color: var(--text-muted);   /* was #9AA5B3: under WCAG AA on cream (8 Oct) */
    font-size: 0.6875rem;                            /* ~11px */
    font-weight: 600;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}
.ins-aside__links {
    margin: 0;
    color: var(--prime);
    font-size: 0.9375rem;                            /* ~15px */
    font-weight: 600;
    a { color: inherit; }
    span { margin: 0 0.5rem; color: var(--text-muted); }
}
/* "Copy link" is a button so it can use the clipboard; make it read as a link */
.ins-copy {
    border: 0;
    padding: 0;
    background: none;
    color: inherit;
    font: inherit;
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 3px;
}
/* RELATED — module 24 → news_latest_related.html.twig, one <a> per item.
   The board sets these at 17/500 navy under the shared aside label, stacked
   with a hairline between. */
.ins-related {
    display: flex;
    flex-direction: column;
    /* A news module wraps its items twice — `.mod_newslist > .layout_wrapper` —
       so the links are grandchildren, not flex items, and the three of them ran
       together as one paragraph. `display: contents` lifts them out of the
       wrappers without changing the markup, the same fix `.ins-grid` needs. */
    > .mod_newslist, .layout_wrapper { display: contents; }
}
.ins-related__link {
    font-family: var(--type-display);
    font-weight: 500;
    font-size: 1.0625rem;                            /* ~17px */
    line-height: 1.35;
    color: var(--heading);
    border-bottom: 0;
    + .ins-related__link {
        margin-top: 1rem;
        border-top: 1px solid var(--hairline);
        padding-top: 1rem;
    }
    /* the link is a block (a flex item): underline the words, not the box */
    &:hover { color: var(--prime); border-bottom: 0; text-decoration: underline; text-underline-offset: 0.2em; text-decoration-thickness: 1px; }
}

/* ==========================================================================
   READER — the article's own image, and the way back
   ========================================================================== */
/* An image set in the article's settings leads the body column. Block spacing
   matches the gap this column puts between its own blocks, so the image reads
   as the first block rather than as part of the header above it. */
.ins-article__media {
    margin: 0 0 clamp(1.5rem, 3vw, 2.25rem);
    img {
        display: block;
        width: 100%;
        height: auto;
        border-radius: 12px;
    }
}

/* "← All insights". Not on the board; John asked for it, because the reader is
   otherwise a dead end. Sits under the two-column body, aligned with the copy
   column rather than centred, and clears the body above it. */
.ins-article__back {
    margin: clamp(2rem, 4vw, 3rem) 0 0;
    a.btn { margin: 0; }
}

/* The filter row is a scroll target: every category pill links to
   #insights-list so the results are what you land on. The offset clears the
   fixed header, which would otherwise sit over the pills. */
#insights-list {
    scroll-margin-top: clamp(96px, 12vw, 140px);
}

@media only screen and (max-width: 992px) {
    .ins-article__body { grid-template-columns: 1fr; row-gap: 2.5rem; }
}

/* ==========================================================================
   INSIGHTS   body.page-insights
   ==========================================================================
   The list and reader are article-cards.css. This file: #subscribe, the
   newsletter band — a Contao form (tl_form "insights-subscribe") laid out as
   one centred row: email field beside a white button. The field's label is
   for screen readers only (`.ins-sr-label`, the field's CSS class).
   ========================================================================== */

body.page-insights .hero__frame { --hero-frame-max: 72.2%; }   /* the board's 1300 of 1800 */

#subscribe {
    text-align: center;

    h2 {
        margin: 0 0 clamp(1.5rem, 3vw, 2.25rem);
        color: var(--white);
    }

    /* The label is for screen readers only — the design shows the placeholder. */
    .ins-sr-label label,
    & label.ins-sr-label {
        position: absolute;
        width: 1px;
        height: 1px;
        margin: -1px;
        padding: 0;
        overflow: hidden;
        clip-path: inset(50%);
        white-space: nowrap;
    }

    .confirmation p { margin: 0; color: var(--white); }

    .formbody {
        display: flex;
        flex-wrap: wrap;
        align-items: flex-start;
        justify-content: center;
        gap: 16px;
        margin: 0;

        /* Contao wraps each field in .widget; the email field takes the
           design's 560px and the submit sits beside it. These have to be
           `flex`, not `width` — forms.css gives every widget
           `flex-basis: 100%`, which beats a width on a flex item. */
        > .widget { margin: 0; }

        /* Spam protection, FLOATING (John, 8 Oct): no checkbox on the page —
           the check runs when the email field is focused, and altcha only
           pops up over the button if someone submits before it has finished.
           The widget's wrapper takes no room in the row. */
        .ins-altcha {
            flex: 0 0 0;
            min-width: 0;
            height: 0;
            margin: 0;
        }
        /* Floating altcha still pops its box (a ticked "I'm human") under the
           button once the focus check has run. Nothing shows: the check and
           its token work the same, and a submit before it finishes waits. */
        .ins-altcha altcha-widget .altcha { display: none !important; }
        .widget-text   { flex: 0 1 min(560px, 100%); }
        .widget-submit { flex: 0 0 auto; }

        /* The hidden token inputs are display:none, but be explicit so they can
           never become flex items and earn a gap (as Contao's post-form
           <script> once did). */
        > input[type="hidden"] { display: none; }

        input:not([type="submit"]) {
            width: 100%;
            text-align: left;
        }
        input:focus-visible {
            outline: 2px solid var(--white);
            outline-offset: 2px;
            border-color: var(--white);
        }

        button {
            min-height: 48px;
            padding: 0 1.5rem;
            border: 0;
            border-radius: 5px;
            background: var(--white);
            color: var(--ink);
            font-family: var(--type-body);
            font-size: 0.9375rem;
            font-weight: 600;
            cursor: pointer;

            &:hover { background: var(--cream); }
        }

        /* Validation reads on the dark band. */
        p.error, .error { color: #FFD9DA; }
        span.mandatory { display: none; }
    }
}

/* ==========================================================================
   COMPLEX PLAN DESIGN   body.page-complex-plan-design
   ==========================================================================
   Sections by id: #built-to-hold-up, #later-start.
   ========================================================================== */

body.page-complex-plan-design {
    /* the board's column dividers: 296px; 175px on the difference band (its
       second row's 296 runs through the rule under it on the board) */
    .feature-cols { --fc-rule-h: min(12.333vw, 296px); }
    .difference .feature-cols { --fc-rule-h: min(7.292vw, 175px); }
    /* the same space above and below each rule (Bob, 13 Oct) */
    .difference .feature-cols + .feature-cols--top { margin-top: var(--fc-rule-gap); }
}

/* Built to hold up: the red wash re-scaled for a full-width band (decor.css
   tunes it for a 1200 half); no rule under the row */
#built-to-hold-up {
    --decor-red-w: 74%;
    --decor-red-out: -26%;
    --decor-red-strength: 0.85;
    .feature-cols--btm::after { content: none; }
}

/* The later the start: no line under the age chart */
#later-start .bc-plot { border-bottom: 0; }

/* ==========================================================================
   CONSULTING & ACTUARIAL SERVICES   body.page-consulting-actuarial-services
   ==========================================================================
   Section by id: #actuaries.
   ========================================================================== */

body.page-consulting-actuarial-services {
    .feature-cols { --fc-rule-h: min(12.333vw, 296px); }   /* the board's 296px dividers */
    /* the scenario chart: 700 bar labels, no rule above its note */
    .bc-label { font-weight: 700; }
    .bar-compare .bc-note { border-top: 0; }
}

/* Actuaries on staff: the red wash re-scaled for a full-width band */
#actuaries {
    --decor-red-w: 74%;
    --decor-red-out: -26%;
    --decor-red-strength: 0.85;
}

/* FOR CPAs   body.page-for-cpas — everything else is a shared component */
body.page-for-cpas .hero__frame { --hero-frame-max: 94.6%; }   /* the board's 1702 of 1800 */

/* ==========================================================================
   SPLIT — the boards' editorial two-column band: 760 | 100 | 940 of 1800
   ==========================================================================
   42.2% | 5.6% gap | 52.2%. Used wherever a heading (or copy) sits left of the
   body or a visual: What We Do and Resources' numbered bands, every Case Study.
   Not a col-* pair — the gap is a PERCENTAGE so it keeps its share at every
   width, and the widths use the framework's `P% - gap x P` so the row sums
   exactly. Stacks at the framework's 992.

   Build: element_group `row split` with two children (no col-* on them).
   ========================================================================== */
.split {
    --gap-x: 5.56%;
    --gap-y: var(--space-40);
    align-items: start;

    > :first-child { flex: 0 0 calc(44.7% - var(--gap-x) * 0.447); }
    > :last-child  { flex: 0 0 calc(55.3% - var(--gap-x) * 0.553); }
}
@media only screen and (max-width: 992px) {
    .split {
        --gap-x: 0px;
        /* the same selectors as the widths above, or (0,1,0) loses to their (0,2,0) */
        > :first-child, > :last-child { flex: 0 0 100%; }
    }
}

