/* ==========================================================================
   Bryder Holdings Ltd, site.css
   Single stylesheet. No build step, no external dependencies.
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Typeface

   Inter for everything: headings, text and interface. The 18 Sep 2026
   redesign follows a corporate reference set in one rounded sans, so the
   display serif (Fraunces) went with it. SIL Open Font Licence, self-hosted
   as the Latin subset of the variable file, so one request covers every
   weight. No third-party request, nothing to license.

   Note the subset stops at U+00FF plus punctuation: it has no U+2192, so the
   arrow on .arrow-link and .btn__arrow is set in --font-ui deliberately.
   -------------------------------------------------------------------------- */

@font-face {
  font-family: "Inter";
  src: url("/assets/fonts/inter-latin.woff2") format("woff2");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* --------------------------------------------------------------------------
   1. Reset
   -------------------------------------------------------------------------- */

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

* { margin: 0; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  min-height: 100vh;
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.65;
  color: var(--text);
  background: var(--bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

img, svg, video { display: block; max-width: 100%; height: auto; }
input, button, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; padding: 0; }

/* Headings are the text face set heavy and tight, in sentence case. The
   reference sets everything in one rounded sans; Inter at 800 with a touch
   of negative tracking reads the same way without a second family. */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  line-height: 1.08;
  letter-spacing: -0.022em;
  font-weight: 800;
  color: var(--heading);
  text-wrap: balance;
}

/* For display-face text that is not a heading: the director name, a large
   figure, anything that should match the headings. */
.h-display {
  font-family: var(--font-display);
  letter-spacing: -0.012em;
  line-height: 1.08;
  font-weight: 700;
}

p { text-wrap: pretty; }

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

::selection { background: var(--accent); color: var(--accent-fg); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}

/* --------------------------------------------------------------------------
   2. Design tokens
   -------------------------------------------------------------------------- */

:root {
  /* One family. --font-display stays as a token because the fact values,
     contact values and .h-display name it; it simply resolves to Inter. */
  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               "Helvetica Neue", Arial, sans-serif;
  --font-display: var(--font-sans);
  --font-ui: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
             "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, monospace;

  --wrap: 74rem;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  --header-h: 4.75rem;
  --topbar-h: 2.5rem;

  --r-sm: 8px;
  --r-md: 14px;
  --r-lg: 22px;
  /* Buttons and tags are full pills. */
  --r-pill: 100px;
}

/* --- Palette -------------------------------------------------------------

   23 Sep 2026: near-monochrome, with the brand green as the one accent.

   The layout now follows an editorial reference (dayos.com): walls of heavy
   capitals, hard black and off-white bands, black pill buttons, and a single
   sculptural object as the only real colour on the page. Here that object is
   the Bryder mark itself, rendered in 3D (scripts/render-mark.cjs), and the
   green that used to cover every surface now appears only where it earns
   its place: the mark, the accent line in the hero, eyebrows on the dark
   bands, links and focus rings.

   The greys are not neutral. Each carries a slight green bias, so the page
   still belongs to the same house as KiwiBudget without being painted in it:

     ink          #0B0E0D  text, dark bands, the top bar, footer, buttons
     paper        #EFF1F0  page background
     paper alt    #E6E9E7  alternate sections
     kowhai       #107A68  the accent on light: links, focus, the hero line
     kowhai bright #47D1B6 the accent on dark: eyebrows on the black bands

   Two contrast decisions carry over unchanged and should not be undone by
   eye. Kowhai is the CTA green darkened until white sits on it at 5.24:1.
   Kowhai bright is too light to carry white text, so it is only ever text
   on the dark bands, where it runs about 10:1.

   --btn-bg and --btn-fg are separate from --accent on purpose. Buttons went
   black in this redesign while links and focus rings stayed green, and
   pulling the two apart is what let that happen without touching either. */

html[data-theme="light"] {
  --bg:        #EFF1F0;
  --bg-alt:    #E6E9E7;
  --surface:   #FFFFFF;
  --line:      #D3D8D5;
  --line-soft: #E2E6E4;
  --text:      #111513;
  --muted:     #545C58;
  --heading:   #0B0E0D;
  --accent:    #107A68;
  --accent-ink:#0D6355;
  --accent-fg: #FFFFFF;
  --accent-bright: #47D1B6;
  --accent-bg: #DDF0EA;
  --ink:       #0B0E0D;
  --ink-text:  #F1F3F2;
  --ink-muted: #9BA49F;
  --ink-line:  #262C29;
  --btn-bg:    #0B0E0D;
  --btn-fg:    #FFFFFF;
  --shadow:    0 1px 2px rgba(11, 14, 13, .05), 0 14px 34px -20px rgba(11, 14, 13, .35);
}

html[data-theme="dark"] {
  --bg:        #0B0D0C;
  --bg-alt:    #111413;
  --surface:   #161A18;
  --line:      #262C29;
  --line-soft: #1C201E;
  --text:      #EEF1EF;
  --muted:     #9AA39F;
  --heading:   #F6F8F7;
  --accent:    #20B69D;
  --accent-ink:#47D1B6;
  /* White fails on the lifted dark-mode green (2.55:1); near-black passes
     at 6.36:1. This is why the accent's text colour is a token and not #fff. */
  --accent-fg: #03261A;
  --accent-bright: #47D1B6;
  --accent-bg: #173029;
  /* The bands lift rather than darken in dark mode: black on black is not a
     band. A step up in value plus the hairline is what separates them. */
  --ink:       #161A18;
  --ink-text:  #F1F3F2;
  --ink-muted: #9AA39F;
  --ink-line:  #2A302D;
  /* The button inverts: a white pill on the dark page, as the black one is
     on the light page. */
  --btn-bg:    #F1F3F2;
  --btn-fg:    #0B0D0C;
  --shadow:    0 1px 2px rgba(0, 0, 0, .4), 0 12px 32px -18px rgba(0, 0, 0, .8);
}

/* --------------------------------------------------------------------------
   3. Layout primitives
   -------------------------------------------------------------------------- */

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

.wrap--narrow { max-width: 50rem; }

.section { padding-block: clamp(3.5rem, 8vw, 6.5rem); }
.section--tight { padding-block: clamp(2.5rem, 5vw, 4rem); }
.section--alt { background: var(--bg-alt); }
.section--line { border-top: 1px solid var(--line); }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  padding: .7rem 1.1rem;
  background: var(--accent);
  color: var(--accent-fg);
  border-radius: 0 0 var(--r-sm) 0;
}
.skip-link:focus { left: 0; }

/* --------------------------------------------------------------------------
   4. Typography helpers
   -------------------------------------------------------------------------- */

/* Wide-tracked caps in the text face, sitting above every section heading.
   The tracking is the point: at .26em it reads as a label rather than as a
   short line of copy. */
.eyebrow {
  font-family: var(--font-sans);
  font-size: .78rem;
  font-weight: 500;
  letter-spacing: .26em;
  text-transform: uppercase;
  color: var(--accent-ink);
  margin-bottom: 1.1rem;
}

/* Display headings: heavy capitals, set tight, the way the reference sets
   them. Inter's variable file already covers 900, so this costs no request.

   Uppercase by CSS, not in the markup, deliberately. The markup stays in
   sentence case so a screen reader says "Who is accountable" rather than
   spelling out capitals, copying a heading gives normal text, and reverting
   the look is one line here rather than an edit to every page.

   Only these two classes are transformed. Card titles, prose headings and
   the newsroom (which has its own typography, see README) stay as written. */
.h-xl,
.h-lg {
  text-transform: uppercase;
  font-weight: 900;
  line-height: .92;
  letter-spacing: -0.032em;
}
.h-xl  { font-size: clamp(2.8rem, 8.2vw, 6.6rem); }
.h-lg  { font-size: clamp(2.2rem, 5.4vw, 4.3rem); }
.h-md  { font-size: clamp(1.4rem, 2.2vw, 1.8rem); }
.h-sm  { font-size: 1.2rem; letter-spacing: -0.008em; }

.lede {
  font-size: clamp(1.04rem, 1.5vw, 1.18rem);
  color: var(--muted);
  max-width: 48ch;
}

.prose p + p,
.prose p + ul,
.prose ul + p,
.prose h3 { margin-top: 1.1rem; }

.prose h3 { margin-top: 2.2rem; }
.prose h3 + p { margin-top: .7rem; }

.prose a {
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.prose a:hover { text-decoration-thickness: 2px; }

.prose ul { display: grid; gap: .55rem; }
.prose ul li {
  position: relative;
  padding-left: 1.2rem;
  color: var(--muted);
}
.prose ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .68em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

/* Small tracked caps, the same treatment the fact and contact labels get.
   Use it for a label that is not part of one of those lists. */
.label {
  font-family: var(--font-sans);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--muted);
}

.muted { color: var(--muted); }
.mt-1 { margin-top: .5rem; }
.mt-2 { margin-top: 1rem; }
.mt-3 { margin-top: 1.75rem; }
.mt-4 { margin-top: 2.5rem; }

/* --------------------------------------------------------------------------
   5. Buttons
   -------------------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  gap: .55rem;
  padding: .82rem 1.7rem;
  border-radius: var(--r-pill);
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-size: .94rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  border: 1px solid var(--btn-bg);
  transition: transform .16s ease, filter .16s ease, background .16s ease;
  white-space: nowrap;
}
/* brightness() does nothing to black, so the hover lifts by opacity instead. */
.btn:hover { opacity: .86; transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn--ghost {
  background: transparent;
  color: var(--text);
  border-color: var(--line);
}
.btn--ghost:hover { background: var(--bg-alt); filter: none; opacity: 1; }

/* The one bright note in the palette. Pounamu text on kowhai bright is
   4.61:1, so it stays a background colour and never a text colour here. */
.btn--bright {
  background: var(--accent-bright);
  border-color: var(--accent-bright);
  color: #06563B;
}

.btn--sm { padding: .58rem 1.2rem; font-size: .875rem; }

/* Trailing arrow, matching the reference's buttons. The glyph lives in the
   markup rather than in `content` so it is one span either way, and it is
   set in --font-ui because the Latin subsets of Fraunces and Inter stop
   short of U+2192 and would otherwise fall back mid-label. */
.btn__arrow {
  font-family: var(--font-ui);
  display: inline-block;
  transition: transform .16s ease;
}
.btn:hover .btn__arrow { transform: translateX(3px); }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem;
  align-items: center;
}

.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  color: var(--accent-ink);
  font-weight: 600;
  font-size: .93rem;
}
.arrow-link::after {
  content: "→";
  font-family: var(--font-ui);
  transition: transform .16s ease;
}
.arrow-link:hover::after { transform: translateX(3px); }

/* --------------------------------------------------------------------------
   6. Top bar, header and nav

   Two rows, after the reference: a thin dark band of company links with a
   dropdown (the top bar, which scrolls away), then the main row with the
   logo, the businesses and a Contact pill, which sticks. On pages with a
   hero the main row floats transparent over the photograph until the first
   scroll. Below 900px the top bar disappears and its links move into the
   drawer under the menu button.
   -------------------------------------------------------------------------- */

.topbar {
  position: relative;
  z-index: 51;
  background: var(--ink);
  color: #fff;
  font-size: .84rem;
}
.topbar__row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--topbar-h);
}
.topbar__home {
  color: rgba(255, 255, 255, .72);
  font-weight: 600;
  letter-spacing: .02em;
  white-space: nowrap;
}
.topbar__home:hover { color: #fff; }

.topbar__nav {
  display: flex;
  align-items: center;
  gap: 1.35rem;
  margin-left: auto;
}
.topbar__nav > a,
.menu__btn {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .35rem 0;
  color: rgba(255, 255, 255, .86);
  font-weight: 500;
  white-space: nowrap;
  transition: color .15s ease;
}
.topbar__nav > a:hover,
.menu__btn:hover,
.topbar__nav > a[aria-current="page"] { color: #fff; }
.topbar__sep {
  width: 1px;
  height: 1rem;
  background: rgba(255, 255, 255, .28);
}

/* Dropdown. CSS opens it on hover and on keyboard focus; site.js adds a
   click toggle (is-open) for touch screens that have neither. */
.menu { position: relative; }
.menu__btn svg {
  width: .8rem;
  height: .8rem;
  transition: transform .15s ease;
}
.menu.is-open .menu__btn svg,
.menu:hover .menu__btn svg { transform: rotate(180deg); }
.menu__panel {
  position: absolute;
  top: calc(100% + .3rem);
  left: -.75rem;
  min-width: 13.5rem;
  padding: .5rem;
  background: var(--surface);
  color: var(--text);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  box-shadow: var(--shadow);
  display: none;
  z-index: 60;
}
/* Bridges the gap between button and panel so the hover does not drop. */
.menu__panel::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: -.45rem;
  height: .45rem;
}
.menu__panel a {
  display: block;
  padding: .55rem .75rem;
  border-radius: var(--r-sm);
  font-size: .9rem;
  color: var(--text);
}
.menu__panel a:hover { background: var(--bg-alt); color: var(--accent-ink); }
.menu.is-open .menu__panel,
.menu:hover .menu__panel,
.menu:focus-within .menu__panel { display: block; }

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 92%, transparent);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid transparent;
  transition: background .25s ease, border-color .2s ease, box-shadow .2s ease;
}
.site-header.is-stuck {
  border-bottom-color: var(--line);
  box-shadow: 0 1px 20px -12px rgba(0, 0, 0, .5);
}

/* --- Transparent header over a hero image -------------------------------

   On pages with `body.has-hero` the main row floats on the photograph until
   the first scroll, then settles into its normal solid state. The hero is
   pulled up by the row's own height so the image starts at the very top of
   the viewport; the row still occupies flow, so nothing else shifts.

   The soft shade behind the floating row lives on ::before and fades by
   opacity, because a gradient cannot transition into the solid background.
   The background itself is written as a 0% color-mix rather than the
   `transparent` keyword so both ends of that transition are the same kind
   of value: going keyword -> color-mix() can leave the header stuck
   transparent, which on a light page means invisible links. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, rgba(11, 14, 13, .58), rgba(11, 14, 13, 0));
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s ease;
  z-index: -1;
}
body.has-hero .site-header:not(.is-stuck) {
  background: color-mix(in srgb, var(--bg) 0%, transparent);
  backdrop-filter: none;
  box-shadow: none;
  border-bottom-color: transparent;
}
body.has-hero .site-header:not(.is-stuck)::before { opacity: 1; }
body.has-hero .site-header:not(.is-stuck) .nav__link { color: rgba(255, 255, 255, .88); }
body.has-hero .site-header:not(.is-stuck) .nav__link:hover,
body.has-hero .site-header:not(.is-stuck) .nav__link[aria-current="page"] {
  color: #fff;
  background: rgba(255, 255, 255, .12);
}
body.has-hero .site-header:not(.is-stuck) .icon-btn {
  color: rgba(255, 255, 255, .85);
  border-color: rgba(255, 255, 255, .3);
}
body.has-hero .site-header:not(.is-stuck) .icon-btn:hover {
  color: #fff;
  background: rgba(255, 255, 255, .14);
}
body.has-hero .site-header:not(.is-stuck) .brand__logo--dark { display: none; }
body.has-hero .site-header:not(.is-stuck) .brand__logo--light { display: block; }

/* The Contact pill: white on the photograph, the button colour once solid. */
body.has-hero .site-header:not(.is-stuck) .nav__cta {
  background: #fff;
  border-color: #fff;
  color: #0B0E0D;
}
/* The link pill goes glass over a photograph rather than a white slab. */
body.has-hero .site-header:not(.is-stuck) .nav__links {
  background: rgba(255, 255, 255, .08);
  border-color: rgba(255, 255, 255, .2);
}

/* Sign-in pages keep a Help pill in the header; it is a navigation item
   wearing a button, so it takes the nav link colour rather than full text. */
.site-header .btn--ghost {
  color: var(--muted);
  border-color: var(--line);
}
.site-header .btn--ghost:hover { color: var(--text); }

.nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  min-height: var(--header-h);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: .65rem;
  flex-shrink: 0;
}

/* Two copies of the lockup, one per theme, swapped in CSS. Both are in the
   markup so the switch is instant and needs no JavaScript. Sized by WIDTH,
   not height: the ink and white lockups are two different compositions, and
   they are exported so that an equal width gives an equal wordmark. */
.brand__logo {
  width: 132px;
  height: auto;
}
html[data-theme="light"] .brand__logo--light,
html[data-theme="dark"]  .brand__logo--dark { display: none; }

/* The footer has its own lockup, the one carrying the New Zealand silhouette.
   It sits on ink in both themes, so there is nothing to swap. */
.footer__logo {
  width: 150px;
  height: auto;
}

/* The links sit in one rounded pill, centred between the logo and the
   actions, after the reference. margin-inline:auto on a flex child in a
   space-between row is what centres it in the space that is left. */
.nav__links {
  display: flex;
  align-items: center;
  gap: .1rem;
  margin-inline: auto;
  padding: .3rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
}

.nav__link {
  padding: .5rem 1rem;
  border-radius: var(--r-pill);
  font-size: .9rem;
  color: var(--text);
  font-weight: 600;
  transition: color .15s ease, background .15s ease;
}
.nav__link:hover { color: var(--heading); background: var(--bg-alt); }
.nav__link[aria-current="page"] { color: var(--heading); background: var(--bg-alt); }

/* The in-menu pill and the secondary links are the drawer's copies of the
   Contact pill and the top bar. On desktop only .nav__cta and .topbar show. */
.nav__links > .btn,
.nav__secondary { display: none; }

.nav__actions {
  display: flex;
  align-items: center;
  gap: .6rem;
}

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--r-sm);
  border: 1px solid var(--line);
  color: var(--muted);
  transition: color .15s ease, background .15s ease;
}
.icon-btn:hover { color: var(--text); background: var(--bg-alt); }

.icon-sun { display: none; }
html[data-theme="dark"] .icon-sun { display: block; }
html[data-theme="dark"] .icon-moon { display: none; }

.nav__toggle { display: none; }

@media (max-width: 900px) {
  .topbar { display: none; }

  .nav__links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: .15rem;
    margin: 0;
    padding: .75rem var(--gutter) 1.25rem;
    background: var(--bg);
    /* Undo the desktop pill: the drawer is a full-width panel. */
    border: 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    box-shadow: var(--shadow);
    display: none;
  }
  .nav__links.is-open { display: flex; }
  .nav__link { padding: .7rem .6rem; font-size: 1rem; }
  .nav__links > .btn { display: inline-flex; justify-content: center; margin-top: .5rem; }

  .nav__secondary {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: .15rem .5rem;
    margin-top: .85rem;
    padding-top: .85rem;
    border-top: 1px solid var(--line);
  }
  .nav__secondary a {
    padding: .55rem .6rem;
    border-radius: var(--r-sm);
    font-size: .92rem;
    font-weight: 550;
    color: var(--muted);
  }
  .nav__secondary a:hover { color: var(--text); background: var(--bg-alt); }

  .nav__cta { display: none; }
  .nav__toggle { display: inline-grid; }

  /* The open drawer needs a solid backdrop even while the header floats,
     so its links go back to their normal colours. */
  body.has-hero .site-header:not(.is-stuck) .nav__links.is-open .nav__link { color: var(--text); }
  body.has-hero .site-header:not(.is-stuck) .nav__links.is-open .nav__link:hover,
  body.has-hero .site-header:not(.is-stuck) .nav__links.is-open .nav__link[aria-current="page"] {
    color: var(--accent-ink);
    background: var(--bg-alt);
  }
}

/* --------------------------------------------------------------------------
   7. Hero
   -------------------------------------------------------------------------- */

/* Base hero: a dark photographic band in both themes. The homepage carousel
   and the profile hero both build on this, and the header floats over it. */
.hero {
  position: relative;
  padding-block: clamp(4rem, 10vw, 8rem) clamp(3.5rem, 8vw, 6rem);
  overflow: hidden;
  background: #0B0E0D;
  color: #F6F9F8;
}

/* Slide the hero under the floating header, then put the space back as
   padding so the content still clears it. */
body.has-hero .hero {
  margin-top: calc(-1 * var(--header-h));
  padding-top: calc(var(--header-h) + clamp(3rem, 7vw, 5rem));
}
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: 60% 45%;
}
/* Readability scrim: heaviest behind the text column. */
.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(97deg, rgba(11,14,13,.94) 0%, rgba(11,14,13,.86) 38%,
                           rgba(11,14,13,.55) 68%, rgba(11,14,13,.32) 100%),
    linear-gradient(to bottom, rgba(11,14,13,.35), rgba(11,14,13,0) 30%);
}
.hero > .wrap { position: relative; z-index: 1; }

.hero .eyebrow { color: var(--accent-bright); }
.hero h1 { color: #FFFFFF; }
.hero p.lede { margin-top: 1.35rem; max-width: 50ch; color: #D3D8D5; }
.hero .btn-row { margin-top: 2.25rem; }
.hero .btn--ghost {
  color: #F6F9F8;
  border-color: rgba(246, 249, 248, .55);
  background: rgba(255, 255, 255, .06);
  backdrop-filter: blur(4px);
}
.hero .btn--ghost:hover { background: rgba(255, 255, 255, .14); }
/* This hero is dark in both themes, so its links cannot take the theme's
   link colour: in the light theme that is the dark green, and on the photo
   hero of /jack-ridder/ it came out at 2.7:1. The bright green is ~10:1 on
   the hero in either theme. Found by a contrast sweep on 23 Sep 2026; it
   predated the monochrome palette, which left the ratio unchanged. */
.hero .arrow-link { color: var(--accent-bright); }

/* --- Homepage carousel ----------------------------------------------------

   One slide showing at a time, cross-faded. Each slide carries its own
   photograph, its own green tint and its own copy, so a slide is a complete
   thought rather than a caption under a shared picture. The first slide
   carries is-active in the markup, so with JavaScript off the page shows it
   and simply has no arrows or dots. */
.hero--carousel {
  padding: 0;
  display: block;
}
body.has-hero .hero--carousel { padding-top: 0; }
.hero--carousel::before,
.hero--carousel::after { content: none; }

/* Every slide sits in the same grid cell, so the tallest one sets the
   hero's height and no caption can ever run into the dots or the strip
   card below. The photographs are absolute inside their slide. */
.slides {
  position: relative;
  display: grid;
  min-height: clamp(34rem, 78vh, 46rem);
}
.slide {
  grid-area: 1 / 1;
  position: relative;
  display: grid;
  align-items: center;
  opacity: 0;
  visibility: hidden;
  transition: opacity .8s ease, visibility 0s linear .8s;
}
.slide.is-active {
  opacity: 1;
  visibility: visible;
  z-index: 1;
  transition-delay: 0s;
}
.slide__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 62% 40%;
}
/* The tint pulls every photograph towards the brand green, heaviest behind
   the text column and fading to the right so the picture still shows. */
.slide::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(92deg, rgba(11,14,13,.90) 0%, rgba(11,14,13,.74) 42%,
                           rgba(11,14,13,.42) 72%, rgba(11,14,13,.30) 100%),
    linear-gradient(to bottom, rgba(11,14,13,.55), rgba(11,14,13,0) 28%),
    linear-gradient(to top, rgba(11,14,13,.6), rgba(11,14,13,0) 34%);
}
.slide__text {
  position: relative;
  z-index: 1;
  /* Clears the floating header at the top; leaves room at the bottom for the
     dots and for the strip card that overlaps the hero's lower edge. */
  padding-top: calc(var(--header-h) + clamp(2.5rem, 6vw, 4rem));
  padding-bottom: clamp(7rem, 14vw, 9.5rem);
}
.slide__inner { max-width: 40rem; }
.slide__title {
  color: #fff;
  font-size: clamp(2.2rem, 4.6vw, 3.6rem);
  line-height: 1.02;
  letter-spacing: -0.028em;
  font-weight: 800;
}
.slide__title .hl { color: var(--accent-bright); }
/* The three bars from the logo, as the flourish after the highlighted phrase. */
.hl__mark {
  display: inline-block;
  width: .5em;
  height: .46em;
  margin-left: .16em;
  vertical-align: -.02em;
  color: var(--accent-bright);
}
.slide__lede {
  margin-top: 1.35rem;
  max-width: 46ch;
  color: #DDE1DF;
  font-size: clamp(1rem, 1.4vw, 1.12rem);
}
.slide .btn-row { margin-top: 2rem; }

.btn--white {
  background: #fff;
  border-color: #fff;
  color: #0B0E0D;
}
.btn--white:hover { filter: none; opacity: 1; background: #E6E9E7; }

.hero__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 3;
  width: 3rem;
  height: 3rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  color: #fff;
  background: rgba(255, 255, 255, .08);
  border: 1px solid rgba(255, 255, 255, .25);
  transition: background .15s ease;
}
.hero__arrow:hover { background: rgba(255, 255, 255, .2); }
.hero__arrow--prev { left: clamp(.6rem, 2vw, 1.5rem); }
.hero__arrow--next { right: clamp(.6rem, 2vw, 1.5rem); }
.hero__arrow svg { width: 1.3rem; height: 1.3rem; }

.hero__dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: clamp(5.4rem, 10vw, 6.6rem);
  z-index: 3;
  display: flex;
  justify-content: center;
  gap: .6rem;
}
.hero__dot {
  width: .72rem;
  height: .72rem;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, .45);
  transition: background .15s ease, transform .15s ease;
}
.hero__dot:hover { background: rgba(255, 255, 255, .8); }
.hero__dot[aria-selected="true"] { background: #fff; transform: scale(1.15); }

/* The controls only make sense once site.js has taken over. */
.hero--carousel:not(.is-ready) .hero__arrow,
.hero--carousel:not(.is-ready) .hero__dots { display: none; }

@media (max-width: 640px) {
  .hero__arrow { display: none; }  /* swipe instead */
  .slide__img { object-position: 70% 40%; }
}

/* --- Profile hero -------------------------------------------------------- */

.hero--profile::before {
  background-image: url("/assets/img/jack-ridder-working.jpg");
  background-position: 22% 38%;
  filter: grayscale(1) contrast(1.04);
}
/* Heavier on the right than the homepage hero: the subject of the photo is
   over there, and the round portrait already shows his face. */
/* Neutral black now, not green-black: the photograph is already greyscale,
   and a green cast on it was the old palette showing through. */
.hero--profile::after {
  background:
    linear-gradient(94deg, rgba(11,14,13,.94) 0%, rgba(11,14,13,.88) 42%,
                           rgba(11,14,13,.74) 72%, rgba(11,14,13,.62) 100%),
    linear-gradient(to bottom, rgba(11,14,13,.55), rgba(11,14,13,0) 26%);
}
.hero--profile .lede { color: #D3D8D5; }
.hero--profile .tag {
  background: rgba(255, 255, 255, .1);
  border-color: rgba(255, 255, 255, .22);
  color: #D3D8D5;
}
.hero--profile .profile__photo {
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .28),
              0 22px 50px -22px rgba(0, 0, 0, .85);
}

.hero__crumb { margin-bottom: 1.75rem; }
.hero__crumb p { font-size: .85rem; color: #A9B1AD; }
.hero__crumb a { color: inherit; }
.hero__crumb a:hover { color: #fff; }

.page-head {
  padding-block: clamp(3rem, 7vw, 5rem) clamp(1.5rem, 3vw, 2.5rem);
  border-bottom: 1px solid var(--line);
}
.page-head .lede { margin-top: 1rem; max-width: 58ch; }

/* --------------------------------------------------------------------------
   8. Cards / grids
   -------------------------------------------------------------------------- */

.grid { display: grid; gap: 1.25rem; }

@media (min-width: 640px) {
  .grid--2 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 900px) {
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
  .grid--2\@lg { grid-template-columns: repeat(2, 1fr); }
}

.card {
  padding: 1.6rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.card:hover { border-color: color-mix(in srgb, var(--accent) 45%, var(--line)); }

a.card:hover { transform: translateY(-2px); box-shadow: var(--shadow); }

.card__num {
  font-family: var(--font-mono);
  font-size: .78rem;
  letter-spacing: .1em;
  color: var(--accent);
  margin-bottom: .9rem;
}
.card h3 { font-size: 1.24rem; }
.card p { margin-top: .6rem; color: var(--muted); font-size: .95rem; }

/* Facts strip */

.facts {
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}
@media (min-width: 700px) {
  .facts { grid-template-columns: repeat(3, 1fr); }
  /* Two-up variant. Without this a two-cell strip keeps the third column and
     renders an empty grey box where the missing cell would be. */
  .facts--2 { grid-template-columns: repeat(2, 1fr); }
}
.fact {
  background: var(--surface);
  padding: 1.4rem 1.5rem;
}
/* Labels are tracked caps in the text face; the values under them are the
   display face in sentence case. Uppercasing a serif this sharp turns a
   two-word label into a wall. */
.fact dt {
  font-family: var(--font-sans);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--muted);
}
.fact dd {
  margin-top: .5rem;
  font-family: var(--font-display);
  letter-spacing: -0.012em;
  font-size: 1.2rem;
  font-weight: 700;
  line-height: 1.25;
  text-wrap: balance;
}
/* Same opt-out as the contact list: a long number set in the display face
   at display size overruns its cell, and a serif with old-style figures is
   the wrong tool for a registration number anyway. */
.fact dd.is-literal {
  font-family: var(--font-sans);
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0;
  font-variant-numeric: tabular-nums;
}

/* Split section */

.split {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: start;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1.15fr; }
  .split__head { position: sticky; top: 6rem; }
}

/* Definition rows */

.rows { border-top: 1px solid var(--line); }
.row {
  display: grid;
  gap: .35rem 2rem;
  padding-block: 1.4rem;
  border-bottom: 1px solid var(--line);
}
@media (min-width: 700px) {
  .row { grid-template-columns: 14rem 1fr; }
}
.row dt, .row__label {
  font-weight: 620;
  font-size: .95rem;
}
.row dd, .row__body { color: var(--muted); font-size: .96rem; }

/* Links in body copy have to look like links. The base reset makes anchors
   inherit their colour and drop the underline, which inside a muted
   definition row leaves them invisible. */
.row dd a,
.contact-item dd a {
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}
.row dd a:hover,
.contact-item dd a:hover { text-decoration-thickness: 2px; }

/* Company entry */

.entry {
  display: grid;
  gap: 1.25rem;
  padding: 1.75rem;
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface);
}
@media (min-width: 760px) {
  .entry { grid-template-columns: 1fr 2fr; gap: 2.5rem; }
}
.entry__meta { display: grid; gap: .5rem; align-content: start; }
.entry__tag {
  font-family: var(--font-sans);
  justify-self: start;
  padding: .3rem .8rem;
  border-radius: var(--r-pill);
  background: var(--accent-bg);
  color: var(--accent-ink);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .16em;
  text-transform: uppercase;
}

/* Callout */

.callout {
  padding: 1.5rem 1.6rem;
  border-left: 3px solid var(--accent);
  background: var(--bg-alt);
  border-radius: 0 var(--r-md) var(--r-md) 0;
}
.callout p { color: var(--muted); }
.callout strong { color: var(--text); }

/* CTA band */

.cta-band {
  background: var(--ink);
  color: var(--ink-text);
  border-radius: var(--r-lg);
  padding: clamp(2rem, 5vw, 3.25rem);
  display: grid;
  gap: 1.5rem;
  align-items: center;
}
@media (min-width: 820px) {
  .cta-band { grid-template-columns: 1fr auto; gap: 2.5rem; }
}
.cta-band h2 { color: #fff; }
.cta-band p { color: var(--ink-muted); margin-top: .6rem; max-width: 46ch; }

/* --------------------------------------------------------------------------
   9. Contact
   -------------------------------------------------------------------------- */

.contact-grid {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: start;
}
@media (min-width: 940px) {
  .contact-grid { grid-template-columns: 1.15fr .85fr; }
}

.contact-list { display: grid; gap: 1.4rem; }

.contact-item {
  display: grid;
  gap: .2rem;
  padding-bottom: 1.4rem;
  border-bottom: 1px solid var(--line);
}
.contact-item:last-child { border-bottom: 0; padding-bottom: 0; }
.contact-item dt {
  font-family: var(--font-sans);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--muted);
}
.contact-item dd {
  font-family: var(--font-display);
  letter-spacing: -0.012em;
  font-size: 1.3rem;
  font-weight: 700;
  margin-top: .3rem;
}
/* Opt-out for values that must stay literal. Uppercasing an email address
   invites people to retype it wrong. */
.contact-item dd.is-literal {
  font-family: var(--font-sans);
  text-transform: none;
  letter-spacing: 0;
  font-size: 1.1rem;
}
.contact-item dd a:hover { color: var(--accent-ink); }
/* The note is a sibling <dd>, so it has to undo the display-face treatment
   the value above it gets. */
.contact-item .note {
  font-family: var(--font-sans);
  text-transform: none;
  letter-spacing: 0;
  font-size: .88rem;
  font-weight: 400;
  color: var(--muted);
}

/* Form */

.form {
  display: grid;
  gap: 1.1rem;
  padding: clamp(1.5rem, 3vw, 2rem);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}

.field-row { display: grid; gap: 1.1rem; }
@media (min-width: 560px) {
  .field-row { grid-template-columns: 1fr 1fr; }
}

.field { display: grid; gap: .4rem; }
.field label { font-size: .875rem; font-weight: 600; }
.field .req { color: var(--accent); }

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: .7rem .85rem;
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  font-size: .95rem;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field textarea { resize: vertical; min-height: 8rem; }

.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 18%, transparent);
}

.field input::placeholder,
.field textarea::placeholder { color: color-mix(in srgb, var(--muted) 70%, transparent); }

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

.form__foot {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  align-items: center;
  justify-content: space-between;
}
.form__note { font-size: .82rem; color: var(--muted); max-width: 32ch; }

.form__status {
  padding: .8rem 1rem;
  border-radius: var(--r-sm);
  background: var(--accent-bg);
  color: var(--accent-ink);
  font-size: .88rem;
  border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
}

/* --------------------------------------------------------------------------
   10. Profile page (Jack Ridder)
   -------------------------------------------------------------------------- */

.profile {
  display: grid;
  gap: clamp(1.75rem, 4vw, 3rem);
  align-items: center;
}
@media (min-width: 820px) {
  .profile { grid-template-columns: auto 1fr; }
}

.profile__photo {
  width: clamp(7rem, 18vw, 10.5rem);
  height: clamp(7rem, 18vw, 10.5rem);
  border-radius: 50%;
  overflow: hidden;
  background: var(--bg-alt);
  box-shadow: 0 0 0 1px var(--line), 0 14px 34px -20px rgba(11, 14, 13, .55);
}
.profile__photo img { width: 100%; height: 100%; object-fit: cover; }

/* Wide photograph, used for the 16:9 shot on the profile page. */
.figure {
  border-radius: var(--r-md);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--bg-alt);
}
.figure img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
}
.figure figcaption {
  padding: .85rem 1.1rem;
  font-size: .84rem;
  color: var(--muted);
  border-top: 1px solid var(--line);
}

.profile h1 { font-size: clamp(2.1rem, 4.8vw, 3.2rem); }
.profile .lede { margin-top: .85rem; max-width: 54ch; }

.tag-row {
  display: flex;
  flex-wrap: wrap;
  gap: .5rem;
  margin-top: 1.25rem;
}
.tag {
  padding: .3rem .7rem;
  border-radius: 100px;
  border: 1px solid var(--line);
  background: var(--surface);
  font-size: .82rem;
  color: var(--muted);
}

.faq {
  border-top: 1px solid var(--line);
  max-width: 52rem;
}
.faq__item {
  padding-block: 1.5rem;
  border-bottom: 1px solid var(--line);
}
.faq__item h3 { font-size: 1.26rem; }
.faq__item p {
  margin-top: .6rem;
  color: var(--muted);
}
.faq__item p a {
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --------------------------------------------------------------------------
   10b. News section

   The news pages run on their own type system, deliberately unlike the rest
   of the site. No Fraunces, no brand green on the headlines. Georgia sets
   the headlines and the body, which is what a lot of newsrooms use online
   and what reads best at length on a screen, and a plain grotesque handles
   the furniture: kickers, bylines, timestamps and section rules.

   Everything below is scoped to `.news` on <main>, so the header, footer and
   the rest of the site keep the corporate treatment.
   -------------------------------------------------------------------------- */

.news {
  --news-serif: Georgia, "Iowan Old Style", "Times New Roman", Times, serif;
  --news-sans: "Helvetica Neue", Helvetica, Arial, "Segoe UI", Roboto, sans-serif;
  font-family: var(--news-serif);
}

.news h1, .news h2, .news h3, .news h4 {
  font-family: var(--news-serif);
  /* Editorial headlines stay in the reading colour. The brand green on a
     newsroom headline reads as a link. */
  color: var(--text);
  letter-spacing: -0.019em;
  line-height: 1.13;
  font-weight: 700;
}

/* The closing call to action is site furniture rather than editorial, so it
   keeps the brand treatment even inside a news page. */
.news .cta-band { font-family: var(--font-sans); }
.news .cta-band h2 {
  font-family: var(--font-display);
  letter-spacing: -0.012em;
  line-height: 1.06;
  /* Needed, not decoration. `.news h2` sets headings to --text and sits later
     in this file at the same specificity as `.cta-band h2 { color: #fff }`,
     so it won, and the newsroom's closing band showed its heading in the
     body text colour on the dark band: 1.7:1 on the old palette, 1.1:1 on
     this one. This rule has the extra class to win it back. */
  color: var(--ink-text);
}

/* Furniture: kickers, section labels, bylines, timestamps. */
.news-kicker,
.news-rule__label,
.news-byline,
.news-tag {
  font-family: var(--news-sans);
  text-transform: uppercase;
  letter-spacing: .1em;
  font-weight: 700;
  font-size: .74rem;
}

.news-kicker { color: var(--accent); margin-bottom: 1rem; }

/* Section rule: a label sitting on a hairline, the way a print section head
   works. */
.news-rule {
  display: flex;
  align-items: center;
  gap: 1rem;
  border-top: 2px solid var(--text);
  padding-top: .7rem;
  margin-bottom: 2rem;
}
.news-rule__label { color: var(--text); }
.news-rule__count {
  margin-left: auto;
  font-family: var(--news-sans);
  font-size: .78rem;
  color: var(--muted);
}

/* --- Index --------------------------------------------------------------- */

.news-lead {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
}
@media (min-width: 860px) {
  .news-lead { grid-template-columns: 1.25fr 1fr; }
}
.news-lead__media img {
  width: 100%;
  aspect-ratio: 16 / 9;
  object-fit: cover;
  border-radius: 2px;
}
.news-lead__body { display: grid; gap: .85rem; align-content: start; }
.news-lead h2 { font-size: clamp(1.7rem, 3.2vw, 2.5rem); }
.news-lead h2 a:hover { color: var(--accent-ink); }
.news-lead__standfirst {
  font-size: 1.08rem;
  line-height: 1.6;
  color: var(--muted);
}

.news-byline { color: var(--muted); font-weight: 400; letter-spacing: .07em; }
.news-byline strong { color: var(--text); font-weight: 700; }
.news-byline .sep { color: var(--line); padding-inline: .45rem; }

.news-tag { color: var(--accent); }

/* Secondary items, listed under the lead. */
.news-items {
  display: grid;
  gap: 0;
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  border-top: 1px solid var(--line);
}
.news-item {
  display: grid;
  gap: .4rem 1.5rem;
  padding-block: 1.5rem;
  border-bottom: 1px solid var(--line);
}
@media (min-width: 700px) {
  .news-item { grid-template-columns: 9rem 1fr; }
}
.news-item__date {
  font-family: var(--news-sans);
  font-size: .78rem;
  text-transform: uppercase;
  letter-spacing: .08em;
  color: var(--muted);
  padding-top: .3rem;
}
.news-item h2, .news-item h3 { font-size: 1.3rem; }
.news-item h2 a:hover, .news-item h3 a:hover { color: var(--accent-ink); }
.news-item p { color: var(--muted); font-size: .98rem; margin-top: .4rem; }

.news-empty {
  padding: 2rem 0 0;
  color: var(--muted);
  font-family: var(--news-sans);
  font-size: .95rem;
}

/* --- Article ------------------------------------------------------------- */

.news-article { max-width: 42rem; }

.news-article__head { max-width: 46rem; }
.news-headline {
  font-size: clamp(2rem, 4.4vw, 3.15rem);
  letter-spacing: -0.022em;
  line-height: 1.08;
}
.news-standfirst {
  margin-top: 1.15rem;
  font-size: clamp(1.15rem, 1.9vw, 1.4rem);
  line-height: 1.5;
  color: var(--muted);
}

/* Byline block, ruled top and bottom like a masthead strip. */
.news-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: .3rem .5rem;
  margin-top: 1.75rem;
  padding-block: .9rem;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  font-family: var(--news-sans);
  font-size: .82rem;
  color: var(--muted);
}
.news-meta__author { color: var(--text); font-weight: 700; }
.news-meta__role { color: var(--muted); }
.news-meta .sep { color: var(--line); padding-inline: .3rem; }

.news-figure { margin-top: 2rem; }
.news-figure img { width: 100%; border-radius: 2px; }
.news-figure figcaption {
  margin-top: .65rem;
  padding-left: .75rem;
  border-left: 3px solid var(--line);
  font-family: var(--news-sans);
  font-size: .8rem;
  line-height: 1.5;
  color: var(--muted);
}

.news-body { margin-top: clamp(2rem, 4vw, 2.75rem); }
.news-body > * + * { margin-top: 1.25rem; }

.news-body p {
  font-size: 1.12rem;
  line-height: 1.78;
  color: var(--text);
}

/* Opening paragraph gets a raised cap. One only, and only on wide enough
   screens that it does not crowd the measure. */
@media (min-width: 640px) {
  .news-body > p:first-child::first-letter {
    float: left;
    font-size: 3.6em;
    line-height: .82;
    padding: .06em .09em 0 0;
    font-weight: 700;
    color: var(--text);
  }
}

.news-body h2 {
  font-size: clamp(1.4rem, 2.4vw, 1.75rem);
  margin-top: 2.75rem;
  padding-top: 1.4rem;
  border-top: 1px solid var(--line);
}
.news-body h3 {
  font-size: clamp(1.12rem, 1.7vw, 1.28rem);
  margin-top: 2rem;
}
.news-body h2 + p, .news-body h3 + p { margin-top: .75rem; }

.news-body a {
  color: var(--text);
  text-decoration: underline;
  text-decoration-color: var(--accent);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}
.news-body a:hover { color: var(--accent-ink); }

.news-body strong { font-weight: 700; }

/* Pull quote, available for future articles. */
.news-pullquote {
  margin-block: 2.25rem;
  padding-left: 1.25rem;
  border-left: 3px solid var(--accent);
  font-size: clamp(1.2rem, 2vw, 1.45rem);
  line-height: 1.42;
  color: var(--text);
}

.news-end {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 2px solid var(--text);
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
  align-items: center;
  font-family: var(--news-sans);
  font-size: .85rem;
  color: var(--muted);
}
.news-end a { color: var(--accent-ink); font-weight: 700; }

/* --------------------------------------------------------------------------
   11. Footer
   -------------------------------------------------------------------------- */

.site-footer {
  background: var(--ink);
  color: var(--ink-text);
  padding-block: clamp(3rem, 6vw, 4.5rem) 2rem;
  /* The last section already carries its own bottom padding, so this only
     has to separate the two bands rather than open a gap. */
  margin-top: clamp(1.5rem, 3vw, 2.5rem);
}

.footer__grid {
  display: grid;
  gap: 2.25rem;
}
@media (min-width: 560px) {
  .footer__grid { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 960px) {
  .footer__grid { grid-template-columns: 1.7fr 1fr 1fr 1fr; }
}

.site-footer p { color: var(--ink-muted); font-size: .92rem; margin-top: 1rem; max-width: 34ch; }

.footer__title {
  font-family: var(--font-sans);
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ink-muted);
  margin-bottom: 1rem;
}

.footer__links { display: grid; gap: .6rem; }
.footer__links a { color: var(--ink-text); font-size: .93rem; opacity: .85; }
.footer__links a:hover { opacity: 1; color: var(--accent-bright); }

.footer__bar {
  /* The 34ch cap above is for the blurb in the first column; the lines down
     here are single lines and must not inherit it. */
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--ink-line);
  display: flex;
  flex-wrap: wrap;
  gap: .75rem 1.5rem;
  justify-content: space-between;
  font-size: .84rem;
  color: var(--ink-muted);
}
.footer__bar p { max-width: none; margin-top: 0; }

/* --------------------------------------------------------------------------
   12. 404
   -------------------------------------------------------------------------- */

.error-page {
  min-height: 58vh;
  display: grid;
  place-content: center;
  text-align: center;
  gap: 1rem;
  padding-block: 4rem;
}
.error-page .lede { margin-inline: auto; }
.error-page .btn-row { justify-content: center; }

/* --------------------------------------------------------------------------
   12b. Sign-in screens (/portal/ and /staff/)

   One shell, two pages. A two-column split that fills what is left of the
   viewport under the header: a dark panel on the left carrying context, the
   form on the right. The client portal puts reassurance in that panel; the
   staff portal puts the quick-link tiles there.

   Both stack on narrow screens, and the dark panel drops below the form
   rather than above it: on a phone the first thing you want is the fields,
   not the marketing.
   -------------------------------------------------------------------------- */

.auth {
  display: grid;
  min-height: calc(100dvh - var(--header-h));
}
@media (min-width: 940px) {
  .auth { grid-template-columns: 1fr 1fr; }
}

/* --- The dark panel ------------------------------------------------------ */

.auth__aside {
  position: relative;
  overflow: hidden;
  background: var(--ink);
  color: var(--ink-text);
  padding: clamp(2rem, 5vw, 4rem) clamp(1.25rem, 4vw, 3.5rem);
  display: flex;
  flex-direction: column;
  gap: 2rem;
  justify-content: center;
  order: 2;
}
@media (min-width: 940px) {
  .auth__aside { order: 0; }
  /* In light mode the two columns separate on their own. In dark mode the
     panel and the page are both nearly black, so the split needs a line. */
  .auth__aside { border-right: 1px solid var(--ink-line); }
}

/* Same sweep as the homepage hero, sized for a column rather than a band. */
.auth__aside::after {
  content: "";
  position: absolute;
  right: -30%;
  bottom: -45%;
  width: 100%;
  aspect-ratio: 1.2 / 1;
  border-radius: 50%;
  background: linear-gradient(135deg, rgba(16,122,104,.5), rgba(71,209,182,.12));
  pointer-events: none;
}
.auth__aside > * { position: relative; z-index: 1; }

.auth__aside h2 { color: #FFFFFF; }
.auth__aside p { color: var(--ink-muted); }

/* Reassurance list on the client portal. */
.auth__points { display: grid; gap: 1.1rem; }
.auth__point { display: grid; grid-template-columns: auto 1fr; gap: .9rem; }
.auth__point svg { margin-top: .2rem; color: var(--accent-bright); flex-shrink: 0; }
.auth__point dt { font-weight: 600; color: #FFFFFF; font-size: .95rem; }
.auth__point dd { color: var(--ink-muted); font-size: .9rem; margin-top: .15rem; }

/* --- The form column ----------------------------------------------------- */

.auth__main {
  display: grid;
  align-content: center;
  justify-items: center;
  padding: clamp(2.5rem, 6vw, 4.5rem) var(--gutter);
  order: 1;
}

.auth__card { width: 100%; max-width: 25rem; }
.auth__card h1 { font-size: clamp(1.9rem, 3.4vw, 2.4rem); }
.auth__card .lede { margin-top: .75rem; font-size: 1rem; }

.auth__form { display: grid; gap: 1.1rem; margin-top: 2rem; }

/* The label row carries the "forgot password" link opposite the label. */
.field__row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
}
.field__aside {
  font-size: .82rem;
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* Password field with a reveal toggle sitting inside the input. */
.field--password { position: relative; }
.field--password input { padding-right: 3.4rem; }
.pw-toggle {
  position: absolute;
  right: .4rem;
  bottom: .3rem;
  padding: .45rem .6rem;
  font-size: .78rem;
  font-weight: 600;
  color: var(--muted);
  border-radius: var(--r-sm);
}
.pw-toggle:hover { color: var(--text); background: var(--bg-alt); }

.auth__submit { width: 100%; justify-content: center; }

.auth__meta {
  margin-top: 1.5rem;
  font-size: .82rem;
  color: var(--muted);
  text-align: center;
}
.auth__meta a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 3px; }

/* Divider with a word in it, between password and SSO. */
.auth__or {
  display: flex;
  align-items: center;
  gap: .9rem;
  color: var(--muted);
  font-size: .78rem;
  letter-spacing: .16em;
  text-transform: uppercase;
}
.auth__or::before,
.auth__or::after {
  content: "";
  height: 1px;
  flex: 1;
  background: var(--line);
}

/* Provider button. Neutral surface, so a provider's own colours can sit in
   the icon slot without fighting the brand green. */
.btn--provider {
  width: 100%;
  justify-content: center;
  background: var(--surface);
  color: var(--text);
  border-color: var(--line);
}
.btn--provider:hover { background: var(--bg-alt); filter: none; }
.btn--provider svg,
.btn--provider img { width: 18px; height: 18px; flex-shrink: 0; }

/* Status line, shared by both forms. Neutral until JS sets a state, so a
   failed sign-in never renders as a success. */
.auth__status {
  padding: .8rem 1rem;
  border-radius: var(--r-sm);
  font-size: .88rem;
  border: 1px solid var(--line);
  background: var(--bg-alt);
  color: var(--text);
}
.auth__status[data-state="error"] {
  border-color: #C4453B;
  background: color-mix(in srgb, #C4453B 10%, var(--bg));
  color: #8E2F27;
}
.auth__status[data-state="success"] {
  border-color: var(--accent);
  background: var(--accent-bg);
  color: var(--accent-ink);
}
html[data-theme="dark"] .auth__status[data-state="error"] {
  border-color: #E0776D;
  background: color-mix(in srgb, #C4453B 22%, var(--bg));
  color: #F3B8B2;
}

/* --- Quick-link tiles, staff portal -------------------------------------- */

/* A single column, capped to roughly the measure of the paragraph above it,
   so the rail reads as a list rather than as a grid of cards competing with
   the sign-in form opposite. */
.tiles {
  display: grid;
  gap: .85rem;
  max-width: 30rem;
}

.tile {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: center;
  gap: .9rem;
  padding: .85rem;
  border-radius: var(--r-md);
  background: rgba(255, 255, 255, .07);
  border: 1px solid rgba(255, 255, 255, .12);
  transition: background .16s ease, border-color .16s ease, transform .16s ease;
}
.tile:hover {
  background: rgba(255, 255, 255, .13);
  border-color: rgba(255, 255, 255, .25);
  transform: translateY(-2px);
}

/* The three logos ship with their own backgrounds, one of them full-bleed
   red, so each sits in a fixed rounded square and keeps it. Cover rather
   than contain: these are app icons, not transparent marks. */
.tile__icon {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  object-fit: cover;
  background: #FFFFFF;
  flex-shrink: 0;
}

/* Both are spans inside one span, so they need to be told to stack: as
   inline elements the title and the meta line run together into a single
   wrapped sentence. */
.tile__title { display: block; font-weight: 600; font-size: .95rem; color: #FFFFFF; }
.tile__meta { display: block; font-size: .78rem; color: var(--ink-muted); margin-top: .1rem; }

/* --------------------------------------------------------------------------
   12c. Help desk (/staff/help/)
   -------------------------------------------------------------------------- */

/* Quick actions. A .card with an icon chip, used as a link out to a provider
   destination. */
.action { display: grid; gap: .8rem; align-content: start; }
.action__icon {
  display: inline-grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  border-radius: var(--r-sm);
  background: var(--accent-bg);
  color: var(--accent-ink);
}
.action h3 { font-size: 1.08rem; }
.action p { margin-top: .35rem; }
.action__out {
  font-size: .8rem;
  color: var(--muted);
  font-family: var(--font-ui);
}

/* Accordion of common fixes. <details> so it works with no JavaScript at
   all, including deep linking straight to an open item. */
.qa { border-top: 1px solid var(--line); }

.qa__item { border-bottom: 1px solid var(--line); }
.qa__item summary {
  cursor: pointer;
  padding: 1.15rem 2.75rem 1.15rem 0;
  font-weight: 600;
  font-size: 1rem;
  position: relative;
  list-style: none;
}
/* Safari draws its own triangle unless both of these are removed. */
.qa__item summary::-webkit-details-marker { display: none; }
.qa__item summary::marker { content: ""; }

.qa__item summary:hover { color: var(--accent-ink); }
.qa__item summary:focus-visible { outline-offset: -2px; }

.qa__item summary::after {
  content: "";
  position: absolute;
  right: .6rem;
  top: 50%;
  width: 11px;
  height: 11px;
  margin-top: -6px;
  border-right: 2px solid var(--accent);
  border-bottom: 2px solid var(--accent);
  transform: rotate(45deg);
  transform-origin: 70% 70%;
  transition: transform .18s ease;
}
.qa__item[open] summary::after { transform: rotate(-135deg); }

.qa__body {
  padding-bottom: 1.4rem;
  color: var(--muted);
  font-size: .96rem;
  max-width: 68ch;
}
.qa__body p + p,
.qa__body p + ol,
.qa__body p + ul,
.qa__body ol + p,
.qa__body ul + p { margin-top: .8rem; }
.qa__body ol { list-style: decimal; padding-left: 1.2rem; display: grid; gap: .45rem; }
.qa__body ul { display: grid; gap: .45rem; }
.qa__body ul li { position: relative; padding-left: 1.1rem; }
.qa__body ul li::before {
  content: "";
  position: absolute;
  left: 0;
  top: .62em;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}
.qa__body a {
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.qa__body strong { color: var(--text); }

/* A link out of the dark quick-links panel on /staff/. */
.aside-link {
  display: inline-flex;
  align-items: center;
  gap: .45rem;
  color: var(--accent-bright);
  font-weight: 600;
  font-size: .92rem;
}
.aside-link:hover { text-decoration: underline; text-underline-offset: 3px; }

/* --------------------------------------------------------------------------
   13. Scroll reveal (progressive enhancement)
   -------------------------------------------------------------------------- */

/* Reveals are opt-in: content is visible by default and only hidden once
   site.js has armed it, so a failed or blocked script can never leave a
   section permanently invisible. `is-armed` is added in JS immediately
   before the IntersectionObserver starts watching. */

[data-reveal].is-armed {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity .5s ease var(--delay, 0ms), transform .5s ease var(--delay, 0ms);
}
[data-reveal].is-armed.is-in { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   14. Print
   -------------------------------------------------------------------------- */

@media print {
  .site-header, .site-footer, .cta-band, .btn-row, .skip-link { display: none !important; }
  body { color: #000; background: #fff; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
}

/* Site tiles in the homepage About section: photo-topped cards linking out
   to the group's public fronts. */
.card--site { padding: 0; overflow: hidden; text-decoration: none; display: block; }
.card--site .card__photo {
  width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block;
  border-bottom: 1px solid var(--line);
}
.card--site .card__body { padding: 1.3rem 1.5rem 1.5rem; }
.card--site .card__go {
  display: inline-block; margin-top: .9rem; font-size: .85rem; font-weight: 600;
  color: var(--accent);
}

/* --------------------------------------------------------------------------
   8b. Portfolio band (#portfolio on the homepage)

   Interactive Brokers' colours, not Bryder's, and identical in both themes.
   Same reasoning as the help desk stylesheet: a door into someone else's
   platform should look like that platform. Black band, IBKR red #D81222,
   sampled from the app icon that used to sit here as a quick-link tile.

   Two reds, on purpose:

     --ibkr-red       #D81222  fills only: buttons, bars, the top rule.
                               White text on it runs 5.2:1.
     --ibkr-red-text  #FF3B47  text and icons on the black band, 5.6:1.
                               The fill red only manages 4.0:1 on black,
                               which fails small text, so it never sets type.

   Everything is scoped to .ibkr and hard-coded rather than tokenised on the
   theme, because the band does not change with the theme toggle.
   -------------------------------------------------------------------------- */

.ibkr {
  --ibkr-bg:       #0B0B0D;
  --ibkr-panel:    #141417;
  --ibkr-line:     #26262C;
  --ibkr-red:      #D81222;
  --ibkr-red-text: #FF3B47;
  --ibkr-text:     #F4F4F6;
  --ibkr-muted:    #A9ACB6;
  --ibkr-faint:    #8A8D97;

  position: relative;
  background:
    radial-gradient(58rem 26rem at 88% -4rem, rgba(216, 18, 34, .16), transparent 62%),
    var(--ibkr-bg);
  color: var(--ibkr-text);
  border-top: 3px solid var(--ibkr-red);
  overflow: hidden;
}

/* The band keeps its own accent for keyboard focus and text selection, so
   tabbing through it does not flash the brand green on black. */
.ibkr :focus-visible { outline-color: var(--ibkr-red-text); }
.ibkr ::selection { background: var(--ibkr-red); color: #FFFFFF; }

.ibkr .eyebrow { color: var(--ibkr-red-text); }
.ibkr .h-lg { color: #FFFFFF; }
.ibkr .lede { color: var(--ibkr-muted); }

.ibkr .btn {
  background: var(--ibkr-red);
  border-color: var(--ibkr-red);
  color: #FFFFFF;
}
.ibkr .btn--ghost {
  background: transparent;
  border-color: rgba(255, 255, 255, .28);
  color: var(--ibkr-text);
}
.ibkr .btn--ghost:hover { background: rgba(255, 255, 255, .09); }

.ibkr__note {
  margin-top: 1.6rem;
  font-size: .82rem;
  line-height: 1.6;
  color: var(--ibkr-faint);
  max-width: 52ch;
}
.ibkr__note a {
  color: var(--ibkr-muted);
  text-decoration: underline;
  text-underline-offset: 3px;
}
.ibkr__note a:hover { color: #FFFFFF; }

.ibkr__grid {
  display: grid;
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: center;
}
@media (min-width: 900px) {
  .ibkr__grid { grid-template-columns: 1.15fr .85fr; }
}

/* --- The account plate ---------------------------------------------------
   A dark panel echoing the hero facts card, wearing IBKR's red keyline and
   their app icon. The ascending bars are decoration, not data: they sit
   behind the rows, clipped by the panel, and say "market chart" without
   claiming to chart anything. */

.ibkr-plate {
  position: relative;
  overflow: hidden;
  background: linear-gradient(165deg, #18181C, #101013);
  border: 1px solid var(--ibkr-line);
  border-top: 3px solid var(--ibkr-red);
  border-radius: var(--r-lg);
  padding: clamp(1.5rem, 3vw, 2rem);
  box-shadow: 0 24px 50px -30px rgba(0, 0, 0, .9);
}

.ibkr-plate__head {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: .9rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--ibkr-line);
}
.ibkr-plate__head img {
  width: 44px;
  height: 44px;
  border-radius: 10px;
  flex-shrink: 0;
}
.ibkr-plate__head strong {
  display: block;
  font-size: .98rem;
  font-weight: 650;
  color: #FFFFFF;
}
.ibkr-plate__head span {
  display: block;
  margin-top: .15rem;
  font-size: .78rem;
  color: var(--ibkr-faint);
}

.ibkr-plate__rows {
  position: relative;
  z-index: 1;
  display: grid;
}
.ibkr-plate__row {
  display: grid;
  gap: .15rem;
  padding-block: 1rem;
  border-bottom: 1px solid var(--ibkr-line);
}
.ibkr-plate__row:last-child { border-bottom: 0; padding-bottom: .25rem; }
.ibkr-plate__row dt {
  font-family: var(--font-sans);
  font-size: .68rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--ibkr-faint);
}
/* Values take the display face, the same pairing as the hero facts. */
.ibkr-plate__row dd {
  font-family: var(--font-display);
  letter-spacing: -0.012em;
  font-size: 1.14rem;
  font-weight: 700;
  line-height: 1.25;
  color: #FFFFFF;
}

.ibkr-plate__bars {
  position: absolute;
  right: -6px;
  bottom: -2px;
  width: 72%;
  height: auto;
  fill: var(--ibkr-red);
  pointer-events: none;
}

/* --- Access cards -------------------------------------------------------- */

.ibkr-cards {
  display: grid;
  gap: 1rem;
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}
@media (min-width: 760px) {
  .ibkr-cards { grid-template-columns: repeat(3, 1fr); }
}

.ibkr-card {
  display: grid;
  gap: .55rem;
  align-content: start;
  padding: 1.5rem;
  background: var(--ibkr-panel);
  border: 1px solid var(--ibkr-line);
  border-radius: var(--r-md);
  transition: border-color .18s ease, transform .18s ease, box-shadow .18s ease;
}
.ibkr-card:hover {
  border-color: rgba(216, 18, 34, .6);
  transform: translateY(-2px);
  box-shadow: 0 18px 40px -24px rgba(0, 0, 0, .9);
}

.ibkr-card__icon {
  display: inline-grid;
  place-items: center;
  width: 2.4rem;
  height: 2.4rem;
  margin-bottom: .35rem;
  border-radius: var(--r-sm);
  background: rgba(216, 18, 34, .16);
  color: var(--ibkr-red-text);
}

.ibkr-card h3 { font-size: 1.15rem; color: #FFFFFF; }
.ibkr-card p { color: var(--ibkr-muted); font-size: .92rem; }

.ibkr-card__go {
  margin-top: .5rem;
  font-size: .85rem;
  font-weight: 600;
  color: var(--ibkr-red-text);
}
/* Same subsetting caveat as .btn__arrow: the arrow glyph is outside the
   Latin subset, so it renders from the system UI face. */
.ibkr-card__go span {
  font-family: var(--font-ui);
  display: inline-block;
  transition: transform .16s ease;
}
.ibkr-card:hover .ibkr-card__go span { transform: translateX(3px); }


/* --------------------------------------------------------------------------
   15. Technology strip

   The white card that overlaps the bottom of the hero, after the reference's
   "Companies we've served" panel. The marks are monochrome on purpose: a
   dozen brands in their own colours fight each other and the page, and a
   grey set with the name under each reads as a list rather than an advert.
   -------------------------------------------------------------------------- */

.strip {
  position: relative;
  z-index: 2;
  margin-top: -4.6rem;
  padding-bottom: clamp(1rem, 3vw, 2rem);
}
.strip__card {
  position: relative;
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: center;
  padding: clamp(1.5rem, 3.5vw, 2.75rem);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  box-shadow: 0 24px 60px -30px rgba(11, 14, 13, .45), var(--shadow);
}
@media (min-width: 900px) {
  .strip__card { grid-template-columns: minmax(14rem, .8fr) 2.2fr; }
}
/* The logo's three bars, poking above the card's top-left corner the way
   the reference's ribbon does. */
.strip__ribbon {
  position: absolute;
  top: -1.15rem;
  left: clamp(1.25rem, 3vw, 2.5rem);
  width: 2.4rem;
  height: 2.1rem;
  color: var(--accent-bright);
}
.strip__title { font-size: clamp(1.5rem, 2.4vw, 1.95rem); }
.strip__note { margin-top: .6rem; color: var(--muted); font-size: .95rem; max-width: 30ch; }

.logo-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  overflow: hidden;
}
@media (min-width: 640px)  { .logo-grid { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1100px) { .logo-grid { grid-template-columns: repeat(6, 1fr); } }
.logo-grid > * {
  display: grid;
  place-items: center;
  align-content: center;
  gap: .4rem;
  min-height: 5.4rem;
  padding: .9rem .6rem;
  background: var(--surface);
  color: var(--muted);
  text-align: center;
  transition: color .15s ease, background .15s ease;
}
.logo-grid > *:hover { color: var(--accent-ink); background: var(--bg-alt); }
.logo-grid svg { width: auto; height: 1.7rem; fill: currentColor; }
.logo-grid img { width: auto; height: 1.7rem; }
.logo-grid .logo--wide { height: 1.35rem; }
html[data-theme="light"] .logo-grid .logo--dark,
html[data-theme="dark"]  .logo-grid .logo--light { display: none; }
.logo-grid .logo-text {
  font-weight: 800;
  letter-spacing: -0.02em;
  font-size: 1.15rem;
  line-height: 1.7rem;
}
/* Full --muted, no opacity: at .75 the names measured 3.8:1 on white, under
   the 4.5:1 text this small needs (Lighthouse, 24 September 2026). The size
   and the capitals already make them the quiet line under each logo. */
.logo-grid .logo-name {
  font-size: .66rem;
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* --------------------------------------------------------------------------
   16. Homepage sections: companies, approach, news
   -------------------------------------------------------------------------- */

.company-grid .card--site h3 { font-size: 1.5rem; }
.card__meta { margin-top: .5rem; font-size: .82rem; color: var(--muted); }
.card__meta b { color: var(--text); font-weight: 600; }
/* Block, not the span's default inline: an inline box ignores a vertical
   margin, and its padding spills over the line box instead of taking room,
   which sat the pill on the photo edge and the title against its underside. */
.card--site .entry__tag {
  display: block;
  width: fit-content;
  margin-bottom: 1.1rem;
}
.company-grid .card--site .card__body {
  padding: 1.6rem 1.6rem 1.7rem;
  container: card-body / inline-size;
}
/* "Subsidiary · Consumer fintech" needs 278px on one line. Narrower than
   that, on a phone or with the cards two across on a small tablet, a pill
   would break over two lines, so both cards drop the fill and the tag reads
   as a plain label, the way the eyebrows do. Both, so the cards match. */
@container card-body (max-width: 290px) {
  .card--site .entry__tag {
    padding: 0;
    background: none;
    border-radius: 0;
    text-wrap: balance;
  }
}

@media (min-width: 700px)  { .facts--4 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .facts--4 { grid-template-columns: repeat(4, 1fr); } }

.features { display: grid; gap: 1.25rem; }
@media (min-width: 640px)  { .features { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .features { grid-template-columns: repeat(4, 1fr); } }
.feature {
  padding: 1.6rem;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
}
.feature__icon {
  width: 2.8rem;
  height: 2.8rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--accent-bg);
  color: var(--accent-ink);
  margin-bottom: 1.1rem;
}
.feature__icon svg { width: 1.3rem; height: 1.3rem; }
.feature h3 { font-size: 1.12rem; }
.feature p { margin-top: .55rem; color: var(--muted); font-size: .93rem; }

.news-card time {
  display: block;
  font-size: .74rem;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--muted);
}
.news-card h3 { margin-top: .7rem; font-size: 1.12rem; line-height: 1.3; }
.news-card__src { margin-top: .5rem; font-size: .85rem; color: var(--muted); }

.section__head {
  display: flex;
  flex-wrap: wrap;
  align-items: end;
  justify-content: space-between;
  gap: 1rem 2rem;
}
.section__head .lede { margin-top: .75rem; }

/* --------------------------------------------------------------------------
   17. Careers
   -------------------------------------------------------------------------- */

.careers-list { display: grid; gap: 1rem; }
.careers-list .card h3 { font-size: 1.15rem; }
/* --------------------------------------------------------------------------
   18. Editorial homepage (23 Sep 2026)

   The homepage after the editorial reference (dayos.com): a wall of heavy
   capitals beside one sculptural object, a black band of one-word
   statements, big stat figures, and a monochrome logo row. The photo
   carousel it replaced still has its styles and script above, both inert
   without the markup, so nothing else changes if it ever comes back.
   -------------------------------------------------------------------------- */

/* --- Typographic hero -----------------------------------------------------

   Light, not a dark photograph: the page opens on type. Selectors carry
   .hero as well as .hero--type so they outrank the base .hero rules, which
   were written for white text on a photo, without leaning on source order. */
.hero.hero--type {
  background: var(--bg);
  color: var(--text);
  padding-block: clamp(2.5rem, 6vw, 5rem) clamp(3.5rem, 8vw, 6.5rem);
}
.hero.hero--type::before,
.hero.hero--type::after { content: none; }
.hero.hero--type .eyebrow { color: var(--accent-ink); }
.hero.hero--type h1 { color: var(--heading); }

/* Sized to the text column, not the window. The longest word, SOFTWARE.,
   is 5.86em wide in these capitals, so the heading has to stay under a
   sixth of the column or that word runs out of it. Measured at 1366px with
   a viewport unit: 23px past the column, 25px short of the object. A vw
   size cannot know how wide the column is once the object takes its share;
   cqi can. 16cqi leaves a little air. The vw line is the fallback for a
   browser without container queries, kept small enough to fit either way. */
.hero__text { container-type: inline-size; }
.hero.hero--type .h-xl {
  font-size: clamp(2.6rem, 7.2vw, 6.2rem);
  font-size: clamp(2.6rem, 16cqi, 6.6rem);
}
.hero.hero--type .lede {
  margin-top: 1.75rem;
  max-width: 44ch;
  color: var(--muted);
}
.hero.hero--type .btn-row { margin-top: 2.25rem; }
.hero.hero--type .btn--ghost {
  color: var(--text);
  border-color: var(--line);
  background: transparent;
  backdrop-filter: none;
}
.hero.hero--type .btn--ghost:hover { background: var(--bg-alt); }

/* The second sentence of the headline, in the accent. The one place the
   green is text at display size, which is why it is kowhai (4.6:1 on the
   paper, well past the 3:1 large text needs) and not the bright green,
   which manages 1.7:1 there. In the dark theme --accent is the lifted
   green, 7.6:1 on the dark page. */
.hero__accent {
  display: block;
  color: var(--accent);
}

.hero__grid {
  display: grid;
  gap: clamp(1.5rem, 5vw, 3rem);
  align-items: center;
}
@media (min-width: 980px) {
  .hero__grid { grid-template-columns: minmax(0, 1.3fr) minmax(0, 1fr); }
}
.hero__object img {
  width: 100%;
  max-width: 34rem;
  height: auto;
  margin-inline: auto;
}
/* Below the headline on a phone, and smaller: it is the illustration, and
   the first screen belongs to the sentence. */
@media (max-width: 979px) {
  .hero__object img { max-width: 22rem; }
}

/* --- The black band -------------------------------------------------------

   Four commitments, each a single capitalised word with the reasoning under
   it. Black in the light theme; lifted a step in the dark one, where a
   black band on a black page would not be a band at all (see --ink). */
.band {
  background: var(--ink);
  color: var(--ink-text);
  padding-block: clamp(3.5rem, 8vw, 6.5rem);
  border-block: 1px solid var(--ink-line);
}
.band .eyebrow { color: var(--accent-bright); }
.band .h-lg { color: var(--ink-text); }
.band .lede { color: var(--ink-muted); }

/* Three pillars, so never two across: that would leave one alone on a row.
   Stacked on a phone, three across from 960px, and in between each pillar
   is a row with its word on the left, so the paragraphs do not run the full
   width of a tablet. */
.pillars {
  display: grid;
  gap: clamp(2.25rem, 4vw, 2.75rem) clamp(1.5rem, 3vw, 2.5rem);
  margin-top: clamp(2.5rem, 5vw, 3.75rem);
}
/* minmax(0, 1fr), not 1fr, for the reason given on .stats below. */
@media (min-width: 960px) { .pillars { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.pillar {
  padding-top: 1.4rem;
  border-top: 1px solid var(--ink-line);
}
/* Sized so the longest word, OWNED., fits a third of the wrap from 960px up
   and the 13rem word column in the tablet rows. */
.pillar__word {
  font-size: clamp(2.3rem, 4vw, 3.6rem);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: -0.035em;
  line-height: .9;
  color: var(--ink-text);
}
.pillar p {
  margin-top: 1.1rem;
  font-size: .95rem;
  line-height: 1.6;
  color: var(--ink-muted);
}
.pillar p strong { color: var(--ink-text); font-weight: 600; }
/* The tablet rows. After .pillar p so its margin reset wins the cascade. */
@media (min-width: 700px) and (max-width: 959.98px) {
  .pillar {
    display: grid;
    grid-template-columns: 13rem minmax(0, 1fr);
    gap: 2rem;
    align-items: start;
  }
  .pillar p { margin-top: 0; }
}

/* --- Stat figures ---------------------------------------------------------

   The four facts about the company, set as big capitals under a hairline.
   "Invercargill" in capitals is twelve wide letters that cannot wrap, and it
   sets every breakpoint here:

     under 520px   one across. Two across on a 320px phone pushed the second
                   column 5px off the screen: a plain 1fr cannot shrink below
                   its content, so the grid grew past its container instead.
     520 to 1099   two across
     1100 and up   four across

   minmax(0, 1fr) rather than 1fr so a column may be narrower than its
   content if it ever has to, and the page scrolls sideways never. */
.stats {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 0 clamp(1rem, 3vw, 2rem);
  margin-top: clamp(2.5rem, 5vw, 3.75rem);
  border-top: 1px solid var(--line);
}
@media (min-width: 520px)  { .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .stats { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.stat { padding-top: 1.5rem; }
.stat dt {
  font-size: .72rem;
  font-weight: 500;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--muted);
}
.stat dd {
  margin-top: .55rem;
  font-size: clamp(1.5rem, 2.3vw, 2rem);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: -0.03em;
  line-height: 1;
  color: var(--heading);
}

/* --- Company cards --------------------------------------------------------

   Titles in the display treatment. The photographs sit in greyscale and come
   into colour on hover: the page keeps its colour for the mark and the
   accent, and a card coming alive under the pointer says it is a link. */
.company-grid .card--site h3 {
  font-size: clamp(1.6rem, 2.6vw, 2.1rem);
  font-weight: 900;
  text-transform: uppercase;
  letter-spacing: -0.03em;
  line-height: .95;
}
.company-grid .card__photo {
  filter: grayscale(1) contrast(1.05);
  transition: filter .45s ease;
}
.company-grid .card--site:hover .card__photo,
.company-grid .card--site:focus-visible .card__photo { filter: none; }

/* --- Logo row -------------------------------------------------------------

   The technology strip, no longer a card lifted over a photograph (there is
   no photograph for it to overlap). Greyscale at rest and in colour on
   hover, the way the reference's partner row reads as one quiet line. */
.logos .logo-grid img {
  filter: grayscale(1);
  opacity: .72;
  transition: filter .2s ease, opacity .2s ease;
}
.logos .logo-grid > *:hover img { filter: none; opacity: 1; }
.logos .section__head { margin-bottom: clamp(1.75rem, 4vw, 2.5rem); }
