/* ==========================================================================
   alcousa.org
   --------------------------------------------------------------------------
   The brief was "less bubbly, more enterprise". Concretely that means:

     - Corners are 0 or 2px. Nothing is a pill. A rounded, shadowed card is
       what makes a site read as a startup landing page.
     - One accent colour, used sparingly. Orange earns attention because it is
       rare; on every button it is just wallpaper.
     - Structure comes from hairline rules and whitespace, not from boxes.
     - Barlow for headings, Arial for body at 15-16px — the same pairing
       analog.com uses, self-hosted because our CSP allows no external origins.
     - No dark mode, by request.
   ========================================================================== */

@font-face { font-family: Barlow; src: url('../fonts/barlow-400.woff2') format('woff2');
             font-weight: 400; font-display: swap; }
@font-face { font-family: Barlow; src: url('../fonts/barlow-500.woff2') format('woff2');
             font-weight: 500; font-display: swap; }
@font-face { font-family: Barlow; src: url('../fonts/barlow-600.woff2') format('woff2');
             font-weight: 600; font-display: swap; }
@font-face { font-family: Barlow; src: url('../fonts/barlow-700.woff2') format('woff2');
             font-weight: 700; font-display: swap; }
:root {
  --accent:      #FF8C2B;
  --accent-dark: #D96C0F;
  --ink:         #1a1a1a;
  --ink-2:       #333333;
  --ink-3:       #5f6469;
  --line:        #dcdfe3;
  --line-2:      #eceef0;
  --bg:          #ffffff;
  --bg-2:        #f6f7f8;
  --bg-3:        #eef0f2;
  --navy:        #16202b;
  --head:        Barlow, "Helvetica Neue", Arial, sans-serif;
  --body:        Arial, "Helvetica Neue", Helvetica, sans-serif;
  --wrap:        1280px;
}
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink-2);
  font: 400 15px/1.65 var(--body);
}
h1, h2, h3, h4, h5 {
  margin: 0 0 .6em;
  font-family: var(--head);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -.015em;
  color: var(--ink);
}
h1 { font-size: clamp(2rem, 4.2vw, 3.25rem); }
h2 { font-size: clamp(1.5rem, 2.6vw, 2.1rem); }
h3 { font-size: 1.18rem; }
h4 { font-size: 1rem; }
p  { margin: 0 0 1rem; }
a { color: var(--ink); text-decoration: none; }
a:hover { color: var(--accent-dark); }
img { max-width: 100%; height: auto; display: block; }
hr { border: 0; border-top: 1px solid var(--line); margin: 3rem 0; }
.wrap { width: 100%; max-width: var(--wrap); margin: 0 auto; padding: 0 1.5rem; }
/* Section width.
 *
 * This was 820px against a 1280px .wrap, which is why blocks like "Work with
 * us" and the FAQ read as narrower than the platforms strip directly above
 * them -- a 460px step change in the middle of a page, on every page that used
 * it.
 *
 * The reason it was ever narrow is that .narrow was doing two unrelated jobs:
 * constraining a LAYOUT section, and constraining a MEASURE for long-form
 * reading. Those want different numbers. This is now the layout width; reading
 * width is .prose (46rem), which the text-heavy pages carry as well. */
.narrow { max-width: 1080px; }
.section { padding: 4.5rem 0; }
.section.tight { padding: 3rem 0; }
.section.grey { background: var(--bg-2); }
.section.dark { background: var(--navy); color: #c9d1d9; }
.section.dark h1, .section.dark h2, .section.dark h3 { color: #fff; }
/* An eyebrow above a heading. Small caps, wide tracking, accent rule — the
   single most "enterprise" typographic move there is. */
.eyebrow {
  display: block; margin-bottom: .7rem;
  font: 600 .72rem/1 var(--head);
  letter-spacing: .16em; text-transform: uppercase;
  color: var(--accent-dark);
}
.section.dark .eyebrow { color: var(--accent); }
.lede { font-size: 1.12rem; line-height: 1.7; color: var(--ink-3); max-width: 62ch; }
.muted { color: var(--ink-3); }
.small { font-size: .87rem; }
/* ---------- buttons: square, bordered, deliberate ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 44px; padding: 0 1.5rem;
  border: 1px solid var(--ink); border-radius: 2px;
  background: transparent; color: var(--ink);
  font: 600 .88rem/1 var(--head); letter-spacing: .02em;
  cursor: pointer; transition: background .15s, color .15s, border-color .15s;
}
.btn:hover { background: var(--ink); color: #fff; }
.btn.primary { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn.primary:hover { background: var(--accent-dark); border-color: var(--accent-dark); color: #fff; }
.btn.ghost { border-color: var(--line); color: var(--ink-2); }
.btn.ghost:hover { border-color: var(--ink); background: transparent; color: var(--ink); }
.btn.light { border-color: rgba(255,255,255,.5); color: #fff; }
.btn.light:hover { background: #fff; color: var(--navy); }
.btn.sm { min-height: 36px; padding: 0 1rem; font-size: .8rem; }
.btnrow { display: flex; flex-wrap: wrap; gap: .7rem; }
/* A text link with an arrow. Used instead of a button wherever a button would
   be shouting. */
.arrow { display: inline-flex; align-items: center; gap: .4rem;
         font: 600 .88rem/1 var(--head); color: var(--ink); }
.arrow::after { content: '›'; font-size: 1.15rem; line-height: 0; transform: translateY(-1px);
                transition: transform .15s; }
.arrow:hover { color: var(--accent-dark); }
.arrow:hover::after { transform: translate(3px, -1px); }
[dir="rtl"] .arrow::after { content: '‹'; }
[dir="rtl"] .arrow:hover::after { transform: translate(-3px, -1px); }
/* ---------- header ---------- */
.topbar {
  background: var(--navy); color: #9aa6b2;
  font-size: .8rem; border-bottom: 1px solid rgba(255,255,255,.08);
}
.topbar .wrap { display: flex; align-items: center; justify-content: flex-end;
                gap: 1.4rem; min-height: 38px; }
/* Hours sit hard left; everything else stays right. `margin-inline-end: auto`
   rather than changing justify-content, so the rest of the strip keeps the
   alignment it already had -- and it flips correctly for Arabic. */
.tb-hours { display: inline-flex; align-items: center; gap: .45rem;
            margin-inline-end: auto; color: #9aa6b2; white-space: nowrap; }
/* Green, always.
   It previously went grey outside office hours, which read as "closed" — but
   the help desk genuinely is staffed 24/7/365, so grey was telling a visitor
   at 2am that nobody was there when somebody was. The dot now tracks the help
   desk, which is the thing a person checking at 2am cares about; the office
   window is stated in the text beside it. */
.hrs-dot { width: 7px; height: 7px; border-radius: 50%; background: #35c46b;
           box-shadow: 0 0 0 2px rgba(53,196,107,.22); flex: 0 0 auto; }
.tb-hours { color: #c9d1d9; }
.topbar a { color: #c9d1d9; }
.topbar a:hover { color: #fff; }
.masthead { position: sticky; top: 0; z-index: 50; background: #fff;
            border-bottom: 1px solid var(--line); }
.masthead .wrap { display: flex; align-items: center; gap: 2rem; min-height: 74px; }
.logo img { height: 34px; width: auto; }
.logo .txt { font: 700 1.15rem/1 var(--head); letter-spacing: -.02em; color: var(--ink); }
.mainnav { display: flex; align-items: center; gap: 1.75rem; margin-inline-start: auto; }
.mainnav > a {
  position: relative; padding: 1.4rem 0;
  font: 500 .92rem/1 var(--head); color: var(--ink-2); letter-spacing: .005em;
}
.mainnav > a::after {
  content: ''; position: absolute; inset-inline: 0; bottom: -1px; height: 2px;
  background: var(--accent); transform: scaleX(0); transition: transform .15s;
}
.mainnav > a:hover { color: var(--ink); }
.mainnav > a:hover::after, .mainnav > a.on::after { transform: scaleX(1); }
.mainnav > a.on { color: var(--ink); }
.navtools { display: flex; align-items: center; gap: .7rem; margin-inline-start: 1rem; }
.navtoggle { display: none; width: 44px; height: 44px; padding: 0;
             background: none; border: 1px solid var(--line); border-radius: 2px;
             cursor: pointer; flex-direction: column; justify-content: center;
             align-items: center; gap: 5px; margin-inline-start: auto; }
.navtoggle span { display: block; width: 18px; height: 2px; background: var(--ink); }
/* ---------- language switcher ---------- */
.langpick { position: relative; }
.langbtn {
  display: inline-flex; align-items: center; gap: .35rem;
  min-height: 36px; padding: 0 .7rem;
  background: none; border: 1px solid var(--line); border-radius: 2px;
  font: 600 .8rem/1 var(--head); color: var(--ink-2); cursor: pointer;
}
.langbtn:hover { border-color: var(--ink); }
.langmenu {
  position: absolute; inset-inline-end: 0; top: calc(100% + 6px); z-index: 60;
  min-width: 170px; padding: .3rem 0; background: #fff;
  border: 1px solid var(--line); box-shadow: 0 10px 30px -12px rgba(0,0,0,.28);
}
.langmenu[hidden] { display: none; }
.langmenu a { display: block; padding: .5rem .9rem; font-size: .88rem; color: var(--ink-2); }
.langmenu a:hover { background: var(--bg-2); }
.langmenu a.on { font-weight: 700; color: var(--ink); }
/* ---------- hero ---------- */
.hero { position: relative; background: var(--navy); color: #cdd5dd; overflow: hidden; }
.hero-img { position: absolute; inset: 0; background-size: cover; background-position: center;
            opacity: .32; }
.hero::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(100deg, rgba(22,32,43,.96) 0%, rgba(22,32,43,.86) 45%, rgba(22,32,43,.55) 100%);
}
[dir="rtl"] .hero::after { background: linear-gradient(260deg, rgba(22,32,43,.96) 0%, rgba(22,32,43,.86) 45%, rgba(22,32,43,.55) 100%); }
.hero .wrap { position: relative; z-index: 2; padding-top: 6rem; padding-bottom: 6rem; }
.hero h1 { color: #fff; max-width: 20ch; }
.hero .lede { color: #b9c3cd; max-width: 56ch; font-size: 1.16rem; }
.hero .btnrow { margin-top: 2rem; }
/* ---------- page header for interior pages ---------- */
.phead { background: var(--bg-2); border-bottom: 1px solid var(--line); padding: 3.2rem 0 2.8rem; }
.phead h1 { margin-bottom: .5rem; }
.crumbs { font-size: .8rem; color: var(--ink-3); margin-bottom: .9rem; }
.crumbs a { color: var(--ink-3); }
.crumbs a:hover { color: var(--accent-dark); }
/* ---------- grids ---------- */
/* Separate boxes, not a slab.
   These grids used to be one bordered block with a 1px gap letting the line
   colour show through, so a row of six people read as a table of six cells
   rather than six people. The gap is now real space and each child carries its
   own border. */
.grid { display: grid; gap: 1.25rem; background: transparent; border: 0; }
.grid.c2 { grid-template-columns: repeat(2, 1fr); }
.grid.c3 { grid-template-columns: repeat(3, 1fr); }
.grid.c4 { grid-template-columns: repeat(4, 1fr); }
.grid > * {
  background: #fff; padding: 2rem 1.8rem;
  border: 1px solid var(--line); border-radius: 2px;
}
/* On a grey section the cards go white rather than matching the section.
   They used to be the same grey, which worked when a shared border defined
   them and leaves them invisible now that each one stands alone. */
.section.grey .grid > * { background: #fff; }
/* A card with no shadow and no radius. Structure from the grid gap alone. */
.card h3 { margin-bottom: .5rem; }
.card p { color: var(--ink-3); font-size: .94rem; margin-bottom: 1.1rem; }
.card .arrow { margin-top: auto; }
.card { display: flex; flex-direction: column; transition: background .15s; }
/* Hover lifts the card instead of repainting it: on a grey section the old
   white-to-grey swap made the card blend into the section behind it. */
.card { border-color: var(--line); transition: border-color .15s, box-shadow .15s; }
.card:hover { border-color: var(--ink-3); box-shadow: 0 4px 14px rgba(22,32,43,.08); }
.section.grey .card:hover { background: #fff; }
.card .ico { width: 34px; height: 34px; margin-bottom: 1.1rem; color: var(--accent-dark); }
.card .ico svg { width: 100%; height: 100%; }
/* ---------- numbered stat row ---------- */
/* Separated too, so the home page does not mix one connected slab in among
   grids that all stand apart. */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.25rem;
         background: transparent; border-block: 0; }
.stats > div { background: #fff; padding: 2rem 1.5rem;
               border: 1px solid var(--line); border-radius: 2px; }
.section.grey .stats > div { background: #fff; }
.stats .n { font: 600 2.4rem/1 var(--head); color: var(--ink); letter-spacing: -.03em; }
.stats .l { margin-top: .5rem; font-size: .84rem; color: var(--ink-3); line-height: 1.45; }
/* ---------- split feature ---------- */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 3.5rem; align-items: center; }
.split.wide-left { grid-template-columns: 1.15fr 1fr; }
.split img { width: 100%; }
/* ---------- list with rules ---------- */
.ruled { list-style: none; margin: 1.5rem 0 0; padding: 0; }
.ruled li { padding: .85rem 0; border-top: 1px solid var(--line-2); font-size: .95rem; }
.ruled li:last-child { border-bottom: 1px solid var(--line-2); }
.ticks { list-style: none; margin: 1.2rem 0 0; padding: 0; }
.ticks li { position: relative; padding: .35rem 0 .35rem 1.6rem; font-size: .95rem; }
[dir="rtl"] .ticks li { padding: .35rem 1.6rem .35rem 0; }
.ticks li::before {
  content: ''; position: absolute; inset-inline-start: 0; top: .78rem;
  width: 8px; height: 8px; border: 2px solid var(--accent); border-radius: 1px;
}
/* ---------- quotes ---------- */
.quote { padding: 2.2rem 1.9rem; background: #fff; border-top: 3px solid var(--accent);
         display: flex; flex-direction: column; }
.quote blockquote { margin: 0 0 1.4rem; font-size: 1rem; line-height: 1.7; color: var(--ink-2); }
.quote .who { margin-top: auto; font: 600 .92rem/1.4 var(--head); color: var(--ink); }
.quote .who span { display: block; font: 400 .84rem/1.5 var(--body); color: var(--ink-3); }
/* ---------- people ---------- */
/* Flex rather than a fixed 4-column grid.
   There are five people. In a four-column grid the fifth sat alone on a second
   row, hard left, which reads as a mistake rather than a layout. Flex with
   `justify-content: center` puts any incomplete final row in the middle, so
   the block stays composed at five, six or seven people without anyone
   revisiting this rule. */
.people { display: flex; flex-wrap: wrap; gap: 1.25rem; justify-content: center;
          background: transparent; border: 0; }
.people > a {
  flex: 1 1 200px; max-width: 260px;
  background: #fff; padding: 0; display: block;
  border: 1px solid var(--line); border-radius: 2px;
  /* Everything in the card is centred on its own axis — photo, name, role. */
  text-align: center;
  transition: border-color .15s, box-shadow .15s;
}
.people > a:hover { border-color: var(--ink-3); box-shadow: 0 4px 14px rgba(22,32,43,.08); }
.avatar {
  width: 74px; height: 74px; margin-bottom: 1.1rem;
  display: grid; place-items: center; border-radius: 2px;
  background: var(--bg-3); color: var(--ink-3);
  font: 600 1.5rem/1 var(--head); letter-spacing: .02em; overflow: hidden;
}
.avatar img { width: 100%; height: 100%; object-fit: cover; }
.people h3 { font-size: 1.02rem; margin-bottom: .15rem; }
.people .role { font-size: .85rem; color: var(--ink-3); }
/* ---------- logos ---------- */
.logos { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1rem;
         background: transparent; border: 0; }
.logos > * { background: #fff; min-height: 92px; display: grid; place-items: center;
             padding: 1rem; font: 600 .95rem/1.3 var(--head); color: var(--ink-3);
             text-align: center;
             border: 1px solid var(--line); border-radius: 2px;
             transition: border-color .15s, box-shadow .15s, color .15s; }
.logos > a:hover { border-color: var(--ink-3); color: var(--ink);
                   box-shadow: 0 4px 14px rgba(22,32,43,.08); }
/* ---------- forms ---------- */
label { display: block; margin: 1.1rem 0 .35rem; font: 600 .84rem/1.3 var(--head); color: var(--ink); }
input[type=text], input[type=email], input[type=tel], select, textarea {
  width: 100%; padding: .7rem .8rem; border: 1px solid var(--line); border-radius: 2px;
  background: #fff; color: var(--ink); font: 400 .95rem/1.5 var(--body);
}
input:focus, select:focus, textarea:focus {
  outline: 0; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(255,140,43,.16);
}
textarea { min-height: 150px; resize: vertical; }
.field-note { margin-top: .35rem; font-size: .8rem; color: var(--ink-3); }
.formgrid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 1.2rem; }
.formgrid .full { grid-column: 1 / -1; }
.notice { padding: 1rem 1.2rem; border-inline-start: 3px solid var(--accent);
          background: var(--bg-2); font-size: .93rem; margin-bottom: 1.5rem; }
.notice.ok  { border-color: #2f8f4e; }
.notice.err { border-color: #c0392b; }
/* ---------- accordion ---------- */
details.faq { border-top: 1px solid var(--line-2); }
details.faq:last-of-type { border-bottom: 1px solid var(--line-2); }
details.faq > summary {
  list-style: none; cursor: pointer; padding: 1.15rem 2rem 1.15rem 0;
  font: 600 1rem/1.4 var(--head); color: var(--ink); position: relative;
}
[dir="rtl"] details.faq > summary { padding: 1.15rem 0 1.15rem 2rem; }
details.faq > summary::-webkit-details-marker { display: none; }
details.faq > summary::after {
  content: '+'; position: absolute; inset-inline-end: 0; top: 1rem;
  font: 400 1.4rem/1 var(--head); color: var(--accent-dark);
}
details.faq[open] > summary::after { content: '–'; }
details.faq > div { padding: 0 0 1.3rem; color: var(--ink-3); font-size: .95rem; max-width: 78ch; }
/* ---------- CTA strip ---------- */
.ctastrip { background: var(--navy); color: #c9d1d9; }
.ctastrip .wrap { display: flex; align-items: center; justify-content: space-between;
                  gap: 2rem; flex-wrap: wrap; padding-block: 3rem; }
.ctastrip h2 { color: #fff; margin: 0 0 .35rem; }
.ctastrip p { margin: 0; color: #9aa6b2; }
/* ---------- footer ---------- */
.foot { background: var(--navy); color: #8d99a6; font-size: .88rem; padding-top: 3.5rem; }
.foot h4 { color: #fff; font-size: .78rem; letter-spacing: .14em; text-transform: uppercase;
           margin-bottom: 1.1rem; }
.foot a { color: #b6c0ca; }
.foot a:hover { color: #fff; }
.footcols { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr 1.2fr; gap: 2.5rem; }
.footcols ul { list-style: none; margin: 0; padding: 0; }
.footcols li { margin-bottom: .55rem; }
.footlogo { margin-bottom: 1rem; }
.footlogo img { height: 32px; filter: brightness(0) invert(1); opacity: .92; }
.footbar {
  margin-top: 3rem; padding: 1.4rem 0; border-top: 1px solid rgba(255,255,255,.1);
  display: flex; justify-content: space-between; align-items: center; gap: 1.5rem;
  flex-wrap: wrap; font-size: .82rem; color: #78838f;
}
.footbar a { color: #78838f; }
/* Monochrome glyphs on a hairline square, the way analog.com does it — not
   brand-coloured circles. */
.social { display: flex; gap: .5rem; margin-top: 1.2rem; }
.social a {
  width: 36px; height: 36px; display: grid; place-items: center;
  border: 1px solid rgba(255,255,255,.22); border-radius: 2px; color: #b6c0ca;
}
.social a:hover { background: #fff; border-color: #fff; color: var(--navy); }
.social svg { width: 17px; height: 17px; fill: currentColor; }
/* The Instagram glyph is drawn edge-to-edge in its 24x24 box, while every
   other mark here sits inset at roughly 20x18. Rendered at the same 17px it
   therefore reads noticeably larger and heavier than its neighbours. Scaling
   it to 20/24 matches the optical weight of the row; the glyph is centred on
   12,12 so scaling about the element centre keeps it aligned. */
.social a[aria-label="Instagram"] svg { transform: scale(.833); }
/* ---------- misc ---------- */
.tag { display: inline-block; padding: .22rem .55rem; border: 1px solid var(--line);
       border-radius: 2px; font: 600 .72rem/1.4 var(--head); letter-spacing: .06em;
       text-transform: uppercase; color: var(--ink-3); }
.sr { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden;
      clip: rect(0 0 0 0); white-space: nowrap; }
.skip { position: absolute; inset-inline-start: -9999px; }
.skip:focus { position: fixed; inset-block-start: .5rem; inset-inline-start: .5rem;
              z-index: 999; padding: .7rem 1rem; background: #fff; border: 2px solid var(--accent); }
/* ==========================================================================
   Responsive. Three real breakpoints, not five near-identical ones.
   ========================================================================== */
@media (max-width: 1080px) {
  .grid.c4, .people, .logos { grid-template-columns: repeat(3, 1fr); }
  .stats { grid-template-columns: repeat(2, 1fr); }
  .footcols { grid-template-columns: 1fr 1fr 1fr; gap: 2rem; }
}
@media (max-width: 900px) {
  .masthead .wrap { flex-wrap: wrap; min-height: 62px; }
  .navtoggle { display: flex; }
  /* The drawer opens by display, not by animating max-height.
     The max-height version did not work: with the .open class applied and
     matching at higher specificity, the used value stayed 0px -- even against
     an inline override -- so the menu never opened at any width below 900px
     and its links were not hittable. Rather than keep chasing why the used
     value refused to resolve, this uses the one mechanism that cannot be
     defeated by a resolution quirk. The cost is a 250ms slide; the benefit is
     a menu that opens. A closed nav is also out of flex flow entirely, so it
     no longer contributes a phantom wrapped line that pushed the toggle off
     the header's vertical centre. */
  .mainnav {
    display: none;
    order: 5; flex-basis: 100%; flex-direction: column; align-items: stretch;
    gap: 0; margin: 0;
  }
  .mainnav.open {
    display: flex; max-height: 75vh; overflow-y: auto;
    border-top: 1px solid var(--line);
  }
  .mainnav > a { padding: .95rem .2rem; border-bottom: 1px solid var(--line-2); font-size: 1rem; }
  .mainnav > a::after { display: none; }
  .mainnav > a.on { color: var(--accent-dark); }
  /* NOT auto. This shares a flex line with .navtoggle, which also wants an
     auto inline-start margin -- and two auto margins on one line split the
     free space between them, parking the toggle at the midpoint instead of
     at the right edge. The toggle gets the auto margin; this gets nothing. */
  .navtools { margin-inline-start: 0; }
  .split, .split.wide-left { grid-template-columns: 1fr; gap: 2rem; }
  .grid.c3, .grid.c4, .people, .logos { grid-template-columns: repeat(2, 1fr); }
  .hero .wrap { padding-top: 4rem; padding-bottom: 4rem; }
  .section { padding: 3.25rem 0; }
}
@media (max-width: 620px) {
  body { font-size: 15px; }
  .wrap { padding: 0 1.1rem; }
  .grid.c2, .grid.c3, .grid.c4, .people, .stats { grid-template-columns: 1fr; }
  .logos { grid-template-columns: repeat(2, 1fr); }
  .formgrid { grid-template-columns: 1fr; }
  .footcols { grid-template-columns: 1fr 1fr; }
  .grid > * { padding: 1.6rem 1.3rem; }
  .topbar .wrap { justify-content: center; gap: 1rem; font-size: .76rem; }
  .ctastrip .wrap { padding-block: 2.2rem; }
  .footbar { justify-content: flex-start; }
  /* 16px stops iOS zooming the page when a field is focused. */
  input, select, textarea { font-size: 16px; }
}
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; scroll-behavior: auto !important; }
}
@media print {
  .masthead, .topbar, .foot, .ctastrip, .navtoggle, .btnrow { display: none; }
  body { font-size: 11pt; }
}
/* ==========================================================================
   Fixes found once it was on screen.
   ========================================================================== */

/* The hero eyebrow used the darker orange, which is for white backgrounds. On
   navy it read as brown. */
.hero .eyebrow { color: var(--accent); }
/* Arabic. The layout already uses logical properties, so direction is handled;
   what is left is the type. Arabic has no italics and no capitals, so the
   letter-spacing and uppercase tricks used on Latin eyebrows have to go —
   applied to Arabic they just break the joins between letters. */
[dir="rtl"] { font-family: "Segoe UI", Tahoma, Arial, sans-serif; }
[dir="rtl"] h1, [dir="rtl"] h2, [dir="rtl"] h3, [dir="rtl"] h4 {
  font-family: "Segoe UI", Tahoma, Arial, sans-serif;
  letter-spacing: normal; line-height: 1.35;
}
[dir="rtl"] .eyebrow, [dir="rtl"] .tag, [dir="rtl"] .foot h4 {
  text-transform: none; letter-spacing: normal;
}
[dir="rtl"] body { line-height: 1.85; }
[dir="rtl"] .lede { font-size: 1.08rem; }
/* Latin brand names inside Arabic text keep their own direction. */
[dir="rtl"] .logos > * { direction: ltr; }
/* ==========================================================================
   Case study, status, careers, modal, cookie notice — and a serious pass on
   small screens. The first cut was "responsive" in the sense that nothing
   overflowed; it was not actually good to use on a phone.
   ========================================================================== */

/* ---------- case study ---------- */
.casehero .wrap { padding-top: 5rem; padding-bottom: 4rem; }
.casehero h1 { max-width: 18ch; }
.casemeta { margin: 1.6rem 0 0; font-size: .84rem; color: #8d99a6; letter-spacing: .01em; }
.stats .n .u { font-size: .95rem; font-weight: 500; color: var(--ink-3); margin-inline-start: .15rem; }
.timeline { list-style: none; margin: 1.4rem 0 0; padding: 0; }
.timeline li {
  position: relative; padding: 0 0 1.4rem 1.9rem;
  border-inline-start: 2px solid var(--line); margin-inline-start: .45rem;
}
[dir="rtl"] .timeline li { padding: 0 1.9rem 1.4rem 0; }
.timeline li::before {
  content: ''; position: absolute; inset-inline-start: -6px; top: .45rem;
  width: 10px; height: 10px; background: var(--accent); border-radius: 1px;
}
.timeline li:last-child { border-inline-start-color: transparent; padding-bottom: 0; }
.pullquote {
  margin: 2.2rem 0 0; padding: 1.3rem 1.5rem;
  border-inline-start: 3px solid var(--accent); background: var(--bg-2);
  font-size: 1.06rem; line-height: 1.65; color: var(--ink);
}
.section.grey .pullquote { background: #fff; }
/* Charts drawn with divs. A charting library would be 200KB of JavaScript to
   draw four rectangles, and our CSP would block it from a CDN anyway. */
.chart { margin: 2.2rem 0 1.4rem; }
.chart .bars {
  display: flex; align-items: flex-end; gap: 1.5rem;
  height: 230px; border-bottom: 1px solid var(--line);
}
.chart .bar { flex: 1; display: flex; flex-direction: column; justify-content: flex-end;
              align-items: center; height: 100%; text-align: center; }
.chart .bar b { font: 600 1.05rem/1 var(--head); color: var(--ink); margin-bottom: .45rem; }
.chart .bar .v {
  width: 100%; max-width: 130px; min-height: 3px;
  background: var(--ink-3); border-radius: 1px 1px 0 0;
}
.chart .bar.on .v { background: var(--accent); }
.chart .bar em {
  order: 3; margin-top: .7rem; font-style: normal;
  font-size: .8rem; line-height: 1.35; color: var(--ink-3);
}
.chart figcaption { margin-top: 2.6rem; font-size: .82rem; color: var(--ink-3); }
.ctable { width: 100%; border-collapse: collapse; margin-top: 1.2rem; font-size: .92rem; }
.ctable th, .ctable td { padding: .75rem .8rem; text-align: start; border-bottom: 1px solid var(--line-2); }
.ctable thead th { border-bottom: 2px solid var(--line); font: 600 .8rem/1.3 var(--head);
                   text-transform: uppercase; letter-spacing: .06em; color: var(--ink-3); }
.ctable tbody tr:hover { background: var(--bg-2); }
.ctable td:last-child { font-weight: 600; color: var(--ink); }
/* ---------- status ---------- */
.statebar {
  display: flex; align-items: center; gap: 1rem;
  padding: 1.2rem 1.4rem; border: 1px solid var(--line);
  border-inline-start-width: 4px; background: var(--bg-2);
}
.statebar > div { flex: 1; display: flex; flex-direction: column; }
.statebar .dot { width: 12px; height: 12px; border-radius: 50%; background: var(--ink-3); flex: 0 0 auto; }
.statebar.state-ok { border-inline-start-color: #2f8f4e; }
.statebar.state-ok .dot { background: #2f8f4e; }
.statebar.state-degraded, .statebar.state-maintenance { border-inline-start-color: #c8871b; }
.statebar.state-degraded .dot, .statebar.state-maintenance .dot { background: #c8871b; }
.statebar.state-down { border-inline-start-color: #c0392b; }
.statebar.state-down .dot { background: #c0392b; }
.statebar.state-unknown { border-inline-start-color: var(--ink-3); }
.statuslist li { display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.pillstate { font: 600 .78rem/1 var(--head); padding: .3rem .55rem; border-radius: 2px;
             border: 1px solid var(--line); color: var(--ink-3); white-space: nowrap; }
.pillstate.s-ok { color: #2f8f4e; border-color: #b7dcc3; background: #f1f9f4; }
.pillstate.s-degraded, .pillstate.s-maintenance { color: #9a6410; border-color: #e8d3a8; background: #fdf7ec; }
.pillstate.s-down { color: #a5301f; border-color: #eebdb6; background: #fdf2f0; }
/* ---------- sign-in modal ---------- */
.modal[hidden] { display: none; }
.modal { position: fixed; inset: 0; z-index: 200; display: grid; place-items: center; padding: 1.2rem; }
.modal-back { position: absolute; inset: 0; background: rgba(10,16,22,.62); }
.modal-box {
  position: relative; z-index: 1; width: 100%; max-width: 560px;
  padding: 2.2rem 2rem; background: #fff; border-top: 3px solid var(--accent);
  box-shadow: 0 30px 70px -20px rgba(0,0,0,.45);
}
.modal-x { position: absolute; inset-inline-end: .6rem; top: .4rem; width: 38px; height: 38px;
           background: none; border: 0; font-size: 1.6rem; line-height: 1; color: var(--ink-3); cursor: pointer; }
.modal-x:hover { color: var(--ink); }
.signin-opts { display: grid; gap: 1px; background: var(--line); border: 1px solid var(--line); margin-top: 1.2rem; }
.signin-opt { display: block; padding: 1.2rem 1.3rem; background: #fff; }
.signin-opt:hover { background: var(--bg-2); }
.signin-opt strong { display: block; font: 600 1.05rem/1.3 var(--head); color: var(--ink); }
.signin-opt > span { display: block; margin-top: .3rem; font-size: .88rem; color: var(--ink-3); }
.signin-opt .arrow { margin-top: .7rem; }
/* ---------- cookie notice ---------- */
.cookiebar[hidden] { display: none; }
.cookiebar {
  position: fixed; inset-inline: 0; bottom: 0; z-index: 150;
  display: flex; align-items: center; gap: 1.4rem;
  padding: 1rem 1.5rem; background: var(--navy); color: #c9d1d9;
  border-top: 2px solid var(--accent); font-size: .88rem;
}
.cookiebar p { margin: 0; flex: 1; max-width: 90ch; }
.cookiebar a { color: #fff; text-decoration: underline; }
.cookiebar .btn { flex: 0 0 auto; }
.footlinks { display: flex; flex-wrap: wrap; gap: .3rem 1.1rem; }
/* ==========================================================================
   Small screens, properly.
   ========================================================================== */
@media (max-width: 900px) {
  .chart .bars { height: 190px; gap: .9rem; }
  .casehero .wrap { padding-top: 3.4rem; padding-bottom: 3rem; }
}
@media (max-width: 620px) {
  /* Headings were sized off viewport width and came out cramped at the bottom
     of the clamp; give phones a floor that still reads as a headline. */
  h1 { font-size: 1.85rem; line-height: 1.18; }
  h2 { font-size: 1.4rem; }
  h3 { font-size: 1.08rem; }
  .lede { font-size: 1rem; line-height: 1.65; }
  .section { padding: 2.6rem 0; }
  .section.tight { padding: 2rem 0; }
  .hero .wrap { padding-top: 3rem; padding-bottom: 3rem; }
  .hero h1, .casehero h1 { max-width: none; }
  .hero .lede { font-size: 1.02rem; }
  .btnrow .btn { flex: 1 1 100%; }
  .topbar .wrap { min-height: 34px; }
  .masthead .wrap { min-height: 56px; gap: .6rem; }
  .logo img { height: 26px; }
  .navtools { gap: .4rem; }
  .navtools .btn.primary.sm { padding: 0 .7rem; font-size: .74rem; }
  .eyebrow { font-size: .68rem; letter-spacing: .13em; }
  .stats .n { font-size: 1.9rem; }
  .grid > * { padding: 1.4rem 1.2rem; }
  /* A four-bar chart at 380px is four slivers. Turn it on its side. */
  .chart .bars { display: block; height: auto; border-bottom: 0; }
  .chart .bar {
    display: grid; grid-template-columns: 8.5rem 1fr auto; align-items: center;
    gap: .7rem; height: auto; text-align: start;
    padding: .55rem 0; border-top: 1px solid var(--line-2);
  }
  .chart .bar:first-child { border-top: 0; }
  .chart .bar em { order: 0; margin: 0; font-size: .82rem; }
  .chart .bar .v { order: 1; width: 100%; max-width: none;
                   height: 10px !important; min-height: 10px; border-radius: 1px; }
  .chart .bar b { order: 2; margin: 0; font-size: .95rem; }
  .chart figcaption { margin-top: 1rem; }
  .timeline li { padding-inline-start: 1.3rem; }
  .pullquote { padding: 1rem 1.1rem; font-size: 1rem; }
  .ctable { font-size: .86rem; }
  .ctable th, .ctable td { padding: .6rem .55rem; }
  .statebar { flex-wrap: wrap; padding: 1rem 1.1rem; }
  .statuslist li { flex-wrap: wrap; gap: .4rem; }
  .cookiebar { flex-direction: column; align-items: stretch; gap: .8rem; padding: 1rem 1.1rem; }
  .cookiebar .btn { width: 100%; }
  .modal-box { padding: 1.6rem 1.2rem; }
  .footcols { grid-template-columns: 1fr; gap: 1.8rem; }
  .footbar { flex-direction: column; align-items: flex-start; gap: .5rem; }
}
@media (max-width: 380px) {
  .chart .bar { grid-template-columns: 1fr auto; }
  .chart .bar .v { grid-column: 1 / -1; }
}
/* v3 — brand blue, team pages, job listings, vendor marks */
:root { --brand-blue: #1B4570; }
.personhead { padding-block: 3rem 2.8rem; }
.personid { display: flex; align-items: center; gap: 2rem; flex-wrap: wrap; }
.personid h1 { margin: 0; }
.avatar.lg { width: 132px; height: 132px; font-size: 2.6rem; flex: 0 0 auto; margin: 0; }
.people .role { min-height: 2.4em; }
.joblist { margin-top: 1.4rem; border-top: 1px solid var(--line); }
.job { padding: 1.5rem 0; border-bottom: 1px solid var(--line); }
.job h3 { margin-bottom: .25rem; }
.jobmeta { margin: 0 0 .6rem; font: 600 .78rem/1 var(--head); letter-spacing: .08em;
           text-transform: uppercase; color: var(--accent-dark); }
[dir="rtl"] .jobmeta { text-transform: none; letter-spacing: normal; }
.jobmore { margin: .6rem 0 .9rem; }
.jobmore > summary { cursor: pointer; font: 600 .86rem/1 var(--head); color: var(--ink); list-style: none; }
.jobmore > summary::-webkit-details-marker { display: none; }
.jobmore > summary::before { content: '+ '; color: var(--accent-dark); }
.jobmore[open] > summary::before { content: '– '; }
.jobmore > div { padding-top: .6rem; color: var(--ink-3); font-size: .94rem; }
.logos > a { flex-direction: column; gap: .6rem; }
.logomark {
  display: grid; place-items: center; width: 46px; height: 46px;
  border: 1px solid var(--line); border-radius: 2px;
  font: 700 1rem/1 var(--head); letter-spacing: .01em;
  color: var(--brand-blue); background: #fff;
}
.logos > a:hover .logomark { border-color: var(--brand-blue); }
.logoname { font: 600 .86rem/1.3 var(--head); color: var(--ink-2); }
@media (max-width: 620px) {
  .personid { gap: 1.2rem; }
  .avatar.lg { width: 92px; height: 92px; font-size: 1.9rem; }
  .personhead { padding-block: 2rem 2rem; }
}
/* ==========================================================================
   v4 — the cookie notice redesigned, and the article/blog typography.
   ========================================================================== */

/* The first cookie bar was a full-width dark strip pinned to the bottom, which
   is the exact pattern everyone has learned to resent. This is a small card in
   the corner: it does not cover content, it does not block the page, and it
   says what it actually does rather than asking permission it does not need. */
.cookiebar[hidden] { display: none; }
.cookiebar {
  position: fixed; z-index: 150;
  inset-block-end: 1.2rem; inset-inline-start: 1.2rem;
  inset-inline-end: auto; bottom: 1.2rem;
  display: block; width: min(30rem, calc(100vw - 2.4rem));
  padding: 1.2rem 1.3rem;
  background: #fff; color: var(--ink-2);
  border: 1px solid var(--line); border-top: 3px solid var(--brand-blue);
  box-shadow: 0 18px 44px -18px rgba(16, 32, 48, .32);
  font-size: .88rem; line-height: 1.6;
  animation: ck-in .28s ease-out both;
}
@keyframes ck-in { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .cookiebar { animation: none; } }
.cookiebar h4 {
  margin: 0 0 .4rem; font: 600 .78rem/1 var(--head);
  letter-spacing: .12em; text-transform: uppercase; color: var(--brand-blue);
}
[dir="rtl"] .cookiebar h4 { letter-spacing: normal; text-transform: none; }
.cookiebar p { margin: 0 0 1rem; color: var(--ink-3); }
.cookiebar a { color: var(--brand-blue); text-decoration: underline; text-underline-offset: 2px; }
.cookiebar .ckrow { display: flex; align-items: center; gap: .8rem; }
.cookiebar .btn { flex: 0 0 auto; }
.cookiebar .cklink { font-size: .84rem; color: var(--ink-3); }
.cookiebar .cklink:hover { color: var(--ink); }
/* ---------- article list ---------- */
.postlist { border-top: 1px solid var(--line); }
/* The card fills its grid column. It used to carry `max-width: 78ch`, which
   made every entry stop short of the column it sits in — with the rail beside
   it that read as a layout bug rather than a measure. The column itself is
   already bounded by the grid, so the cap was doing nothing but leaving a
   ragged gap. */
.post { padding: 2rem 0; border-bottom: 1px solid var(--line); }
.post.lead { padding-top: 1.6rem; }
.post.lead h2 { font-size: clamp(1.7rem, 3vw, 2.4rem); }
.post h2 { margin: .35rem 0 .5rem; }
.post h2 a { color: var(--ink); }
.post h2 a:hover { color: var(--brand-blue); }
.postmeta {
  margin: 0; font: 600 .76rem/1.4 var(--head); letter-spacing: .08em;
  text-transform: uppercase; color: var(--ink-3);
}
[dir="rtl"] .postmeta { letter-spacing: normal; text-transform: none; }
.poststand { margin: 0 0 .7rem; font-size: 1.04rem; line-height: 1.65; color: var(--ink-3); }
.postby { margin: 0 0 .9rem; font-size: .86rem; color: var(--ink-3); }
.card .postmeta { margin-bottom: .6rem; }
/* ---------- long-form article body ----------
   Measure capped at ~68 characters. Anything wider and the eye loses the line
   return, which is the single most common reason a long piece feels like work. */
.prose {
  /* ~46rem lands at roughly 72 characters at the 1.06rem body size below --
     the measure long-form actually wants. Absolute rather than `ch` because
     `ch` here resolved against the container font, not the paragraph font,
     and silently rendered ~14 characters narrower than specified. */
  max-width: 46rem;
}
/* Articles opt out of the measure cap and fill the column they sit in.
   The 46rem measure above is the better default for reading, and it still
   applies everywhere else prose is used; on the article page it left an
   obvious empty right-hand third that read as broken. The `narrow` wrap
   (1080px) is what bounds the line length here instead. */
.prose-wide { max-width: none; }
.prose p { margin: 0 0 1.3rem; font-size: 1.06rem; line-height: 1.75; color: var(--ink-2); }
.prose h3 {
  margin: 2.4rem 0 .8rem; font-size: 1.28rem; letter-spacing: -.01em;
  padding-top: 1.4rem; border-top: 1px solid var(--line-2);
}
.prose h3:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.prose .ticks { margin: 0 0 1.4rem; }
.prose .ticks li { font-size: 1.02rem; line-height: 1.7; padding-block: .3rem; }
.prose > *:last-child { margin-bottom: 0; }
@media (max-width: 620px) {
  .cookiebar {
    inset-inline: .8rem; bottom: .8rem; width: auto;
    padding: 1rem 1.1rem;
  }
  .cookiebar .ckrow { flex-direction: column; align-items: stretch; gap: .6rem; }
  .cookiebar .btn { width: 100%; }
  .cookiebar .cklink { text-align: center; }
  .post { padding: 1.5rem 0; }
  .prose p, .prose .ticks li { font-size: 1rem; }
  .prose h3 { margin-top: 1.8rem; font-size: 1.15rem; }
}
/* On desktop these two controls live in the header; on mobile they move into
   the drawer. One copy in the markup, shown wherever the width suits. */
.navextra { display: none; }
@media (max-width: 900px) {
  .topbar .tb-hide { display: none; }
  /* On a phone the strip has room for exactly one thing, and "is anyone there
     right now" beats a portal link the client already has bookmarked. */
  .topbar .tb-portal { display: none; }
  .topbar .wrap { justify-content: center; }
  .tb-hours { margin-inline-end: 0; font-size: .76rem;
              white-space: normal; text-align: center; }
  .navtools .langpick, .navtools .btn.primary.sm { display: none; }
  /* With both of its children hidden, .navtools is a zero-width flex item that
     still claims the 9.6px column gap between itself and the toggle -- the
     last thing holding the button off the right margin. Take it out entirely. */
  .navtools { display: none; }
  .navextra {
    display: block; padding: 1rem .2rem 1.2rem; border-top: 1px solid var(--line);
  }
  .navextra .btn { width: 100%; }
  .navlangs { display: flex; flex-wrap: wrap; gap: .4rem; margin-top: .9rem; }
  .navlangs a {
    padding: .45rem .75rem; border: 1px solid var(--line); border-radius: 2px;
    font: 600 .82rem/1 var(--head); color: var(--ink-2);
  }
  .navlangs a.on { border-color: var(--accent); color: var(--accent-dark); }
}
/* v6 — compliance badges, parked domain, and the mobile hamburger */
.badges { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1rem;
          background: transparent; border: 0; }
.badge { background: #fff; padding: 1.4rem 1.1rem; display: flex; flex-direction: column;
         border: 1px solid var(--line); border-radius: 2px; }
.badge-mark {
  display: inline-grid; place-items: center; align-self: flex-start;
  min-width: 3.2rem; height: 2.1rem; padding: 0 .5rem; margin-bottom: .9rem;
  border: 1px solid var(--brand-blue); border-radius: 2px;
  font: 700 .8rem/1 var(--head); letter-spacing: .04em; color: var(--brand-blue);
}
.badge strong { font: 600 .95rem/1.3 var(--head); color: var(--ink); margin-bottom: .3rem; }
.badge > span { font-size: .82rem; line-height: 1.55; color: var(--ink-3); }
.parkhero .wrap { padding-top: 5.5rem; padding-bottom: 5rem; }
@media (max-width: 1080px) { .badges { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 620px)  {
  .badges { grid-template-columns: repeat(2, 1fr); }
  .badge { padding: 1.1rem .9rem; }
  .badge-mark { min-width: 2.8rem; height: 1.9rem; font-size: .74rem; margin-bottom: .7rem; }
  .badge > span { font-size: .78rem; }
  .parkhero .wrap { padding-top: 3.2rem; padding-bottom: 3rem; }
  /* Hamburger hard right and centred on the logo, not floating above it. */
  .masthead .wrap { align-items: center; }
  .navtoggle { align-self: center; margin-inline-start: auto; }
  /* The closed .mainnav has flex-basis 100%, so it wraps to a second flex line
     even at zero height. That line's row gap sits below the toggle and makes
     the masthead ~13px taller than the row the toggle is centred in -- so the
     button reads as sitting high. Zero row gap removes the phantom line; the
     open menu gets its separation from its own border-top, not from this. */
  .masthead .wrap {
    row-gap: 0;
    /* ...and centre the LINES, not just the items within them. The default
       align-content: stretch shares the masthead's spare height across every
       flex line, so the zero-height nav line absorbs half of it and drags the
       toggle's line upward. Centring the lines leaves the toggle on the
       header's true midline. */
    align-content: center;
  }
  /* Emptying .navtools happens in the narrower breakpoint below, where it is
     also removed from the flow -- an empty flex item still claims a column
     gap, which is what holds the toggle off the right margin. */
}
/* v7 — team portraits.
   A headshot is portrait-shaped; cropping one into a 74px square shows a
   forehead. 4:5 tiles with the subject sitting high in the frame. */
.people { grid-template-columns: repeat(4, 1fr); }
.persontile { padding: 0 !important; display: block; }
.portrait {
  /* Square, to match what the CRM actually stores.
     This was 4/5. Staff photos are centre-cropped to a square on upload, so a
     4:5 frame with object-fit:cover threw away 20% of every one of them —
     10% off each side — which on a tightly framed headshot clips hair and
     shoulders and makes the subject look off-centre even though the crop is
     symmetric. Matching the frame to the source means nothing is cropped and
     every face sits exactly where the photographer put it. */
  position: relative; width: 100%; aspect-ratio: 1 / 1; overflow: hidden;
  background: var(--bg-3); display: grid; place-items: center;
}
/* Centred. The old `center 22%` biased towards the top of the frame, which
   suits a tall portrait and mis-crops the square headshots we actually have. */
.portrait img { width: 100%; height: 100%; object-fit: cover; object-position: center; }
.portrait-initials {
  font: 600 2.4rem/1 var(--head); color: var(--ink-3); letter-spacing: .03em;
}
/* Symmetric margins so the text is genuinely centred in the box rather than
   centred within an off-centre column. */
.persontile h3 { margin: 1rem 1rem .15rem; font-size: 1.05rem; text-align: center; }
.persontile .role { margin: 0 1rem 1.2rem; font-size: .86rem; color: var(--ink-3);
                    min-height: 0; text-align: center; }
.persontile:hover .portrait img { filter: brightness(1.04); }
.portrait.lg { aspect-ratio: 1 / 1; border: 1px solid var(--line); }
.portrait.lg .portrait-initials { font-size: 4rem; }
@media (max-width: 900px) { .people > a { flex-basis: 180px; } }
@media (max-width: 520px) { .people > a { flex-basis: 140px; max-width: 46%; }
                            .persontile h3 { font-size: .95rem; margin-inline: .8rem; }
                            .persontile .role { margin-inline: .8rem; font-size: .8rem; } }
/* v9 — the controls strip.
   Drawn seals rather than letter monograms, and rather than borrowed
   certification marks we are not entitled to display. */
.badge-mark {
  display: inline-grid; place-items: center; align-self: flex-start;
  width: 2.9rem; height: 2.9rem; margin-bottom: 1rem; padding: 0;
  min-width: 0; border: 0; border-radius: 0;
  color: var(--brand-blue); background: none;
}
.badge-mark svg { width: 100%; height: 100%; }
.badge-mark svg .tick { stroke-width: 1.4; opacity: .72; }
.badge {
  /* The 3px top is reserved space for the hover accent, so colouring it in
     never shifts the layout. It used to be transparent at rest, which was fine
     while the badges sat inside one bordered slab that drew the outline for
     them — now each badge has its own border, and a transparent top edge left
     the box visibly open along the top. */
  border-top: 3px solid var(--line);
  transition: border-color .15s, background .15s;
}
.badge:hover { border-top-color: var(--accent); background: var(--bg-2); }
.badge strong { font-size: 1rem; }
@media (max-width: 620px) { .badge-mark { width: 2.3rem; height: 2.3rem; margin-bottom: .7rem; } }
/* ---------- article figures (v10) ----------
   Figures break out past the 46rem reading measure, because a chart squeezed
   into a text column is unreadable, while a paragraph at chart width is. */
.prose figure, .prose .figNote { margin: 2.6rem 0; }
@media (min-width: 1000px) {
  .prose figure, .prose .figNote { width: calc(100% + 8rem); margin-inline: -4rem; }
}
.prose .figtitle {
  margin: 0 0 1.5rem; font: 600 .82rem/1.4 var(--head);
  text-transform: uppercase; letter-spacing: .07em; color: var(--ink-3);
}
.prose figure figcaption {
  margin-top: 1.1rem; padding-top: .8rem; border-top: 1px solid var(--line-2);
  font-size: .8rem; line-height: 1.5; color: var(--ink-3);
}
.prose .chart figcaption { margin-top: 1.6rem; }
.figstats-row { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1px;
                background: var(--line); border-block: 1px solid var(--line); }
.figstat { background: var(--bg); padding: 1.6rem 1.4rem; }
.figstat b { display: block; font: 600 2.3rem/1 var(--head); color: var(--accent);
             letter-spacing: -.02em; margin-bottom: .55rem; }
.figstat span { display: block; font-size: .88rem; line-height: 1.5; color: var(--ink-3); }
@media (max-width: 760px) { .figstats-row { grid-template-columns: 1fr; } }
.figtable { overflow-x: auto; }
.figNote {
  padding: 1.4rem 1.6rem; background: var(--bg-2);
  border-inline-start: 3px solid var(--accent);
}
.figNote b { display: block; margin-bottom: .6rem; font: 600 .95rem/1.4 var(--head); color: var(--ink); }
.figNote p { margin: 0 0 .7rem; font-size: .97rem; line-height: 1.7; color: var(--ink-2); }
.figNote p:last-child { margin-bottom: 0; }
/* v11 — in a "lower is better" chart the highlighted bar is the SHORTEST one,
   so height cannot be what carries the emphasis: a 34-vs-1 comparison renders
   the good outcome as a 7px sliver. The value label carries it instead, and
   every bar keeps a floor tall enough to still read as a bar. */
.chart .bar .v { min-height: 10px; }
.chart .bar.on b { color: var(--accent); font-size: 1.25rem; }
.chart .bar.on .v { box-shadow: 0 0 0 1px var(--accent); }

/* v12 — team portraits were far too large.
   The hero portrait rendered 340x425 on a phone: 52% of the first screen given
   to a headshot, pushing the person's actual role and background below the
   fold. A portrait is supporting material on a bio page, not the content. */
.portrait.lg { max-width: 210px; }
/* margin-inline:auto, and it is not optional.
   .portrait is a BLOCK that is width:100% capped to a max-width, sitting in a
   tile that is wider than the cap. `text-align: center` on the tile centres the
   name and role — inline content — but has no effect on a block box, so every
   photo sat hard against the left edge while the text under it was centred.
   Auto inline margins are what centre a block. */
.people .portrait { max-width: 150px; margin-inline: auto; }
@media (max-width: 620px) {
  .portrait.lg { max-width: 132px; }
  .people .portrait { max-width: 116px; }
  /* Sit it beside the name rather than stacked above it, so the top of the
     page leads with who the person is. The wrapper is .personid. */
  .personid { display: flex; align-items: flex-start; gap: 1.1rem; }
  .personid > .portrait.lg { flex: 0 0 auto; }
  .personid > div:last-child { min-width: 0; }
}

/* v13 — LinkedIn cards. A link to the live profile, not an embedded feed:
   LinkedIn retired its public feed plugins, so anything claiming to be an
   automatic feed here would be a paid aggregator or a scraper. */
.linkedincard {
  display: flex; align-items: center; gap: 1rem; margin: 2.4rem 0 0;
  padding: 1.1rem 1.3rem; border: 1px solid var(--line); border-radius: 3px;
  background: var(--bg-2);
}
.linkedincard > div { flex: 1; min-width: 0; }
.linkedincard strong { display: block; font: 600 .98rem/1.4 var(--head); }
.linkedincard p { margin: .2rem 0 0; }
.li-mark { flex: none; display: inline-flex; align-items: center; justify-content: center;
           width: 2.4rem; height: 2.4rem; border-radius: 3px;
           background: #0a66c2; color: #fff; }
@media (max-width: 620px) {
  .linkedincard { flex-wrap: wrap; }
  .linkedincard .btn { width: 100%; }
}

/* Insights: articles beside a narrow rail. */
.insightswrap { display: grid; grid-template-columns: minmax(0,1fr) 290px; gap: 3rem; align-items: start; }
.insightsrail { position: sticky; top: 5rem; display: grid; gap: 1rem; }
.railcard { padding: 1.3rem; border: 1px solid var(--line); border-radius: 3px; background: var(--bg-2); }
.railcard .li-mark { margin-bottom: .8rem; }
.railcard strong { display: block; margin-bottom: .35rem; font: 600 1rem/1.4 var(--head); }
.railcard p { margin: 0 0 1rem; }
@media (max-width: 980px) {
  .insightswrap { grid-template-columns: 1fr; gap: 2.2rem; }
  .insightsrail { position: static; grid-template-columns: 1fr 1fr; }
}
@media (max-width: 620px) { .insightsrail { grid-template-columns: 1fr; } }

/* v14 — cal.com embed on the contact page, restored with the feature. */
.calwrap { margin-top: .6rem; border: 1px solid var(--line); border-radius: 2px;
           overflow: hidden; background: #fff; }
.calembed { width: 100%; min-height: 660px; overflow: auto; background: #fff; }
@media (max-width: 620px) { .calembed { min-height: 580px; } }

/* v15 — Google reviews. Masonry-ish columns so the long lead review does not
   force every other card to its height. */
.reviews { columns: 2; column-gap: 1.6rem; }
.review {
  break-inside: avoid; margin: 0 0 1.6rem; padding: 1.5rem 1.6rem;
  background: var(--bg); border: 1px solid var(--line); border-radius: 3px;
}
.review-lead { border-color: var(--accent-br); }
.review .stars { display: flex; gap: 2px; margin-bottom: .9rem; color: #f5a623; }
.review blockquote { margin: 0; }
.review blockquote p { margin: 0 0 .8rem; font-size: .98rem; line-height: 1.7; color: var(--ink-2); }
.review blockquote p:last-child { margin-bottom: 0; }
.review figcaption { margin-top: 1rem; padding-top: .8rem; border-top: 1px solid var(--line-2); font-size: .86rem; }
.review figcaption strong { display: block; color: var(--ink); }
.review figcaption span { display: block; color: var(--ink-3); }
.review .revwhen { font-size: .8rem; }
@media (max-width: 860px) { .reviews { columns: 1; } }

/* ---- Image tint ---------------------------------------------------------
   A dark navy wash over photography, so images sit back behind the text
   instead of competing with it. Applied to the wrapper rather than the <img>,
   because an <img> cannot carry a ::after.

   Deliberately NOT applied to team photographs. Those are pictures of people,
   and darkening someone's face to match a brand palette is the one place this
   treatment makes the page worse. */
.tint { position: relative; overflow: hidden; border-radius: inherit; }
.tint::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: rgba(22, 32, 43, .42);
  border-radius: inherit;
}
.tint img { display: block; width: 100%; }

/* A partner logo image sits inside the same mark box the initials use, so a
   strip that mixes uploaded artwork and fallback initials still lines up. */
.logomark img { max-width: 100%; max-height: 100%; object-fit: contain; }

/* The note under the reviews, with the case-study link beside it. Side by side
   on desktop where there is room, stacked on a phone -- a full-width button
   under a one-line caption looks like a mistake. */
.revfoot { display: flex; flex-wrap: wrap; align-items: center;
           justify-content: space-between; gap: 1.2rem;
           margin-top: 1.6rem; padding-top: 1.4rem;
           border-top: 1px solid var(--line); }
.revfoot .hint { margin: 0; flex: 1 1 22rem; }
.revfoot .btn { flex: 0 0 auto; }
@media (max-width: 620px) {
  .revfoot { flex-direction: column; align-items: stretch; }
  .revfoot .btn { justify-content: center; }
}

/* ---- Legal pages --------------------------------------------------------
   Full page width, matching every other section on the site — these were the
   last blocks still sitting at a narrower measure.

   Long-form legal text set edge to edge at 1280px is genuinely hard to read,
   so rather than leave it as one very wide column the body flows into columns
   on a wide screen: the page fills its width, and no single line runs much
   past a comfortable length. Below 1100px it collapses to one column, which is
   where most people read it anyway. */
.legal { max-width: var(--wrap); }
.legal h2 { margin-top: 2rem; }
.legal h2:first-of-type { margin-top: 0; }

@media (min-width: 1100px) {
  .legal .lede { max-width: 62ch; }
  .legal > h2,
  .legal > p:not(.lede) { break-inside: avoid; }
  .legal { column-count: 2; column-gap: 3.5rem; }
  /* The intro and the closing note read as page furniture, not body copy, so
     they span both columns instead of being chopped in half. */
  .legal > .lede,
  .legal > .muted { column-span: all; }
}


/* The cookie notice heading sat in the muted grey used for body copy, which
   made the one thing identifying the panel the quietest thing in it. */
.cookiebar h4 { color: var(--ink); }

/* ---- Sign-in overlay ----------------------------------------------------
   The page behind blurs and dims; the sign-in card floats in front. The card
   is an iframe of /signin on this same origin — the real page, doing the real
   work — so there is one implementation of sign-in rather than two. */
body.signin-open { overflow: hidden; }
/* Everything except the overlay itself gets the treatment. */
body.signin-open > *:not(.signin-overlay) {
  filter: blur(4px) saturate(.85);
  transition: filter .18s ease;
  pointer-events: none;
}
.signin-overlay { position: fixed; inset: 0; z-index: 200;
                  display: flex; align-items: center; justify-content: center;
                  padding: 1.5rem; }
.signin-overlay .modal-back { position: absolute; inset: 0;
                              background: rgba(10,16,22,.55); }
.signin-frame-wrap { position: relative; width: 100%; max-width: 760px;
                     background: #fff; border-radius: 4px; overflow: hidden;
                     box-shadow: 0 30px 70px rgba(0,0,0,.45); }
/* Height is set from the frame's own content by the script in inc/foot.php.
   The value here is only what shows for the instant before that runs, and a
   floor so an empty frame is never zero-height. A fixed height was the bug:
   the two-factor step and any error state are taller than the first screen,
   and that is where the scrollbar came from. */
#signin-frame { display: block; width: 100%; height: 470px; min-height: 320px;
                border: 0; overflow: hidden; }
.signin-overlay .modal-x { position: absolute; top: .4rem; inset-inline-end: .5rem;
                           z-index: 2; width: 34px; height: 34px; padding: 0;
                           background: transparent; border: 0; cursor: pointer;
                           font-size: 1.5rem; line-height: 1; color: var(--ink-3); }
.signin-overlay .modal-x:hover { color: var(--ink); }
@media (max-width: 720px) {
  .signin-overlay { padding: .8rem; }
}
/* Motion is a nicety; blur on a low-powered machine is not. */
@media (prefers-reduced-motion: reduce) {
  body.signin-open > *:not(.signin-overlay) { filter: none; transition: none; }
}

/* ---- Hero slides --------------------------------------------------------
   Three panels stacked in the same space, cross-faded. Stacked rather than
   slid sideways so the section's height is the tallest slide and never jumps
   between them. */
.heroslider { position: relative; display: grid; }
.heroslide { grid-area: 1 / 1; opacity: 0; visibility: hidden;
             transition: opacity .5s ease, visibility .5s; }
.heroslide.on { opacity: 1; visibility: visible; }
/* NOTE: there is deliberately no `:first-child { opacity: 1 }` fallback here.
   There was, and it broke the slider outright: it carries the same specificity
   as `.heroslide.on` but sits later in the file, so slide one stayed visible on
   top of whichever slide was fading in — two headlines over each other. The
   companion rule meant to cancel it could never match, because a first child is
   never a following sibling.
   The no-JavaScript case is handled in the markup instead: home.php renders the
   first slide with `class="heroslide on"` already applied, so it shows whether
   or not the script ever runs. One mechanism, not two fighting. */

/* The active slide sits above the others while it fades, so the outgoing one
   cannot show through it mid-transition. */
.heroslide.on { z-index: 2; }

.herodots { position: absolute; z-index: 3; bottom: 1.6rem; inset-inline-start: 0;
            width: 100%; display: flex; gap: .5rem; justify-content: center; }
.herodots button { width: 34px; height: 4px; padding: 0; border: 0; cursor: pointer;
                   background: rgba(255,255,255,.32); border-radius: 0;
                   transition: background .2s; }
.herodots button:hover { background: rgba(255,255,255,.55); }
.herodots button[aria-selected="true"] { background: var(--accent); }
@media (prefers-reduced-motion: reduce) {
  .heroslide { transition: none; }
}

/* `.hero-img` is the plain full-bleed treatment used by the parked page and
   the case study: a photograph behind the navy gradient at low opacity.

   It briefly carried a constrained, edge-feathered variant built for the home
   slider. The slider now uses a contained panel (.heroshot) instead, so that
   variant had no user left — and because it also matched these two pages, it
   was quietly reframing them. Deleted rather than kept "in case": dead CSS
   that still matches live elements is how a page changes for no reason. */

/* Resolution switching for the hero photographs. Descriptors are 1x/2x
   because that is the only thing image-set() accepts — width descriptors
   (`1600w`) are srcset syntax and make the whole declaration invalid, which
   is what used to leave every visitor on the 1600px file. */
.heroshot {
  background-image: var(--img-md);
  background-image: image-set(var(--img-md) 1x, var(--img-lg) 2x);
}
@media (max-width: 700px) {
  .heroshot {
    background-image: var(--img-sm);
    background-image: image-set(var(--img-sm) 1x, var(--img-md) 2x);
  }
}

/* ---------- split hero ----------
   The slider no longer paints a photograph across the whole section, so the
   navy wash that used to sit on top of it would now just dim the text. Both
   are switched off for the slider alone; interior pages still use them. */
.heroslider::after { display: none; }
.heroslider .hero-img { display: none; }

.herosplit {
  display: grid;
  /* minmax(0,…) on both tracks: without it a long unbroken word in the
     headline sets the column's minimum and the photograph gets squeezed. */
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: center;
  padding-block: clamp(3.5rem, 6vw, 5.5rem);
}
.herocopy { min-width: 0; }
.heroart  { min-width: 0; }

/* Order rather than direction so the DOM stays copy-then-image: a screen
   reader and a keyboard should always meet the headline before the
   decoration, whichever side it is drawn on. */
.herosplit.flip .herocopy { order: 2; }
/* …and because `order` moves the copy into the SECOND track, the track sizes
   have to swap with it, or the flipped slide hands the wider column to the
   photograph. That is exactly what it was doing: measured on the live page,
   slide two's copy sat in 569px while slides one and three had 597px.

   Behind a min-width query, not bare. Written unscoped it was `.herosplit.flip`
   — two classes — against the mobile rule's single `.herosplit`, and since a
   media query contributes nothing to specificity, it beat the one-column
   layout at every size. On a 375px phone that produced two columns of 143px
   and 164px with the headline in the narrow one. */
@media (min-width: 861px) {
  .herosplit.flip { grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); }
}

.heroshot {
  aspect-ratio: 4 / 3;
  background-size: cover;
  background-position: center;
  /* Shown at full strength. It is a photograph, not a texture. */
  border: 1px solid rgba(255, 255, 255, .12);
  box-shadow: 0 18px 50px rgba(0, 0, 0, .35);
}

/* These caps, not the grid, are what made the copy look pinched: the column is
   ~620px but the headline was held to 16ch (416px), so it wrapped to three and
   four lines with a third of its column empty beside it. Widened to roughly
   fill the track while still stopping short of edge-to-edge text. */
.hero .herosplit h1 { max-width: 22ch; }
.hero .herosplit .lede { max-width: 54ch; }

/* One column on narrow screens, photograph second so the headline still
   opens the page. Shorter crop because a 4:3 panel plus copy is more
   scrolling than a phone hero should ask for. */
@media (max-width: 860px) {
  .herosplit { grid-template-columns: 1fr; gap: 2rem; }
  .herosplit.flip .herocopy { order: 0; }
  .heroshot { aspect-ratio: 16 / 9; }
}




/* ---------- "we work in your area" line ----------
   Quiet by design. It is a courtesy to the reader, not a claim competing with
   the headline above it, and it is absent entirely for the substantial share
   of visitors whose IP tells us nothing. A loud bar that appears for some
   people and not others reads as a broken page. */
.localnote {
  background: var(--bg-2, #f6f7f8);
  border-block: 1px solid var(--line);
  font-size: .92rem;
  color: var(--ink-2);
}
.localnote .wrap { padding-block: .7rem; }


/* ---------- the home slider is light, not navy ----------
   Everything below is scoped to .heroslider on purpose. `.hero` is also the
   page head on every interior page, where the navy band still does its job;
   restyling `.hero` itself would have repainted twenty pages to fix one. */
.heroslider { background: var(--bg-2); color: var(--ink-2); }
.heroslider h1 { color: var(--ink); }
.heroslider .lede { color: var(--ink-3); }

/* `.btn.light` is drawn for dark grounds — a white border and white text, which
   on grey is an invisible button with invisible writing. */
.heroslider .btn.light { border-color: var(--line); color: var(--ink); background: #fff; }
.heroslider .btn.light:hover { background: var(--navy); border-color: var(--navy); color: #fff; }

/* The dots were white-on-navy for the same reason. */
.heroslider .herodots button { background: rgba(0, 0, 0, .18); }
.heroslider .herodots button:hover { background: rgba(0, 0, 0, .34); }
.heroslider .herodots button[aria-selected="true"] { background: var(--accent); }

/* A white hairline vanished against the new ground; the shadow lightens too,
   because a heavy drop shadow on a pale background reads as a sticker. */
.heroslider .heroshot {
  border-color: var(--line);
  box-shadow: 0 14px 34px rgba(22, 32, 43, .14);
}


/* ---------- team member page ----------
   The bio used to carry the reading measure twice: `narrow` capped the wrap at
   1080 and `prose` capped again at 46rem inside it, so the text sat in the
   middle third with dead space either side.
   Note prose-wide must NOT share an element with .wrap — it sets
   max-width:none, which would cancel the site's content cap and run the text
   to the window edge at ~200 characters a line. It goes on a child instead, so
   .wrap still bounds the page and the prose fills what .wrap allows. */
.personbio { max-width: none; }

/* The "rest of the team" row is faces, not prose, so it spans the content
   width instead of sitting inside a reading measure. Tiles grow to fill rather
   than leaving a gap at the end of the row. */
.people-wide { justify-content: stretch; }
.people-wide > a { max-width: none; flex: 1 1 200px; }

/* Imagery: the CSS half of the casual-copy deterrent in inc/foot.php.
   The JS cancels contextmenu and dragstart; these three cover what an event
   handler cannot reach:
     -webkit-user-drag    stops the drag in WebKit before dragstart fires
     -webkit-touch-callout stops the iOS long-press "Save Image" sheet, which
                          is the mobile equivalent of a right-click and is not
                          a contextmenu event at all
     user-select          keeps an image out of a drag-select of the page
   Scoped to img rather than the body on purpose: making page text unselectable
   would break ordinary copying of addresses and phone numbers, which visitors
   legitimately need. As noted in foot.php, none of this prevents a determined
   copy — it removes the one-click path. */
img {
  -webkit-user-drag: none;
  -webkit-touch-callout: none;
  user-select: none;
  -webkit-user-select: none;
}
