@charset "utf-8";
/* TW Development Group - rebuilt stylesheet.
   Replaces publicstyle.css (24 @font-face families, 20 of them referenced by
   nothing, and an 842 KB TTF of Segoe UI - a font Windows already has), plus
   layerslider.css, mbcsmbmcp.css and Window.Metro.css.

   PALETTE. The colours are the client's, with three pairs solved for WCAG AA
   by walking the SAME hue down in lightness until the pair cleared - so each
   replacement is recognisably the brand colour, not one picked by eye
   (_flatpack_build/palette.py):

     body text   #888888 on white  3.54:1  FAIL -> #717171  4.88:1
     link hover  #31A2E1 on white  2.84:1  FAIL -> #1a7db4  4.53:1
     nav hover   #AAAAAA on navy   3.46:1  FAIL -> #c2c2c2  4.51:1

   #31A2E1 is kept as the accent ON DARK, where it is 6.55:1.

   SOLVE A COLOUR AGAINST EVERY SURFACE IT LANDS ON. The first answer here was
   #767676, solved against white alone at 4.54:1 - and it FAILS on --wash at
   4.19:1. --wash is what the service cards, the home band and the contact
   panel are painted with, so the miss was on three pages and tw_contrast.html
   is the only thing that found it. #717171 clears both: 4.88:1 on white,
   4.51:1 on the wash. */

:root {
  --navy:   #011425;   /* headerbg.jpg's own colour: masthead, footer, hero bar */
  --blue:   #1D547C;   /* brand: links, page headings, buttons */
  --blue-d: #16405f;
  --sky:    #31A2E1;   /* accent, DARK BACKGROUNDS ONLY - 2.84:1 on white */
  --link-h: #1a7db4;   /* solved: the same hue at AA on white */
  --ink:    #00162B;   /* headings */
  --body:   #717171;   /* solved from #888888, against BOTH white and --wash */
  --line:   #d9dde1;
  --wash:   #f4f6f8;
  --white:  #ffffff;

  --shell: 1200px;
  --read: 74ch;
  --gutter: clamp(20px, 4vw, 40px);
  --head: 96px;            /* kept in step with .tw-headrow's own arithmetic */
  /* MEASURED, not picked. In the browser: brand 74 + menu 540 + call 147 +
     two 24px gaps + two 40px gutters = 889px of content. 1080 leaves 191px of
     slack for the fallback stack, since Arial sets these labels wider than
     Segoe UI. The media query is `max-width: 1079.98px`, NOT 1080 - written as
     1080 the bar and the burger swap one pixel early and the probe's
     "exactly one of them is visible" check fails on the boundary width. */
  --nav-bp: 1080px;
  --radius: 4px;
  --sans: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
}

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

/* The UA's own `[hidden] { display: none }` is a NORMAL author-weight-losing
   rule of specificity (0,1,0), so ANY author rule that sets `display` on the
   same element silently defeats it - and the element is then still in the
   layout while every script in the page believes it is gone.
   That shipped here: `.tw-backdrop { display: block }` inside the drawer's
   media query left an invisible position:fixed, inset:0, z-index:1 panel over
   the whole viewport on every phone page load, so every tap hit the backdrop
   instead of the link under it and ran its close handler - which scrolls to
   the stored offset, i.e. 0. "Anywhere I click takes me to the top." */
[hidden] { display: none !important; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
/* clip on BOTH: the propagation rule is specified for `overflow`, and `clip`
   does not reliably survive it - in an iframe the parked drawer then extends
   scrollWidth by its own width on about half the page/width combinations.
   Never `hidden`: that forces overflow-y:auto, makes the root a scroll
   container and silently kills position:sticky on the masthead. */
html, body { overflow-x: clip; }

/* sticky footer, so a short page does not leave a band of white under it */
body {
  margin: 0;
  min-height: 100vh;
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.6;
  color: var(--body);
  background: var(--white);
  overflow-wrap: break-word;   /* a 28-character e-mail address is one token */
}
body > * { flex-shrink: 0; }   /* the masthead's negative margin must survive */
main { flex: 1 0 auto; }

img, picture, svg, video { max-width: 100%; }
picture { display: block; }    /* inline by default: will not fill a track */
img { height: auto; }

h1, h2, h3, h4 { color: var(--ink); font-weight: 600; line-height: 1.2; margin: 0; }
p, ul, ol { margin: 0; }

a { color: var(--blue); text-decoration: none; }
a:hover, a:focus-visible { color: var(--link-h); text-decoration: underline; }

:focus-visible { outline: 3px solid var(--sky); outline-offset: 2px; }

button { font: inherit; }      /* a <button> does not inherit the page font */

.tw-vh {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.tw-skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--navy); color: #fff; padding: 12px 20px;
}
.tw-skip:focus { left: 0; }

.tw-shell {
  width: 100%; max-width: var(--shell); margin-inline: auto;
  padding-inline: var(--gutter);
}

/* `display: block` is load-bearing, not tidiness. An inline SVG is laid out on
   the TEXT BASELINE, so it reserves the font's descender space underneath and
   sits ~3px above the optical centre of anything it is centred in - which is
   exactly what made the phone glyph look off-centre in its 44px circle. */
.tw-icon { display: block; fill: none; stroke: currentColor; stroke-width: 1.7;
           stroke-linecap: round; stroke-linejoin: round; flex: none; }

/* ============================================================== masthead */

.tw-head {
  position: sticky; top: 0; z-index: 60;
  background: var(--navy);
  color: #fff;
}
.tw-headrow {
  display: flex; align-items: center; gap: 24px;
  min-height: var(--head);
}
.tw-brand { display: flex; align-items: center; flex: none; }
/* set ONE axis and leave the other auto: pinning both to integers rounds the
   aspect off on its own */
.tw-brand img { width: auto; height: 62px; display: block; }

.tw-nav { margin-left: auto; }
.tw-menu {
  display: flex; align-items: center; gap: 2px;
  list-style: none; margin: 0; padding: 0;
  flex-wrap: nowrap;   /* let it OVERFLOW rather than silently wrap to two rows */
}
.tw-menu > li { position: relative; }

.tw-top {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 10px 13px;
  color: #fff; background: none; border: 0; cursor: pointer;
  font-size: 15px; font-weight: 600; letter-spacing: .04em;
  text-transform: uppercase; white-space: nowrap;
  border-radius: var(--radius);
  text-decoration: none;
}
.tw-top:hover, .tw-top:focus-visible { color: #fff; background: var(--blue); text-decoration: none; }
.tw-menu a.tw-top[aria-current="page"],
.tw-menu .tw-top[aria-current="true"] { background: var(--blue); color: #fff; }
/* a straight line has to be its own box: an inset box-shadow follows the
   border-radius and curves up at both ends */
.tw-menu .tw-top[aria-current]::after {
  content: ""; position: absolute; left: 13px; right: 13px; bottom: 2px;
  height: 2px; background: var(--sky);
}

.tw-chev {
  width: 8px; height: 8px; border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor; transform: rotate(45deg) translate(-2px, -2px);
}

.tw-sub {
  position: absolute; top: 100%; left: 0; min-width: 268px;
  list-style: none; margin: 0;
  /* padding INSIDE the panel, not a gap above it: `top: calc(100% + 6px)` is a
     6px hole in the hover target and the menu closes mid-travel */
  padding: 6px 0 8px;
  background: var(--navy);
  border-top: 3px solid var(--sky);
  box-shadow: 0 18px 40px rgba(0, 0, 0, .34);
  opacity: 0; visibility: hidden; transform: translateY(-4px);
  transition: opacity .16s ease, transform .16s ease;
  z-index: 5;
}
.tw-menu > li:last-child .tw-sub,
.tw-menu > li:nth-last-child(2) .tw-sub { left: auto; right: 0; }
.tw-sub a {
  display: block; padding: 9px 20px; color: #dfe6ec;
  font-size: 15px; line-height: 1.35;
}
.tw-sub a:hover, .tw-sub a:focus-visible { background: var(--blue); color: #fff; text-decoration: none; }
.tw-sub a[aria-current="page"] { color: #fff; box-shadow: inset 3px 0 0 var(--sky); }

/* Scope the hover rule so there is nothing to CANCEL later. A tap leaves an
   element in :hover on a touch screen, and a `li:hover > .tw-sub{display:none}`
   cancel is MORE specific than the rule that drives the drawer's own submenu -
   so every phone submenu opens and is forced shut in the same instant. */
@media (hover: hover) and (min-width: 1080px) {
  .tw-menu > li:hover > .tw-sub { opacity: 1; visibility: visible; transform: none; }
}
.tw-menu > li:focus-within > .tw-sub,
.tw-subtoggle[aria-expanded="true"] + .tw-sub {
  opacity: 1; visibility: visible; transform: none;
}

.tw-call {
  display: inline-flex; align-items: center; gap: 8px; flex: none;
  padding: 9px 16px; border: 1px solid rgba(255, 255, 255, .34);
  border-radius: 999px; color: #fff; font-weight: 600; font-size: 15px;
  white-space: nowrap;
}
.tw-call:hover, .tw-call:focus-visible { background: var(--blue); border-color: var(--blue); color: #fff; text-decoration: none; }

.tw-burger {
  display: none; flex: none; position: relative; z-index: 3;
  width: 48px; height: 48px; margin-left: auto;
  background: none; border: 1px solid rgba(255, 255, 255, .3);
  border-radius: var(--radius); color: #fff; cursor: pointer;
}
/* bars positioned absolutely: 16/23/30 gives 7px gaps by construction, so the
   +-7px the X transform assumes always lands on the middle bar - and a
   visually-hidden label cannot become a fourth grid row */
.tw-bars i {
  position: absolute; left: 13px; width: 22px; height: 2px;
  background: #fff; border-radius: 2px;
  transition: transform .22s ease, opacity .16s ease;
}
.tw-bars i:nth-child(1) { top: 16px; }
.tw-bars i:nth-child(2) { top: 23px; }
.tw-bars i:nth-child(3) { top: 30px; }
.tw-burger[aria-expanded="true"] i:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.tw-burger[aria-expanded="true"] i:nth-child(2) { opacity: 0; }
.tw-burger[aria-expanded="true"] i:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.tw-navfoot { display: none; }
.tw-backdrop { display: none; }

/* ============================================================== drawer */

@media (max-width: 1079.98px) {
  .tw-burger { display: block; }
  .tw-call .tw-call-num { display: none; }
  .tw-call { padding: 0; width: 44px; height: 44px; justify-content: center; }

  .tw-nav {
    position: fixed; top: var(--head-real, var(--head)); right: 0; bottom: 0;
    width: min(360px, 86vw);
    margin: 0; padding: 8px 0 28px;
    background: var(--navy);
    overflow-y: auto; -webkit-overflow-scrolling: touch;
    transform: translateX(100%);
    /* transition TRANSFORM only. Making the panel's very existence depend on a
       `visibility` animation means a throttled tab never reveals it. */
    transition: transform .26s ease;
    will-change: transform;
    visibility: hidden;
    box-shadow: -14px 0 40px rgba(0, 0, 0, .4);
    z-index: 2;
  }
  html.tw-open .tw-nav { transform: none; visibility: visible; }
  .tw-nav:focus { outline: none; }

  .tw-menu { display: block; }
  .tw-menu > li { border-bottom: 1px solid rgba(255, 255, 255, .09); }
  .tw-top { display: flex; width: 100%; justify-content: space-between;
            padding: 15px 24px; border-radius: 0; font-size: 16px; }
  .tw-menu .tw-top[aria-current]::after { left: 0; right: auto; top: 0; bottom: 0;
                                          width: 3px; height: auto; }
  .tw-sub {
    position: static; min-width: 0; opacity: 1; visibility: visible;
    transform: none; transition: none;
    background: rgba(0, 0, 0, .3); border-top: 0; box-shadow: none;
    padding: 0; display: none;
  }
  .tw-subtoggle[aria-expanded="true"] + .tw-sub { display: block; }
  .tw-menu > li:focus-within > .tw-sub { display: none; }
  .tw-subtoggle[aria-expanded="true"] .tw-chev { transform: rotate(-135deg) translate(-2px, -2px); }
  .tw-sub a { padding: 12px 24px 12px 38px; }

  .tw-navfoot { display: grid; gap: 10px; padding: 22px 24px 0; }
  /* Driven by the CLASS, and inert until it is set. Three independent things
     have to be true before this element can swallow a tap, so no single one of
     them going wrong can make the page unclickable again:
       * the [hidden] rule above, which the JS toggles
       * pointer-events, which is off unless the drawer is open
       * opacity, which is what actually animates
     `display` is deliberately NOT animated here - display:none -> block would
     skip the fade, and transitioning `visibility` on something that reveals UI
     leaves it stuck at its start value in a throttled tab. */
  .tw-backdrop {
    display: block; position: fixed; inset: 0; z-index: 1;
    background: rgba(0, 0, 0, .5);
    opacity: 0; pointer-events: none;
    transition: opacity .26s ease;
  }
  html.tw-open .tw-backdrop { opacity: 1; pointer-events: auto; }

  /* The scroll lock has THREE parts and they only work together.
     1. body pinned at -scrollY (the JS sets the inline top) - also the only
        lock that holds on iOS.
     2. `overflow:hidden` on the root stops the document being a scroll
        container, so a position:sticky masthead has nothing to stick against
        and snaps back to its STATIC position - 900px above the viewport if
        that is how far down the reader was. It has to go FIXED.
     3. a fixed header has left the flow, so everything below jumps up by the
        header's own height. padding-top on body cancels it exactly. */
  html.tw-locked, html.tw-locked body { overflow: hidden; }
  html.tw-locked body { position: fixed; left: 0; right: 0; width: 100%;
                        padding-top: var(--head-real, var(--head)); }
  html.tw-locked .tw-head { position: fixed; top: 0; left: 0; right: 0; }
  /* ...and on any page whose masthead is genuinely in flow, put the space back */
  html.tw-locked body:not(.tw-home) main { margin-top: 0; }
}

@media (max-width: 560px) {
  .tw-brand img { height: 50px; }
  :root { --head: 76px; }
}

/* ============================================================== hero */

.tw-hero { position: relative; background: var(--navy); }
/* Write the height DIRECTLY. `aspect-ratio` next to `min-height` back-computes
   the WIDTH: at 375px the ratio gives 130px, min-height raises it to 260, and
   the ratio then resolves the other way and sets the width to 749px - the
   photograph drawn wider than the viewport, cropped, inside overflow:hidden
   where no page-level scrollWidth check can see it. */
.tw-slides {
  position: relative;
  height: clamp(300px, 34vw, 460px);
  /* a <ul> repurposed as a layout track keeps its 40px UA padding, and
     anything sized against its content box is then 40px narrower than the box */
  list-style: none; margin: 0; padding: 0;
  overflow: hidden;
}
/* every slide absolute, INCLUDING the first: a relative first child has no
   height for `height:100%` on its picture to resolve against, so the image
   collapses to nothing and the hero renders as a flat navy band */
.tw-slide {
  position: absolute; inset: 0; opacity: 0;
  transition: opacity .7s ease;
  pointer-events: none;
}
.tw-slide[data-on="1"] { opacity: 1; pointer-events: auto; z-index: 1; }
.tw-slide picture, .tw-slide img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}

.tw-slide-cap {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  /* the CMS's own "blue bar": eight byte-identical 1920x100 PNGs of one flat
     rgba(0,17,31,.85). Two lines of CSS, zero requests. */
  background: rgba(1, 20, 37, .85);
  color: #fff;
}
/* padding-BLOCK, never the `padding` shorthand. `.tw-slide-cap > div` is
   (0,1,1) and `.tw-shell { padding-inline: var(--gutter) }` is (0,1,0), so the
   shorthand's implicit `padding-inline: 0` won and the caption sat flush
   against the left edge of the phone. Any rule that adds vertical padding to
   an element that IS a .tw-shell has to use the logical property. */
.tw-slide-cap > div { display: flex; flex-wrap: wrap; gap: 4px 34px; padding-block: 15px; }
.tw-slide-cap span {
  font-size: clamp(15px, 2.1vw, 22px); letter-spacing: .03em;
  line-height: 1.3;
}
/* above the caption bar, not inside it: eight dots need ~150px and the caption
   is the client's own copy, which must not have to make room for the chrome */
.tw-hero-ui {
  position: absolute; z-index: 3;
  right: var(--gutter); top: 18px;
  display: flex; gap: 9px;
}
.tw-dot {
  width: 11px; height: 11px; padding: 0; border-radius: 50%;
  border: 2px solid rgba(255, 255, 255, .8); background: none; cursor: pointer;
}
.tw-dot[aria-current="true"] { background: var(--sky); border-color: var(--sky); }
.tw-hero-nav {
  position: absolute; top: calc(50% - 28px); transform: translateY(-50%);
  z-index: 3;
  width: 46px; height: 46px; display: grid; place-items: center;
  background: rgba(1, 20, 37, .55); color: #fff; border: 0; cursor: pointer;
  border-radius: 50%;
}
.tw-hero-nav:hover { background: var(--blue); }
.tw-hero-prev { left: 12px; }
.tw-hero-next { right: 12px; }
.tw-hero-prev .tw-icon { transform: rotate(180deg); }

@media (prefers-reduced-motion: reduce) {
  .tw-slide { transition: none; }
  html { scroll-behavior: auto; }
}

/* ============================================================== page banner */

.tw-band { position: relative; background: var(--navy); }
.tw-band picture, .tw-band img {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
.tw-band-img { height: clamp(130px, 15vw, 210px); }
.tw-band-txt {
  position: absolute; inset: 0; display: flex; align-items: center;
  /* SOLVED, not chosen. fp_heroink.py composites each of the five banner
     photographs through the scrim in sRGB the way a browser does and reports
     the WORST single pixel, not the mean - a DOM contrast sweep is blind here,
     because a linear-gradient is a background IMAGE and the walker climbs past
     it to <body> and reports white on white at 1:1.

       left 60%, where the heading sits, at .86   worst 12.56:1
       right edge         at .50   worst 3.52:1   large text only
                          at .60   worst 4.91:1   AA at ANY size

     Nothing is drawn past 60% today, but a longer heading at a narrow width
     could reach it - so the light end is .62, which clears AA at any size with
     margin and survives someone changing the type size later. Re-run
     `python fp_heroink.py --solve` if either number is touched. */
  background: linear-gradient(90deg, rgba(1,20,37,.86) 0%, rgba(1,20,37,.72) 62%, rgba(1,20,37,.62) 100%);
}
.tw-band-txt h1 { color: #fff; font-size: clamp(23px, 3.4vw, 38px); letter-spacing: .01em; }

/* ============================================================== content */

.tw-page { padding: clamp(34px, 5vw, 62px) 0 clamp(40px, 6vw, 76px); }
.tw-page > .tw-shell { display: grid; gap: clamp(26px, 3.4vw, 40px); }

.tw-prose { max-width: var(--read); }
/* same specificity as the flow rule, so source order decides - `.tw-prose p`
   is (0,1,1) and would beat `.tw-prose > * + *` (0,1,0) whichever way round */
.tw-prose > * { margin: 0; }
.tw-prose > * + * { margin-top: 1.05em; }
.tw-prose h2 {
  font-size: clamp(21px, 2.4vw, 28px); color: var(--ink);
  margin-top: 1.7em; letter-spacing: .01em;
}
.tw-prose h2:first-child { margin-top: 0; }
.tw-prose ul, .tw-prose ol { padding-left: 1.35em; }
.tw-prose li + li { margin-top: .4em; }
.tw-prose a { text-decoration: underline; text-underline-offset: 2px; }

.tw-lead { font-size: clamp(18px, 1.5vw, 20px); color: #5c6166; }

.tw-h1 {
  font-size: clamp(26px, 3.6vw, 38px); color: var(--blue);
  letter-spacing: .01em;
}
.tw-rule { width: 100%; height: 3px; background: var(--navy); border: 0; margin: 14px 0 0; }

/* the CMS floated a 225x353 monogram into the copy at margin-right:-51px, which
   hangs it outside the column at every width below the fixed 1024 it was drawn
   for. Give it a column of its own instead. */
.tw-withart { display: grid; gap: clamp(24px, 4vw, 54px); align-items: start; }
@media (min-width: 900px) {
  .tw-withart { grid-template-columns: minmax(0, 1fr) 232px; }
  .tw-withart .tw-prose { max-width: none; }
}
.tw-art { justify-self: center; }
.tw-art img { width: 200px; height: auto; opacity: .9; }
@media (max-width: 899.98px) { .tw-art { display: none; } }

/* ============================================================== cards */

.tw-cards {
  display: grid; gap: clamp(14px, 1.8vw, 22px);
  /* a hard 300px track floor is 336px with the gutter on a 320px screen, and
     the whole page then gains horizontal scroll */
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 620px) { .tw-cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 940px) { .tw-cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* The resting surface comes from a CUSTOM PROPERTY, not from a second
   `background` declaration further down the file. `.tw-strip .tw-card` (0,2,0)
   and `.tw-card:hover` (0,2,0) are the SAME specificity, so source order
   decided - and the strip rule, being later, kept the card white on hover
   while every hover TEXT colour still applied. The blurb went to #c8d2da on
   white: 1.42:1, and the title inherited #fff on white and vanished
   altogether. Nothing but hovering it can see that, which is why the contrast
   sweep now walks the hover state too. */
.tw-card {
  display: grid; align-content: start; gap: 10px;
  padding: 26px 24px 24px;
  background: var(--card-bg, var(--wash));
  border: 1px solid var(--line);
  border-top: 3px solid var(--blue);
  border-radius: var(--radius);
  color: var(--ink);
  transition: background .18s ease, border-color .18s ease, transform .18s ease;
}
.tw-card:hover, .tw-card:focus-visible {
  background: var(--navy); border-color: var(--navy); border-top-color: var(--sky);
  text-decoration: none; transform: translateY(-2px);
}
.tw-card .tw-icon { color: var(--blue); }
.tw-card:hover .tw-icon, .tw-card:focus-visible .tw-icon { color: var(--sky); }
/* every part states its colour in BOTH states - nothing inherits its way to
   white-on-white if one rule is ever out-specified again */
.tw-card-t {
  font-size: 18px; font-weight: 700; letter-spacing: .02em;
  text-transform: uppercase; line-height: 1.25; color: var(--ink);
}
.tw-card-b { font-size: 15.5px; line-height: 1.5; color: var(--body); }
.tw-card-go { color: var(--blue); margin-top: 2px; }
.tw-card:hover .tw-card-t, .tw-card:focus-visible .tw-card-t { color: #fff; }
.tw-card:hover .tw-card-b, .tw-card:focus-visible .tw-card-b { color: #c8d2da; }
.tw-card:hover .tw-card-go, .tw-card:focus-visible .tw-card-go { color: var(--sky); }

@media (prefers-reduced-motion: reduce) { .tw-card:hover { transform: none; } }

/* ============================================================== buttons */

.tw-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 12px 24px; border: 2px solid var(--blue); border-radius: var(--radius);
  background: var(--blue); color: #fff;
  font: inherit; font-size: 16px; font-weight: 600; letter-spacing: .03em;
  cursor: pointer; text-align: center;
}
.tw-btn:hover, .tw-btn:focus-visible { background: var(--blue-d); border-color: var(--blue-d); color: #fff; text-decoration: none; }
.tw-btn-ghost { background: none; border-color: rgba(255, 255, 255, .4); color: #fff; }
.tw-btn-ghost:hover, .tw-btn-ghost:focus-visible { background: rgba(255, 255, 255, .12); border-color: #fff; }

/* ============================================================== home bands */

.tw-strip { background: var(--wash); border-block: 1px solid var(--line);
            padding: clamp(38px, 5vw, 64px) 0; }
.tw-strip-h { text-align: center; margin-bottom: 8px; font-size: clamp(23px, 2.8vw, 31px);
              color: var(--blue); }
.tw-strip-s { text-align: center; margin: 0 auto clamp(26px, 3vw, 38px); max-width: 58ch; }
/* set the TOKEN, never `background` again: a second background declaration
   here is the same specificity as .tw-card:hover and would win on source
   order, leaving the card white while the hover text colours all applied */
.tw-strip { --card-bg: #fff; }

.tw-cta { background: var(--navy); color: #fff; padding: clamp(34px, 4.6vw, 56px) 0; }
.tw-cta .tw-shell { display: grid; gap: 22px; align-items: center; }
@media (min-width: 800px) { .tw-cta .tw-shell { grid-template-columns: minmax(0, 1fr) auto; } }
.tw-cta h2 { color: #fff; font-size: clamp(21px, 2.6vw, 29px); }
.tw-cta p { color: #c8d2da; margin-top: 8px; }
.tw-cta .tw-btn { background: var(--sky); border-color: var(--sky); color: var(--navy); }
.tw-cta .tw-btn:hover, .tw-cta .tw-btn:focus-visible { background: #fff; border-color: #fff; color: var(--navy); }

/* ============================================================== news */

.tw-posts { display: grid; gap: clamp(18px, 2.4vw, 26px); list-style: none; margin: 0; padding: 0; }
.tw-post {
  display: grid; gap: 8px; padding: 24px;
  border: 1px solid var(--line); border-left: 4px solid var(--blue);
  border-radius: var(--radius); background: #fff;
}
.tw-post h2 { font-size: clamp(19px, 2.1vw, 23px); }
.tw-post h2 a { color: var(--ink); }
.tw-post h2 a:hover, .tw-post h2 a:focus-visible { color: var(--blue); }
.tw-date { font-size: 14px; font-style: italic; color: var(--body); }
.tw-more { font-weight: 600; }

.tw-postgrid { display: grid; gap: clamp(28px, 4vw, 48px); align-items: start; }
@media (min-width: 900px) { .tw-postgrid { grid-template-columns: minmax(0, 1fr) 300px; } }
.tw-morenews h2 { font-size: 17px; letter-spacing: .06em; text-transform: uppercase; }
.tw-morenews ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 14px; }
.tw-morenews li { display: grid; gap: 2px; }
.tw-morenews a { font-weight: 600; color: var(--ink); }
.tw-morenews a:hover, .tw-morenews a:focus-visible { color: var(--blue); }

.tw-article { max-width: 78ch; }
.tw-article .tw-date { display: block; margin-top: 6px; }
.tw-figure { margin: 0 0 clamp(20px, 3vw, 30px); }
.tw-figure img { width: 100%; }
.tw-embed { position: relative; aspect-ratio: 16 / 9; margin: 0 0 clamp(20px, 3vw, 30px); background: #000; }
.tw-embed iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }
.tw-backlink { margin-top: clamp(28px, 4vw, 40px); }

/* ============================================================== contact */

.tw-contact { display: grid; gap: clamp(24px, 3.4vw, 40px); align-items: start; }
@media (min-width: 860px) { .tw-contact { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }

.tw-form { display: grid; gap: 16px; }
.tw-field { display: grid; gap: 6px; }
.tw-field label { font-size: 15px; font-weight: 600; color: var(--ink); }
.tw-field .tw-req { color: #b3261e; }
.tw-field input, .tw-field textarea, .tw-field select {
  font: inherit; font-size: 16px; width: 100%;
  padding: 11px 13px;
  /* 3:1 is what WCAG 1.4.11 wants of a non-text UI boundary, and a DOM
     contrast sweep walks text nodes so it can never tell you. #757575 on
     white is 4.6:1. */
  border: 1px solid #757575; border-radius: var(--radius);
  background: #fff; color: var(--ink);
}
.tw-field input:focus, .tw-field textarea:focus { border-color: var(--blue); }
.tw-field textarea { min-height: 150px; resize: vertical; }
.tw-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.tw-ok, .tw-err {
  padding: 14px 18px; border-radius: var(--radius); margin-bottom: 4px;
  border-left: 4px solid;
}
.tw-ok { background: #eaf4ec; border-color: #1e7b34; color: #145223; }
.tw-err { background: #fdecea; border-color: #b3261e; color: #8c1d17; }
.tw-err ul { margin: 6px 0 0; padding-left: 1.2em; }

.tw-side { display: grid; gap: 20px; }
.tw-panel { padding: 26px 24px; background: var(--wash); border: 1px solid var(--line);
            border-top: 3px solid var(--blue); border-radius: var(--radius); }
.tw-panel h2 { font-size: 20px; margin-bottom: 12px; }
.tw-deets { display: grid; gap: 12px; list-style: none; margin: 0; padding: 0; }
.tw-deets li { display: grid; grid-template-columns: 26px 1fr; gap: 12px; align-items: start; }
.tw-deets .tw-icon { color: var(--blue); margin-top: 2px; }
.tw-deets address { font-style: normal; }
.tw-deets-name { font-weight: 600; color: var(--ink); }
.tw-map { aspect-ratio: 4 / 3; border: 1px solid var(--line); border-radius: var(--radius); overflow: hidden; }
.tw-map iframe { width: 100%; height: 100%; border: 0; display: block; }
@media (min-width: 500px) { .tw-map { aspect-ratio: 16 / 10; } }

.tw-badges { display: flex; flex-wrap: wrap; gap: 22px; align-items: center; }
.tw-badges img { width: auto; height: 88px; }

/* ============================================================== footer */

.tw-foot { background: var(--navy); color: #cfd8e0; margin-top: auto; }
.tw-footgrid {
  display: grid; gap: clamp(26px, 3.4vw, 44px);
  padding-block: clamp(36px, 4.6vw, 56px);
}
@media (min-width: 720px) { .tw-footgrid { grid-template-columns: 1.4fr 1fr auto; } }
.tw-foot-h {
  color: #fff; font-size: 16px; letter-spacing: .12em; text-transform: uppercase;
  margin-bottom: 14px;
}
.tw-foot address { font-style: normal; line-height: 1.8; }
.tw-foot-name { color: #fff; font-weight: 600; }
.tw-foot-cta { margin-top: 14px; display: flex; flex-wrap: wrap; gap: 8px 18px; }
.tw-foot a { color: #cfd8e0; }
.tw-foot a:hover, .tw-foot a:focus-visible { color: #fff; }
.tw-foot-tel { color: #fff !important; font-weight: 600; }
.tw-footlinks { list-style: none; margin: 0; padding: 0;
                display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px 20px; }
.tw-socrow { display: flex; gap: 10px; }
.tw-soc {
  width: 42px; height: 42px; display: grid; place-items: center;
  border: 1px solid rgba(255, 255, 255, .28); border-radius: 50%;
  color: #cfd8e0;
}
.tw-soc svg { fill: currentColor; }
.tw-soc:hover, .tw-soc:focus-visible { background: var(--blue); border-color: var(--blue); color: #fff; }

.tw-copy {
  display: flex; flex-wrap: wrap; gap: 6px 20px;
  justify-content: space-between;
  padding-block: 18px;
  border-top: 1px solid rgba(255, 255, 255, .13);
  font-size: 15px;
}
.tw-copy p { margin: 0; }
.tw-copy-links a { text-decoration: underline; text-underline-offset: 2px; }

/* ============================================================== 404 */

.tw-404 { text-align: center; padding: clamp(48px, 8vw, 96px) 0; }
.tw-404 h1 { font-size: clamp(30px, 5vw, 48px); color: var(--blue); }
.tw-404 p { margin: 16px auto 26px; max-width: 52ch; }
.tw-404 ul { list-style: none; margin: 0; padding: 0;
             display: flex; flex-wrap: wrap; gap: 10px; justify-content: center; }
