/* ==========================================================================
   nicolecadden.com — rebuilt from Squarespace
   Layout system reproduced from measured values (see _source/tokens.json)
   ========================================================================== */

:root{
  /* scaling basis: viewport width, capped at the site max content width */
  --vw: min(100vw, 1800px);
  --content-max: 1800px;
  --gutter: 6vw;                     /* mobile */
  --container: min(var(--content-max), calc(100vw - var(--gutter) * 2));

  --accent:#957F5E;
  --light-accent:#F8F7F5;
  --dark-accent:#45413D;
  --black:#000000;
  --white:#FFFFFF;

  --heading-font:'Playfair Display', Georgia, 'Times New Roman', serif;
  --body-font:'Mulish', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;

  --text:var(--black);
  --bg:var(--white);
  --header-h:76px;
  --hero-size:calc(21.72 * var(--vw) / 100);
  --hero-track:0.02em;
  --card-pad:9%;
  --banner-ratio:3 / 1;
  --banner-focus:35%;
  --gap-tight:14px;
  --gap-step:48px;
  --fe-row:0.0215;   /* Squarespace's grid row minimum, as a fraction of the content width */
}
@media (min-width:768px){ :root{
  --header-h:106px;
  --hero-size:calc(22.78 * var(--vw) / 100);
} }
@media (min-width:768px){ :root{ --gutter:3vw; } }

*,*::before,*::after{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; }
/* --section-pad lives on body, not :root, so it resolves against the floor
   set on the same element. The viewport-proportional value alone collapses on
   a narrow window, so it takes whichever is larger.
   <body> also carries page-landing / page-case, if the two ever want to
   diverge again. */
body{
  --section-pad-min:56px;
  --section-pad:max(var(--section-pad-min), calc(1.8 * var(--vw) / 100));
}

body{
  /* a short page (contact) would otherwise end mid-screen and leave the
     footer floating with blank space beneath it. The header is fixed and the
     skip link absolute, so main and the footer are the only flex children. */
  min-height:100svh; display:flex; flex-direction:column;
  margin:0; background:var(--bg); color:var(--text);
  font-family:var(--body-font); font-weight:var(--body-weight,350);
  font-size:calc(16.747px + 0.0539vw); line-height:1.6;
  -webkit-font-smoothing:antialiased; -moz-osx-font-smoothing:grayscale;
}
/* main absorbs the slack on a short page, and hands it to the last section so
   that section's background reaches the footer instead of leaving a band of
   body colour. No .section carries a margin, so nothing collapses here. */
main{ flex:1 0 auto; display:flex; flex-direction:column; }
main > .section:last-child{ flex:1 0 auto; }
img,video{ max-width:100%; height:auto; display:block; }
a{ color:inherit; }
/* A link in body copy, marked with the accent underline the site already
   uses for emphasis. Links inherit their colour, so without this one a
   link is indistinguishable from the text around it. */
/* :not(.btn) because a button can sit inside a text block, and this rule
   would otherwise outrank .btn's own text-decoration:none */
.block-text a:not(.btn){
  text-decoration:underline;
  text-decoration-color:var(--accent);
  /* Capped, not purely proportional: at display sizes a .08em rule becomes
     a 4px bar, far heavier than the accent underline used on body copy. */
  text-decoration-thickness:clamp(1px, .07em, 2px);
  text-underline-offset:clamp(2px, .16em, 5px);
}
.block-text a:not(.btn):hover{ text-decoration-color:currentColor; }

/* ---------- type scale (exact reproduction) ---------- */
h1,h2,h3,h4,h5,h6{ font-family:var(--heading-font); font-weight:400; margin:0 0 .5em; }
p{ margin:0 0 1em; }
p:last-child,h1:last-child,h2:last-child,h3:last-child,h4:last-child{ margin-bottom:0; }

/* Squarespace's text-highlight: a rule under a phrase, 0.1em thick in the
   accent colour with a square cap, drawn behind the text -- so it runs
   through descenders instead of skipping them. */
.hl{
  text-decoration-line:underline;
  text-decoration-color:var(--accent);
  text-decoration-thickness:.1em;
  text-underline-offset:.14em;
  text-decoration-skip-ink:none;
}

h1{ font-size:calc(42.201px + 0.8082vw); line-height:1.232; }
h2{ font-size:calc(33.468px + 0.5388vw); line-height:1.288; }
h3{ font-size:calc(27.354px + 0.3502vw); line-height:1.3272; }
h4{ font-size:calc(19.494px + 0.1078vw); line-height:1.3776; }
h5{ font-size:calc(18.5px + 0.08vw); line-height:1.4; }
h6{ font-size:calc(17.7px + 0.05vw); line-height:1.4; }

@media (min-width:768px){
  body{ font-size:calc(15px + 0.24 * var(--vw) / 100); }
  h1{ font-size:calc(16px + 3.6  * var(--vw) / 100); }
  h2{ font-size:calc(16px + 2.4  * var(--vw) / 100); }
  h3{ font-size:calc(16px + 1.56 * var(--vw) / 100); }
  h4{ font-size:calc(16px + 0.48 * var(--vw) / 100); }
  h5{ font-size:calc(16px + 0.36 * var(--vw) / 100); }
  h6{ font-size:calc(16px + 0.28 * var(--vw) / 100); }
}

/* ---------- section themes ---------- */
/* A block can carry its own background; Squarespace picks the colour from the
   section theme rather than storing it on the block. */

.section{ position:relative; background:var(--bg); color:var(--text); }
.section.white,.section.white-bold{ --bg:var(--white);        --text:var(--black); --block-bg:var(--light-accent); --block-fg:var(--black); }
.section.light,.section.light-bold{ --bg:var(--light-accent); --text:var(--black); --block-bg:var(--white);        --block-fg:var(--black); }
.section.dark,.section.dark-bold  { --bg:var(--dark-accent);  --text:var(--white); --block-bg:var(--white);        --block-fg:var(--black); }
.section.black,.section.black-bold{ --bg:var(--black);        --text:var(--white); --block-bg:var(--white);        --block-fg:var(--black); }
.section.accent                   { --bg:var(--accent);       --text:var(--white); --block-bg:var(--white);        --block-fg:var(--black); }
.section.bright,.section.bright-inverse{ --bg:var(--accent);  --text:var(--white); --block-bg:var(--accent);       --block-fg:var(--white); }

/* ---------- classic Layout Engine sections ---------- */
.section__wrapper{
  padding-left:var(--gutter); padding-right:var(--gutter);
  padding-top:var(--section-pad); padding-bottom:var(--section-pad);
  max-width:calc(var(--content-max) + var(--gutter) * 2); margin:0 auto;
}
main > .section:first-child > .section__wrapper{ padding-top:calc(var(--header-h) + var(--section-pad)); }
.section__content{ width:100%; margin:0 auto; }
.w-narrow .section__content{ width:50%; }
.w-medium .section__content{ width:75%; }
.w-wide   .section__content{ width:100%; }
@media (max-width:767px){ .section__content{ width:100% !important; } }

/* Half the gutter on each side of every column, with the row pulling its own
   edges back, so columns of the same span end up the same width. Padding
   on one side only made the second column narrower than the first. */
.row{ display:flex; flex-wrap:wrap; align-items:flex-start;
      margin-inline:calc(var(--gap-tight,14px) / -2); }
.col{ min-width:0; padding-inline:calc(var(--gap-tight,14px) / 2); }
@media (max-width:767px){ .col{ width:100% !important; } }

/* block rhythm inside classic columns.
   `* + *` (not `.block + .block`) so a nested row following a block also gets
   spacing -- that pairing was falling through to zero. */
.col > * + *{ margin-top:var(--gap-tight,14px); }
/* a panel behind a group of rows, sitting inside the section's own measure
   rather than bleeding to the page edges */
.col.u-persona{ align-self:stretch; display:flex; flex-direction:column; }
.col.u-persona > .block-text{ margin-bottom:var(--gap-tight,14px); }
.col.u-persona > .block-image{ margin-top:auto; }
.col.u-panel{
  background:var(--block-bg, var(--light-accent));
  color:var(--block-fg, var(--text));
  /* less inset at the sides than a card: the panel wraps a two-column layout
     and every pixel it takes comes off the label and the copy */
  padding:var(--card-pad, 9%) 6%;
  /* the row above already carries the tight step, so top this up to a full one */
  margin-top:calc(var(--gap-step,48px) - var(--gap-tight,14px));
}
.row + .row{ margin-top:var(--gap-step,36px); }
/* A section's intro copy followed by its rows is a boundary between chunks,
   so it takes the step, like the rows beneath it. Without this it inherits
   the tight gap meant for a heading and its own paragraph. */
.col > .block-text + .row{ margin-top:var(--gap-step,48px); }
/* Blocks sitting straight in a section, with no row structure around them,
   had nothing setting the space between them and so ran flush together. */
.section__content > .block + .block{ margin-top:var(--gap-step,48px); }


/* Adjacent sections on the same background: the two paddings stack into one
   uninterrupted gap with no colour boundary to justify it, so halve the
   second one. Sections on different backgrounds keep both halves -- each sits
   inside its own colour band.
   Fluid sections carry padding on the section; classic ones on the inner
   wrapper, so the two cases are targeted separately. */
.section.white + .section--fluid.white:not(.section--bleed),
.section.light + .section--fluid.light:not(.section--bleed),
.section.dark + .section--fluid.dark:not(.section--bleed),
.section.black + .section--fluid.black:not(.section--bleed),
.section.accent + .section--fluid.accent:not(.section--bleed),
.section.bright + .section--fluid.bright:not(.section--bleed){ padding-top:calc(var(--section-pad) * .5); }

.section.white + .section:not(.section--fluid):not(.section--bleed).white > .section__wrapper,
.section.light + .section:not(.section--fluid):not(.section--bleed).light > .section__wrapper,
.section.dark + .section:not(.section--fluid):not(.section--bleed).dark > .section__wrapper,
.section.black + .section:not(.section--fluid):not(.section--bleed).black > .section__wrapper,
.section.accent + .section:not(.section--fluid):not(.section--bleed).accent > .section__wrapper,
.section.bright + .section:not(.section--fluid):not(.section--bleed).bright > .section__wrapper{ padding-top:calc(var(--section-pad) * .5); }

/* ---------- Fluid Engine sections ---------- */
.section--fluid{ padding-top:var(--section-pad); padding-bottom:var(--section-pad); }
/* The hero carries more air than a mid-page section. Overriding --section-pad
   on the section itself means its padding *and* the cover image's bleed, which
   is derived from the same value, both follow. */
main > .section:first-child{
  --section-pad:max(72px, calc(3.2 * var(--vw) / 100));
}
/* clearing the fixed header belongs on whichever element carries the padding:
   the section for fluid layouts, the inner wrapper for the rest. Applying it
   to both doubled it on the classic and centred sections. */
main > .section--fluid:first-child{
  padding-top:calc(var(--header-h) + var(--section-pad));
}

.fe{
  display:grid; position:relative;
  --colgap:0px; --rowgap:0px;
  --grid-gutter:calc(var(--gutter) - var(--colgap));
  --cell:calc((var(--content-max) - (var(--colgap) * 7)) / 8);
  grid-template-columns:minmax(var(--grid-gutter),1fr) repeat(8,minmax(0,var(--cell))) minmax(var(--grid-gutter),1fr);
  grid-template-rows:repeat(var(--rows-m,1),minmax(24px,auto));
  row-gap:var(--rowgap); column-gap:var(--colgap);
  overflow-x:clip;
}
/* Rows sized to their content instead of a fixed minimum. Opt-in per section:
   Squarespace's reserved row heights can leave a block far taller than its
   text, which shows up as dead space under the last paragraph.
   Desktop only -- some mobile grids use overlapping row spans that need the
   fixed minimum to stay legible. */

@media (min-width:768px){
  /* not pure auto: a fully collapsed spacer row erases the gaps that separate
     subsections within a section. A small floor keeps that rhythm while still
     letting over-allocated rows shrink to their content. */
  .fe.fe--auto{ grid-template-rows:repeat(var(--rows-d,1),minmax(var(--fe-row-auto,22px),auto)); }
  .fe{
    --cell:calc((var(--content-max) - (var(--colgap) * 23)) / 24);
    grid-template-columns:minmax(var(--grid-gutter),1fr) repeat(24,minmax(0,var(--cell))) minmax(var(--grid-gutter),1fr);
    grid-template-rows:repeat(var(--rows-d,1),minmax(calc(var(--container) * var(--fe-row)),auto));
  }
}
/* A section marked desktopFrom keeps the eight-column stacked grid past the
   usual breakpoint. Its blocks hold their mobile areas over the same range,
   because the generator raises their media query to match. */
@media (min-width:768px) and (max-width:1023.98px){
  .fe--late{
    --cell:calc((var(--content-max) - (var(--colgap) * 7)) / 8);
    grid-template-columns:minmax(var(--grid-gutter),1fr) repeat(8,minmax(0,var(--cell))) minmax(var(--grid-gutter),1fr);
    grid-template-rows:repeat(var(--rows-m,1),minmax(24px,auto));
  }
  .fe--late.fe--auto{ grid-template-rows:repeat(var(--rows-m,1),minmax(24px,auto)); }
  /* the stacked areas are sized for a phone, where 70% of the measure is a
     sensible portrait. On a tablet it is enormous, so cap it at the width
     the photo reaches in the two-column layout. */
  .fe--late .block-image img{ max-width:380px; }
  /* Stacked, the copy inherits the full measure and runs to 104 characters
     a line. Capped to about 70, which is what the two-column layout gives
     it at full width. u-fill headings are sized to their container and
     must keep it. */
  .fe--late .block-text:not(.u-fill){ max-width:640px; margin-inline:auto; }
}
.fe .block{ display:flex; flex-direction:column; min-width:0; }
/* blocks that touch (a heading and its body) get the tight step; larger gaps
   come from the explicit row tracks the generator emits per section. The grid
   pulls back the last row's trailing margin so it doesn't add to the section
   padding below. */
.fe .block{ margin-bottom:var(--gap-tight,14px); }
/* --fe-pull is how much trailing block margin the grid cancels. It has to
   match what the blocks in that section actually carry, and the cover image's
   bleed is measured from the same number, so both are derived from it. */
.section--fluid{ --fe-pull:var(--gap-tight,14px); }
main > .section:first-child{ --fe-pull:var(--gap-step,48px); }
.fe{ margin-bottom:calc(-1 * var(--fe-pull, var(--gap-tight,14px))); }

.section-bg{ position:absolute; inset:0; overflow:hidden; z-index:0; }
.section-bg img{ width:100%; height:100%; object-fit:cover; }
.section--fluid > .fe{ position:relative; z-index:1; }

/* ---------- hero (home) ---------- */
.section--hero{
  min-height:calc(100svh - var(--header-h));
  margin-top:var(--header-h);
  display:flex; align-items:center; justify-content:center;
  padding:calc(2 * var(--vw)/100) var(--gutter);
}
main > .section--hero:first-child{ padding-top:calc(2 * var(--vw)/100); }
.hero{ width:100%; max-width:var(--content-max); text-align:center; }
.hero__name h1,.hero__name h2,.hero__name h3,.hero__name p{
  font-family:var(--heading-font); font-weight:400;
  font-size:var(--hero-size); line-height:.95;
  letter-spacing:var(--hero-track); white-space:nowrap;
  text-indent:calc(var(--hero-track) / 2); margin:0;
}
.hero__surname{ margin-top:.35em; }
.hero__surname p,.hero__surname strong{
  font-family:var(--body-font); font-weight:600;
  font-size:calc(2.6px + 2.6vw); letter-spacing:.08em;
  margin:0; text-indent:.04em;   /* half the trailing letter-space, so it optically centres */
}
.hero__role{ margin-top:1.6em; }
.hero__role p{
  font-family:var(--body-font); font-size:calc(11px + .48vw);
  letter-spacing:.16em; text-indent:.16em; margin:0;
}
@media (max-width:767px){
  .hero__role{ margin-top:1.2em; }
}

/* ---------- centred section ---------- */
.section--centered .section__content{ text-align:center; }
.section--centered .block + .block{ margin-top:.55em; }
.section--centered .section__content > *{ margin-left:auto; margin-right:auto; }

/* ---------- card grid (work) ---------- */
.section--cards .section__wrapper{ padding-top:0; }
.cards{
  display:grid; gap:calc(2.4 * var(--vw)/100) calc(2 * var(--vw)/100);
  grid-template-columns:1fr;
}
@media (min-width:600px){ .cards{ grid-template-columns:repeat(2,1fr); } }
/* One or two columns: the row gap is all that separates a case study from
   the next one's heading, and the proportional value falls to 9px on a
   phone. Below the three-column layout it takes the step instead. */
@media (max-width:999px){ .cards{ row-gap:var(--gap-step,48px); } }
@media (min-width:1000px){ .cards{ grid-template-columns:repeat(3,1fr); } }
.card{ display:flex; flex-direction:column; min-width:0; }
.card__text + .card__text{ margin-top:.5em; }
.card__text h1,.card__text h2,.card__text h3,.card__text h4{ margin:0 0 .35em; }
.card__text p{ margin:0 0 .9em; }
.card__text a{ text-decoration:underline; text-underline-offset:.14em; }
.card__text a:hover{ color:var(--accent); }
.card__media{
  display:block; margin-top:auto; overflow:hidden;
  aspect-ratio:1/1; background:rgba(0,0,0,.04);
}
.card__media img{
  width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .45s ease;
}
.card__media:hover img{ transform:scale(1.03); }
@media (prefers-reduced-motion:reduce){ .card__media img{ transition:none; } }

.sep{ margin:0 .38em; }   /* adds to the surrounding spaces, which stay as wrap points */

/* square-cropped thumbnail */
.u-square{ align-self:start; }
.u-square img,.u-square a{ display:block; width:100%; }
.u-square img{ aspect-ratio:1/1; height:auto; object-fit:cover; }

/* image fills its cell instead of sitting letterboxed inside it */
.u-cover{ min-height:0; align-self:stretch; }
/* bleed past the section's own vertical padding so it reaches the edges.
   The first section keeps its header offset -- the fixed header is opaque,
   so sliding under it would just hide part of the image. */
.section--fluid .u-cover{
  margin-top:calc(-1 * var(--section-pad));
  /* the grid already pulls back --fe-pull of trailing margin, so the bleed
     only needs to cover what remains of the section padding */
  margin-bottom:calc(var(--fe-pull, var(--gap-tight,14px)) - var(--section-pad));
}
/* Taken out of flow so the photo contributes no intrinsic height. It spans
   every row of the hero grid, so otherwise its aspect ratio inflates the rows
   that hold no text: at 1800px that put 132px into the two empty rows above
   the role/year meta. Absolute means the rows size to the copy and the photo
   fills whatever that comes to. */
.u-cover{ position:relative; }
.u-cover img{ position:absolute; inset:0; width:100%; height:100%;
              object-fit:cover; min-height:0;
              object-position:var(--cover-pos, center); }

/* Hero interior. The fitted title and subtitle run on a 1.06 line-height, so
   their glyphs sit far closer than the block boxes suggest -- the standard
   14px step leaves them about 3px apart optically. These get their own steps. */
main > .section:first-child .u-fill{ margin-bottom:var(--gap-step,36px); }
main > .section:first-child .block-text:not(.u-fill){ margin-bottom:var(--gap-step,36px); }

/* ---------- per-block utilities ---------- */
/* Heading scaled to fill its own container.
   --fill-k is the font-size in cqw that makes this exact string span ~97% of
   the container, measured per string; because it is container-relative it
   holds at every viewport width. Re-measure if the wording changes. */
.u-fill{ container-type:inline-size; }
.u-fill h1,.u-fill h2,.u-fill h3,.u-fill h4,.u-fill p{
  font-size:calc(var(--fill-k, 9) * 1cqw); line-height:1.06;
  white-space:nowrap; letter-spacing:0; margin:0;
}
/* bio: heading and signature both flush left with the body copy */
.u-fill,.u-bio,.u-center,.u-left{ align-items:stretch; justify-content:flex-start; }
.u-left{ align-items:flex-start; }
.u-bio h3,.u-bio h4,.u-bio p{ text-align:left; }
.u-bio h4{ margin-top:1.4em; }
.block > .block-button{ margin-top:1.8em; align-items:flex-start; }
.u-center,.u-center h1,.u-center h2,.u-center h3,.u-center p{ text-align:center; }

/* a block with its own background: 6% inset, matching Squarespace */
.block.has-bg{
  background:var(--block-bg, var(--light-accent));
  color:var(--block-fg, var(--text));
  padding:var(--card-pad, 9%);
}

/* Squarespace "shape" block: a filled rectangle sitting behind other blocks
   as a panel. Its own z-index (1) is below the text it backs (2 and up), and
   it fills its grid area exactly, so the tight-gap margin is dropped. */
.fe .block.block-shape{
  background:var(--block-bg, var(--light-accent));
  box-shadow:1px 2px 3px rgba(0,0,0,.07);   /* source: 2px at 145deg, 3px blur */
  /* needs .fe .block's specificity to drop the tight-gap margin, or the panel
     stops 14px short of the grid area it is meant to fill */
  margin-bottom:0;
}
.block.has-bg h1,.block.has-bg h2,.block.has-bg h3,
.block.has-bg h4,.block.has-bg h5,.block.has-bg h6,
.block.has-bg p{ color:inherit; }

/* ---------- list sections (Squarespace 'auto layout') ---------- */
.list-section__title{ text-align:center; margin:0 0 calc(var(--gap-step,36px) * 1.4); }
.list-items{
  list-style:none; margin:0; padding:0;
  display:grid; gap:calc(var(--gap-step,36px) * 1.2) calc(2 * var(--vw)/100);
  grid-template-columns:1fr;
}
@media (min-width:600px){ .list-items{ grid-template-columns:repeat(2,1fr); } }
@media (min-width:900px){ .list-items{ grid-template-columns:repeat(3,1fr); } }
/* Squarespace had cards enabled on these items; the colour comes from the
   section theme, same as any other block that carries its own background. */
.list-item{
  min-width:0;
  background:var(--block-bg, var(--light-accent));
  color:var(--block-fg, var(--text));
  padding:var(--card-pad, 9%);
}
.list-item h3{
  font-size:calc(16px + 0.62 * var(--vw) / 100); line-height:1.3; margin:0 0 .5em;
}
.list-item p{ margin:0 0 .8em; }
.list-item p:last-child{ margin-bottom:0; }
/* the photographs sit smaller than the card, centred, as they did originally */
.list-item__media{
  margin:0 auto 1.3em; width:72%; overflow:hidden;
  aspect-ratio:1/1; background:rgba(0,0,0,.05);
}
.list-item__media img{ width:100%; height:100%; object-fit:cover; display:block; }
/* the photo cards read better a touch narrower than the full column width */
.list-section--media .list-items{
  gap:calc(var(--gap-step,36px) * 1.4) calc(2.4 * var(--vw)/100);
  /* a fixed cap rather than a percentage: it brings the cards in on a wide
     screen without squeezing the line length on a narrow one */
  max-width:1220px; margin-inline:auto;
}

/* a fluid section that is nothing but a full-width image: no padding, or the
   section colour shows as a strip above and below it */
.section--bleed{ padding-top:0; padding-bottom:0; }
.section--bleed .fe{ margin-bottom:0; }
.section--bleed .block{ margin-bottom:0; }

/* ---------- full-bleed banner section ---------- */
.section--banner{ padding:0; line-height:0; }
/* full width, but capped height: the source photos range from 2.53:1 to
   1.89:1, so left alone the taller one dominates the page. Crop to a shared
   band rather than scaling, biased up so faces stay in frame. */
.section--banner img{
  width:100%; height:auto; display:block;
  aspect-ratio:var(--banner-ratio, 3 / 1);
  object-fit:cover; object-position:center var(--banner-focus, 35%);
}

/* ---------- blocks ---------- */
.block-image img{ width:100%; }
.block-image a{ display:block; }

/* ---------- roles: a short employment history ---------- */
.roles{ list-style:none; margin:0; padding:0; }
.roles__title{ margin-bottom:calc(var(--gap-step,48px) * .8); }
.role{
  display:flex; flex-wrap:wrap; align-items:baseline;
  justify-content:space-between; gap:var(--gap-tight,14px);
  padding-block:calc(var(--gap-step,48px) * .55);
  border-bottom:1px solid color-mix(in srgb, var(--text) 16%, transparent);
}
.role:first-of-type{ padding-top:0; }
.role__what,.role__org{
  font-family:var(--heading-font);
  font-size:calc(16px + 0.62 * var(--vw) / 100); line-height:1.25;
}
.role__where{ text-align:right; }
.role__org{ display:block; }
.role__when{ display:block; font-size:.8em; opacity:.68; margin-top:.25em; }
.roles__more{
  margin:calc(var(--gap-step,48px) * .5) 0 0;
  text-align:right; font-size:.85em;
}
.roles__more a{
  text-decoration:underline;
  text-decoration-color:var(--accent);
  text-decoration-thickness:clamp(1px, .07em, 2px);
  text-underline-offset:clamp(2px, .16em, 5px);
}
/* On a phone the two halves stack, so the dates read under the role rather
   than pushed to an edge that is no longer there. */
@media (max-width:599px){
  .role{ flex-direction:column; gap:.15em; }
  .role__where{ text-align:left; }
  .roles__more{ text-align:left; }
}

/* ---------- device mock-up ---------- */
/* A full-page screenshot taller than the screen scrolls inside it. The
   travel is derived from the image itself rather than measured per shot:
   translating by its own height less the screen's height lands the foot of
   the page on the foot of the screen, whatever the screenshot's proportions.
   min() keeps a short image still. */
.device{ width:100%; }
.device__lid{
  background:#1c1c1e;
  border-radius:12px 12px 4px 4px;
  padding:10px 10px 14px;
  box-shadow:0 14px 34px rgba(0,0,0,.16);
}
.device__screen{
  container-type:size;
  aspect-ratio:var(--screen-ratio, 16 / 10);
  overflow:hidden;
  border-radius:3px;
  background:var(--white);
}
.device__screen img{
  width:100%;
  animation:device-scroll 24s ease-in-out infinite alternate;
}
/* a framed video plays itself, so it does not scroll; with --screen-ratio
   set to the recording's own proportions it fills the screen exactly */
.device__screen video{ width:100%; height:100%; object-fit:cover; }
@keyframes device-scroll{
  0%, 6%    { transform:translateY(0); }
  94%, 100% { transform:translateY(min(0px, calc(-100% + 100cqh))); }
}
/* the foot, a little wider than the lid, notched for the lip. The overhang
   is a fixed lip rather than a percentage: on a phone the lid already fills
   the measure, so a proportional overhang runs off the side of the screen. */
.device--laptop{ --device-lip:clamp(6px, 1.2vw, 16px); }
.device__base{
  width:calc(100% + 2 * var(--device-lip));
  margin-inline:calc(-1 * var(--device-lip));
  height:10px;
  background:linear-gradient(#d9d9de, #a9a9b1);
  border-radius:0 0 9px 9px;
  position:relative;
}
.device__base::after{
  content:""; position:absolute; top:0; left:50%; translate:-50% 0;
  width:13%; height:4px; border-radius:0 0 5px 5px; background:#8d8d95;
}
@media (prefers-reduced-motion:reduce){
  .device__screen img{ animation:none; }
}
.block-line hr{ border:0; border-top:1px solid currentColor; opacity:.25; margin:0; width:100%; }
/* Pull quote. Indented off the copy's left edge with a hairline in the accent
   so it reads as a quotation rather than another paragraph, and given air
   above and below so it separates from the copy it sits between. */
.block-quote{ margin-block:var(--gap-step,48px); }
.block-quote blockquote{
  margin:0; font-family:var(--heading-font); font-size:1.15em; line-height:1.45;
  padding-left:1.15em; border-left:2px solid var(--accent);
}
/* attribution: body face, smaller, upright, and kept close to its quote */
.block-quote .quote-attr{
  font-family:var(--body-font); font-size:.66em; font-style:normal;
  opacity:.72; margin:.5em 0 0;
}
.block-embed{ width:100%; }
.block-embed iframe{ width:100%; border:0; aspect-ratio:16/9; display:block; }
.block-video video{ width:100%; display:block; }

.btn{
  display:inline-block; text-decoration:none; cursor:pointer;
  font-family:var(--body-font); font-weight:500; letter-spacing:.02em;
  padding:.85em 2em; border:1px solid currentColor; background:transparent; color:inherit;
  transition:background .2s ease,color .2s ease;
}
.btn:hover,.btn:focus-visible{ background:var(--text); color:var(--bg); }

/* ---------- header ---------- */
.site-header{
  position:fixed; top:0; left:0; right:0; z-index:100;
  background:var(--light-accent);
  min-height:var(--header-h);
  padding:1.1rem var(--gutter);
  display:flex; align-items:center; justify-content:space-between; gap:1.5rem;
}
.site-header__logo img{ height:clamp(34px,3.2vw,52px); width:auto; }
.site-nav{ display:flex; align-items:center; gap:clamp(1rem,2.2vw,2.5rem); }
.site-nav a{ text-decoration:none; font-size:calc(15px + .2vw); }
.site-nav a:hover{ color:var(--accent); }
/* Every case study opens on a black hero, so the light header sat over it as
   a pale band. On those pages it goes black and meets the hero seamlessly.
   The logo is black artwork on a transparent ground, so it has to be forced
   to white or it disappears into the bar. */
.page-case .site-header,
.page-case .site-header.open{ background:var(--black); color:var(--white); }
.page-case .site-header__logo img{ filter:brightness(0) invert(1); }

.site-social{ display:flex; align-items:center; gap:1rem; }
.site-social a{ display:inline-flex; color:inherit; }
.site-social svg{ width:20px; height:20px; fill:currentColor; display:block; }
.nav-toggle{ display:none; background:none; border:0; padding:.4rem; cursor:pointer; color:inherit; }
.nav-toggle svg{ width:26px; height:26px; fill:none; stroke:currentColor; stroke-width:1.6; }

@media (max-width:767px){
  .site-header{ flex-wrap:wrap; }
  .nav-toggle{ display:inline-flex; }
  .site-header__group{ display:none; width:100%; flex-direction:column; align-items:flex-start; gap:1.25rem; padding:1.25rem 0 .5rem; }
  .site-header.open .site-header__group{ display:flex; }
  .site-nav{ flex-direction:column; align-items:flex-start; gap:1rem; }

  /* The open menu takes the whole screen rather than a panel hanging off the
     top, and each destination gets a full-width row to tap. Inline links gave
     a 29px target, under the 44px a finger needs. */
  .site-header.open{
    position:fixed; inset:0; height:100dvh;
    background:var(--light-accent);
    align-content:flex-start; row-gap:0; overflow-y:auto;
  }
  /* The header stays a wrapping row, so the logo and the toggle keep sharing
     the top line and the toggle does not move when the menu opens. The group
     wraps beneath them and takes the rest of the screen: the allowance covers
     that top line and the header's own padding, and the row gap is dropped so
     it cannot push the whole thing past the fold. */
  .site-header.open .site-header__group{
    min-height:calc(100dvh - 6rem);
    justify-content:center; gap:2rem; padding:0;
  }
  .site-header.open .site-nav{ width:100%; gap:0; }
  .site-header.open .site-nav a{
    display:block; width:100%; padding:1.15rem 0;
    font-size:1.5rem; font-family:var(--heading-font);
    border-bottom:1px solid color-mix(in srgb, currentColor 16%, transparent);
  }
  .site-header.open .site-nav a:first-child{
    border-top:1px solid color-mix(in srgb, currentColor 16%, transparent);
  }
  .site-header.open .site-social{ justify-content:center; gap:1.75rem; }
  .site-header.open .site-social a{ padding:.6rem; }
  /* the logo and the close button stay on their own row at the top */
  .site-header.open .site-header__logo,
  .site-header.open .nav-toggle{ flex:0 0 auto; }
  .site-nav a{ font-size:1.15rem; }
}
/* the page behind a full-screen menu should not scroll under it */
body:has(.site-header.open){ overflow:hidden; }
@media (min-width:768px){
  /* the original layout: nav left, logo centred, icons right. Grid placement
     rather than source order, so the mobile markup stays as it is. */
  .site-header{ display:grid; grid-template-columns:1fr auto 1fr; align-items:center; }
  .site-header__group{ display:contents; }
  .site-nav{ grid-area:1/1; justify-self:start; }
  .site-header__logo{ grid-area:1/2; justify-self:center; }
  .site-social{ grid-area:1/3; justify-self:end; }
}

/* ---------- footer ---------- */
.site-footer{
  background:var(--black); color:var(--white);
  padding:calc(3 * var(--vw)/100) var(--gutter);
  display:flex; align-items:center; justify-content:space-between; gap:1rem; flex-wrap:wrap;
  font-size:.92em;
}
.site-footer .site-social svg{ width:18px; height:18px; }

/* ---------- contact form ---------- */
/* the contact page links the address directly; no form to style */
.block-email{ font-size:1.05em; }

/* per-element alignment, as set in the original content */
.ta-center{ text-align:center; }
.ta-right { text-align:right; }

/* ---------- a11y ---------- */
.skip-link{
  position:absolute; left:-9999px; top:0; z-index:200;
  background:var(--black); color:var(--white); padding:.7rem 1.1rem; text-decoration:none;
}
.skip-link:focus{ left:0; }
:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }
.visually-hidden{
  position:absolute!important; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0;
}
@media (prefers-reduced-motion:reduce){
  *{ animation-duration:.01ms!important; transition-duration:.01ms!important; scroll-behavior:auto!important; }
}
