:root{/* --------------------------------------------------------------
     Short names for the theme.json presets, which are the single
     source of truth: Appearance → Editor → Styles drives them.
     -------------------------------------------------------------- */
  --paper:var(--wp--preset--color--paper);
  --paper-2:var(--wp--preset--color--paper-raised);
  --paper-3:var(--wp--preset--color--paper-sunken);
  --ink:var(--wp--preset--color--ink);
  --fg-dim:var(--wp--preset--color--ink-soft);
  --line:var(--wp--preset--color--line);
  --sig:var(--wp--preset--color--green);
  --sig-soft:var(--wp--preset--color--green-soft);
  --deep:var(--wp--preset--color--green-deep);
  /* derived — follow whatever the colours above are set to */
  --line-2:color-mix(in srgb,var(--line) 68%,var(--ink));
  --sig-dim:color-mix(in srgb,var(--sig) 82%,var(--paper));
  --sig-deep:color-mix(in srgb,var(--sig) 78%,#000);
  --prose:color-mix(in srgb,var(--ink) 92%,var(--paper));
  --on-deep:color-mix(in srgb,var(--paper) 92%,var(--deep));
  --on-deep-dim:color-mix(in srgb,var(--paper) 55%,var(--deep));
  --nav-bg:color-mix(in srgb,var(--paper) 94%,transparent);
  --display:var(--wp--preset--font-family--display);
  --body:var(--wp--preset--font-family--body);
  --mono:var(--wp--preset--font-family--mono);
  /* the site gutter, from theme.json's root padding */
  --pad:var(--wp--style--root--padding-left,clamp(1.25rem,4vw,4rem));
  /* the layout width, from theme.json, so Styles → Layout moves it */
  --max:var(--wp--style--global--wide-size,1340px);
  --h:72px;
  --r:var(--wp--custom--radius--control);
  --r-media:var(--wp--custom--radius--media);
  --rule:1px solid var(--line);
  --measure:68ch;
  /* shared with site.js, which reads it rather than repeating the number */
  --nav-overlay-max:1080px}

/* The content width is the wide width less the gutter on each side, so text
   lines up with the header and Wide reaches exactly to the band's edges.
   theme.json holds 1212px, the same thing at full width; it is restated here
   because core declares the gutter on body, one level below where it declares
   the widths. */
body{--wp--style--global--content-size:calc(var(--wp--style--global--wide-size) - var(--wp--style--root--padding-left) - var(--wp--style--root--padding-right))}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth}
body{margin:0;background:var(--paper);color:var(--ink)}
img,svg,video{max-width:100%;height:auto;display:block}
::selection{background:var(--sig);color:var(--paper-2)}
:focus-visible{outline:2px solid var(--sig);outline-offset:3px}
h1,h2,h3,h4{margin:0;color:var(--ink);font-family:var(--display)}
/* Heading sizes are theme.json's: per level, or a size preset on the block.
   The front-page hero is the one heading with its own. */
.h-hero{font-size:var(--wp--preset--font-size--hero);line-height:1.02;max-width:26ch;letter-spacing:-.02em}
p{margin:0 0 1.15em}
.is-style-lede{max-width:60ch;font-family:var(--display);font-size:clamp(1.15rem,1.6vw,1.42rem);line-height:1.45;color:var(--fg-dim);font-weight:400}
.prose{color:var(--prose);max-width:var(--measure);font-size:1.075rem;line-height:1.72}
/* Running text placed straight into a section keeps a readable line length,
   as `prose` does for its own contents. Not straight on the page: there core's
   layout would centre anything narrower than the content width. */
.section > :is(p,.wp-block-list):not(.has-text-align-center,.has-text-align-right){max-width:var(--measure)}
.prose p,.prose ul,.prose ol{font-size:1.0625rem}
/* Links are green and underlined everywhere, from elements.link in theme.json;
   a component that wants a plain link (a card heading, the footer, a menu)
   says so itself. In running text the underline is drawn finer and lower. */
.prose a,
:where(.entry-content) :where(p,li,dd,blockquote,cite) a:not(.wp-element-button,.more-link,.doi,.wp-block-social-link-anchor){color:var(--sig);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:3px}
.prose a:hover,
:where(.entry-content) :where(p,li,dd,blockquote,cite) a:not(.wp-element-button,.more-link,.doi,.wp-block-social-link-anchor):hover{color:var(--sig-deep)}
.prose strong{font-weight:600}
.prose h3{margin:2.4rem 0 .7rem}
.prose ul{padding-left:1.15rem}
.prose li{margin:.35em 0}
.prose li::marker{color:var(--sig-dim)}
.is-style-dim{color:var(--fg-dim)}
.is-style-overline{font-family:var(--body);font-size:.75rem;letter-spacing:.14em;text-transform:uppercase;font-weight:500}
/* as a paragraph it is a quiet label (a card's kicker, a breadcrumb); a colour picked in the editor still wins */
.is-style-overline:not(h1,h2,h3,h4,h5,h6){color:var(--fg-dim);margin-bottom:1rem;font-size:.78rem}
.is-style-eyebrow{
  display:flex;
  align-items:center;
  margin:0 0 1.3rem;
  font-family:var(--body);
  font-size:.7rem;
  font-weight:600;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--sig);
  gap:.75rem
}
.is-style-eyebrow::before{content:"";flex:none;width:2.2rem;height:1px;background:var(--ink);opacity:.35}
.is-style-ordinal{font-family:var(--body);font-size:.72rem;font-weight:600;letter-spacing:.14em;color:var(--sig-dim)}

/* ---------- layout ----------
   Page content uses core's constrained layout (templates, theme.json): every
   block is held to the content width inside the site gutter, and Wide and
   Full widen one. `wrap` does the same job by hand for the header, footer,
   call-to-action band and the templates' own sections, which sit outside page
   content. */
.wrap{max-width:var(--max);margin:0 auto;padding:0 var(--pad)}
.section{padding-block:clamp(1.5rem,3vw,2.75rem);border-top:1px solid var(--line);margin-block:0}
/* Sections are spaced by their own padding and rule, so they take no block
   gap from the layout. */
/* A section draws a rule against the one above it. The first thing on the
   page sits under the header's own rule, and the section after a page heading
   (a group that closes on the Ruler) under that ruler, so neither draws one. */
.wp-block-post-content > .section:first-child,
:has(> .is-style-ruler:last-child) + .section{border-top:0}
/* A section given a background (styles/sections/) is a box of its own, so it
   stands apart from its neighbours instead of drawing the rule. Raised keeps
   its full outline. This loads after the styles' own CSS and would otherwise
   undo them, so the overrides live here. */
.section:is(.is-style-tinted,.is-style-sunken,.is-style-raised){margin-block:var(--wp--preset--spacing--40)}
.section:is(.is-style-tinted,.is-style-sunken){border-top:0}
.section.is-style-raised,
.wp-block-post-content > .section.is-style-raised{border-top:var(--rule)}
/* position and z-index anchor .nav::before, which is absolutely positioned. */
.nav{position:relative;z-index:50;height:var(--h);display:flex;align-items:center;border-bottom:2px solid var(--ink)}
/* The translucent blur lives on a pseudo-element. backdrop-filter on .nav
   itself would make the header a containing block for position:fixed
   descendants, which traps the mobile menu overlay inside the header band. */
.nav::before{content:"";position:absolute;inset:0;background:var(--nav-bg);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);z-index:-1}
.nav__in{display:flex;align-items:center;justify-content:space-between;gap:1rem;width:100%}
.brand{display:flex;align-items:center;gap:.65rem;font-family:var(--display);font-weight:600;font-size:1.2rem;letter-spacing:-.01em}

/* ---------- hero ---------- */
.hero{padding-block:clamp(2.5rem,5.5vw,4.5rem) clamp(2rem,4vw,3.5rem)}
.hero__grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:clamp(1.5rem,4vw,3.5rem);align-items:center}
@media(max-width:980px){.hero__grid{grid-template-columns:1fr}}
.hero h1{margin-bottom:1.3rem}
/* Tag pills. The row is a group on core's flex layout; naming the row as well
   as the pill keeps a pill ahead of whatever body-copy rule its container
   carries, such as a card's body text. */
.is-style-chips{margin-top:1.5rem}
.is-style-chips .is-style-chip,
.is-style-chips .is-style-chip-accent{
  margin:0;
  font-size:.82rem;
  color:var(--fg-dim);
  border:1px solid var(--line);
  padding:.3rem .8rem;
  border-radius:999px;
  background:var(--paper-2)
}
.is-style-chips .is-style-chip-accent{color:var(--sig);border-color:var(--sig-dim);background:var(--sig-soft)}
/* A row of label/value pairs under a page title. The row is a group on core's
   flex layout, so only the rule above it and the type need naming here. */
.is-style-specs{
  font-size:.85rem;
  color:var(--fg-dim);
  border-top:1px solid var(--line);
  padding-top:.8rem;
  margin-top:.8rem
}
.is-style-specs > p{margin:0;font-size:inherit}
.is-style-specs :is(b,strong){color:var(--ink);font-weight:600}

/* ---------- buttons ----------
   A plain Button block is the green one; its look, radius included, comes
   from theme.json (styles.elements.button). The light one is core's Outline
   style. Core wraps the padded element in a div, so the visible control is
   the descendant. */
.wp-block-button.is-style-outline > .wp-block-button__link:not(.has-background){
  display:inline-flex;
  align-items:center;
  gap:.55rem;
  font-size:.95rem;
  font-weight:500;
  border:1px solid var(--line-2);
  padding:.8rem 1.4rem;
  color:var(--ink);
  background:var(--paper-2);
  text-decoration:none;
  transition:.16s
}
.wp-block-button.is-style-outline > .wp-block-button__link:not(.has-background):hover{border-color:var(--sig);color:var(--sig);background:var(--paper-2)}
.btn__arrow{transition:transform .16s}
.wp-block-button__link:hover .btn__arrow{transform:translateX(3px)}

/* ---------- cards ----------
   Borderless: a picture, a small label and a heading sitting straight on the
   page. The whole card is the link, done the accessible way — the heading
   holds a real <a> whose ::after covers the card, so assistive technology gets
   one meaningful link instead of a wrapper that swallows image and prose.
   It is the Card style on a Group: an Image, an Overline label, a linked
   heading and a line of text, optionally with the text in a Group of its own. */
.is-style-card{position:relative;display:flex;flex-direction:column;gap:.65rem;background:none;border:0;border-radius:0;padding:0;transition:none}
.is-style-card :is(h2,h3){font-size:clamp(1.15rem,1.7vw,1.5rem);line-height:1.2;margin:0}
.is-style-card :is(h2,h3) a{color:var(--ink);text-decoration:none}
.is-style-card :is(h2,h3) a::after{content:"";position:absolute;inset:0;z-index:1}
.is-style-card:is(:hover,:focus-within) :is(h2,h3) a{
  text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:5px}
/* body text only: a styled paragraph (the Overline label) keeps its own size */
.is-style-card p:not([class*="is-style-"]){margin:0;color:var(--fg-dim);font-size:.98rem}
.is-style-card p.is-style-overline{margin:0}
.is-style-card > .wp-block-image{margin:0 0 .35rem;border-radius:var(--r-media);overflow:hidden;aspect-ratio:8/5;border:0}
.is-style-card > .wp-block-image img{width:100%;height:100%;object-fit:cover;border-radius:inherit;
  /* Rests enlarged and settles back on hover, so the picture appears to zoom
     out while staying inside its frame. Scaling past 1 would need
     overflow:visible, and the image would cover its caption and the next card. */
  transform:scale(1.06);transition:transform .6s cubic-bezier(.2,.7,.2,1)}
.is-style-card:is(:hover,:focus-within) > .wp-block-image img{transform:scale(1)}
.is-style-card > .wp-block-group{padding:0;display:flex;flex-direction:column;gap:.65rem;flex:1}
/* the green arrow link that closes a card or a section */
.more-link{font-size:.92rem;font-weight:500;color:var(--sig);text-decoration:none}
.more-link:hover{color:var(--sig-deep)}

/* ---------- panels ----------
   Each cell carries its own outline, so the hairline grid holds at any count. */
.is-style-panels{border-radius:var(--r);overflow:hidden}
/* Panels: each item on a raised panel, divided by hairlines. The hairline is
   the 1px gap, so the style sets it rather than asking for it in Spacing. */
.wp-block-group.is-style-panels{gap:1px}
.is-style-panels > *{background:var(--paper-2);padding:clamp(1.2rem,2vw,1.9rem);outline:1px solid var(--line)}

/* ---------- figures ----------
   A picture or video is framed when it has a caption, or the author picks
   Framed; Plain turns it off. `fig` frames an uncaptioned Video block, which
   has no Framed style of its own. One :is() list so the frame is defined once. */
figure{margin:0}
:is(.fig,figure.wp-block-image:has(figcaption),figure.wp-block-video:has(figcaption),.wp-block-image.is-style-framed):not(.is-style-plain){
  border:1px solid var(--line);
  border-radius:var(--r-media);
  background:var(--paper-2);
  overflow:hidden;
  --cap-rule:1px solid var(--line);
  --cap-bg:transparent;
  --cap-pad:.7rem .9rem
}
.fig :is(img,video),
:is(figure.wp-block-image:has(figcaption),figure.wp-block-video:has(figcaption),.wp-block-image.is-style-framed):not(.is-style-plain) :is(img,video){width:100%}
/* One definition of what a caption looks like. The gallery arm is spelled out
   in full because core's own gallery rules are printed after this file and
   outrank a plain class; the id inside :not() matches the weight core gives
   them, the same trick core uses on its own selectors. */
.caption,
.wp-block-image figcaption,
.wp-block-video figcaption,
.wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) figcaption{
  margin:0;
  line-height:1.55;
  display:flex;
  flex-wrap:wrap;
  gap:.2rem 1.1rem;
  padding:var(--cap-pad,0);
  border-top:var(--cap-rule,0);
  background:var(--cap-bg,transparent);
  font-family:var(--body);
  font-size:.85rem;
  color:var(--fg-dim)
}
.caption b,.wp-block-image figcaption b,.wp-block-video figcaption b{color:var(--ink);font-weight:600}
/* Core lays a gallery caption over the picture: absolutely positioned, centred,
   on a dark gradient, free to grow and with its own scrollbar. Undo that much;
   the rule above supplies the look. Without the flex reset a one-line caption
   stretches to fill the height left over, leaving a band of empty panel. */
.wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) figcaption{
  position:static;
  flex:0 1 auto;
  max-height:none;
  overflow:visible;
  text-align:start;
  text-shadow:none;
  will-change:auto
}
.wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image)::before{content:none}

/* ---------- image styles ----------
   Image > Styles in the editor. Square resets the radius tokens rather than
   the property, so it reaches every rule that reads them. */
.is-style-square{--r:0;--r-media:0;border-radius:0}
.is-style-square img{border-radius:0}
.is-style-invert img,img.is-style-invert{filter:invert(1) contrast(1.1)}
.figure-grid{align-items:start}
.figure-grid figure{border:1px solid var(--line);border-radius:var(--r);background:var(--paper-2);overflow:hidden}
/* Shape comes from the editor: Image > Dimensions > Aspect ratio, Scale. */
.figure-grid img{width:100%}
/* ---------- hover-reveal figures ---------- */

.reveal{position:relative;border:1px solid var(--line);border-radius:var(--r-media);overflow:hidden}
.reveal img{width:100%}
.reveal img+img{position:absolute;inset:0;height:100%;object-fit:cover;opacity:0;transition:opacity .35s}
.reveal:hover img+img,.reveal:focus-within img+img,.reveal[data-on] img+img{opacity:1}
.reveal__hint{
  position:absolute;
  top:.7rem;
  left:.7rem;
  font-size:.78rem;
  background:rgba(255,255,255,.92);
  border-radius:999px;
  padding:.22rem .7rem;
  color:var(--sig);
  box-shadow:0 1px 4px rgba(27,30,26,.15)
}

/* ---------- page heading ---------- */
/* the breadcrumb: Overline links stay grey rather than taking the body-link green */
.is-style-overline:not(h1,h2,h3,h4,h5,h6) a{color:var(--fg-dim);text-decoration:none}
.is-style-overline:not(h1,h2,h3,h4,h5,h6) a:hover{color:var(--sig);text-decoration:underline}
.is-style-ruler{display:block;height:0;margin-top:clamp(1.5rem,3vw,2.5rem);border:0;border-top:2px solid var(--ink);box-shadow:0 3px 0 -1px var(--line);opacity:1;width:auto}

/* ---------- case filter bar ---------- */
.filterbar{display:flex;flex-wrap:wrap;gap:.5rem;margin:0 0 2.5rem}
.filterbar button{
  font-size:.92rem;
  background:var(--paper-2);
  border:1px solid var(--line);
  color:var(--fg-dim);
  padding:.5rem 1.1rem;
  cursor:pointer;
  transition:.15s;
  font-family:var(--body);
  border-radius:999px
}
.filterbar button:hover{border-color:var(--line-2);color:var(--ink)}
.filterbar button[aria-pressed="true"]{background:var(--sig);border-color:var(--sig);color:var(--paper-2)}
/* any author display rule (e.g. the Card style's display:flex) outranks the
   browser's [hidden] styling, so filtering needs this to actually hide anything */
[hidden]{display:none!important}

/* ---------- data tables ---------- */
.tablewrap{overflow-x:auto;border:1px solid var(--line);margin:1.5rem 0;background:var(--paper-2);border-radius:var(--r)}
/* Picking Data table is enough: the style brings its own frame. Older pages
   wrap the table in `tablewrap`, which already draws one, so it steps aside. */
.wp-block-table.is-style-datatable{overflow-x:auto;border:1px solid var(--line);background:var(--paper-2);border-radius:var(--r)}
.tablewrap > .wp-block-table.is-style-datatable{border:0;background:none;border-radius:0}
.is-style-datatable table{width:100%;border-collapse:collapse;font-size:.9rem}
/* The cells do not wrap, so a table with many columns is wider than a phone;
   core's own figure scrolls it, leaving the table its full-width layout.
   Core also draws a full 1px box around every cell — this keeps only the
   hairline under each row, and needs the extra class to outweigh it. */
.wp-block-table.is-style-datatable th,.wp-block-table.is-style-datatable td{text-align:left;padding:.7rem .9rem;border:0;border-bottom:1px solid var(--line);vertical-align:top;line-height:1.5}
.wp-block-table.is-style-datatable thead,.wp-block-table.is-style-datatable tfoot{border:0}
.wp-block-table.is-style-datatable thead th{
  position:sticky;
  top:0;
  font-family:var(--body);
  font-size:.74rem;
  font-weight:600;
  letter-spacing:.1em;
  text-transform:uppercase;
  border-bottom:1px solid var(--line);
  background:var(--paper-3);
  color:var(--ink)
}
.is-style-datatable tbody tr:hover{background:var(--paper-3)}
/* On a phone, wrapping makes columns so narrow the table grows several screens
   tall and still overflows. Keep rows on one line and let the figure scroll. */
@media(max-width:600px){
  .wp-block-table.is-style-datatable th,.wp-block-table.is-style-datatable td{white-space:nowrap}
}
.is-style-datatable img{max-height:84px;width:auto;border:1px solid var(--line);border-radius:2px}
/* An image column sizes to its image rather than to the space left over. */
.wp-block-table td img,.wp-block-table th img{max-width:none}
.is-style-datatable a{color:var(--sig);text-decoration:underline;text-underline-offset:2px}
/* Citations use the Code block; a terminal session with its command picked out
   uses Preformatted, which keeps inline formatting. */

/* ---------- code and citations ---------- */
.wp-block-code,.wp-block-preformatted{
  font-family:var(--mono);
  font-size:.78rem;
  line-height:1.65;
  border:1px solid var(--line);
  padding:1.1rem 1.2rem;
  overflow-x:auto;
  color:var(--prose);
  margin:1.2rem 0;
  border-radius:var(--r);
  background:var(--paper-3)
}
.wp-block-preformatted :is(b,strong){color:var(--sig);font-weight:600}
/* the inline-code treatment below would otherwise box the block's own <code> */
.wp-block-code code{background:none;border:0;padding:0;font-size:inherit;font-family:inherit}
code{font-family:var(--mono);font-size:.86em;background:var(--paper-3);border:1px solid var(--line);border-radius:2px;padding:.1em .35em}

/* ---------- stats ---------- */
/* Each cell carries its own outline, so the hairline grid holds at any count.
   auto-fit rather than core's auto-fill: three cells then spread across the row
   instead of sitting narrow beside empty tracks.

   A cell is a group whose first line is the figure and whose remaining lines
   are its label, so an author fills one in without reaching for a class. The
   unit beside a figure is a <span> inside that first line. */
.is-style-stats{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  border-radius:var(--r);
  gap:1px;
  overflow:hidden
}
.is-style-stats > .wp-block-group{background:var(--paper-2);padding:clamp(1.1rem,1.8vw,1.6rem);outline:1px solid var(--line)}
.is-style-stats > .wp-block-group > p:first-child{font-family:var(--display);font-weight:600;font-size:clamp(1.45rem,2.2vw,2rem);line-height:1;color:var(--sig);margin:0}
.is-style-stats > .wp-block-group > p:first-child span{font-size:.6em;color:var(--fg-dim)}
.is-style-stats > .wp-block-group > p:not(:first-child){font-size:.86rem;color:var(--fg-dim);margin:.5rem 0 0;line-height:1.4}

/* ---------- people ----------
   The Person style on a Group: a portrait Image, then a Group holding the
   contact icons, the name, the role line straight after it, and a short bio. */
.is-style-person{background:var(--paper-2);border-radius:var(--r-media);border:var(--rule);overflow:hidden}
.is-style-person img{width:100%;aspect-ratio:3/4;object-fit:cover;filter:none;border-radius:var(--r-media) var(--r-media) 0 0}
.is-style-person > .wp-block-group{padding:1rem 1.1rem 1.3rem}
.is-style-person > .wp-block-image{margin:0}
.is-style-person :is(h2,h3,h4){font-size:1.05rem;line-height:1.2}
.is-style-person :is(h2,h3,h4) + p{font-size:.8rem;color:var(--sig-dim);font-weight:500;margin:.4rem 0 .6rem}
.is-style-person p:not(:is(h2,h3,h4) + p){font-size:.9rem;color:var(--fg-dim);margin:0;line-height:1.5}

/* ---------- client logo wall ---------- */
/* Each cell carries its own outline, so the logo grid holds at any count. */
.logos{border-radius:var(--r);overflow:hidden}
.logos > *{outline:1px solid var(--line);background:var(--paper-2);display:grid;place-items:center;padding:1.7rem 1rem;min-height:110px;margin:0}
/* each logo carries its own width, set on the Image block, so that a 10:1
   wordmark and a 1.5:1 roundel take up about the same area */
/* Every logo is shown in quiet grey, and darker on hover. Black artwork lands
   on the wall's grey; light artwork takes the Invert style to flip it dark. */
.logos img{max-width:100%;max-height:48px;filter:grayscale(1) opacity(.35);transition:.2s}
.logos > *:hover img{filter:grayscale(1) opacity(.55)}
.logos .is-style-invert img{filter:invert(1) opacity(.55)}
.logos > .is-style-invert:hover img{filter:invert(1) opacity(.85)}

/* ---------- pull quotes ---------- */
.quote{border-left:3px solid var(--sig);padding:.2rem 0 .2rem 1.3rem;margin:0}
.quote p{font-size:clamp(1.1rem,1.6vw,1.4rem);line-height:1.45;color:var(--ink);font-family:var(--display);font-style:italic}
.quote cite{font-size:.85rem;color:var(--fg-dim);font-style:normal}

/* ---------- download list ---------- */
.downloads{border:1px solid var(--line);border-radius:var(--r);background:var(--paper-2);overflow:hidden}
.downloads > *{
  position:relative;
  display:flex;
  justify-content:space-between;
  align-items:center;
  gap:1rem;
  padding:.85rem 1.1rem;
  border-bottom:1px solid var(--line);
  font-size:.95rem
}
.downloads > *:last-child{border-bottom:0}
.downloads p{margin:0}
.downloads a{color:inherit;text-decoration:none}
/* a row holding a link is clickable across its whole width */
.downloads a::after{content:"";position:absolute;inset:0}
.downloads > *:has(a):hover{background:var(--sig-soft)}
.downloads > *:has(a):hover a{color:var(--sig)}
/* the size or country, second in the row */
.downloads > * > :last-child:not(:first-child){color:var(--fg-dim);font-size:.82rem}

/* ---------- call to action band ---------- */
.cta{border-top:1px solid var(--line);padding-block:clamp(1.5rem,3vw,2.5rem);background:var(--sig-soft);border-radius:0}
@media(max-width:800px){.cta__in{grid-template-columns:1fr}}

/* ---------- footer ---------- */
.footer{color:var(--on-deep);padding-block:clamp(2.5rem,5vw,3.5rem) 2rem;border:0;background:var(--deep)}
.footer .brand,.footer h4,.footer a,.footer p,.footer .addr{color:var(--on-deep)}
.footer .is-style-dim{color:var(--on-deep-dim)}
.footer h4{
  font-family:var(--body);
  font-size:.72rem;
  font-weight:600;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--on-deep-dim);
  margin-bottom:.9rem
}
.footer ul{list-style:none;margin:0;padding:0}
.footer li{margin:.35rem 0}
.footer a{font-size:.95rem;color:var(--on-deep);text-decoration:none}
.footer a:hover{color:var(--paper-2);text-decoration:underline}
.footer__bar{
  margin-top:2.6rem;
  padding-top:1.2rem;
  border-top:1px solid color-mix(in srgb,var(--on-deep) 25%,transparent);
  display:flex;
  flex-wrap:wrap;
  justify-content:space-between;
  gap:.8rem;
  font-size:.82rem;
  color:var(--on-deep-dim)
}
.addr{font-style:normal;font-size:.95rem;line-height:1.9}

/* ---------- motion and scripting preferences ---------- */
/* The reveal is an enhancement, so it only arms itself where a script can undo
   it. Without this the initial opacity:0 is permanent when JavaScript is off or
   fails to load, and the content is simply invisible. */
@media (scripting: enabled) {
  .anim{opacity:0;transform:translateY(12px)}
  .anim.in{opacity:1;transform:none;transition:opacity .6s ease,transform .6s cubic-bezier(.2,.7,.2,1)}
}
@media(prefers-reduced-motion:reduce){
  *{animation:none!important;transition:none!important}
  .anim{opacity:1;transform:none}
  html{scroll-behavior:auto}
}

/* ---------- project logos in a case ---------- */
.logo{height:44px;width:auto;margin:1.2rem 0;opacity:.85}
figure.logo{height:auto}
figure.logo img{height:44px;width:auto}

/* ---------- numbered process steps ---------- */
/* Each cell carries its own outline, so the step grid holds at any count. */
/* auto-fit rather than core's auto-fill, so three steps spread across the row
   instead of leaving a fourth track empty. Two classes to outweigh the layout
   rule core prints for the block after this file. */
.wp-block-group.steps{grid-template-columns:repeat(auto-fit,minmax(16rem,1fr))}
.steps{border-radius:var(--r);overflow:hidden}
.steps > *{outline:1px solid var(--line);background:var(--paper-2);padding:clamp(1.2rem,2vw,1.9rem)}
.steps .n{font-family:var(--display);font-size:2rem;line-height:1;color:var(--sig);display:block;margin-bottom:.5rem}

/* evidence column on a case page: a stack with breathing room, or .figure-grid when
   there are enough figures to read as a grid */
.media-stack{display:flex;flex-direction:column;gap:1.1rem}

/* ---------- icons ----------
   Icons come from core's Social Icons block (Logos Only style): core maintains
   the block, the accessibility and ~50 brand marks; the theme adds only the
   services core lacks, in blocks/social-extras. Nothing here overrides core's
   own colours — that would be the fragile part across updates.
   Gap is the exception: the block has no blockGap of its own, so it falls
   back to the theme's generic flex gap (1.5rem), wide enough that a row of
   five icons wraps onto two lines in a portrait card. */
.wp-block-social-links.is-style-logos-only{gap:.5rem}
.wp-block-social-links.is-style-logos-only li.wp-social-link{color:var(--fg-dim)}
.wp-block-social-links.is-style-logos-only li.wp-social-link:hover{color:var(--sig)}
.footer .wp-block-social-links.is-style-logos-only li.wp-social-link{color:var(--on-deep)}

.wp-block-social-links.is-style-logos-only .wp-social-link:hover{color:var(--sig);transform:none}


/* ---------- type details ---------- */
p.has-drop-cap:not(:focus)::first-letter{float:left;font-family:var(--display);font-weight:600;font-size:3.2em;line-height:.8;margin:.05em .12em 0 0;color:var(--sig)}

/* ============================================================
   Core block markup.
   Rules below target the markup the block editor emits —
   core wrappers, the navigation block, buttons, the site
   title — rather than this theme's own class names.
   ============================================================ */

/* Grid containers declare WordPress' flow layout, so core spaces their children
   with a top margin meant for a vertical stack. Cancel it: they space themselves.
   The :is() list is doubled to reach two classes of specificity, which is what
   core's own gap rule carries. Every argument must stay class-only — an element
   or id in there changes the weight of the whole list. */
:is(.is-style-stats,.hero__grid,.is-style-card,.filterbar):is(.is-style-stats,.hero__grid,.is-style-card,.filterbar) > * { margin-block-start: 0; }
:is(.is-style-card > *,.is-style-panels > *,.is-style-stats > *,.is-style-person > *,.cta__in):is(.is-style-card > *,.is-style-panels > *,.is-style-stats > *,.is-style-person > *,.cta__in) > * { margin-block-start: 0; }
/* A cell is a small document: its headings need rhythm the reset above removes.
   Doubled so it outweighs that rule; cards and people are left out because
   their flex gap already spaces them. */
.is-style-panels > *:is(.is-style-panels > *) > :is(h2,h3,h4){margin-block:.7rem .6rem}
.is-style-panels > *:is(.is-style-panels > *) > :is(h2,h3,h4):first-child{margin-block-start:0}
.wp-block-group.is-layout-flow > *:first-child { margin-block-start: 0; }
.nav .wp-block-site-title{font-size: 1.2rem;line-height: 1.1;margin: 0;font-family:var(--display);font-weight:600;letter-spacing:-.02em}
.nav .wp-block-site-title a { color: var(--ink);text-decoration: none; }
.nav .wp-block-site-title a:hover { color: var(--sig); }

.nav .wp-block-navigation { gap: 0; }
.nav .wp-block-navigation__container { gap: 0; }
.nav .wp-block-navigation-item__content{
  font-family: var(--body);
  color: var(--fg-dim);
  text-decoration: none;
  font-size:.95rem;
  letter-spacing:.01em;
  border-bottom:0;
  padding:1rem .85rem;
  border-radius:999px
}
.nav .wp-block-navigation-item__content:hover{border-bottom-color: var(--sig);background:var(--sig-soft);color:var(--sig)}
.nav .current-menu-item > .wp-block-navigation-item__content, .nav .current-menu-ancestor > .wp-block-navigation-item__content{border-bottom-color: var(--sig);background:var(--sig-soft);color:var(--sig);border-bottom:0}
.nav .wp-block-navigation__submenu-container{
  background: var(--paper-2);
  min-width: 250px;
  border-radius:var(--r);
  border:var(--rule);
  box-shadow:0 14px 40px rgba(28,27,23,.10);
  padding:.5rem
}
.nav .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
  padding: .5rem .7rem;border: 0;border-radius: 2px;
}
.nav .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover {
  background: var(--sig-soft);color: var(--sig);
}
/* ---------- core's mobile overlay ----------
   Core's overlay rules are four classes deep — the :where() wrappers in them
   add no specificity — so any shorter selector loses to whatever core declares,
   however emphatic. Every rule below names the path from .nav down, which is
   what lets this section state its values plainly. theme.css also loads after
   the block stylesheet, so an equal-specificity tie falls this way as well.

   Core reads --navigation-layout-* to decide direction and alignment, and the
   overlay inherits them from the right-justified bar. Re-pointing those two
   properties here lets core's own rules build the left-aligned stack. */
.nav .wp-block-navigation__responsive-container.is-menu-open {
  --navigation-layout-justification-setting: flex-start;
  --navigation-layout-justify: flex-start;
  background: var(--paper);padding: 1.25rem var(--pad) 3rem;align-items: flex-start;
}
.nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content,
.nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container,
.nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-item { width: 100%; }
.nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__container { flex-direction: column;gap: 0; }

/* The CTA joins the list here: inside the overlay there is no bar for it to
   stand out from, so it reads as one more menu row. The padding gives every
   row the same height, clearing the 44px tap target the chevron occupies. */
.nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-item__content,
.nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-button__link {
  font-family: var(--display);font-size: 1.35rem;font-weight: 600;color: var(--ink);
  padding: .7rem 0;width: 100%;border-bottom: 1px solid var(--line);text-align: left;
  justify-content: flex-start;
  /* the bar's pill shape would curl the row's dividing line up at both ends */
  border-radius: 0;
}
/* A buttons block is not a navigation item, so the stack rules reach it by name. */
.nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-buttons,
.nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-buttons .wp-block-button { width: 100%;margin: 0; }
.nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-buttons .wp-block-button__link {
  background: none;border: 0;border-bottom: 1px solid var(--line);border-radius: 0;
}
.nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-buttons .wp-block-button__link:hover { color: var(--sig); }

/* Core switches to its overlay below 600px; this design needs it from 1080px,
   where the horizontal menu stops fitting beside the logo. */
@media (min-width: 600px) and (max-width: 1080px) {
  .nav .wp-block-navigation__responsive-container-open:not(.always-shown) { display: flex; }
  .nav .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) { display: none; }
  .nav .wp-block-navigation__responsive-container:not(.is-menu-open) .wp-block-navigation__responsive-container-close { display: none; }
}

@media (max-width: 1080px) {
  /* Core hides the chevron in its overlay because it shows every submenu
     already expanded. This design collapses them, so the chevron is the
     control that opens one. */
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__submenu-icon {
    display: flex;align-items: center;justify-content: center;
    width: 44px;height: 44px;margin-left: auto;
    background: none;border: 0;color: var(--fg-dim);cursor: pointer;
  }
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__submenu-icon svg { width: 18px;height: 18px;transition: transform .15s; }
  /* Core points the chevron from its own aria-expanded, which is wrong inside
     the overlay; drive the rotation from our class instead. */
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-submenu__toggle[aria-expanded="true"] > svg,
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation-submenu__toggle[aria-expanded="true"] + .wp-block-navigation__submenu-icon > svg { transform: none; }
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child.ailab-submenu-open > .wp-block-navigation__submenu-icon svg { transform: rotate(180deg); }

  /* Core stacks every item as a column in its overlay, which would put a label
     above its own chevron. Keep the two on one row. */
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child {
    display: flex;flex-direction: row;align-items: center;justify-content: flex-start;
    flex-wrap: wrap;width: 100%;border-bottom: 1px solid var(--line);
  }
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child > .wp-block-navigation-item__content {
    flex: 1 1 auto;width: auto;border-bottom: 0;
  }

  /* Collapsed by default, opened by the class site.js sets. Core's own
     !important already holds the background transparent here. */
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child > .wp-block-navigation__submenu-container { display: none; }
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .has-child.ailab-submenu-open > .wp-block-navigation__submenu-container {
    display: block;position: static;width: 100%;flex-basis: 100%;min-width: 0;
    height: auto;opacity: 1;visibility: visible;overflow: visible;
    border: 0;box-shadow: none;padding: .2rem 0 .6rem;
  }
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__submenu-container > li { width: 100%;display: block; }
  .nav .wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-container-content .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
    font-family: var(--body);font-size: 1rem;font-weight: 400;color: var(--fg-dim);
    justify-content: flex-start;padding: .45rem 0 .45rem 1rem;border-bottom: 0;
  }
}
.nav .wp-block-navigation__responsive-container-close { color: var(--ink); }
.footer .wp-block-site-title{font-size: 1.2rem;margin: 0 0 1rem;font-family:var(--display);font-weight:600}
.footer .wp-block-site-title a { color: var(--on-deep);text-decoration: none; }
.footer .wp-block-navigation__container { flex-direction: column;gap: .35rem;align-items: flex-start; }
.footer .wp-block-navigation-item__content { color: var(--on-deep);font-size: .95rem;padding: 0; }
.footer .wp-block-navigation-item__content:hover { text-decoration: underline; }
.footer .wp-block-columns { gap: 2rem; }
/* Core gives Columns a bottom margin of its own. Blocks here are spaced by the
   layout's block gap, so on top of that it only opens an extra gap under
   every Columns block. */
.wp-block-columns{margin-bottom:0}

/* the mark is a dark-green PNG; flip it light on the deep-green footer */
.footer .wp-block-site-logo img { filter: brightness(0) invert(1);opacity: .8; }
.footer .wp-block-site-logo { margin-bottom: .4rem; }
/* a vertical footer list has no room for dropdown affordances */
.footer .wp-block-navigation__submenu-icon { display: none; }
.footer .wp-block-navigation ul ul { display: none; }

/* ---------- gallery carousel ----------
   A Carousel style on core's Gallery block: one scroll-snapping row rather than
   a grid, for a page with more sample photographs than it has room for. Core
   keeps the block, its captions and its Expand on click, so another theme shows
   an ordinary gallery.

   The row is sized by height alone and each picture keeps its own width, so no
   aspect-ratio or object-fit is imposed. Core's lightbox reads the size a
   thumbnail is displayed at, so cropping here would enlarge to the crop. */
.wp-block-gallery:is(.is-style-carousel,.is-style-carousel-plain){
  flex-wrap:nowrap;
  overflow-x:auto;
  scroll-snap-type:x proximity;
  overscroll-behavior-x:contain;
  padding-bottom:.7rem;
  scrollbar-width:thin;
  scrollbar-color:var(--line-2) transparent
}
/* :is() so both carousel styles share the track; it takes the weight of one
   class, so the count above is unchanged.
   Core sizes each figure to half the row from a selector carrying an id inside
   :not(), and prints it inline after this file. Naming has-nested-images too
   puts these rules one class ahead of it. */
.wp-block-gallery.has-nested-images:is(.is-style-carousel,.is-style-carousel-plain) figure.wp-block-image:not(#individual-image){
  width:auto;
  flex:0 0 auto;
  /* a flex item will not shrink below its content, and the picture's own width
     is the content here, so the track has to be told it may */
  min-width:0;
  scroll-snap-align:start
}
.wp-block-gallery.has-nested-images:is(.is-style-carousel,.is-style-carousel-plain) figure.wp-block-image:not(#individual-image) img{
  height:clamp(150px,22vw,230px);
  width:auto;
  max-width:none;
  border-radius:var(--r-media)
}
/* A captioned picture sits in the figure frame, which rounds and clips its own
   corners; rounding the image as well would round it above the caption too. */
.wp-block-gallery.has-nested-images:is(.is-style-carousel,.is-style-carousel-plain) figure.wp-block-image:not(#individual-image):has(figcaption):not(.is-style-plain) img{
  border-radius:0
}
/* ---------- rows of pictures and videos ----------
   Two styles, on a Gallery (pictures) and on a Group (Image and Video blocks
   mixed), for a few items side by side, each keeping its own shape.

   Each item grows in proportion to its --ratio (width ÷ height), which
   inc/editor.php writes on the figure from the upload's dimensions, so the
   items always share one height.
   - "Row, fill width": that height is whatever makes the row span the column.
   - "Row, same height": the same, but no taller than --row-height. A row that
     fits at that height stays at it and leaves the rest of the line free; one
     that does not shrinks to fit.
   Either way, an item that would drop below --row-min tall goes to the next
   line, and on a phone the items stack. An item with no known size (an
   embedded video, or anything in the editor) is simply set to --row-height.

   The row decides each item's size and position, so it overrides a width,
   height or margin set on an individual image: one of the few places this
   theme uses !important. The gallery selectors carry an id's weight, as the
   carousel's do, because core's own figure sizing does. */
.wp-block-gallery.has-nested-images:is(.is-style-row,.is-style-row-fill),
.wp-block-group:is(.is-style-row,.is-style-row-fill){flex-wrap:wrap;align-items:flex-start}
.wp-block-group:is(.is-style-row,.is-style-row-fill){display:flex;gap:var(--wp--style--unstable-gallery-gap,16px)}
.wp-block-gallery.has-nested-images:is(.is-style-row,.is-style-row-fill) figure.wp-block-image:not(#individual-image),
.wp-block-group:is(.is-style-row,.is-style-row-fill) > *{
  --row-height:clamp(180px,22vw,280px);
  --row-min:120px;
  width:auto;
  flex:0 1 auto;
  min-width:0;
  margin:0!important
}
.wp-block-gallery.has-nested-images:is(.is-style-row,.is-style-row-fill) figure.wp-block-image:not(#individual-image) img,
.wp-block-group:is(.is-style-row,.is-style-row-fill) > :is(.wp-block-image,.wp-block-video) :is(img,video){
  height:var(--row-height)!important;
  width:auto!important;
  max-width:100%;
  object-fit:cover;
  border-radius:var(--r-media)
}
/* known proportions: grow by them, so heights match */
.wp-block-gallery.has-nested-images:is(.is-style-row,.is-style-row-fill) figure.wp-block-image[style*="--ratio"]:not(#individual-image),
.wp-block-group:is(.is-style-row,.is-style-row-fill) > [style*="--ratio"]{
  flex:var(--ratio) 1 0;
  min-width:calc(var(--ratio) * var(--row-min));
  max-width:none
}
.wp-block-gallery.has-nested-images.is-style-row figure.wp-block-image[style*="--ratio"]:not(#individual-image),
.wp-block-group.is-style-row > [style*="--ratio"]{max-width:calc(var(--ratio) * var(--row-height))}
.wp-block-gallery.has-nested-images:is(.is-style-row,.is-style-row-fill) figure.wp-block-image[style*="--ratio"]:not(#individual-image) img,
.wp-block-group:is(.is-style-row,.is-style-row-fill) > [style*="--ratio"] :is(img,video){height:auto!important;width:100%!important}
.wp-block-group:is(.is-style-row,.is-style-row-fill) > .wp-block-video[style*="--ratio"] video{aspect-ratio:var(--ratio)}
/* a captioned item sits in the frame, which rounds its own corners; its
   caption wraps to the item's width instead of widening it */
.wp-block-gallery.has-nested-images:is(.is-style-row,.is-style-row-fill) figure.wp-block-image:not(#individual-image):has(figcaption):not(.is-style-plain) img,
.wp-block-group:is(.is-style-row,.is-style-row-fill) > :has(figcaption):not(.is-style-plain) :is(img,video){border-radius:0}
.wp-block-gallery.has-nested-images:is(.is-style-row,.is-style-row-fill) figure.wp-block-image:not(#individual-image) > figcaption,
.wp-block-group:is(.is-style-row,.is-style-row-fill) > * > figcaption{width:0;min-width:100%}
@media(max-width:600px){
  /* :is(*,[style]) matches every item but carries the weight of the --ratio rules */
  .wp-block-gallery.has-nested-images:is(.is-style-row,.is-style-row-fill) figure.wp-block-image:is(*,[style]):not(#individual-image),
  .wp-block-group:is(.is-style-row,.is-style-row-fill) > :is(*,[style]){flex:1 1 100%;width:100%;min-width:0;max-width:none}
  .wp-block-gallery.has-nested-images:is(.is-style-row,.is-style-row-fill) figure.wp-block-image:is(*,[style]):not(#individual-image) img,
  .wp-block-group:is(.is-style-row,.is-style-row-fill) > :is(*,[style]) :is(img,video){height:auto!important;width:100%!important}
}
/* Core's Enlarge button blurs what is behind it. One is cheap; a row of them
   inside a scrolling track each hold a compositing layer, so the track keeps
   core's translucent chip without the blur. */
.is-style-carousel .wp-lightbox-container button{
  backdrop-filter:none;
  -webkit-backdrop-filter:none
}
/* Core zooms the picture from the thumbnail to the middle of the screen. That
   scale is smooth only while the browser keeps the image on its own compositing
   layer; without the hint it re-rasterises a full-size texture on every frame.
   The overlay is appended to the body, so this cannot be scoped to a gallery. */
.wp-lightbox-overlay.zoom.active .lightbox-image-container,
.wp-lightbox-overlay.zoom.show-closing-animation:not(.active) .lightbox-image-container{
  will-change:transform
}
.wp-lightbox-overlay .lightbox-image-container img{
  backface-visibility:hidden
}

/* ---------- media & misc core blocks ---------- */
.wp-block-image { margin: 0; }
/* An image keeps its own size, up to the width of its column; a small icon
   stays small. Framed and captioned figures, cards and figure grids fill their
   space through their own rules. */
.logos .wp-block-image { margin: 0;border: 0; }
/* An image resized in the editor carries its width inline on the <img>. Core
   ships no rule for the figure, so shrink it to the image — otherwise the
   caption and frame stay full width around a narrow picture. The caption is
   laid out at zero width so its text cannot widen the figure, then filled back
   out to the image width, where it wraps onto as many lines as it needs. */
.wp-block-image.is-resized { width: fit-content; }
.wp-block-image.is-resized > figcaption { width: 0;min-width: 100%; }
.logos .wp-block-image.is-resized { width: auto; }
.wp-block-quote.quote { margin: 0; }
.wp-block-list { margin: 0 0 1.15em; }

/* The header CTA is a buttons block inside the navigation menu, so it follows
   the links into the overlay on small screens instead of needing its own
   responsive treatment. */
.nav .wp-block-buttons { margin: 0;gap: .7rem; }
.nav .wp-block-buttons .wp-block-button__link { padding: .62rem 1.1rem; }
@media (max-width: 860px) {
  .nav .wp-block-buttons .wp-block-button__link { padding: .5rem .8rem;font-size: .85rem; }
}

/* Core pairs sizes="auto" with a 2:1 contain-intrinsic-size, which letterboxes
   a portrait image until it loads. Keep the feature, drop the placeholder. */
img:is([sizes="auto" i],[sizes^="auto," i]){contain-intrinsic-size:auto}

