@charset "UTF-8";
/* =========================================================================
   Omnivery 2026 design system
   Palette is the brand manual (omnivery-logo-manual.pdf, p.6) — the only
   4 brand colors. Fonts: Poppins + IBM Plex Mono (p.7).
   Loaded LAST in base.html.twig so it wins over Spectre + compiled theme.
   Frontend-only (never loaded by Grav admin).
   ========================================================================= */
:root{
  --navy:#243842;       /* brand — primary dark */
  --navy-deep:#1b2b33;  /* darker shade of brand navy (stat band) */
  --slate:#546670;      /* brand — muted / secondary */
  --amber:#FBB040;      /* brand — primary accent */
  --orange:#F26522;     /* brand — secondary accent */
  --ink:#243842;        /* body text = brand navy */
  --paper:#fff;
  --mist:#f4f6f7;
  --line:#e4eaec;
}

/* ---- global frontend base (light) ---- */
body{
  background:var(--paper);
  color:var(--ink);
  font-family:'Poppins',system-ui,sans-serif;
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
}
.wrap{max-width:960px;margin:0 auto;padding:0 24px}
/* align the Spectre containers (header nav + blog/default pages) to the same
   960px content width used by .wrap everywhere else */
#header .container{max-width:960px;padding-left:24px;padding-right:24px}
#body-wrapper .container{max-width:960px;padding-left:24px;padding-right:24px}
.eyebrow{
  font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--amber);font-weight:500;margin:0 0 14px;
}

/* =========================================================================
   HEADER / NAV  (site-wide navy sticky bar)
   ========================================================================= */
#header,
#header.scrolled{
  background:var(--navy)!important;
  border-bottom:none!important;
  position:sticky;top:0;z-index:30;
  height:auto;
  box-shadow:none;
}
#header .navbar{padding:14px 0;min-height:0}
#header .navbar-section{height:auto!important}
/* logo */
#header .logo svg,
#header .navbar-section.logo svg{height:26px;width:auto}
/* nav links
   NOTE the `> ul` child combinator: this rule must not reach the nested <ul>
   of a dropdown, or the submenu is laid out as a horizontal flex row instead
   of a stacked panel. Same class of collision as .wrap/.statband-head. */
#header .dropmenu > ul{display:flex;align-items:center;gap:22px;margin:0}
#header .dropmenu ul li a,
#header a{
  font-family:'IBM Plex Mono',monospace;font-size:13px;font-weight:400;
  color:#b9c9cf;border:none;text-transform:none;
}
#header .dropmenu ul li a:hover,
#header .dropmenu ul li a:focus,
#header .dropmenu ul li a.active{color:#fff!important}

/* ---- one-level dropdown submenus ----------------------------------------
   Base behaviour already ships in css-compiled/theme.min.css: `.dropmenu ul ul`
   is absolute + visibility:hidden, `.dropmenu ul li:hover > ul` reveals it, and
   `.dropmenu.animated ul ul` supplies the translateY/opacity transition. The
   caret is automatic too - theme.min.css emits '\f107' on every nav <a> and
   blanks it for `a:only-child`, so a leaf <li> (anchor only) has no caret while
   a .has-children <li> (anchor + <ul>) gets one. What is missing is the 2026
   brand skin, a hover bridge, and keyboard access. */

/* Hover bridge: pad the top-level <li> so the pointer never crosses dead space
   between the link and the panel. Padding moves off the <a> onto the <li> to
   keep the flex row's vertical rhythm identical to before. */
#header .dropmenu > ul > li{padding:8px 0}
#header .dropmenu > ul > li > a{padding:7px 0}
/* theme.min.css floats the caret right with a -20px pull, which assumed the old
   30px right padding. Re-flow it inline so .has-children and leaf items keep the
   same horizontal spacing inside the 22px flex gap. */
#header .dropmenu > ul > li.has-children > a:before{
  content:'\f107';font-family:FontAwesome;
  float:none;margin:0 0 0 6px;font-size:11px;opacity:.6;vertical-align:baseline;
}
/* The panel. theme.min.css defaults it to background:#fff. */
/* display:block is load-bearing. theme.min.css carries its own UNSCOPED
   `.dropmenu ul{display:flex}`, which reaches this nested <ul> too, and it only
   switches to block via `.dropmenu ul li:hover > ul`. Without an explicit block
   here the keyboard (:focus-within) path below would reveal a horizontal row. */
#header .dropmenu > ul > li > ul{
  display:block;
  left:0;min-width:238px;z-index:40;padding:8px 0;gap:0;list-style:none;
  background:var(--navy-deep,#1b2b33);border:1px solid rgba(255,255,255,.09);
  border-radius:10px;box-shadow:0 12px 32px rgba(0,0,0,.28);
}
#header .dropmenu > ul > li > ul > li{display:block;margin:0;padding:0}
/* Beats `.dropmenu ul ul a{color:#454d5d!important}` from theme.min.css, which
   would otherwise render submenu text dark grey on the navy panel. */
#header .dropmenu > ul > li > ul > li > a{
  display:block;padding:8px 18px;white-space:nowrap;color:#b9c9cf!important;
}
#header .dropmenu > ul > li > ul > li > a:hover,
#header .dropmenu > ul > li > ul > li > a:focus{
  color:#fff!important;background:rgba(255,255,255,.06);
}
/* Second-level items must not inherit the parent's caret ('\f105' in base). */
#header .dropmenu > ul > li > ul > li > a:before{content:none}
/* Group labels inside a dropdown (a `heading:` entry in site.menu). Not links, so
   they need their own type treatment; the first one drops its top margin so the
   panel's own 8px padding is not doubled. */
#header .dropmenu > ul > li > ul > li.menu-heading{padding:0}
#header .dropmenu > ul > li > ul > li.menu-heading > span{
  display:block;padding:12px 18px 5px;font-family:'IBM Plex Mono',monospace;
  font-size:10px;letter-spacing:.11em;text-transform:uppercase;color:#7c949d;
}
#header .dropmenu > ul > li > ul > li.menu-heading:first-child > span{padding-top:4px}
/* Keyboard access: base CSS reveals on :hover only, so tabbing into a submenu
   link would leave the panel hidden. */
#header .dropmenu > ul > li:focus-within > ul{
  visibility:visible;opacity:1;transform:none;
}
/* login link + get started button, grouped together on the right. Hidden
   below 840px alongside .desktop-menu - they move into the hamburger
   overlay instead (.overlay-cta below), not into the collapsed header. */
#header .navbar-section.nav-cta{display:flex;align-items:center;gap:18px}
#header .navbar-section.nav-cta .nav-login{white-space:nowrap}
@media (max-width:840px){#header .navbar-section.nav-cta{display:none}}
/* get started button */
#header .navbar-section .btn.btn-start{
  background:var(--amber);border-color:var(--amber);color:var(--navy)!important;
  border-radius:8px;padding:9px 18px;font-family:'IBM Plex Mono',monospace;
  font-weight:600;font-size:13px;text-transform:none;height:auto;line-height:normal;
}
#header .navbar-section .btn.btn-start:hover{background:#e89b2e;border-color:#e89b2e}

/* mobile hamburger + overlay recolor (markup/JS unchanged) */
/* Bordered, rounded chip instead of the bare 28x24 bars the base theme
   ships - modeled on the docs site's #navToggle (localhost:8090/resources/docs),
   which uses a 36x36 box with a 1px/22%-opacity border and 8px radius.
   The 8px vertical gap between bars (top:9/17/25) is unchanged from the
   base theme's default gap, so `.button_container.active`'s
   translateY(+-8px) X-transform still lands correctly - only size/spacing
   changed, not the open/close animation. */
#toggle{
  width:36px;height:36px;top:9px;right:40px;box-sizing:border-box;
  border:1px solid rgba(255,255,255,.22);border-radius:8px;background:transparent;
}
#toggle > span{background:#b9c9cf;width:22px;height:2px;left:7px;border-radius:2px}
#toggle > span:nth-of-type(1){top:9px}
#toggle > span:nth-of-type(2){top:17px}
#toggle > span:nth-of-type(3){top:25px}
/* .overlay-menu's inherited `overflow-y:scroll` (base theme) permanently
   reserves a scrollbar gutter even when content doesn't overflow, eating
   into the 24px right column unevenly - switch to auto so it only appears
   when actually scrolling. */
#overlay .overlay-menu{overflow-y:auto}
.mobile-container .overlay,
#overlay{background:var(--navy)}
.mobile-container .overlay.open,
#overlay.open{background:var(--navy);opacity:1}
#overlay nav ul li a{font-family:'IBM Plex Mono',monospace;color:#cfe0e4}
#overlay nav ul li a:hover{color:#fff}

/* ---- overlay alignment system --------------------------------------------
   One 24px side padding, reused by the logo, the nav list and the CTA
   buttons, so every element's left/right edge lines up - modeled on the
   docs site's mobile menu (localhost:8090/resources/docs), which uses the
   same single-column trick instead of the mismatched margins this overlay
   had before (16px tree-root margin + 19.2px per-link margin from the base
   .treemenu rules, none of it matching the logo's 24px). */
.mobile-logo{padding:24px 24px 0}
#overlay .mobile-logo svg,
#overlay .mobile-logo img{height:26px;width:auto;margin:0}
#overlay .overlay-menu{padding:0 24px}
#overlay .overlay-menu > ul.tree{margin:0}
#overlay .overlay-menu a{margin-left:0}

/* Top-level items: left-aligned text, a hairline divider between rows (not
   after the last one), and the toggler moved to the right of the label via
   flex `order` - the JS prepends the toggler span before the <a>, so this
   reorders it visually without touching jquery.treemenu.js. */
#overlay > nav > ul.tree > li{border-bottom:1px solid rgba(255,255,255,.1)}
#overlay > nav > ul.tree > li:last-child{border-bottom:none}
#overlay > nav > ul.tree > li > a{padding:11px 0}
#overlay > nav > ul.tree > li.has-children{display:flex;flex-wrap:wrap;align-items:center}
#overlay > nav > ul.tree > li.has-children > a{flex:1 1 auto;order:1}
#overlay > nav > ul.tree > li.has-children > span.toggler{order:2;flex:0 0 auto}
#overlay > nav > ul.tree > li.has-children > ul{flex-basis:100%;order:3}
/* jquery.treemenu.js injects a .toggler span into EVERY li and marks
   childless ones .tree-empty, so custom.css blanket-hides the glyph with
   `#overlay > nav > ul > li > span.toggler::before{content:none}` - correct
   back when no top-level item had children, but it also hides the +/-
   affordance now that the menu has groups. Restore it for real groups only.
   This rule is both later-loading and higher-specificity than the
   custom.css one, so it wins. */
#overlay > nav > ul.tree > li.has-children > span.toggler::before{
  content:'+';display:inline-block;color:var(--amber);font-weight:600;font-size:16px;
}
#overlay > nav > ul.tree > li.has-children.tree-opened > span.toggler::before{content:'\2212'}
/* Indent and de-emphasise second-level items so the hierarchy is legible -
   16px beyond the 24px base column, same ratio as the docs reference. */
#overlay nav ul li.has-children > ul{margin:4px 0 8px 16px}
#overlay nav ul li.has-children > ul > li{background:none;margin-bottom:0}
#overlay nav ul li.has-children > ul > li > a{font-size:.95rem;color:#b9c9cf;padding:8px 0}

/* Log in + Get started, moved here from the collapsed header (see
   .navbar-section.nav-cta above) so mobile keeps both without a second
   header row. Stacked, full-width buttons in the same column as the logo
   and nav text, rather than a centered inline pair. */
.overlay-cta{display:flex;flex-direction:column;gap:8px;padding:16px 0 24px}
.overlay-cta .nav-login,
.overlay-cta .btn.btn-start{
  display:block;width:100%;box-sizing:border-box;text-align:center;
  border-radius:8px;padding:10px 8px;font-family:'IBM Plex Mono',monospace;
  font-size:14px;font-weight:600;text-transform:none;height:auto;line-height:normal;
}
.overlay-cta .nav-login{background:transparent;border:1px solid rgba(255,255,255,.22);color:#e6edf0}
.overlay-cta .nav-login:hover{color:#fff;border-color:rgba(255,255,255,.4)}
.overlay-cta .btn.btn-start{background:var(--amber);border:1px solid var(--amber);color:var(--navy)!important}
.overlay-cta .btn.btn-start:hover{background:#e89b2e;border-color:#e89b2e}
/* treemenu injects a .toggler into EVERY li and marks childless ones .tree-empty,
   which renders a '\2022' bullet. On a second-level item that bullet is not a list
   marker, it is the "this branch has no children" affordance leaking through - and
   on a group label it reads as a broken link. Hide it at this level; custom.css
   already does the equivalent for the top level. */
#overlay nav ul li.has-children > ul li > span.toggler{display:none}
/* group labels in the mobile tree */
#overlay nav ul li.has-children > ul > li.menu-heading{margin:10px 0 2px}
/* :not(.toggler) is required. treemenu prepends its own <span class="toggler">
   into every li, so a bare `> span` here also matched the toggler and re-showed
   it at higher specificity than the hide rule above - a stray bullet beside each
   group label. */
#overlay nav ul li.has-children > ul > li.menu-heading > span:not(.toggler){
  display:block;font-family:'IBM Plex Mono',monospace;font-size:10px;
  letter-spacing:.11em;text-transform:uppercase;color:#7c949d;margin-left:0;
}
#overlay nav ul li.has-children > ul > li.menu-heading:first-child{margin-top:2px}

/* =========================================================================
   FOOTER  (navy 3-col)
   ========================================================================= */
#footer{background:var(--navy)!important;padding:48px 0 36px!important;border:none;text-align:left}
.site-footer-2026{color:#9db4bc;font-size:14px;text-align:left}
.site-footer-2026 .foot-grid > div{text-align:left}
.site-footer-2026 .wrap{max-width:960px;margin:0 auto;padding:0 24px}
/* scope link reset under #footer so it beats .ov-page a (footer lives inside body.ov-page) */
#footer a{color:#cfe0e4;text-decoration:none;border-bottom:none}
#footer a:hover{color:#fff}
/* brand column + 4 link columns (Products / Alternatives / Solutions / Company) */
.site-footer-2026 .foot-grid{
  display:grid;grid-template-columns:1.4fr repeat(4,1fr);gap:32px;margin-bottom:32px;
}
.site-footer-2026 .foot-grid .brandcol .logo svg{height:30px;width:auto;margin-bottom:16px}
.site-footer-2026 .foot-grid .tagline{max-width:340px;font-size:13.5px;line-height:1.6;color:#9db4bc;margin:0}
.site-footer-2026 .foot-grid h4{
  font-family:'IBM Plex Mono',monospace;font-size:11.5px;letter-spacing:.08em;
  text-transform:uppercase;color:#8aa2ab;margin:0 0 14px;font-weight:500;
}
/* Column headings link to their section hub. Inherit the muted heading colour
   rather than the brighter #footer a colour, so the heading still reads as a
   heading; brighten only on hover. */
.site-footer-2026 .foot-grid h4 a{color:inherit}
.site-footer-2026 .foot-grid h4 a:hover{color:#cfe0e4}
.site-footer-2026 .foot-grid ul{list-style:none;padding:0;margin:0}
.site-footer-2026 .foot-grid ul li{margin:0 0 9px;font-size:13.5px}
.site-footer-2026 .certs{
  display:flex;flex-wrap:wrap;gap:24px;align-items:center;justify-content:space-between;
  padding-top:28px;border-top:1px solid rgba(255,255,255,.1);
}
.site-footer-2026 .certs a{display:inline-flex;align-items:center;border:none;flex:0 1 auto}
.site-footer-2026 .certs img{height:42px;width:auto;object-fit:contain;opacity:.9;transition:opacity .2s}
.site-footer-2026 .certs a:hover img{opacity:1}
.site-footer-2026 .copyright{
  margin-top:26px;font-size:12.5px;color:#7c949d;font-family:'IBM Plex Mono',monospace;
}
.site-footer-2026 .copyright a{color:#7c949d}
.site-footer-2026 .copyright a:hover{color:#cfe0e4}

/* =========================================================================
   HOMEPAGE  (scoped under body.ov-page)
   Sections render full-bleed inside #start; each supplies its own .wrap.
   ========================================================================= */
.ov-page #start{padding:0}

/* section rhythm for the light middle sections */
.ov-page .case,
.ov-page .security,
.ov-page .compliance,
.ov-page .switch,
.ov-page .feature-section.plain{
  padding:52px 0;border-bottom:1px solid var(--line);
}
.ov-page .trusted{padding:52px 0;border-bottom:1px solid var(--line)}
.ov-page .cta-section{padding:52px 0}
.ov-page h2{font-size:clamp(24px,3.4vw,33px);font-weight:700;margin:0 0 8px;letter-spacing:-.01em;color:var(--ink)}
.ov-page h3{font-size:19px;font-weight:600;margin:0 0 6px;color:var(--ink)}
.ov-page p{margin:14px 0}
.ov-page .lead{font-size:19px;color:#33474f}
.ov-page a{color:var(--orange);text-decoration:none}
.ov-page a:hover{border-color:var(--orange)}

/* hero */
.ov-page .hero{display:block;background:var(--navy);color:#eef3f4;padding:72px 0 80px;position:relative;overflow:hidden}
.ov-page .hero:after{content:"";position:absolute;right:-120px;top:-100px;width:380px;height:380px;border:2px solid rgba(251,176,64,.15);border-radius:50%}
.ov-page .hero:before{content:"";position:absolute;right:40px;top:120px;width:180px;height:180px;border:2px solid rgba(84,102,112,.20);border-radius:50%}
.ov-page .hero h1{font-size:clamp(34px,5.8vw,58px);line-height:1.04;font-weight:700;margin:0 0 22px;letter-spacing:-.01em;max-width:780px;color:#fff}
.ov-page .hero h1 .hl{color:var(--amber)}
.ov-page .hero .dek{font-size:clamp(16px,2.3vw,19px);color:#b9c9cf;max-width:650px;margin:0 0 32px}
.ov-page .hero-cta{display:flex;flex-wrap:wrap;gap:14px;align-items:center}
.ov-page .hero-cta a{font-family:'IBM Plex Mono',monospace;font-size:14px;text-decoration:none;border:none}
.ov-page .hero-cta a.primary{background:var(--amber);color:var(--navy);border-radius:8px;padding:13px 26px;font-weight:600}
.ov-page .hero-cta a.ghost{color:#dfe8ea;border:1px solid rgba(255,255,255,.22);border-radius:8px;padding:13px 24px;font-weight:500}
.ov-page .hero-cta a.ghost:hover{border-color:var(--amber);color:var(--amber)}
.ov-page .hero-meta{margin-top:36px;display:flex;flex-wrap:wrap;gap:10px 26px;font-family:'IBM Plex Mono',monospace;font-size:12.5px;color:#88a0a9}
.ov-page .hero-meta b{color:#dfe8ea;font-weight:500}

/* stat band */
.ov-page .statband{background:var(--navy-deep);color:#fff;padding:38px 0}
.ov-page .statband .statband-head{text-align:center;margin-bottom:30px}
.ov-page .statband .statband-title{color:#fff;font-size:clamp(20px,2.6vw,26px);font-weight:700;margin:0 0 10px}
.ov-page .statband .statband-intro,.ov-page .statband .statband-intro p{color:#b9c9cf;font-size:15px;line-height:1.6;margin:0 auto;max-width:760px}
.ov-page .statband .wrap:not(.statband-head){display:flex;flex-wrap:wrap;gap:24px;justify-content:space-between}
.ov-page .stat{flex:1 1 155px}
.ov-page .stat .num{font-family:'IBM Plex Mono',monospace;font-size:clamp(28px,4.4vw,40px);font-weight:600;color:var(--amber);line-height:1}
.ov-page .stat .lbl{font-size:12.5px;color:#a7bcc4;margin-top:8px;line-height:1.45}

/* trusted-by */
.ov-page .trusted .eyebrow{text-align:center}
/* auto-scrolling logo marquee (replicates the original Embla autoplay carousel).
   Customer logos ship white (built for dark bg); darkened to gray for the light strip. */
.ov-page .logos-marquee{overflow:hidden;margin-top:30px;-webkit-mask:linear-gradient(to right,transparent,#000 10%,#000 90%,transparent);mask:linear-gradient(to right,transparent,#000 10%,#000 90%,transparent)}
.ov-page .logos-track{display:flex;align-items:center;width:max-content;animation:ov-logos-scroll 45s linear infinite}
.ov-page .logos-marquee:hover .logos-track{animation-play-state:paused}
.ov-page .logo-slide{flex:0 0 auto;margin-right:72px;display:inline-flex;align-items:center;border:none}
.ov-page .logo-slide img{height:46px;width:auto;filter:brightness(0) opacity(.5);transition:filter .2s}
.ov-page .logo-slide:hover img{filter:brightness(0) opacity(.9)}
@keyframes ov-logos-scroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
@media (prefers-reduced-motion: reduce){.ov-page .logos-track{animation:none;flex-wrap:wrap;justify-content:center;row-gap:28px}}

/* callout / case study */
.ov-page .callout{background:var(--mist);border-left:4px solid var(--amber);border-radius:0 10px 10px 0;padding:28px 30px;margin:8px 0 0}
.ov-page .callout .q{font-size:21px;font-weight:600;line-height:1.42;margin:0}
/* A callout's background is --mist, so inside a .mist section it disappears and
   the quote loses its container - only the amber rule and the padding survive.
   Affects the finance, MTA-replacement, SMTP-relay and case-study pages, all of
   which put a customer quote in a mist band. */
.ov-page .prose-section.mist .callout{background:#fff}
/* Quote attribution: the second <p> in a callout. Smaller and quieter than the
   quote itself so the name reads as a source rather than as more quote. */
.ov-page .callout .q + p{margin:14px 0 0;font-size:14.5px;color:var(--slate);font-weight:600}
.ov-page .casebar{display:flex;flex-wrap:wrap;gap:32px;margin-top:26px;align-items:flex-start}
.ov-page .casebar .num{font-family:'IBM Plex Mono',monospace;font-size:38px;font-weight:600;color:var(--amber);line-height:1}
.ov-page .casebar .lbl{font-size:13px;color:var(--slate);margin-top:6px}
.ov-page .casebar-link{align-self:center}

/* feature blocks */
.ov-page .feature.navy{background:var(--navy);color:#dfe8ea;border-radius:14px;padding:34px 34px 26px;margin:6px 0}
.ov-page .feature-section.navy{padding:52px 0}
.ov-page .feature.navy h2{color:#fff}
.ov-page .feature.navy p{color:#b9c9cf}
.ov-page .feature.navy .eyebrow{color:var(--amber)}
.ov-page .feature-link{color:var(--amber);border-bottom-color:rgba(251,176,64,.4)}
.ov-page .feature-link:hover{border-bottom-color:var(--amber)}
/* Optional secondary link (feature.link2_url), used to cite a source alongside
   the primary CTA. Muted so it reads as attribution rather than a second CTA. */
.ov-page .feature-link-alt{margin-left:22px;color:#b9c9cf;border-bottom-color:rgba(185,201,207,.35)}
.ov-page .feature-link-alt:hover{color:#fff;border-bottom-color:#fff}
@media(max-width:600px){
  .ov-page .feature-link-alt{display:block;margin:12px 0 0}
}

/* clean lists */
.ov-page ul.clean{list-style:none;padding:0;margin:18px 0 0}
.ov-page ul.clean li{padding:11px 0 11px 30px;position:relative;border-bottom:1px solid var(--line);font-size:15px}
.ov-page ul.clean li:last-child{border-bottom:none}
.ov-page ul.clean li:before{content:"";position:absolute;left:4px;top:19px;width:8px;height:8px;background:var(--amber);border-radius:2px}
.ov-page ul.clean li b{font-weight:600}
.ov-page .feature.navy ul.clean li{border-color:rgba(255,255,255,.1)}

/* cards grid */
.ov-page .cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:18px;margin-top:26px}
.ov-page .cards.cols-2{grid-template-columns:repeat(2,1fr)}
.ov-page .cards.cols-3{grid-template-columns:repeat(3,1fr)}
@media(max-width:680px){.ov-page .cards.cols-2,.ov-page .cards.cols-3{grid-template-columns:1fr}}
.ov-page .card{border:1px solid var(--line);border-radius:12px;padding:24px;background:var(--paper)}
.ov-page .card .tag{font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--slate);font-weight:600}
/* h4 matches h3 inside a card: a card nested under an h3 section heading needs
   an h4 to keep the outline correct, and it should look identical. */
.ov-page .card h3,
.ov-page .card h4{margin:8px 0 6px;font-size:18px;font-weight:700}
.ov-page .card p{margin:6px 0;font-size:14.5px;color:#33474f}
.ov-page .card a{color:var(--orange);text-decoration:none}
.ov-page .card a:hover{text-decoration:underline}
/* Whole-card link, used by modular/pagecards.html.twig for section hubs. The
   <a> IS the card, so it must reset the inherited link styling above and inherit
   text colour instead, or the whole tile turns orange and underlined on hover. */
.ov-page a.card.cardlink{
  display:block;text-decoration:none;color:inherit;
  transition:border-color .2s,box-shadow .2s,transform .2s;
}
.ov-page a.card.cardlink:hover{
  border-color:var(--amber);box-shadow:0 8px 24px rgba(36,56,66,.10);text-decoration:none;
}
.ov-page a.card.cardlink:hover h3{color:var(--navy)}
.ov-page a.card.cardlink .cardcta{
  display:inline-block;margin-top:12px;font-family:'IBM Plex Mono',monospace;
  font-size:12.5px;color:var(--orange);
}
.ov-page a.card.cardlink:hover .cardcta{text-decoration:underline}
/* navy hubs: keep card text legible if a hub uses variant: navy */
.ov-page .prose-section.navy a.card.cardlink{color:#e6eef1}
.ov-page .prose-section.navy a.card.cardlink p{color:#b9c9cf}
.ov-page .prose-section.navy a.card.cardlink:hover h3{color:#fff}

/* A plain .card inside a navy section keeps its WHITE background, so the navy
   text colours must not reach into it. Unfixed, `.prose-section.navy h3{color:#fff}`
   rendered card headings white-on-white (contrast 1.0, invisible) and
   `.navy .rich-text{color:#b9c9cf}` gave body text 1.7 against a required 4.5.
   Same leak-into-a-child class of bug as the .wrap collision.
   Headings here are stat figures, so they take the house number treatment: orange
   and larger, which also lifts them over the WCAG large-text threshold where
   orange-on-white (3.14) is a pass.

   Note the doubled selectors. `.navy .card p` and `.navy .rich-text p` have
   IDENTICAL specificity (0,0,4,1), so source order alone decided it and the
   .rich-text rule further down the file won - the p stayed at 1.7. The
   `.rich-text .card` variant adds one class to win outright. Both forms are kept
   because cards.html.twig renders .cards directly inside .wrap (no .rich-text
   ancestor) while hand-written cards in a prose body sit inside .rich-text. */
.ov-page .prose-section.navy .card h3,
.ov-page .prose-section.navy .rich-text .card h3{color:var(--orange);font-size:26px;line-height:1.2}
.ov-page .prose-section.navy .card p,
.ov-page .prose-section.navy .rich-text .card p{color:#33474f}
.ov-page .prose-section.navy .card .tag,
.ov-page .prose-section.navy .rich-text .card .tag{color:var(--slate)}
.ov-page .prose-section.navy .card,
.ov-page .prose-section.navy .rich-text .card{color:var(--ink)}
.ov-page ul.checks a{color:var(--orange);text-decoration:none}
.ov-page ul.checks a:hover{text-decoration:underline}

/* comparison table - navy-only, amber/orange reserved for the "soon" status */
.ov-page .switch .eyebrow{color:var(--navy)}
.ov-page .switch table{width:100%;border-collapse:collapse;margin:24px 0 0;font-size:14.5px}
.ov-page .switch th,.ov-page .switch td{padding:11px 12px;text-align:center;border-bottom:1px solid var(--line)}
.ov-page .switch th:first-child,.ov-page .switch td:first-child{text-align:left}
.ov-page .switch th{font-family:'IBM Plex Mono',monospace;font-size:11.5px;letter-spacing:.04em;text-transform:uppercase;color:var(--slate);font-weight:500}
.ov-page .switch td .ok{color:var(--navy);font-weight:600;font-family:'IBM Plex Mono',monospace}
.ov-page .switch td .soon{color:var(--orange);font-family:'IBM Plex Mono',monospace;font-size:12px}
.ov-page .switch td .dash{color:var(--line)}

/* CTA banner */
.ov-page .cta{background:var(--amber);color:var(--navy);border-radius:12px;padding:30px 32px;margin:8px 0 0;display:flex;flex-wrap:wrap;gap:16px;align-items:center;justify-content:space-between}
.ov-page .cta p{margin:0;font-weight:600;font-size:19px;max-width:540px}
.ov-page .cta .grp{display:flex;gap:12px;flex-wrap:wrap}
.ov-page .cta a{background:var(--navy);color:#fff;border:none;border-radius:8px;padding:13px 24px;font-weight:600;font-family:'IBM Plex Mono',monospace;font-size:14px;white-space:nowrap;text-decoration:none}
.ov-page .cta a.alt{background:transparent;color:var(--navy);border:1px solid rgba(36,56,66,.35)}

/* =========================================================================
   BLOG  (same design system as every other page: .page-content > .wrap,
   article body uses .rich-text; listing uses design-system cards)
   ========================================================================= */
/* listing cards */
.ov-page .blog-cards{display:grid;grid-template-columns:1fr 1fr;gap:28px;margin-top:8px}
.ov-page .post-card{display:block;border:1px solid var(--line);border-radius:12px;overflow:hidden;background:var(--paper);text-decoration:none;border-bottom:1px solid var(--line);transition:box-shadow .2s,transform .2s}
.ov-page .post-card:hover{box-shadow:0 10px 30px rgba(36,56,66,.10);transform:translateY(-2px)}
.ov-page .post-card-img img{display:block;width:100%;height:auto;aspect-ratio:16/9;object-fit:cover}
.ov-page .post-card-body{padding:20px 22px 22px}
.ov-page .post-card-title{font-size:19px;font-weight:600;color:var(--ink);margin:0 0 8px;line-height:1.3}
.ov-page .post-card-date{font-family:'IBM Plex Mono',monospace;font-size:12px;color:var(--slate);margin:0}

/* category pill (listing + article) */
.ov-page .post-cat{display:inline-block;font-family:'IBM Plex Mono',monospace;font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--slate);background:var(--mist);border-radius:6px;padding:4px 10px;margin-bottom:12px}

/* single article header + chrome (body itself is styled by .rich-text) */
.ov-page .post-head{margin-bottom:22px}
.ov-page .post-head .page-title{margin:0 0 10px}
.ov-page .post-sub{font-size:19px;color:var(--slate);margin:0 0 10px}
.ov-page .post-date{font-family:'IBM Plex Mono',monospace;font-size:13px;color:var(--slate);margin:0}
/* article title now sits in the navy hero (same as content pages) */
.ov-page .prose-section.navy .post-sub{color:#b9c9cf}
.ov-page .prose-section.navy .post-date{color:#88a0a9;margin-top:14px}
.ov-page .post-cover{margin:6px 0 30px}
.ov-page .post-cover img{display:block;width:100%;height:auto;border-radius:12px}
.ov-page .post-nav{display:flex;justify-content:space-between;gap:16px;margin-top:44px;padding-top:24px;border-top:1px solid var(--line)}
.ov-page .post-nav a{font-family:'IBM Plex Mono',monospace;font-size:13px;color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:10px 16px;text-decoration:none}
.ov-page .post-nav a:hover{border-color:var(--slate)}
.ov-page .post-pagination{margin-top:34px;text-align:center}
@media(max-width:680px){.ov-page .blog-cards{grid-template-columns:1fr}}

/* standalone content page (legal, prose-heavy) */
.page-content{padding:56px 0}
.page-content .page-title{font-size:clamp(30px,4.5vw,44px);font-weight:700;color:var(--ink);margin:0 0 8px;letter-spacing:-.01em}
.page-content .page-meta{font-family:'IBM Plex Mono',monospace;font-size:12.5px;color:var(--slate);margin:0 0 28px}

/* =========================================================================
   PROSE / RICH-TEXT  (ported marketing + legal pages)
   Applies on .ov-page (modular prose blocks) and standard #body-wrapper pages.
   ========================================================================= */
.ov-page .prose-section{padding:52px 0;border-bottom:1px solid var(--line)}
.ov-page .prose-section.mist{background:var(--mist)}
.ov-page .prose-section.navy{background:var(--navy);color:#dfe8ea;position:relative;overflow:hidden;border-bottom:none}
.ov-page .prose-section.navy h1,.ov-page .prose-section.navy h2,.ov-page .prose-section.navy h3,.ov-page .prose-section.navy h4{color:#fff}
.ov-page .prose-section.navy .rich-text{color:#b9c9cf}
.ov-page .prose-section.navy .rich-text .eyebrow{color:var(--amber)}
.ov-page .prose-section.navy .rich-text a{color:var(--amber);border-bottom-color:rgba(251,176,64,.4)}
.ov-page .prose-section.navy .wrap{position:relative;z-index:1}
/* navy hero (homepage-style headline on the ported pages) */
.ov-page .prose-section.navy:first-of-type{padding:64px 0 72px}
.ov-page .prose-section.navy h1,.ov-page .prose-section.navy .page-hero h1{font-size:clamp(34px,5.8vw,58px);line-height:1.04;font-weight:700;letter-spacing:-.01em;color:#fff}
.ov-page .prose-section.navy h1 .hl,.ov-page .prose-section.navy .page-hero h1 .hl{color:var(--amber)}
/* all body text on the navy hero must be light (beats .rich-text p/li{color:ink}
   even when nested inside .page-hero) — otherwise it renders navy-on-navy */
.ov-page .prose-section.navy .rich-text p,
.ov-page .prose-section.navy .rich-text li,
.ov-page .prose-section.navy .rich-text .dek,
.ov-page .prose-section.navy .page-hero p{color:#b9c9cf}
.ov-page .prose-section.navy .updated{color:#88a0a9}
.ov-page .prose-section.navy:first-of-type:after{content:"";position:absolute;right:-120px;top:-100px;width:380px;height:380px;border:2px solid rgba(251,176,64,.15);border-radius:50%;pointer-events:none}
.ov-page .prose-section.navy:first-of-type:before{content:"";position:absolute;right:40px;top:120px;width:180px;height:180px;border:2px solid rgba(84,102,112,.22);border-radius:50%;pointer-events:none}

.rich-text{max-width:100%}
.rich-text h1{font-size:clamp(30px,4.5vw,44px);font-weight:700;letter-spacing:-.01em;margin:0 0 16px;color:var(--ink)}
.rich-text h2{font-size:clamp(24px,3.4vw,33px);font-weight:700;letter-spacing:-.01em;margin:28px 0 10px;color:var(--ink)}
.rich-text h3{font-size:21px;font-weight:700;margin:22px 0 8px;color:var(--ink)}
.rich-text h4,.rich-text h5,.rich-text h6{font-size:17px;font-weight:600;margin:18px 0 6px;color:var(--ink)}
.rich-text p{margin:12px 0;color:var(--ink)}
.rich-text a{color:var(--orange);text-decoration:none}
.rich-text a:hover{text-decoration:underline}
.rich-text ul,.rich-text ol{margin:12px 0;padding-left:1.4em}
.rich-text li{margin:6px 0}
/* highlight: amber has poor contrast on white — use dark orange on light backgrounds, amber on navy */
.rich-text .hl,.rich-text strong.hl{color:var(--orange)}
.ov-page .prose-section.navy .rich-text .hl,.ov-page .prose-section.navy .rich-text strong.hl{color:var(--amber)}
.rich-text img{max-width:100%;height:auto;border-radius:10px}
/* logos must never be rounded/cropped — keep them intact */
.partner-grid img,.rich-text img.logo{border-radius:0}
.rich-text blockquote{background:var(--mist);border-left:4px solid var(--amber);border-radius:0 10px 10px 0;padding:20px 26px;margin:18px 0}
.rich-text hr{border:none;border-top:1px solid var(--line);margin:28px 0}
/* Wide comparison matrices scroll inside their own container. A 7-column table
   resolves to ~856px of min-content width, which in a 375px .wrap used to drag
   the entire page sideways - hero, body copy and all - not just the table.
   The table keeps width:100% so it still fills the container when it fits. */
.table-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;margin:18px 0;max-width:100%}
.table-scroll > table{margin:0}
/* Only force a min-width once the viewport is too narrow to fit the columns,
   so the scroll is deliberate rather than a side effect of table layout. */
@media(max-width:760px){
  .table-scroll > table{min-width:560px}
}
/* Markdown tables in `template: page` bodies (the legal pages) get no
   .table-scroll wrapper, because that wrapper is emitted by the modular Twig
   templates and these pages have no template to add it to. Without this rule the
   sub-processor table on /legal/gdpr - four columns, two of them long postal
   addresses - is 444px wide in a 375px container and drags the whole page 109px
   sideways, and the deliverability-threshold table on /legal/terms overflows by
   18px because it sits inside an indented clause list.
   `:not(.compare)` excludes the modular comparison tables, which are already
   inside a .table-scroll wrapper - double-wrapping them would break their
   min-width scroll behaviour. Not a child selector, because a markdown table
   nested in an <li> is not a direct child of .rich-text. */
.rich-text table:not(.compare){display:block;overflow-x:auto;-webkit-overflow-scrolling:touch;max-width:100%}
/* ...but a table that already has a .table-scroll wrapper must stay a real table,
   or it ends up scrolling twice - once itself, once in the wrapper - and the
   wrapper's min-width no longer applies to a block-level box. This catches the
   hand-written HTML tables on /products/transactional-email-api, which sit inside
   .rich-text AND .table-scroll and carry no .compare class. Equal specificity to
   the rule above (0,0,2,1), so source order decides and this must stay after it. */
.rich-text .table-scroll table{display:table;overflow-x:visible}
.rich-text table{width:100%;border-collapse:collapse;margin:18px 0;font-size:14.5px}
.rich-text thead th{padding:12px 14px;text-align:left;border-bottom:2px solid var(--slate);font-family:'IBM Plex Mono',monospace;font-size:11.5px;letter-spacing:.04em;text-transform:uppercase;color:var(--slate);font-weight:600;vertical-align:bottom}
.rich-text tbody td{padding:12px 14px;text-align:left;border-bottom:1px solid var(--line);vertical-align:top}
.rich-text tbody tr:nth-child(even){background:rgba(36,56,66,.035)}
.rich-text tbody td:first-child{font-weight:600;color:var(--ink)}
/* comparison tables: highlight the last (Omnivery) column with a light amber
   band - the column reads as "ours", the content stays navy (orange/amber text
   reads as a warning, not as an affirmative check) */
.rich-text table.compare th:last-child,
.rich-text table.compare td:last-child{background:#fdf2e1}
.rich-text table.compare thead th:last-child{color:var(--navy);border-bottom-color:var(--amber)}
.rich-text table.compare tbody td:last-child{color:var(--navy);font-weight:600}
/* on navy sections navy text would vanish - keep the amber accent there */
.ov-page .prose-section.navy .rich-text table.compare th:last-child,
.ov-page .prose-section.navy .rich-text table.compare td:last-child{background:rgba(251,176,64,.12)}
.ov-page .prose-section.navy .rich-text table.compare thead th:last-child,
.ov-page .prose-section.navy .rich-text table.compare tbody td:last-child{color:var(--amber)}
/* two-column prose helper (wrap raw HTML .cols in markdown) */
.ov-page .cols-2{display:grid;grid-template-columns:1fr 1fr;gap:32px}
/* let grid children shrink so wide content (code blocks, tables) can't blow out the track */
.ov-page .cols-2 > *{min-width:0}
.ov-page .prose-cards > *{min-width:0}
/* code blocks: contained + horizontally scrollable, never overflow the content width */
.rich-text pre{background:var(--navy);color:#e6edf0;border-radius:10px;padding:16px 18px;margin:14px 0;overflow-x:auto;max-width:100%;font-size:13px;line-height:1.5}
/* display:inline-block + min-width:100% is what makes the pre's overflow-x
   scroll actually reach. As a plain block the code element stays at the pre's
   content width, its long lines overflow a box that clips them, and pre
   scrollWidth never exceeds clientWidth - so on a phone the right-hand end of
   a long line is invisible and unreachable. */
.rich-text pre code{font-family:'IBM Plex Mono',monospace;white-space:pre;display:inline-block;min-width:100%;background:transparent!important;border:none!important;padding:0!important;color:#e6edf0}
.rich-text code{font-family:'IBM Plex Mono',monospace;font-size:.9em;background:var(--mist);border:1px solid var(--line);border-radius:5px;padding:1px 6px}
.ov-page .prose-section.navy .rich-text code{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.16);color:#e6edf0}
.ov-page .prose-cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:18px;margin-top:8px}
.ov-page .prose-card{border:1px solid var(--line);border-radius:12px;padding:24px;background:var(--paper)}
.ov-page .prose-card.dark{background:var(--navy);color:#dfe8ea;border-color:transparent}
.ov-page .logo-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:40px 32px;align-items:center;justify-items:center}
.ov-page .logo-grid .logo-item img{height:56px;width:auto;max-width:220px;object-fit:contain;transition:opacity .2s}
.ov-page .logo-grid .logo-item a{border-bottom:none}
.ov-page .partner-grid .prose-card > a{border-bottom:none}
.ov-page .logo-grid .logo-item a:hover img{opacity:.8}
.ov-page .prose-section.logo-section h3,.ov-page .prose-section.logo-section .eyebrow{text-align:center}
.ov-page .prose-section.logo-section h3{margin-bottom:44px}
/* logogrid `columns:` - the auto-fit default needs 240px per track, so four logos
   in a 912px wrap fall to 3+1. A fixed count keeps the row intact. Sizing is left
   to the default rule above, which suits the /img/customers set: those files are
   each padded into a shared 100x50 frame, so a fixed height gives them a matching
   artwork size and any box fit just renders them small. */
.ov-page .logo-grid.cols-4{grid-template-columns:repeat(4,1fr);gap:44px 60px}
@media(max-width:680px){.ov-page .logo-grid.cols-4{grid-template-columns:repeat(2,1fr);gap:36px 32px}}
/* `fit: height` - for a set cropped tight to the artwork, where the frame is the
   logo. Every logo is drawn at one height and the width falls out of its aspect
   ratio; without this the /img/partners logos run 3.07:1 to 4.62:1 and the widest
   reads as much bigger than the rest. Heights keep the widest inside its cell:
   166px in 183px on desktop, 129px in 140px at two columns. max-width guards the
   cell, since hitting it would cost the logo the height this rule is fixing. */
.ov-page .logo-grid.cols-4.fit-height .logo-item img{width:auto;height:36px;max-width:100%}
@media(max-width:680px){.ov-page .logo-grid.cols-4.fit-height .logo-item img{height:28px}}

/* buttons (heroes, CTAs authored in prose HTML) */
.ov-page .btn-row{display:flex;flex-wrap:wrap;gap:14px;margin:22px 0 0}
.ov-page a.btn-primary{background:var(--amber);color:var(--navy)!important;border:none;border-radius:8px;padding:12px 24px;font-family:'IBM Plex Mono',monospace;font-weight:600;font-size:14px;text-decoration:none}
.ov-page a.btn-primary:hover{background:#e89b2e}
.ov-page a.btn-ghost{color:var(--ink);border:1px solid var(--line);border-radius:8px;padding:12px 22px;font-family:'IBM Plex Mono',monospace;font-weight:500;font-size:14px;text-decoration:none}
.ov-page a.btn-ghost:hover{border-color:var(--slate)}
.ov-page .prose-section.navy a.btn-ghost{color:#dfe8ea;border-color:rgba(255,255,255,.22)}

/* two-column hero (text + image) */
.ov-page .page-hero{display:grid;grid-template-columns:1.1fr .9fr;gap:40px;align-items:center}
.ov-page .page-hero .hero-media img{max-width:100%;height:auto}
.ov-page .page-hero h1{font-size:clamp(30px,4.6vw,46px);font-weight:700;letter-spacing:-.01em;line-height:1.08;margin:0 0 16px;color:var(--ink)}
.ov-page .updated{font-family:'IBM Plex Mono',monospace;font-size:12px;color:var(--slate);margin-top:16px}

/* light stat row */
.ov-page .stat-row{display:flex;flex-wrap:wrap;gap:24px;justify-content:space-between;margin-top:8px}
.ov-page .stat-row .stat{flex:1 1 150px}
.ov-page .stat-row .stat .num{font-family:'IBM Plex Mono',monospace;font-size:clamp(26px,4vw,38px);font-weight:600;color:var(--amber);line-height:1}
.ov-page .stat-row .stat .lbl{font-size:13px;color:var(--slate);margin-top:8px;line-height:1.45}

/* check list (green/orange tick bullets) */
.ov-page ul.checks{list-style:none;padding:0;margin:16px 0 0}
.ov-page ul.checks li{position:relative;padding:9px 0 9px 30px;border-bottom:1px solid var(--line);font-size:15px}
.ov-page ul.checks li:last-child{border-bottom:none}
/* \2713 rather than a literal check mark: a literal only decodes correctly when
   the stylesheet is served as UTF-8, and where it is not (no charset on the
   response, no @charset in the file) the browser reads it as latin-1 and the
   bullet renders as "âœ“". The escape is charset-independent. */
.ov-page ul.checks li:before{content:"\2713";position:absolute;left:2px;top:9px;color:var(--navy);font-weight:700;font-family:'IBM Plex Mono',monospace}
/* on navy sections navy ticks would vanish - keep the amber accent there */
.ov-page .prose-section.navy ul.checks li:before{color:var(--amber)}
.ov-page ul.checks.checks-2{display:grid;grid-template-columns:1fr 1fr;gap:0 40px}
@media(max-width:680px){.ov-page ul.checks.checks-2{grid-template-columns:1fr}}
.ov-page .faq-list{margin-top:8px}

/* FAQ accordion (native <details>) */
.ov-page details.faq{border-bottom:1px solid var(--line)}
.ov-page details.faq summary{list-style:none;cursor:pointer;padding:16px 28px 16px 0;position:relative;font-weight:600;font-size:16px;color:var(--ink)}
.ov-page details.faq summary::-webkit-details-marker{display:none}
.ov-page details.faq summary:after{content:"+";position:absolute;right:4px;top:14px;color:var(--amber);font-size:22px;font-weight:400;line-height:1}
.ov-page details.faq[open] summary:after{content:"\2013"}
.ov-page details.faq .faq-body{padding:0 0 18px;color:var(--ink)}
.ov-page details.faq .faq-body p:first-child{margin-top:0}

/* numbered steps */
.ov-page ol.steps{list-style:none;counter-reset:step;padding:0;margin:20px 0 0;display:grid;gap:18px}
.ov-page ol.steps li{counter-increment:step;position:relative;padding-left:52px;min-height:36px}
.ov-page ol.steps li:before{content:counter(step);position:absolute;left:0;top:0;width:36px;height:36px;border-radius:50%;background:var(--amber);color:var(--navy);font-family:'IBM Plex Mono',monospace;font-weight:600;display:flex;align-items:center;justify-content:center}
.ov-page ol.steps li h4{margin:4px 0 4px}
.ov-page ol.steps li p{margin:0}

/* sources / small captions */
.ov-page .sources{font-size:12px;color:var(--slate);margin-top:14px}

/* milestone timeline (about-us) — one continuous heritage line, Mailkit -> Omnivery */
.ov-page .timeline{margin-top:44px;border-radius:14px;padding:22px 22px 24px;
  background:linear-gradient(to right,transparent 44%,rgba(251,176,64,.07) 66%)}
.ov-page .tl-eras{display:grid;grid-template-columns:1fr 1fr;margin-bottom:16px}
.ov-page .tl-era{font-family:'IBM Plex Mono',monospace;font-size:12px;letter-spacing:.14em;text-transform:uppercase;font-weight:600}
.ov-page .tl-era.mk{color:#8aa0a9}
.ov-page .tl-era.ov{color:var(--amber)}
.ov-page .tl-track{position:relative;display:grid;grid-template-columns:repeat(6,1fr)}
/* the single unbroken line, evolving slate -> amber at the era boundary */
.ov-page .tl-track::before{content:"";position:absolute;top:5px;left:0;right:0;height:2px;
  background:linear-gradient(to right,var(--slate) 0%,var(--slate) 38%,var(--amber) 60%,var(--amber) 100%)}
.ov-page .tl-item{position:relative;padding:26px 14px 0 0}
.ov-page .tl-item::before{content:"";position:absolute;top:0;left:0;width:11px;height:11px;border-radius:50%}
.ov-page .tl-item.mk::before{background:var(--slate)}
.ov-page .tl-item.ov::before{background:var(--amber);box-shadow:0 0 0 4px rgba(251,176,64,.16)}
.ov-page .tl-item.tl-current::before{box-shadow:0 0 0 5px rgba(251,176,64,.34)}
.ov-page .tl-year{display:block;font-family:'IBM Plex Mono',monospace;font-weight:600;margin-bottom:9px}
.ov-page .tl-item.mk .tl-year{color:#a7bcc4;font-size:14px}
.ov-page .tl-item.ov .tl-year{color:var(--amber);font-size:15px}
.ov-page .tl-item ul{list-style:none;padding:0;margin:0}
.ov-page .tl-item li{font-size:12.5px;line-height:1.45;margin:0 0 6px}
.ov-page .tl-item.mk li{color:#8aa0a9}
.ov-page .tl-item.ov li{color:#e6edf0}
/* tablet/mobile: keep it ONE continuous line, rotated vertical */
@media(max-width:900px){
  .ov-page .timeline{background:none;padding:0}
  .ov-page .tl-eras{display:none}
  .ov-page .tl-track{display:block;position:relative}
  .ov-page .tl-track::before{top:2px;bottom:8px;left:5px;right:auto;width:2px;height:auto;
    background:linear-gradient(to bottom,var(--slate) 0%,var(--slate) 34%,var(--amber) 52%,var(--amber) 100%)}
  .ov-page .tl-item{padding:0 0 22px 28px}
  .ov-page .tl-item::before{top:2px;left:0}
}

@media(max-width:760px){
  .ov-page .page-hero{grid-template-columns:1fr}
  .ov-page .page-hero .hero-media{order:-1}
}

/* =========================================================================
   RESPONSIVE
   ========================================================================= */
/* Raised from 680px when the footer went from 3 link columns to 4: at 5 total
   columns the 680-900px range squeezed each to ~104px, which wrapped every
   multi-word link onto three lines. */
@media(max-width:900px){
  .site-footer-2026 .foot-grid{grid-template-columns:1fr 1fr}
  .site-footer-2026 .foot-grid .brandcol{grid-column:1/-1}
}
@media(max-width:760px){
  .ov-page .cols-2{grid-template-columns:1fr}
}
