/* ==========================================================================
   SUMERIXA
   CPM planning, scheduling and project controls.

   Design intent: a well set technical document. White dominant, editorial
   type, hairline rules, an asymmetric rail grid. Navy is the only brand
   color. Red means one thing and one thing only: the critical path.

   Every token lives in :root. Restyle the whole site from there.
   ========================================================================== */

:root {
  /* --- brand ------------------------------------------------------------ */
  --navy:        #002F6E;   /* taken from the wordmark */
  --navy-800:    #002556;
  --navy-600:    #0A4189;   /* pressed state on links that are already navy */
  --navy-050:    #EDF1F7;

  /* --- ink -------------------------------------------------------------- */
  --ink:         #0B1420;   /* body copy and headings */
  --ink-2:       #454F5B;   /* secondary copy */
  --ink-3:       #646B76;   /* labels, captions, meta. 4.97:1 on the grey band */
  /* Deliberately below the 4.5:1 body-text threshold, about 3.4:1 on white.
     For small print that must be present without drawing the eye, which is
     the experience page disclaimer and nothing else so far. Do not reach for
     it for anything a reader is meant to act on. */
  --ink-4:       #878D95;

  /* --- surfaces --------------------------------------------------------- */
  --paper:       #FFFFFF;
  --paper-2:     #F5F6F8;   /* alternating band, barely there */
  --rule:        #E2E5EA;
  --rule-2:      #C9CED6;
  --rule-dark:   rgba(255, 255, 255, 0.16);

  /* --- the critical path. Reserved. ------------------------------------- */
  --critical:      #C4402A;
  --critical-deep: #9E3122;   /* only for error text, which needs 4.5:1 */

  /* --- type ------------------------------------------------------------- */
  --f-display: "Source Serif 4", "Iowan Old Style", Georgia, "Times New Roman", serif;
  --f-sans:    "Libre Franklin", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;

  --t-hero:  clamp(2.6rem, 1.35rem + 3.6vw, 5.1rem);
  --t-h1:    clamp(2.3rem, 1.35rem + 2.9vw, 4.1rem);
  --t-h2:    clamp(1.85rem, 1.25rem + 1.9vw, 3rem);
  --t-h3:    clamp(1.3rem, 1.08rem + 0.7vw, 1.7rem);
  --t-lede:  clamp(1.12rem, 1.02rem + 0.42vw, 1.42rem);
  --t-body:  1.0425rem;
  --t-small: 0.885rem;
  --t-micro: 0.735rem;

  /* --- measure and rhythm ----------------------------------------------- */
  /* Full width. This was 1240px, which left a wide monitor mostly empty.
     Widening it is safe for reading because the text sets its own measure
     independently: .prose caps at 40rem, .measure at 62ch, .measure-s at
     48ch, so no line grows with the viewport. What does grow is the work,
     which is the point: the project wall and the image bands.
     Revert by putting 1240px back. Nothing else depends on the value. */
  --shell:   100%;
  --gutter:  clamp(1.25rem, 0.4rem + 3.1vw, 4rem);
  --rail:    10.5rem;      /* collapses to zero under 1000px, see .rail */
  --rail-gap: clamp(1.5rem, 0.5rem + 1.6vw, 2.75rem);
  --band:    clamp(4.25rem, 2.4rem + 6.2vw, 8.5rem);

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}

/* ==========================================================================
   RESET
   ========================================================================== */

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

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
  /* Mobile browsers paint a translucent block over whatever you tap, and it
     lingers while the next page loads. Switched off here; touch gets its own
     feedback from the :active rules at the foot of this file. */
  -webkit-tap-highlight-color: transparent;
}

body {
  font-family: var(--f-sans);
  font-size: var(--t-body);
  font-weight: 400;
  line-height: 1.62;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-variant-numeric: tabular-nums;
  overflow-x: hidden;
}

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

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

::selection { background: var(--navy); color: #fff; }

.skip {
  position: absolute; left: 0; top: -100%;
  z-index: 200; padding: 0.85rem 1.4rem;
  background: var(--navy); color: #fff;
  font-size: var(--t-small); font-weight: 600;
}
.skip:focus { top: 0; }

.sr {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* ==========================================================================
   TYPE PRIMITIVES
   ========================================================================== */

h1, h2, h3, h4 {
  font-family: var(--f-display);
  font-weight: 600;
  line-height: 1.06;
  letter-spacing: -0.018em;
  color: var(--ink);
  text-wrap: balance;
}
h1 { font-size: var(--t-h1); }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); line-height: 1.18; letter-spacing: -0.012em; }

p { text-wrap: pretty; }

/* small tracked label, used for section eyebrows and field labels */
.label {
  display: block;
  font-family: var(--f-sans);
  font-size: var(--t-micro);
  font-weight: 600;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.label--navy { color: var(--navy); }
.label--onink { color: rgba(255, 255, 255, 0.82); }
.label-optional { font-weight: 400; text-transform: none; letter-spacing: 0; }

.lede {
  font-size: var(--t-lede);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 46ch;
}

.measure  { max-width: 62ch; }
.measure-s { max-width: 48ch; }

/* inline link with a rule that grows from the left */
.tlink {
  position: relative;
  color: var(--navy);
  font-weight: 500;
  background-image: linear-gradient(var(--navy), var(--navy));
  background-repeat: no-repeat;
  background-position: 0 100%;
  background-size: 100% 1px;
  transition: background-size 0.3s var(--ease);
}

/* ==========================================================================
   LAYOUT
   ========================================================================== */

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

.band { padding-block: var(--band); }
.band--tight { padding-block: calc(var(--band) * 0.62); }
.band--grey { background: var(--paper-2); }
.band--ink  { background: var(--navy); color: #fff; }
.band--ink h1, .band--ink h2, .band--ink h3 { color: #fff; }
.band--ink .lede { color: rgba(255, 255, 255, 0.76); }

/* The rail: a persistent left column carrying the section index and label.
   It collapses to zero under ~1000px and the content reflows to full width. */
.rail {
  display: grid;
  grid-template-columns: var(--rail) minmax(0, 1fr);
  gap: 0 var(--rail-gap);
  align-items: start;
}
.rail__aside { position: sticky; top: 6.5rem; }
.rail__idx {
  font-family: var(--f-display);
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--critical);
  font-variant-numeric: tabular-nums;
  display: block;
  margin-bottom: 0.35rem;
}
.band--ink .rail__idx { color: #fff; opacity: 0.5; }

/* When the rail collapses, the aside becomes an inline eyebrow above content */
@media (max-width: 1000px) {
  .rail { grid-template-columns: minmax(0, 1fr); }
  .rail__aside { position: static; margin-bottom: 1.4rem; display: flex; gap: 0.9rem; align-items: baseline; }
  .rail__idx { margin-bottom: 0; }
}

.stack > * + * { margin-top: var(--gap, 1.15rem); }

/* ==========================================================================
   HEADER
   ========================================================================== */

.hdr {
  position: sticky; top: 0; z-index: 100;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: saturate(180%) blur(14px);
  -webkit-backdrop-filter: saturate(180%) blur(14px);
  border-bottom: 1px solid var(--rule);
}
.hdr__in {
  display: flex; align-items: center; gap: 2rem;
  height: 76px;
  max-width: var(--shell); margin-inline: auto;
  padding-inline: var(--gutter);
}
.brand { flex: none; display: block; }
.brand img { height: 21px; width: auto; }

.nav { margin-left: auto; display: flex; align-items: center; gap: clamp(1.1rem, 0.2rem + 1.5vw, 2.1rem); }
.nav__link {
  position: relative;
  font-size: 0.9rem; font-weight: 500;
  color: var(--ink-2);
  padding-block: 0.4rem;
  transition: color 0.2s var(--ease);
  white-space: nowrap;
}
.nav__link::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -0.15rem;
  height: 1.5px; background: var(--navy);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.28s var(--ease);
}
.nav__link[aria-current="page"] { color: var(--ink); font-weight: 600; }
.nav__link[aria-current="page"]::after { transform: scaleX(1); background: var(--critical); }

/* services dropdown */
.nav__grp { position: relative; }
.nav__panel {
  position: absolute; top: calc(100% + 0.9rem); left: -1.15rem;
  min-width: 19rem;
  background: var(--paper);
  border: 1px solid var(--rule);
  box-shadow: 0 24px 48px -28px rgba(11, 20, 32, 0.35);
  padding: 0.5rem;
  opacity: 0; visibility: hidden; transform: translateY(-6px);
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease), visibility 0.2s;
}
.nav__grp:focus-within .nav__panel { opacity: 1; visibility: visible; transform: none; }
.nav__panel a {
  display: block; padding: 0.7rem 0.9rem;
  border-left: 2px solid transparent;
  transition: background 0.16s var(--ease), border-color 0.16s var(--ease);
}
.nav__panel b { display: block; font-size: 0.925rem; font-weight: 600; color: var(--ink); }
.nav__panel span { display: block; font-size: var(--t-small); color: var(--ink-3); line-height: 1.4; margin-top: 0.1rem; }

/* portal button, sits at the top right */
.portal {
  display: inline-flex; align-items: center; gap: 0.55rem;
  flex: none;
  padding: 0.55rem 1rem;
  border: 1px solid var(--rule-2);
  font-size: 0.855rem; font-weight: 600;
  color: var(--ink);
  transition: border-color 0.22s var(--ease), background 0.22s var(--ease);
  white-space: nowrap;
}
.portal__soon {
  padding-left: 0.6rem;
  margin-left: 0.05rem;
  border-left: 1px solid var(--rule);
  font-size: 0.66rem; font-weight: 600;
  letter-spacing: 0.11em; text-transform: uppercase;
  color: var(--ink-3);
}

.burger { display: none; flex: none; padding: 0.5rem; margin-right: -0.5rem; }
.burger span {
  display: block; width: 22px; height: 1.5px; background: var(--ink);
  transition: transform 0.28s var(--ease), opacity 0.2s var(--ease);
}
.burger span + span { margin-top: 5px; }
.burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

@media (max-width: 900px) {
  .burger { display: block; margin-left: auto; }
  .nav {
    position: fixed; inset: 76px 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 0;
    margin: 0; padding: 0.5rem var(--gutter) 1.6rem;
    background: var(--paper);
    border-bottom: 1px solid var(--rule);
    max-height: calc(100dvh - 76px); overflow-y: auto;
    transform: translateY(-8px); opacity: 0; visibility: hidden;
    transition: opacity 0.24s var(--ease), transform 0.24s var(--ease), visibility 0.24s;
    /* Load bearing. The closed menu is a fixed band across the top of every
       page, and hiding it with visibility alone is not enough, because
       visibility is inherited and .nav__panel below sets itself back to
       visible so the services submenu can show inline when the menu is open.
       That left an invisible but tappable strip of services links over the
       page: a tap near the top of any page went to a services page. Opacity
       zero does not stop a tap either. This does. */
    pointer-events: none;
  }
  .nav[data-open="true"] {
    opacity: 1; visibility: visible; transform: none;
    pointer-events: auto;
  }
  .nav__link { padding: 0.95rem 0; border-bottom: 1px solid var(--rule); font-size: 1rem; }
  .nav__link::after { display: none; }
  .nav__grp { border-bottom: 1px solid var(--rule); padding-bottom: 0.4rem; }
  .nav__grp > .nav__link { border-bottom: 0; }
  .nav__panel {
    position: static; opacity: 1; visibility: visible; transform: none;
    border: 0; box-shadow: none; padding: 0 0 0.4rem 0.9rem; min-width: 0;
  }
  .nav__panel a { padding: 0.5rem 0.7rem; }
  .portal { margin-top: 1.1rem; justify-content: center; padding-block: 0.8rem; }
}

/* ==========================================================================
   BUTTONS
   ========================================================================== */

.btn {
  display: inline-flex; align-items: center; gap: 0.6rem;
  padding: 0.92rem 1.6rem;
  font-size: 0.905rem; font-weight: 600; letter-spacing: 0.005em;
  border: 1px solid transparent;
  transition: background 0.22s var(--ease), color 0.22s var(--ease),
              border-color 0.22s var(--ease), transform 0.22s var(--ease);
}
.btn svg { flex: none; transition: transform 0.28s var(--ease); }

.btn--solid { background: var(--navy); color: #fff; }

.btn--line { border-color: var(--rule-2); color: var(--ink); }

.btn--onink { border-color: rgba(255, 255, 255, 0.42); color: #fff; }

.btn--fill { background: #fff; color: var(--navy); }

.cta-row { display: flex; flex-wrap: wrap; gap: 0.8rem; }

/* ==========================================================================
   HERO
   ========================================================================== */

.hero {
  position: relative;
  min-height: min(92vh, 840px);
  display: flex; flex-direction: column; justify-content: flex-end;
  overflow: hidden;
  background: var(--navy-800);
  color: #fff;
  isolation: isolate;
}
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img,
.hero__media video {
  width: 100%; height: 100%;
  object-fit: cover;
}
/* Navy wash rather than a flat black scrim, so the footage stays on brand */
.hero__media::after {
  content: ""; position: absolute; inset: 0;
  background:
    linear-gradient(180deg, rgba(0, 24, 56, 0.62) 0%, rgba(0, 24, 56, 0.42) 38%, rgba(0, 20, 48, 0.9) 100%),
    linear-gradient(90deg, rgba(0, 24, 56, 0.66) 0%, rgba(0, 24, 56, 0.12) 62%);
}
/* Roughly half the top inset it used to carry. The hero lost its button row,
   so the block sat low against the figures strip with dead space above it. */
.hero__in { padding-block: clamp(1.9rem, 0.8rem + 3vw, 3.2rem) 0; }
/* 30ch, not 17ch: the headline is three short sentences rather than one long
   one, and 17ch broke it across five lines of hero-sized type. This lets the
   longest sentence hold a line on its own, so it lands as three. */
.hero h1 {
  font-size: var(--t-hero);
  color: #fff;
  max-width: 30ch;
  letter-spacing: -0.024em;
}
.hero .lede { color: rgba(255, 255, 255, 0.82); max-width: 52ch; margin-top: 1.5rem; }
.hero .cta-row { margin-top: 2.4rem; }
/* Deliberate breathing room under the headline, where the hero lede used to
   sit. Kept as an explicit element so the gap is obvious and adjustable
   rather than hidden in a margin somewhere. */
.hero__space { height: clamp(4rem, 1.5rem + 9vw, 11rem); }

/* the figures strip pinned to the base of the hero */
.hero__figures {
  margin-top: clamp(2.25rem, 1rem + 3.4vw, 3.75rem);
  border-top: 1px solid var(--rule-dark);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
}
.hero__figures .fig { padding: 1.2rem 1.6rem 1.6rem 0; }
.hero__figures .fig + .fig { border-left: 1px solid var(--rule-dark); padding-left: 1.6rem; }
.fig__n {
  font-family: var(--f-display);
  font-size: clamp(1.6rem, 1.1rem + 1.5vw, 2.4rem);
  font-weight: 600; line-height: 1; color: #fff;
  letter-spacing: -0.02em;
}
.fig__l {
  margin-top: 0.5rem;
  font-size: var(--t-small); line-height: 1.4;
  color: rgba(255, 255, 255, 0.62);
  max-width: 24ch;
}
@media (max-width: 720px) {
  .hero { min-height: 0; }
  .hero__figures { grid-template-columns: minmax(0, 1fr); }
  .hero__figures .fig { padding: 1.15rem 0; border-top: 1px solid var(--rule-dark); }
  .hero__figures .fig:first-child { border-top: 0; }
  .hero__figures .fig + .fig { border-left: 0; padding-left: 0; }
  .fig__l { max-width: none; }
}

/* muted-autoplay control, bottom right of the hero */
.hero__vid-toggle {
  position: absolute; right: var(--gutter); bottom: 1.5rem; z-index: 2;
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.45rem 0.8rem;
  border: 1px solid rgba(255, 255, 255, 0.28);
  color: rgba(255, 255, 255, 0.78);
  font-size: var(--t-micro); font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase;
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
@media (max-width: 720px) { .hero__vid-toggle { display: none; } }

/* ==========================================================================
   PAGE HEAD (inner pages, no video)
   ========================================================================== */

.phead { padding-block: clamp(3.5rem, 2rem + 5vw, 6rem) clamp(2.5rem, 1.5rem + 3vw, 4rem); }
/* For a header that is a title and nothing else. The standard bottom padding
   assumes a lede beneath the heading; with only a word there it stacks with
   the following band's top padding and opens a hole. Zeroing the header's own
   padding is not enough, because --band is up to 8.5rem on its own, so the
   band that follows a bare title gets a much smaller top inset too. */
.phead--bare { padding-bottom: 0; }
.phead--bare + .band { padding-top: clamp(1.5rem, 0.9rem + 1.6vw, 2.6rem); }
.phead h1 { max-width: 19ch; }
.phead .lede { margin-top: 1.4rem; }
.phead__meta {
  margin-top: 2.4rem; padding-top: 1.2rem;
  border-top: 1px solid var(--rule);
  display: flex; flex-wrap: wrap; gap: 0.6rem 2rem;
  font-size: var(--t-small); color: var(--ink-3);
}

.crumb {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem;
  font-size: var(--t-small); color: var(--ink-3);
  margin-bottom: 1.6rem;
}
.crumb svg { opacity: 0.5; }

/* ==========================================================================
   INDEX LIST
   The services and markets pattern. Editorial rows on hairlines.
   Deliberately not a card grid.
   ========================================================================== */

.ilist { border-top: 1px solid var(--rule); }
.ilist__row {
  display: grid;
  grid-template-columns: 3.5rem minmax(0, 1fr) minmax(0, 1.05fr) 2rem;
  gap: 0 clamp(1rem, 0.2rem + 2vw, 2.75rem);
  align-items: start;
  padding: clamp(1.6rem, 1rem + 1.6vw, 2.5rem) 0;
  border-bottom: 1px solid var(--rule);
  position: relative;
  transition: background 0.3s var(--ease);
}
a.ilist__row::before {
  content: ""; position: absolute; inset: 0 calc(var(--gutter) * -0.5);
  background: var(--paper-2); opacity: 0; z-index: -1;
  transition: opacity 0.3s var(--ease);
}
.ilist__n {
  font-family: var(--f-display);
  font-size: 0.95rem; font-weight: 600;
  color: var(--critical);
  padding-top: 0.42rem;
}
.ilist__t {
  display: block;
  font-family: var(--f-display);
  font-weight: 600;
  line-height: 1.1;
  letter-spacing: -0.015em;
  font-size: clamp(1.35rem, 1.05rem + 1.1vw, 2rem);
}
.ilist__t--sm { font-size: clamp(1.15rem, 1rem + 0.55vw, 1.4rem); }
.ilist__d { color: var(--ink-2); font-size: var(--t-body); padding-top: 0.3rem; }
.ilist__go {
  align-self: center; justify-self: end;
  color: var(--ink-3);
  transition: transform 0.28s var(--ease), color 0.28s var(--ease);
}

/* wide variant: short titles against long descriptions, as on Markets */
.ilist--wide .ilist__row { grid-template-columns: 3.5rem minmax(0, 0.55fr) minmax(0, 1.45fr) 0; }
@media (max-width: 860px) {
  .ilist--wide .ilist__row { grid-template-columns: 2.4rem minmax(0, 1fr); }
}

/* the sub-capability chips inside a row */
.ilist__tags {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(11.5rem, 1fr));
  gap: 0.45rem 1.5rem;
  margin-top: 0.95rem;
}
.ilist__tags li {
  font-size: var(--t-small); color: var(--ink-3);
  position: relative; padding-left: 0.85rem;
}
.ilist__tags li::before {
  content: ""; position: absolute; left: 0; top: 0.66em;
  width: 4px; height: 4px; background: var(--rule-2);
}

@media (max-width: 860px) {
  .ilist__row { grid-template-columns: 2.4rem minmax(0, 1fr); }
  .ilist__d { grid-column: 2; padding-top: 0.7rem; }
  .ilist__go { grid-column: 2; justify-self: start; margin-top: 1rem; }
}

/* roles variant: job title over its location, against the summary. No index
   column, because open roles are not a numbered sequence and an empty first
   cell would just indent every row for nothing. */
.ilist--roles .ilist__row { grid-template-columns: minmax(0, 0.55fr) minmax(0, 1.45fr) 2rem; }
.ilist__loc {
  display: block; margin-top: 0.5rem;
  font-size: var(--t-small); color: var(--ink-3);
}
@media (max-width: 860px) {
  .ilist--roles .ilist__row { grid-template-columns: minmax(0, 1fr); }
  .ilist--roles .ilist__d,
  .ilist--roles .ilist__go { grid-column: 1; }
}

/* ==========================================================================
   FIGURES BAND (proof points on hairlines, not cards)
   ========================================================================== */

.figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  border-top: 1px solid var(--rule);
}
.figures .fig {
  padding: 1.9rem 1.75rem 1.9rem 0;
  border-bottom: 1px solid var(--rule);
}
.figures .fig + .fig { border-left: 1px solid var(--rule); padding-left: 1.75rem; }
.figures .fig__n { color: var(--ink); }
.figures .fig__l { color: var(--ink-3); }

/* The values block on the about page, where the three ARE the section rather
   than a footnote under a heading. Everything scales with it: the type, the
   space around it, and the column floor that keeps them three abreast until
   there is genuinely not room. */
.figures--lg .fig {
  padding: clamp(2.1rem, 1.3rem + 2.2vw, 3.4rem) clamp(1.6rem, 1rem + 1.8vw, 2.8rem)
           clamp(2.1rem, 1.3rem + 2.2vw, 3.4rem) 0;
}
.figures--lg .fig + .fig { padding-left: clamp(1.6rem, 1rem + 1.8vw, 2.8rem); }
.figures--lg .fig__n {
  font-size: clamp(1.7rem, 1.2rem + 1.7vw, 2.7rem);
  letter-spacing: -0.015em;
}
.figures--lg .fig__l {
  margin-top: 1rem;
  font-size: clamp(1rem, 0.94rem + 0.3vw, 1.2rem);
  line-height: 1.6;
  color: var(--ink-2);
}
@media (max-width: 700px) {
  .figures--lg .fig { padding: 1.8rem 0; }
  .figures--lg .fig + .fig { padding-left: 0; }
}

/* on the navy band the same component has to invert, or it goes unreadable */
.band--ink .figures,
.band--ink .figures .fig { border-color: var(--rule-dark); }
.band--ink .figures .fig__n { color: #fff; }
.band--ink .figures .fig__l { color: rgba(255, 255, 255, 0.66); }
@media (max-width: 700px) {
  .figures .fig { padding: 1.4rem 0; }
  .figures .fig + .fig { border-left: 0; padding-left: 0; }
}

/* A legal note that has to be present and legible without competing with the
   work above it. --ink-3 is the lightest grey in the palette that still
   clears 4.5:1, so it recedes as far as it can without becoming the kind of
   disclaimer nobody can read, which is the kind that fails to do its job. */
.disclaimer {
  font-size: 0.78rem;
  line-height: 1.65;
  color: var(--ink-4);
  border-top: 1px solid var(--rule);
  padding-top: 1.4rem;
}

/* ==========================================================================
   PROJECT GRID (the experience page)
   ========================================================================== */

/* A masonry wall, not a grid of equal tiles. Multi column layout rather than
   grid, because the tiles are different heights by design and this is the one
   technique that packs them without leaving ragged gaps or needing JavaScript.
   Each tile carries its own aspect ratio inline, chosen to suit the subject.

   Same editorial treatment as everything else: a hairline over the image, the
   name in the display face below it, no borders and no boxes. */
.pgrid {
  list-style: none;
  columns: 4;
  column-gap: clamp(1rem, 0.4rem + 1.4vw, 1.8rem);
}
.pgrid__item {
  margin: 0 0 clamp(1.6rem, 0.8rem + 2vw, 2.6rem);
  break-inside: avoid;
  /* Safari needs both, and without them a tile can be split across columns. */
  -webkit-column-break-inside: avoid;
  page-break-inside: avoid;
}
.pgrid__fig {
  position: relative;
  overflow: hidden;
  background: var(--navy-050);
  border-top: 1px solid var(--rule-2);
}
/* Reserves the tile's shape before a photograph exists, so the wall keeps its
   rhythm while the remaining images are gathered. */
.pgrid__soon {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  padding: 1rem;
  text-align: center;
  font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.11em; text-transform: uppercase;
  color: var(--ink-3);
}
.pgrid__fig img {
  display: block; width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.5s var(--ease);
}
.pgrid__name {
  font-family: var(--f-display);
  font-size: 1.15rem; font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin-top: 0.9rem;
}
.pgrid__place {
  font-size: 0.875rem;
  letter-spacing: 0.03em;
  color: var(--ink-3);
  margin-top: 0.32rem;
}

@media (hover: hover) and (pointer: fine) {
  .pgrid__item:hover .pgrid__fig img { transform: scale(1.03); }
}
@media (prefers-reduced-motion: reduce) {
  .pgrid__fig img { transition: none; }
  .pgrid__item:hover .pgrid__fig img { transform: none; }
}

/* Four across at every desktop width. A fifth column was tried on very wide
   monitors to keep tiles near the photographs' native size, but larger images
   are worth more here than pixel perfect sharpness. */
@media (max-width: 1100px) {
  .pgrid { columns: 3; }
}
@media (max-width: 820px) {
  .pgrid { columns: 2; }
}
@media (max-width: 560px) {
  .pgrid { columns: 1; max-width: 26rem; }
}

/* ==========================================================================
   TEAM (portraits with a biography behind them)
   ========================================================================== */

/* Deliberately not cards: no border, no box, no shadow. A hairline over each
   portrait and the name set below it, which is the same editorial treatment
   the lists use elsewhere. */
.team {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.4rem, 0.4rem + 2.4vw, 2.6rem);
  margin-top: 3rem;
}
/* The member is the positioning context, not the portrait, so the biography
   panel can lie over the portrait on a desktop while still being a sibling of
   it in the markup. It used to be a child, which meant that on a phone, where
   the panel is ordinary flowing text, it was trapped inside a square with
   overflow hidden and silently clipped away. */
.team__member { margin: 0; position: relative; }

.team__portrait {
  display: block;
  position: relative;
  aspect-ratio: 1 / 1;
  overflow: hidden;
  background: var(--navy-050);
  border-top: 1px solid var(--rule-2);
}
a.team__portrait:focus-visible { outline: 2px solid var(--navy); outline-offset: 4px; }
.team__portrait img { display: block; width: 100%; height: 100%; object-fit: cover; }

/* Stands in until a photograph exists. Initials, not a grey silhouette,
   because a silhouette reads as a broken image. */
.team__ph {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-family: var(--f-display);
  font-size: clamp(1.8rem, 1rem + 2vw, 2.6rem);
  letter-spacing: 0.06em;
  color: var(--navy);
  opacity: 0.28;
}

.team__name {
  font-family: var(--f-display);
  font-size: 1.075rem;
  line-height: 1.3;
  color: var(--ink);
  margin-top: 1rem;
}
.team__creds {
  display: block;
  font-family: var(--f-sans);
  font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 0.3rem;
}
.team__role {
  font-size: var(--t-small);
  color: var(--ink-2);
  margin-top: 0.35rem;
}
.team__social { margin-top: 0.45rem; }
.team__social a {
  font-size: 0.7rem; font-weight: 600;
  letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--ink-3);
  border-bottom: 1px solid var(--rule-2);
  padding-bottom: 1px;
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}

/* Sits inside the biography panel, so it inherits the panel's colour when the
   panel is an overlay and the page colour when it is not. */
.team__more {
  display: inline-flex; align-items: center; gap: 0.5rem;
  margin-top: 0.9rem;
  font-size: 0.78rem; font-weight: 600;
  letter-spacing: 0.02em;
  color: inherit;
  border-bottom: 1px solid currentColor;
  padding-bottom: 2px;
  align-self: start;
}
.team__more svg { transition: transform 0.22s var(--ease); }
.team__more:hover svg { transform: translateX(3px); }

/* Touch first: there is no hover on a phone, so the biography is simply part
   of the page. The overlay below is the enhancement, not the baseline. */
.team__bio { margin-top: 0.9rem; font-size: var(--t-small); line-height: 1.6; color: var(--ink-2); }
.team__bio p { margin: 0; }

@media (hover: hover) and (pointer: fine) {
  /* Over the portrait only, which is a square at the top of the member, so the
     name and role underneath stay readable while the panel is open. */
  .team__bio {
    position: absolute; top: 0; left: 0; right: 0;
    aspect-ratio: 1 / 1;
    margin-top: 0;
    display: grid; align-content: center;
    padding: clamp(1rem, 0.4rem + 1.2vw, 1.6rem);
    background: var(--navy);
    color: var(--paper);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.28s var(--ease);
  }
  .team__member:hover .team__bio,
  .team__member:focus-within .team__bio { opacity: 1; pointer-events: auto; }
}

/* The portrait beside a full biography, in the page's left rail. */
.bio__fig { margin: 0; }
.bio__fig img {
  display: block; width: 100%; height: auto;
  border-top: 1px solid var(--rule-2);
}
.bio__ph {
  display: grid; place-items: center;
  aspect-ratio: 1 / 1;
  background: var(--navy-050);
  border-top: 1px solid var(--rule-2);
  font-family: var(--f-display);
  font-size: 2rem; letter-spacing: 0.06em;
  color: var(--navy); opacity: 0.28;
}

@media (max-width: 860px) {
  .team { grid-template-columns: 1fr; gap: 2.75rem; max-width: 24rem; }
  .bio__fig { max-width: 11rem; }
}

@media (prefers-reduced-motion: reduce) {
  .team__bio { transition: none; }
}

/* ==========================================================================
   FEATURE (asymmetric image and text, alternating)
   ========================================================================== */

.feature {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr);
  gap: clamp(2rem, 0.5rem + 5vw, 5rem);
  align-items: center;
}
.feature--flip > *:first-child { order: 2; }
.feature__fig { position: relative; }
.feature__fig img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.feature__fig--wide img { aspect-ratio: 5 / 4; }
.feature__cap {
  margin-top: 0.8rem;
  font-size: var(--t-micro); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-3);
}
@media (max-width: 860px) {
  .feature { grid-template-columns: minmax(0, 1fr); }
  .feature--flip > *:first-child { order: 0; }
}

/* full bleed image band */
.bleed { position: relative; overflow: hidden; }
.bleed img { width: 100%; height: clamp(16rem, 8rem + 26vw, 30rem); object-fit: cover; }

/* The banner height depends on viewport WIDTH while the photo's aspect ratio
   is fixed, so the wider the window the harder `cover` crops top and bottom.
   At 1280px the band is 2.78:1, at 2560px it is 5.33:1, against a 1.5:1 photo.
   Centred cropping therefore shows a different slice on every machine.
   Use this where the subject sits low in the frame, such as a skyline over
   water. Anchoring at 85% keeps both the skyline and the waterline in shot
   from roughly 1000px right up to an ultrawide, and spends the empty sky
   instead. Pinning to `bottom` also works but goes almost all water once the
   window passes about 1700px. */
.bleed--bottom img { object-position: center 85%; }
.bleed--tint::after {
  content: ""; position: absolute; inset: 0;
  background: linear-gradient(90deg, rgba(0, 24, 56, 0.86) 0%, rgba(0, 24, 56, 0.32) 100%);
}
.bleed__over {
  position: absolute; inset: 0; z-index: 2;
  display: flex; align-items: center;
}
.bleed__over * { color: #fff; }

/* ==========================================================================
   PROSE (articles and long form)
   ========================================================================== */

.prose { max-width: 40rem; }
.prose > * + * { margin-top: 1.35rem; }
.prose h2 {
  font-size: clamp(1.5rem, 1.2rem + 1vw, 2rem);
  margin-top: 3rem; padding-top: 1.5rem;
  border-top: 1px solid var(--rule);
}
.prose h3 { font-size: 1.25rem; margin-top: 2.2rem; }
.prose p { color: var(--ink-2); }
.prose strong { color: var(--ink); font-weight: 600; }
/* Direct children only. Lists that belong to embedded components, such as the
   schedule legend, must not inherit prose bullets or indentation. */
.prose > ul, .prose > ol { margin-top: 1.1rem; display: grid; gap: 0.7rem; }
.prose > ul > li, .prose > ol > li { color: var(--ink-2); position: relative; padding-left: 1.5rem; }
.prose > ul > li::before {
  content: ""; position: absolute; left: 0; top: 0.72em;
  width: 6px; height: 1.5px; background: var(--critical);
}
.prose > ol { counter-reset: n; }
.prose > ol > li { counter-increment: n; }
.prose > ol > li::before {
  content: counter(n, decimal-leading-zero);
  position: absolute; left: 0; top: 0.06em;
  font-family: var(--f-display); font-size: 0.85rem; font-weight: 600;
  color: var(--critical);
}
.prose a { color: var(--navy); text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1px; }

/* The chart is wider than the reading measure, so let it break out. It still
   sits inside the rail content column and never exceeds the viewport. */
.prose .sched {
  width: 46rem;
  max-width: calc(100vw - (2 * var(--gutter)));
  margin-block: 2.2rem;
}

.pullquote {
  margin-block: 2.6rem;
  padding-left: 1.75rem;
  border-left: 2px solid var(--critical);
  font-family: var(--f-display);
  font-size: clamp(1.25rem, 1.05rem + 0.8vw, 1.6rem);
  line-height: 1.34; letter-spacing: -0.01em;
  color: var(--ink);
}

.note {
  padding: 1.4rem 1.6rem;
  background: var(--paper-2);
  border-left: 2px solid var(--navy);
  font-size: var(--t-small); line-height: 1.6; color: var(--ink-2);
}
.note b { color: var(--ink); }

/* ==========================================================================
   DEFINITION PANEL (the CPM explainer)
   ========================================================================== */

.defn {
  display: grid;
  grid-template-columns: minmax(0, 0.94fr) minmax(0, 1fr);
  gap: clamp(2rem, 0.5rem + 4vw, 4.5rem);
  align-items: start;
}
.defn__term {
  font-family: var(--f-display);
  font-size: clamp(1.6rem, 1.2rem + 1.6vw, 2.5rem);
  font-weight: 600; line-height: 1.1; letter-spacing: -0.02em;
}
.defn__term em { font-style: normal; color: var(--critical); }
.defn__body > * + * { margin-top: 1.15rem; }
.defn__body p { color: var(--ink-2); }
@media (max-width: 880px) { .defn { grid-template-columns: minmax(0, 1fr); } }

/* the small key used under the schedule diagram */
.key { display: flex; flex-wrap: wrap; gap: 0.55rem 1.75rem; }
.key li { display: flex; align-items: center; gap: 0.55rem; font-size: var(--t-small); color: var(--ink-3); }
.key i { display: block; width: 1.4rem; height: 0.55rem; flex: none; }
.key i.is-crit  { background: var(--critical); }
.key i.is-norm  { background: var(--navy); }
.key i.is-float { background: repeating-linear-gradient(135deg, var(--rule-2) 0 2px, transparent 2px 5px); border: 1px solid var(--rule-2); }

/* ==========================================================================
   SCHEDULE DIAGRAM (hand built, no client data)
   ========================================================================== */

.sched {
  border: 1px solid var(--rule);
  background: var(--paper);
}
.sched__head {
  display: flex; flex-wrap: wrap; gap: 0.4rem 1.5rem;
  align-items: baseline; justify-content: space-between;
  padding: 1rem 1.25rem;
  border-bottom: 1px solid var(--rule);
}
.sched__title { font-size: var(--t-small); font-weight: 600; color: var(--ink); }
.sched__scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; position: relative; }

/* On narrow screens the chart scrolls inside its own box. Say so, because a
   chart cut off at the right edge otherwise just looks broken. */
@media (max-width: 780px) {
  .sched__head::after {
    content: "Scroll the chart sideways to see the full program";
    display: block; width: 100%;
    margin-top: 0.5rem;
    font-size: var(--t-micro); font-weight: 600;
    letter-spacing: 0.08em; text-transform: uppercase;
    color: var(--ink-3);
  }
}
.sched__svg { min-width: 660px; width: 100%; height: auto; display: block; }
.sched__foot { padding: 0.95rem 1.25rem; border-top: 1px solid var(--rule); background: var(--paper-2); }

/* bars grow from the left once the diagram scrolls into view */
.sched__svg .bar { transform: scaleX(0); transform-origin: left center; }
.is-drawn .sched__svg .bar {
  animation: barIn 0.62s var(--ease) forwards;
  animation-delay: calc(var(--i) * 90ms);
}
@keyframes barIn { to { transform: scaleX(1); } }

.sched__svg .tie { opacity: 0; }
.is-drawn .sched__svg .tie {
  animation: fadeIn 0.4s var(--ease) forwards;
  animation-delay: calc(var(--i) * 90ms + 380ms);
}
.sched__svg .lbl { opacity: 0; }
.is-drawn .sched__svg .lbl {
  animation: fadeIn 0.5s var(--ease) forwards;
  animation-delay: calc(var(--i) * 90ms + 120ms);
}
@keyframes fadeIn { to { opacity: 1; } }

/* the data date sweeps in last */
.sched__svg .datadate { opacity: 0; }
.is-drawn .sched__svg .datadate { animation: fadeIn 0.5s var(--ease) 1.15s forwards; }

/* ==========================================================================
   METHOD STRIP (a horizontal sequence, not a step card row)
   ========================================================================== */

.method { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0; border-top: 1px solid var(--rule); }
.method__step { padding: 1.6rem 1.5rem 0 0; position: relative; }
.method__step + .method__step { border-left: 1px solid var(--rule); padding-left: 1.5rem; }
.method__step::before {
  content: ""; position: absolute; top: -1px; left: 0;
  width: 2.2rem; height: 2px; background: var(--critical);
}
.method__step + .method__step::before { left: -1px; }
.method__n { font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.14em; color: var(--ink-3); text-transform: uppercase; }
.method__t { font-family: var(--f-display); font-size: 1.22rem; font-weight: 600; margin-top: 0.55rem; letter-spacing: -0.01em; }
.method__d { font-size: var(--t-small); color: var(--ink-2); margin-top: 0.5rem; line-height: 1.55; }
@media (max-width: 900px) { .method { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 560px) {
  .method { grid-template-columns: minmax(0, 1fr); }
  .method__step + .method__step { border-left: 0; padding-left: 0; border-top: 1px solid var(--rule); margin-top: 1.5rem; }
  .method__step + .method__step::before { left: 0; }
}

/* ==========================================================================
   DELIVERABLES TABLE
   ========================================================================== */

.dtable { width: 100%; border-collapse: collapse; font-size: var(--t-small); }
.dtable caption { text-align: left; margin-bottom: 1.1rem; }
.dtable th, .dtable td { text-align: left; padding: 0.95rem 1.25rem 0.95rem 0; border-bottom: 1px solid var(--rule); vertical-align: top; }
.dtable thead th {
  font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.13em;
  text-transform: uppercase; color: var(--ink-3);
  border-bottom-color: var(--rule-2); padding-bottom: 0.7rem;
}
.dtable tbody th { font-weight: 600; color: var(--ink); width: 34%; }
.dtable td { color: var(--ink-2); }
@media (max-width: 640px) {
  .dtable thead { display: none; }
  .dtable tbody th, .dtable td { display: block; width: auto; border-bottom: 0; padding: 0; }
  .dtable tbody th { padding-top: 1.1rem; }
  .dtable td { padding-bottom: 1.1rem; border-bottom: 1px solid var(--rule); }
}

/* ==========================================================================
   STANDARDS CHIPS
   ========================================================================== */

.stds { display: flex; flex-wrap: wrap; gap: 0.55rem; }
.stds li {
  padding: 0.42rem 0.8rem;
  border: 1px solid var(--rule);
  font-size: var(--t-small); color: var(--ink-2);
  background: var(--paper);
}
.stds li b { color: var(--ink); font-weight: 600; }

/* ==========================================================================
   ARTICLE CARDS (insights index) -- two-up editorial, not a 3x3 grid
   ========================================================================== */

.posts { border-top: 1px solid var(--rule); }
.post {
  display: grid;
  grid-template-columns: minmax(0, 13rem) minmax(0, 1fr);
  gap: clamp(1.25rem, 0.3rem + 2.4vw, 2.75rem);
  padding: clamp(1.75rem, 1rem + 1.8vw, 2.75rem) 0;
  border-bottom: 1px solid var(--rule);
  align-items: start;
}
.post__fig img { aspect-ratio: 4 / 3; object-fit: cover; width: 100%; filter: grayscale(1); transition: filter 0.4s var(--ease); }
.post__meta { display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem; font-size: var(--t-micro); letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-3); }
.post__t { font-size: clamp(1.28rem, 1.05rem + 0.9vw, 1.75rem); margin-top: 0.7rem; }
.post__x { color: var(--ink-2); margin-top: 0.7rem; max-width: 58ch; }
@media (max-width: 700px) { .post { grid-template-columns: minmax(0, 1fr); } .post__fig { max-width: 20rem; } }

/* ==========================================================================
   FORM
   ========================================================================== */

.contact-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr);
  gap: clamp(2.25rem, 0.5rem + 5vw, 5rem);
  align-items: start;
}
@media (max-width: 900px) { .contact-grid { grid-template-columns: minmax(0, 1fr); } }

.form { display: grid; gap: 1.15rem; }
.f2 { display: grid; grid-template-columns: 1fr 1fr; gap: 1.15rem; }
@media (max-width: 620px) { .f2 { grid-template-columns: 1fr; } }
.field label { display: block; margin-bottom: 0.42rem; }
.field input, .field select, .field textarea {
  width: 100%;
  padding: 0.82rem 0.95rem;
  border: 1px solid var(--rule-2);
  background: var(--paper);
  font-size: 0.965rem;
  transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.field textarea { min-height: 8.5rem; resize: vertical; }
/* The file control inherits the field box above, but its own button is a
   native widget that otherwise sits in the form looking like a different
   decade. Only the two properties that matter are set. */
.field input[type="file"] { padding: 0.66rem 0.8rem; cursor: pointer; }
.field input[type="file"]::file-selector-button {
  margin-right: 0.85rem;
  padding: 0.42rem 0.9rem;
  border: 1px solid var(--rule-2);
  background: var(--paper-2);
  color: var(--ink);
  font: inherit;
  font-size: 0.88rem;
  cursor: pointer;
}
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--navy);
  box-shadow: inset 0 0 0 1px var(--navy);
}
.field input::placeholder, .field textarea::placeholder { color: var(--ink-3); }
.form__note { font-size: var(--t-small); color: var(--ink-3); }
.form__note--bad { color: var(--critical-deep); }

/* Honeypot. Taken out of the layout, out of the tab order and off the
   accessibility tree, but still a real field a bot will happily fill.
   display:none is avoided because some bots skip hidden inputs. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* Sent state: the fields are replaced by a confirmation. */
.form__done {
  border-left: 2px solid var(--navy);
  background: var(--paper-2);
  padding: 1.6rem 1.75rem;
}
.form__done h3 { font-size: 1.3rem; }
.form__done p { margin-top: 0.7rem; color: var(--ink-2); font-size: 0.97rem; }

.btn[disabled] { opacity: 0.55; cursor: progress; }

.contact-line {
  display: grid; grid-template-columns: 5.5rem 1fr; gap: 1rem;
  padding: 0.85rem 0; border-bottom: 1px solid var(--rule);
  font-size: 0.97rem;
}
.contact-line dt { font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.12em; text-transform: uppercase; color: var(--ink-3); padding-top: 0.28rem; }
.contact-line dd { margin: 0; }

.offices { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(13rem, 100%), 1fr)); border-top: 1px solid var(--rule); }
.office { padding: 1.5rem 1.5rem 1.5rem 0; border-bottom: 1px solid var(--rule); }
.office + .office { border-left: 1px solid var(--rule); padding-left: 1.5rem; }
/* stacked variant, for narrow columns where three across would orphan one */
.offices--stack { grid-template-columns: minmax(0, 1fr); }
.offices--stack .office { padding: 1.15rem 0; }
.offices--stack .office + .office { border-left: 0; padding-left: 0; }

.office h3 { font-size: 1.15rem; }
.office p { font-size: var(--t-small); color: var(--ink-2); margin-top: 0.5rem; line-height: 1.55; }
@media (max-width: 720px) {
  .office { padding: 1.25rem 0; }
  .office + .office { border-left: 0; padding-left: 0; }
}

/* ==========================================================================
   CTA BAND
   ========================================================================== */

.endcta { background: var(--navy); color: #fff; }
.endcta__in {
  display: grid; grid-template-columns: minmax(0, 1fr) auto;
  gap: clamp(1.5rem, 0.5rem + 3vw, 4rem);
  align-items: center;
  padding-block: clamp(3rem, 1.8rem + 4vw, 5rem);
}
.endcta h2 { color: #fff; font-size: clamp(1.7rem, 1.25rem + 1.7vw, 2.6rem); max-width: 22ch; }
.endcta p { color: rgba(255, 255, 255, 0.7); margin-top: 0.9rem; max-width: 48ch; }
@media (max-width: 820px) { .endcta__in { grid-template-columns: minmax(0, 1fr); } }

/* ==========================================================================
   PROJECT MARQUEE (home page)
   ========================================================================== */

.marquee-band { overflow: hidden; }
/* The strip's title is a plain h2 and deliberately has no font rules of its
   own: the base h1-h4 block already gives it --t-h2, the display face, the
   weight and the colour, which is exactly what the headings elsewhere on the
   page use. Setting any of it again here is how it ended up smaller than
   every other h2 on the home page. */
.marquee__more { margin-top: 1.5rem; font-size: 1rem; }

/* Full bleed: the strip runs edge to edge, outside .shell, so it is not
   governed by --shell and stays the same at every width setting.

   A REAL scroll container, not a transform animation. The drift is driven by
   scrollLeft in site.js, which means a finger can grab it, throw it, and get
   native momentum on iOS. A translateX animation would have looked identical
   and been completely dead to touch. */
.marquee {
  margin-top: 1.8rem;
  overflow-x: auto;
  overflow-y: hidden;
  /* A swipe that runs past the end must not trigger the browser's back
     gesture or rubber band the whole page sideways. */
  overscroll-behavior-x: contain;
  -webkit-overflow-scrolling: touch;
  /* The bar itself is noise under a photo strip; the content is obviously
     draggable without it. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.marquee::-webkit-scrollbar { display: none; }
.marquee__track {
  display: flex;
  width: max-content;
  gap: clamp(0.9rem, 0.5rem + 1vw, 1.5rem);
}

.marquee__item {
  flex: 0 0 auto;
  width: clamp(14rem, 10rem + 12vw, 21rem);
  color: inherit;
}
.marquee__item img {
  display: block; width: 100%; aspect-ratio: 4 / 3;
  object-fit: cover; background: var(--paper-2);
}
.marquee__cap { display: block; margin-top: 0.75rem; }
.marquee__name {
  display: block;
  font-family: var(--f-display); font-weight: 600; font-size: 0.98rem;
  line-height: 1.3; color: var(--ink);
}
.marquee__place {
  display: block; margin-top: 0.2rem;
  font-size: 0.8rem; color: var(--ink-3);
}

/* Page-width preview control. Owner-only: site.js builds it only when ?width
   is in the URL or a choice is stored, so an ordinary visitor never sees it.
   Fixed above everything, including the sticky masthead at z-index 100. */
.widthtog {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 900;
  display: flex; gap: 1px;
  font-family: var(--f-sans); font-size: 0.8rem;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.28);
}
.widthtog button {
  border: 0; cursor: pointer; font: inherit; line-height: 1;
  background: var(--navy); color: #fff;
  padding: 0.75rem 0.85rem;
}
/* The step in force. Inverted rather than merely tinted, so which one you are
   looking at is readable at a glance from across the desk. */
.widthtog button.widthtog__on { background: #fff; color: var(--navy); font-weight: 600; }
.widthtog__tag {
  background: var(--navy); color: rgba(255, 255, 255, 0.62);
  padding: 0.75rem 0.7rem 0.75rem 0.9rem;
  letter-spacing: 0.08em; text-transform: uppercase; font-size: 0.68rem;
  display: flex; align-items: center;
}
.widthtog__x { padding-inline: 0.8rem; opacity: 0.72; }

/* ==========================================================================
   FOOTER
   ========================================================================== */

.foot { background: var(--ink); color: rgba(255, 255, 255, 0.6); padding-block: clamp(3rem, 2rem + 3vw, 4.5rem) 2rem; }
.foot__grid {
  display: grid; grid-template-columns: minmax(0, 1.5fr) repeat(3, minmax(0, 1fr));
  gap: clamp(1.75rem, 0.5rem + 3vw, 3.5rem);
}
.foot img { height: 19px; width: auto; }
.foot__blurb { font-size: var(--t-small); line-height: 1.65; margin-top: 1.15rem; max-width: 34ch; }

/* The three offices, in place of the old descriptive blurb. */
.foot__offices {
  margin-top: 1.25rem;
  display: grid;
  gap: 0.95rem;
  font-size: var(--t-small);
  line-height: 1.5;
  max-width: 30ch;
}
.foot__offices b {
  display: block;
  font-weight: 600;
  color: rgba(255, 255, 255, 0.88);
}
.foot h4 { font-size: var(--t-micro); font-weight: 600; letter-spacing: 0.14em; text-transform: uppercase; color: #fff; font-family: var(--f-sans); }
.foot__col ul { margin-top: 1rem; display: grid; gap: 0.6rem; }
.foot__col a { font-size: var(--t-small); color: rgba(255, 255, 255, 0.72); transition: color 0.2s var(--ease); }
.foot__base {
  margin-top: clamp(2.5rem, 1.5rem + 3vw, 4rem); padding-top: 1.5rem;
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  display: flex; flex-wrap: wrap; gap: 0.6rem 2rem; justify-content: space-between;
  font-size: var(--t-micro); color: rgba(255, 255, 255, 0.56);
}
@media (max-width: 860px) { .foot__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 520px) { .foot__grid { grid-template-columns: minmax(0, 1fr); } }

/* ==========================================================================
   POINTER STATES

   Hover is a mouse idea. A touch browser fires it on tap and then leaves it
   applied until you tap something else, so a hover style becomes a smear that
   sits there while the next page loads. Guarding on `hover: hover` means a
   phone never enters these states at all.
   ========================================================================== */

@media (hover: hover) and (pointer: fine) {
  .tlink:hover { background-size: 0 1px; background-position: 100% 100%; }
  .nav__link:hover { color: var(--ink); }
  .nav__link:hover::after { transform: scaleX(1); }
  .nav__grp:hover .nav__panel { opacity: 1; visibility: visible; transform: none; }
  .nav__panel a:hover { background: var(--navy-050); border-left-color: var(--navy); }
  .team__social a:hover { color: var(--navy); border-color: var(--navy); }
  .portal:hover { border-color: var(--navy); background: var(--navy-050); }
  .btn:hover svg { transform: translateX(4px); }
  .btn--solid:hover { background: var(--navy-800); }
  .btn--line:hover { border-color: var(--navy); color: var(--navy); }
  .btn--onink:hover { background: #fff; color: var(--navy); border-color: #fff; }
  .btn--fill:hover { background: var(--navy-050); }
  .widthtog button:hover { background: var(--navy-800); }
  .marquee__item:hover .marquee__name { color: var(--navy); }
  .hero__vid-toggle:hover { border-color: #fff; color: #fff; }
  .crumb a:hover { color: var(--navy); }
  a.ilist__row:hover::before { opacity: 1; }
  a.ilist__row:hover .ilist__go { transform: translateX(5px); color: var(--navy); }
  a.ilist__row:hover .ilist__t { color: var(--navy); }
  .prose a:hover { text-decoration-thickness: 2px; }
  .dtable tbody tr:hover { background: var(--paper-2); }
  .post:hover .post__fig img { filter: none; }
  .post:hover .post__t { color: var(--navy); }
  .foot__col a:hover { color: #fff; }
}

/* A wide touch screen, such as a tablet in landscape, gets neither hover nor a
   way to focus inside a hidden panel, so the Services dropdown would be
   unreachable. Hide it there and let the tap follow the link: Services goes to
   the overview page, which lists all three anyway. Below 900px the panel is
   part of the drawer and must stay. */
@media (hover: none) and (min-width: 901px) {
  .nav__panel { display: none; }
}

/* Touch feedback. The browser's own tap highlight is off, so this is the
   "something happened" signal. It clears the moment the finger lifts. */
@media (hover: none) {
  .btn:active { transform: scale(0.985); }
  .btn--solid:active { background: var(--navy-800); }
  .btn--fill:active,
  .btn--line:active { background: var(--navy-050); }
  .btn--onink:active { background: rgba(255, 255, 255, 0.18); }
  .portal:active { background: var(--navy-050); border-color: var(--navy); }
  a.ilist__row:active::before { opacity: 1; }
  .nav__link:active,
  .crumb a:active,
  .tlink:active,
  .prose a:active { color: var(--navy-600); }
  .foot__col a:active { color: #fff; }
  .post:active .post__t { color: var(--navy); }
}

/* ==========================================================================
   REVEAL
   ========================================================================== */

/* Scoped to .js so that content is never hidden when scripting is off or
   fails to run. Without JS these elements simply render, fully visible. */
.js .rv { opacity: 0; transform: translateY(14px); }
.js .rv.is-in {
  opacity: 1; transform: none;
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
  transition-delay: var(--d, 0ms);
}

/* Above the fold, do not wait on an observer. The hero reveals on load. */
.js .hero .rv {
  opacity: 0;
  animation: heroIn 0.85s var(--ease) forwards;
  animation-delay: calc(180ms + var(--h, 0) * 110ms);
}
@keyframes heroIn { from { opacity: 0; transform: translateY(16px); } to { opacity: 1; transform: none; } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .js .rv, .js .hero .rv { opacity: 1; transform: none; animation: none; }
  .sched__svg .bar { transform: scaleX(1); }
  .sched__svg .tie, .sched__svg .lbl, .sched__svg .datadate { opacity: 1; }
}

/* ==========================================================================
   PRINT
   ========================================================================== */

@media print {
  .hdr, .foot, .endcta, .hero__media, .hero__vid-toggle, .burger { display: none !important; }
  body { color: #000; }
  .rv { opacity: 1; transform: none; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.8em; color: #555; }
}
