/* latin-ext */
@font-face {
  font-family: 'Atkinson Hyperlegible Next';
  font-style: italic;
  font-weight: 200 800;
  font-display: swap;
  src: url(/fonts/atkinson-hyperlegible-next-italic-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Atkinson Hyperlegible Next';
  font-style: italic;
  font-weight: 200 800;
  font-display: swap;
  src: url(/fonts/atkinson-hyperlegible-next-italic-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Atkinson Hyperlegible Next';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url(/fonts/atkinson-hyperlegible-next-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C4, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Atkinson Hyperlegible Next';
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
  src: url(/fonts/atkinson-hyperlegible-next-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --bg: #F7F5F0;
  --text: #16150F;
  --muted: #57554D;
  --rule: #DCD8CE;
  --accent: LinkText;
  /* Body text size: rem plus a little viewport, so it grows gently with the screen */
  --text-size: clamp(1.125rem, 1rem + 0.5vw, 1.375rem);
  /* Headline size: grows much faster with the screen than body text */
  --heading-size: clamp(2.125rem, 1rem + 4.4vw, 4rem);
  /* Column width follows the headline size, so it widens with the screen as the headline does,
     and is the same on every element (unlike ch, which follows each element's own size).
     15 × heading size: about 30rem at the smallest, 60rem (960px) from ~1090px wide. */
  --measure: calc(var(--heading-size) * 15);
  --gutter: clamp(1rem, 0.5rem + 2.5vw, 1.75rem);
  --space: clamp(3rem, 2rem + 4vw, 5.5rem);
  --top-h: 3.75rem;
  --bottom-h: 5rem; /* roughly the contact bar's height, for scroll-padding */
  --avatar-sm: 2.5rem;
  --avatar-lg: clamp(5.5rem, 20vw, 9rem);
  /* Space between the top bar and the headline, clear of the large photo hanging below the bar.
     Also how far you scroll before the headline reaches the bar, so the header animations use it too. */
  --head-gap: max(calc(var(--avatar-lg) - 1.75rem), calc(var(--space) * .8));
}
/* Thinner antialiasing helps light-on-dark text (less bleed) but makes dark-on-light text
   faint on macOS, so only use it in dark mode */
@media (prefers-color-scheme: dark) {
  body { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; }
}
@media (prefers-color-scheme: dark) {
  :root {
    --bg: #131311;
    --text: #ECE8DF;
    --muted: #A8A399;
    --rule: #33322D;
  }
}

* { box-sizing: border-box; }
html {
  background: var(--bg);
  color: var(--text);
  /* Stop iOS enlarging text on rotation (pinch-zoom still works) */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
  /* Safari: let an opening quote mark sit in the margin so the letters line up */
  hanging-punctuation: first;
  text-wrap: pretty;
  /* Keep focused/anchored content clear of the sticky bars (WCAG 2.4.11) */
  scroll-padding-top: calc(var(--top-h) + 1rem);
  scroll-padding-bottom: calc(var(--bottom-h) + 1rem);
}
body {
  margin: 0;
  font-family: "Atkinson Hyperlegible Next", system-ui, -apple-system, "Segoe UI", sans-serif;
  font-size: var(--text-size);
  line-height: 1.5;
  letter-spacing: 0.015em;
}
.wrap {
  max-width: var(--measure);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

a { color: LinkText; text-decoration: underline; text-underline-offset: .2em; text-decoration-thickness: max(1px, .06em); }
a:visited { color: VisitedText; }
a[target="_blank"]::after {
  content: "" / "(opens in a new window)";
  display: inline-block;
  width: .9em; height: .9em;
  margin-left: .25em;
  vertical-align: -.1em;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 4h6v6'/%3E%3Cpath d='M20 4 10 14'/%3E%3Cpath d='M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5'/%3E%3C/svg%3E") center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2.25' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14 4h6v6'/%3E%3Cpath d='M20 4 10 14'/%3E%3Cpath d='M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5'/%3E%3C/svg%3E") center / contain no-repeat;
}
a:active { color: ActiveText; }
a:hover { text-decoration-thickness: max(2px, .1em); }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; border-radius: 2px; }

.skip {
  position: absolute; left: -999px; top: 0; z-index: 20;
  background: var(--text); color: var(--bg);
  padding: .5rem 1rem;
}
.skip:focus { left: var(--gutter); top: .5rem; }

/* ---- Sticky top: name + headshot lockup ---- */
.top {
  position: sticky; top: 0; z-index: 10;
  background: var(--bg);
  border-bottom: 1px solid transparent;
}
@supports (animation-timeline: scroll()) {
  /* The line fades in over the last 1rem before the headline reaches the bar. The photo and name
     have finished shrinking by then (below), so the name is already inside the bar. */
  .top { animation: edge linear both; animation-timeline: scroll(); animation-range: calc(var(--head-gap) - 1rem) var(--head-gap); }
  @keyframes edge { to { border-bottom-color: var(--rule); } }
}
.top .wrap {
  min-height: var(--top-h);
  display: flex; align-items: center;
}
/* LinkedIn sits at the right of the header. On very narrow screens it would collide
   with the name as it slides into place, so there it moves to the footer instead. */
.top-link { margin-left: auto; font-size: calc(var(--text-size) * .9); } /* same size as the footer's ABN line */
.foot-linkedin { display: none; }
@media (max-width: 24.75em) { /* below ~396px the larger link would crowd the name */
  .top-link { display: none; }
  .foot-linkedin { display: list-item; }
}
.lockup {
  margin: 0;
  display: inline-flex; align-items: center; gap: .65rem;
  color: var(--text); text-decoration: none;
  font-weight: 700; font-size: 1.365rem; letter-spacing: 0.02em; /* the size it used to start at (1.05rem × 1.3) */
}
.lockup .avatar { width: var(--avatar-sm); height: var(--avatar-sm); }
/* The photo sits in a round frame so it can zoom in on the face as the frame shrinks (below).
   Default (no scroll animation, or reduced motion): the zoomed-in, small-size crop. */
.lockup .avatar { overflow: clip; } /* clip, not hidden: hidden would make it a scroll container and capture the img's scroll() timeline */
.lockup .avatar img {
  display: block; width: 100%; height: 100%;
  background-size: cover; /* for the blurred preview below */
  transform-origin: 48.3% 13.3%; /* top-anchored: whole head with a little room above the hair, less chest; same framing as the favicon */
  transform: scale(var(--avatar-zoom));
  --avatar-zoom: 1.15;
}
.lockup .name { display: inline-block; }
/* Tagline on its own line under the name: smaller, normal weight, dimmed. It sits inside .name,
   so it moves and shrinks with the name on scroll. The space before it in the HTML keeps the two
   apart for screen readers; display: block hides it visually. */
.lockup .name { line-height: 1.15; --name-scale: 1.3; } /* size at the top of the page, relative to the bar */
@media (max-width: 21.25em) { .lockup .name { --name-scale: 1.2; } } /* below ~340px, 1.3 would run into the right gutter */
.lockup .tag { display: block; font-size: .62em; font-weight: 400; letter-spacing: .01em; color: var(--muted); }
.lockup .tag abbr { text-decoration: none; } /* the browser's dotted underline is noise in a small tagline; the title still shows on hover */

/* Large at the top of the page, shrinking into the bar as you scroll.
   Transforms only, so nothing reflows and the page doesn't jump.
   Browsers without scroll-driven animations just show the small lockup. */
@supports (animation-timeline: scroll()) {
  .lockup .avatar, .lockup .name, .top-link {
    animation-timing-function: linear;
    animation-fill-mode: both;
    animation-timeline: scroll();
    /* The photo shrinks 1px for every 1px scrolled, so its bottom edge moves up with the page and
       keeps a steady gap to the headline. This ends before the headline reaches the bar (--head-gap),
       so the name is inside the bar before the line under it appears. */
    animation-range: 0 calc(var(--avatar-lg) - var(--avatar-sm));
  }
  .lockup .avatar { transform-origin: left top; animation-name: avatar-shrink; }
  /* Same scroll range as the shrink: zoomed out when large, zoomed in on the face when small */
  .lockup .avatar img {
    animation: avatar-zoom linear both; animation-timeline: scroll();
    animation-range: 0 calc(var(--avatar-lg) - var(--avatar-sm));
  }
  @keyframes avatar-zoom { from { transform: none; } to { transform: scale(var(--avatar-zoom)); } }
  .lockup .name   { transform-origin: left center; animation-name: name-shrink; }
  .top-link       { animation-name: link-follow; }
  @keyframes avatar-shrink {
    /* tan(atan2(a, b)) = a ÷ b as a plain number, so the scale follows --avatar-lg */
    from { transform: scale(tan(atan2(var(--avatar-lg), var(--avatar-sm)))); }
    to   { transform: none; }
  }
  /* LinkedIn drops by the same amount as the name, so the two stay level */
  @keyframes link-follow {
    from { transform: translateY(calc((var(--avatar-lg) - var(--avatar-sm)) / 2)); }
    to   { transform: none; }
  }
  @keyframes name-shrink {
    /* moves beside the large photo, level with its centre, and starts larger (--name-scale),
       shrinking to its bar size as you scroll */
    from { transform: translate(calc(var(--avatar-lg) - var(--avatar-sm)), calc((var(--avatar-lg) - var(--avatar-sm)) / 2)) scale(var(--name-scale)); }
    to   { transform: none; }
  }
}
@media (prefers-reduced-motion: reduce) {
  .lockup .avatar, .lockup .name, .top-link { animation: none !important; transform: none !important; }
}

/* ---- Round photos ---- */
.avatar {
  border-radius: 50%;
  object-fit: cover;
  display: block;
  flex: none;
}
/* Blurred 16px previews shown behind each photo until it loads (WebP can't load progressively).
   Inline data: images are allowed by the CSP's img-src; inline style attributes aren't. */
img.avatar { background-size: cover; }
img[src="/img/stefano.webp"] { background-image: url("data:image/webp;base64,UklGRl4AAABXRUJQVlA4IFIAAABQAgCdASoQABAAAoBCJZQCdH8AE6yca9MrcQAA/vgZfQmUlh5HBG4AC5iTSyfuqMlVu3QFB8pQzy2WSuR/MTvQo9eSg0y8esHIAh5zsD9MGNgA"); }
img[src="/img/michal-amir.webp"] { background-image: url("data:image/webp;base64,UklGRmoAAABXRUJQVlA4IF4AAADwAQCdASoQABAAAoBCJYwCdAD7vNWN1QAA/vhAE3vttvIxorUP5dO4b8RmkpkViznzXDAcqyITlSG1bcFtBopE1kMkVziCZ9Lp7ibxPPrcVgodFJLM1Fa5LEyb58AA"); }
img[src="/img/veronica-sherman.webp"] { background-image: url("data:image/webp;base64,UklGRlgAAABXRUJQVlA4IEwAAAAwAgCdASoQABAAAoBCJQBOj+AB+rT40X1jQAD++6p3DNOo96lsr2Goo45LGDd6LjpJ/ugudKXPZhnjpFYr57zs8C/lPGaSPRx6qBgA"); }
img[src="/img/dot-green.webp"] { background-image: url("data:image/webp;base64,UklGRlQAAABXRUJQVlA4IEgAAADwAQCdASoQABAAAoBCJYgCdADiY9dpEgAA/cVSN6rp/xsPnNb7ZYubodVAws06giyC4sZIJCst50Ja67wFh8p3dv8nez6IAAA="); }
.float {
  float: right;
  shape-outside: circle(50%);
  margin: .2rem 0 .5rem 1.25rem;
}
blockquote .float { width: var(--avatar-lg); height: var(--avatar-lg); }

/* ---- Headline + lede ---- */
h1 {
  /* Leaves room for the large headshot hanging below the top bar */
  margin: var(--head-gap) 0 0;
  font-size: var(--heading-size);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.01em;
}
h1, h2 { text-wrap: balance; }
h1 span { display: block; }
h1 span + span { margin-top: .42em; }

.lede {
  margin: calc(var(--space) * .55) 0 0;
  font-size: clamp(1.5rem, 1.1rem + 1.8vw, 2.125rem);
  font-weight: 300;
  line-height: 1.3;
  letter-spacing: 0.005em;
  max-width: 30ch;
}

/* ---- About ---- */
.about { margin-top: calc(var(--space) * .7); }
.about p { margin: 0; }
.nowrap { white-space: nowrap; } /* keeps "e-commerce" from splitting at the hyphen */
blockquote::after { content: ""; display: block; clear: both; }

/* ---- Testimonials ---- */
.quotes { margin-top: var(--space); }
h2 {
  margin: 0 0 calc(var(--space) * .5);
  font-size: clamp(1.5rem, 1.1rem + 1.8vw, 2.125rem); /* same as the lede */
  font-weight: 800;
  line-height: 1.2;
  letter-spacing: 0.005em;
}
blockquote { margin: 0; padding: 0; }
blockquote + blockquote { margin-top: calc(var(--space) * 1); }
.quotes { padding-bottom: var(--space); }
blockquote .words { font-weight: 400; }
blockquote .words p { margin: 0 0 .9em; }
/* Every testimonial paragraph opens with “. Safari hangs it with hanging-punctuation (on html);
   elsewhere, pull the first line left by the mark's width (measured in Atkinson Hyperlegible Next
   at weight 400, including letter-spacing) so the letters line up with the lines below. */
@supports not (hanging-punctuation: first) {
  blockquote .words p { text-indent: -0.414em; }
}
/* Key phrases in testimonials: <mark> because the highlighting is mine, not the speaker's emphasis.
   A soft band under the lower half of the text. */
blockquote mark {
  color: inherit;
  font-weight: 650;
  background: linear-gradient(transparent 55%, var(--mark-band) 55%);
  -webkit-box-decoration-break: clone; box-decoration-break: clone;
  padding-inline: .05em;
}
/* A soft yellow band, so highlights don't read as links (which use the link blue).
   Light: 45% yellow into the page colour; dark: 32%, which reads as the same band without glare. */
blockquote mark { --mark-band: color-mix(in srgb, #F2C12E 45%, var(--bg)); }
@media (prefers-color-scheme: dark) { blockquote mark { --mark-band: color-mix(in srgb, #E8B931 32%, var(--bg)); } }
/* Name, role and each link: one line each, all the same gap apart */
blockquote footer { font-size: .85em; color: var(--muted); line-height: 1.45; display: flex; flex-direction: column; gap: .3em; }
blockquote cite { font-style: normal; display: block; color: var(--text); font-weight: 750; font-size: 1.12em; line-height: 1.3; }
.links { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: .3em; }
.links li { text-wrap: balance; } /* even out long organisation names across lines */

/* ---- Page footer ---- */
.site-foot {
  margin-top: var(--space); /* same gap above it as under the testimonials */
  border-top: 1px solid var(--rule);
  padding-block: 1.5rem;
  color: var(--muted);
}
.site-foot ul {
  font-size: .9em;
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-wrap: wrap; justify-content: center; gap: .5rem 1.75rem;
}
abbr[title] { text-decoration: none; }

/* ---- Sticky bottom CTA ---- */
/* A box in the page column, sticky to the bottom of the screen.
   It sits before the footer, so at the end of the page it unsticks
   and the footer scrolls into view below it. */
.cta {
  position: sticky; bottom: 0; z-index: 10;
  color: var(--text);
  line-height: 1.4;
}
.cta {
  /* As wide as its content (the email line), centred; never wider than the screen */
  width: fit-content;
  max-width: 100%;
  margin-inline: auto;
  padding-inline: .5em;
  /* Lifts off the bottom edge gradually: flush on narrow phones (30em and below),
     rising with the screen width to the box's own vertical padding (.5em) at 60em and wider. */
  padding-bottom: clamp(0em, (100vw - 30em) / 60, .5em);
}
.cta .box {
  border-radius: .75em;
  background: color-mix(in srgb, var(--accent) var(--cta-mix, 9%), var(--bg));
  border: max(2px, .1em) solid var(--accent);
  padding: .5em .75em calc(.5em + env(safe-area-inset-bottom));
  display: flex; align-items: center; justify-content: center;
}
/* Stretched link: the email link covers the whole box, so the entire bar is the tap target,
   while the link's accessible name stays just the address. */
.cta .box { position: relative; }
.cta .act a::before { content: ""; position: absolute; inset: 0; }
.cta .box:has(a:hover) { background: color-mix(in srgb, var(--accent) var(--cta-mix-hover, 16%), var(--bg)); }
/* On the dark background 9%/16% barely shows. 18%/28% reads as the same tint; 28% is the
   ceiling that keeps the link (LinkText) at WCAG AA (4.6:1) on the hover background. */
@media (prefers-color-scheme: dark) { .cta .box { --cta-mix: 18%; --cta-mix-hover: 28%; } }
.cta .act a:focus-visible { outline: none; }
.cta .box:has(a:focus-visible) { outline: 3px solid var(--accent); outline-offset: -7px; }
.cta p { font-size: clamp(.875rem, .82rem + .3vw, 1rem); margin: 0; text-align: center; text-wrap: balance; }
.cta .act { display: block; line-height: 1.3; margin-bottom: .3em;
  /* Shrinks with the screen so the address stays on one line where it can (4.9vw; the box sizes to
     its content, so it can't be measured with container units); never above 1.4em, never below 1.05em. */
  font-size: clamp(1.05em, 4.9vw, 1.4em); font-weight: 700; color: var(--text); letter-spacing: 0.005em; }
.cta a { font-weight: 700; overflow-wrap: anywhere; } /* last resort on very narrow screens, so the address never overflows */
/* Each sentence breaks as a unit: one line together, or one line each */
.cta .sentence { display: inline-block; }

@media print { .top, .cta { position: static; } }
