/* The form is the book's (lab.alehhaiko.com, UX-directives-skill/tools/build_site.py): a value the book has is the book's value */
:root{
  --bg:#ffffff;--bg-soft:#f7f6f3;--text:#37352f;--muted:var(--text);--line:#e9e9e7;--link:#1929c4;
  --peach:#fbecdd;--blue:#e7f3f8;--pink:#f9e8ef;--yellow:#fbf3db;--green:#e8f1ec;--gray:#f1f1ef;--quote:#d44c47;
  --sans:"Inter",-apple-system,BlinkMacSystemFont,"SF Pro Text","Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";
  --mono:ui-monospace,"SF Mono",SFMono-Regular,Menlo,Consolas,"Liberation Mono",monospace;
  --spring:ease-out;--soft:ease-out;
  --top:56px;--cover-h:0px;--side:280px;--toc:220px;--measure:760px;--shell:1340px;
  color-scheme:light;
}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){
  --bg:#191919;--bg-soft:#202020;--text:#e6e6e4;--muted:var(--text);--line:#2f2f2f;--link:#7fb8e6;
  --peach:#3a2a1f;--blue:#1c2c37;--pink:#38222c;--yellow:#3a321d;--green:#1f2f27;--gray:#252525;--quote:#e06c66;color-scheme:dark;}}
:root[data-theme="dark"]{
  --bg:#191919;--bg-soft:#202020;--text:#e6e6e4;--muted:var(--text);--line:#2f2f2f;--link:#7fb8e6;
  --peach:#3a2a1f;--blue:#1c2c37;--pink:#38222c;--yellow:#3a321d;--green:#1f2f27;--gray:#252525;--quote:#e06c66;color-scheme:dark;}
@supports (transition-timing-function:linear(0, 1)){:root{
  --spring:linear(0, 0.042, 0.145, 0.282, 0.432, 0.579, 0.712, 0.825, 0.916, 0.985, 1.033, 1.063, 1.079, 1.084, 1.08, 1.072, 1.06, 1.048, 1.035, 1.024, 1.015, 1.007, 1.001, 0.997, 0.995, 0.993, 0.993, 0.993, 0.994, 0.995, 0.996, 0.997, 1);  /* damped spring, ~8% overshoot */
  --soft:linear(0, 0.029, 0.099, 0.189, 0.285, 0.381, 0.471, 0.552, 0.624, 0.687, 0.741, 0.787, 0.825, 0.857, 0.884, 0.906, 0.924, 0.939, 0.951, 0.96, 0.968, 0.975, 0.98, 0.984, 0.987, 0.99, 0.992, 0.994, 0.995, 0.996, 0.997, 0.997, 1);}}  /* critically damped spring, no overshoot */
*{box-sizing:border-box}
/* the page always has its scrollbar, idle when there is nothing to scroll: opening a section does not narrow the column, and the header's rule
   ends at the scrollbar's track, not at an empty strip (scrollbar-gutter: stable keeps the room but leaves it bare: nothing can be drawn there) */
html{overflow-y:scroll}
.preload *{transition:none!important}
[id]{scroll-margin-top:calc(var(--top) + var(--cover-h,0px) + 16px)}
/* line height 1.5, not the book's 1.6: the density is Notion's, whose lines stand 24px apart at this size */
body{margin:0;background:var(--bg);color:var(--text);font:500 16px/1.5 var(--sans);-webkit-font-smoothing:antialiased}
a{color:var(--link);text-decoration:none}
/* every hover look sits in @media (hover:hover): on touch it would stay on the element last tapped */
@media (hover:hover){a:hover{text-decoration:underline}}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
.skip{position:absolute;left:-999px;top:8px;background:var(--text);color:var(--bg);padding:8px 12px;border-radius:6px;z-index:100}.skip:focus{left:8px}
:focus-visible{outline:2px solid var(--link);outline-offset:2px;border-radius:4px}
[tabindex="-1"]:focus{outline:none}

/* top bar */
.top{position:sticky;top:0;z-index:30;height:var(--top);background:var(--bg);border-bottom:1px solid var(--line)}
/* header content sits on the same grid as the page: menu button over the sidebar */
.top-in{height:100%;max-width:var(--shell);margin:0 auto;display:flex;align-items:center;gap:16px;padding:0 20px}
.brand{color:var(--text);font-weight:650;letter-spacing:-.01em;white-space:nowrap}@media (hover:hover){.brand:hover{text-decoration:none}}
.theme-btn,.menu-btn{flex:none;width:36px;height:36px;border:0;background:transparent;color:var(--text);border-radius:8px;cursor:pointer;font-size:16px}
/* the book's search field pushes the theme button to the bar's end; here the button takes itself there */
.theme-btn{margin-left:auto}
.theme-btn span{display:inline-block}
.theme-btn.turn span{animation:bb-turn .6s var(--spring)}
@keyframes bb-turn{from{transform:rotate(-120deg) scale(.5);opacity:0}}
/* --dk: the theme (0 light, 1 dark); --m: what the icon draws (0 sun, 1 moon) */
.theme-btn{--dk:0;--m:var(--dk)}
:root[data-theme="dark"] .theme-btn{--dk:1}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .theme-btn{--dk:1}}
/* hover previews the click: the icon turns into the other theme's; after a click, not until the pointer has left */
@media (hover:hover){.theme-btn:hover:not(.pv-off){--m:calc(1 - var(--dk))}}
/* sun to moon in .5s: rays draw in, the disc grows, the cutting circle arrives, the exact moon takes over; moon to sun in .45s, in reverse */
.th-rays,.th-disc,.th-cut{transform-box:view-box;transform-origin:10px 10px}
.th-rays{opacity:calc(1 - var(--m));transform:scale(calc(1 - .6*var(--m)));transition:transform .25s var(--spring) calc((1 - var(--m))*.2s),opacity .2s var(--soft) calc((1 - var(--m))*.2s)}
.th-disc{vector-effect:non-scaling-stroke;opacity:calc(1 - var(--m));transform:scale(calc(1 + 1.4167*var(--m)));transition:transform .3s var(--soft) calc((1 - var(--m))*.1s),opacity 0s calc(var(--m)*.5s)}
.th-cut{opacity:calc(1 - var(--m));transform:translate(calc((1 - var(--m))*12px),calc((1 - var(--m))*-12px));transition:transform calc(.3s + var(--m)*.1s) var(--soft) calc(var(--m)*.1s),opacity 0s calc(var(--m)*.5s)}
.th-cf{fill:var(--bg);stroke:none}
.th-moon{opacity:var(--m);transition:opacity 0s calc(var(--m)*.5s)}
/* a click swaps the icon at once, under the turn */
.theme-btn.turn .ic-theme *{transition:none}
.theme-btn,.menu-btn{display:grid;place-items:center;padding:0}
.menu-btn svg{width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.theme-btn svg{display:block;width:20px;height:20px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round}
.ic-panel .col{fill:currentColor;stroke:none;transform-box:fill-box;transform-origin:left center;transition:transform .5s var(--spring),opacity .3s var(--soft)}
.ic-burger{display:none}.ic-burger path{transform-box:fill-box;transform-origin:center;transition:transform .5s var(--spring),opacity .2s var(--soft)}
/* shown: filled column; hidden: empty column that slides out on hover as a preview */
.side-hidden .ic-panel .col{transform:scaleX(0);opacity:0}
@media (hover:hover){.side-hidden .menu-btn:hover:not(.pv-off) .ic-panel .col{transform:none;opacity:1}
  :root:not(.side-hidden) .menu-btn:hover:not(.pv-off) .ic-panel .col{transform:scaleX(0);opacity:0}}
/* tooltip of an icon-only control: one element, placed by script under the control (above it with .up) */
.tip{position:fixed;left:0;top:0;z-index:60;width:max-content;max-width:min(320px,calc(100vw - 16px));padding:5px 9px;border:1px solid var(--text);border-radius:6px;background:var(--text);color:#fff;
  font-size:12px;font-weight:500;line-height:1.35;text-align:center;box-shadow:0 12px 32px rgba(0,0,0,.18);opacity:0;visibility:hidden;transform:translateY(-4px) scale(.94);
  transition:opacity .15s var(--soft),transform .15s var(--soft),visibility 0s .15s}
.tip.up{transform:translateY(4px) scale(.94)}
.tip.on{opacity:1;visibility:visible;transform:none;transition:opacity .18s var(--soft),transform .4s var(--spring),visibility 0s}
/* the gap to the control belongs to the tooltip, so the pointer can cross it */
.tip::before{content:"";position:absolute;left:0;right:0;top:-7px;height:7px}.tip.up::before{top:auto;bottom:-7px}
:root[data-theme="dark"] .tip{background:#2f2f2f;color:var(--text);border-color:#474747}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .tip{background:#2f2f2f;color:var(--text);border-color:#474747}}
/* touch: a long press on an icon-only control shows its tooltip, so the browser's own callout and text selection are off on these controls */
@media (hover:none){.menu-btn,.theme-btn,.foot a,.foot-b,.consent-x{-webkit-touch-callout:none;-webkit-user-select:none;user-select:none}}
/* the buttons work by script: without it they are not shown */
html:not(.js) .menu-btn,html:not(.js) .theme-btn{display:none}

/* shell */
.shell{--side-w:var(--side);--toc-w:var(--toc);display:grid;grid-template-columns:var(--side-w) minmax(0,1fr) var(--toc-w);grid-template-rows:1fr auto;max-width:var(--shell);margin:0 auto;overflow-x:clip;transition:grid-template-columns .45s var(--soft)}
.sidebar{grid-column:1;grid-row:1/span 2}
.sidebar{width:var(--side);transition:transform .45s var(--soft),opacity .3s var(--soft),visibility 0s}
/* the panel hidden: the text column is 900px and stands in the middle of the window. Both side columns give up their room (the right one holds nothing here),
   and the column keeps its centring in what is left; the book, whose right column holds "On this page", moves its text to that column's edge instead */
@media (min-width:861px){.side-hidden{--measure:900px}}
@media (min-width:861px){.side-hidden .shell{--side-w:0px;--toc-w:0px}.side-hidden .sidebar{transform:translateX(-100%);opacity:0;visibility:hidden;transition:transform .45s var(--soft),opacity .3s var(--soft),visibility 0s .45s}}
.sidebar{position:sticky;top:calc(var(--top) + var(--cover-h));height:calc(100vh - var(--top) - var(--cover-h));overflow:auto;scrollbar-gutter:stable;padding:36px 12px 40px 20px;font-size:14px;scrollbar-width:thin}
/* beside the page, the menu's first plate starts on the line of the heading's cap top: the page's 24.5px
   and the 10px from the heading's line box to its capitals (40px at 1.15) */
@media (min-width:861px){.sidebar{padding-top:calc(24.5px + 10px)}}
/* the menu: the page list. Every row is the book's "Contents" row */
.nav-pages{list-style:none;margin:0;padding:0}
/* the row is the plate: it takes the tints, and the link inside reaches over the whole of it (::after), so the row is pressed anywhere.
   The mark of a link that leaves the site follows the link, outside it, and takes no clicks: a press on it goes to the row under it */
.nav-pages li{position:relative;display:flex;align-items:center;border-radius:6px;transition:background-color .35s var(--soft)}
.nav-home{padding:6px 8px;color:var(--text);font-weight:600}
.nav-pages li:has(.nav-home.is-cur){background:var(--home-sel)}
.nav-home.is-cur{cursor:default}
a.nav-home::after{content:"";position:absolute;inset:0;border-radius:6px}
@media (hover:hover){a.nav-home:hover{text-decoration:none}.nav-pages li:has(a.nav-home:hover){background:var(--home-hov)}}
/* the focus ring goes round the row */
a.nav-home:focus-visible{outline:none}.nav-pages li:has(a.nav-home:focus-visible){outline:2px solid var(--link);outline-offset:2px}
/* the mark stands 4px after the name: the link before it keeps 4px of its right padding, and the mark starts where the link's box ends */
a.nav-home:has(+.ext){padding-right:4px}.nav-pages .ext{margin-left:0}
/* a finger's target: rows stand 44px apart, the plate as it is; the link takes taps over the 5.5px above and below it */
@media (hover:none){.nav-pages li{margin-block:5.5px}a.nav-home::after{inset:-5.5px 0}}
.main{--pad:clamp(16px,3vw,40px);min-width:0;padding:28px var(--pad) 80px}
.main>*{max-width:var(--measure);margin-left:max(0px,calc((100% - var(--measure)) / 2));margin-right:auto;transition:max-width .45s var(--soft),margin-left .45s var(--soft)}

/* headings */
h1,.lede{font-size:clamp(28px,4.2vw,40px);line-height:1.15;letter-spacing:-.02em;margin:40px 0 18px;font-weight:700}
h2{font-size:22px;line-height:1.3;margin:36px 0 12px;letter-spacing:-.01em;font-weight:650;display:flex;flex-wrap:wrap;align-items:baseline;gap:0 8px}
section>h2{margin-top:36px}
/* a heading inside a section is the text's size: bold alone sets it apart */
h3.fa{font-size:inherit;margin:16px 0 8px;font-weight:650}

/* blocks */
.call{border-radius:12px;padding:16px 20px 16px 20px}
.call.has-em{display:grid;grid-template-columns:auto minmax(0,1fr);column-gap:10px;align-items:start}
.call-em{font-size:24px;line-height:1lh}
.call p{margin:0}
.c-peach{background:var(--peach)}.c-blue{background:var(--blue)}.c-pink{background:var(--pink)}
.c-yellow{background:var(--yellow)}.c-green{background:var(--green)}
.prose h2{margin-top:44px}.prose h2+*{margin-top:0}
.prose ul,.prose ol{padding-left:22px}.prose li+li{margin-top:6px}

/* sections that fold: rows at the text's size, as in Notion: the topic bold, the rest regular, a hairline above the group and under it.
   The row's title is text, so it can be selected; the chevron at the row's start is the button, named by the title, and the row takes the click (app.js).
   The chevron and the motion are the book menu's. Under the pointer the row shows on the chevron's box alone: the row itself takes no fill */
:root{interpolate-size:allow-keywords}
/* rows stand 38px apart (7px above and below a 24px line); the group's padding keeps the first row 26.5px under the rule above and the last 41px over the rule below, cap top to rule */
.folds{margin-top:36px;padding:13px 0 15.5px;border-top:1px solid var(--line);border-bottom:1px solid var(--line);transition:border-color .45s var(--soft)}
/* with a section open the group's lower rule gives way, so one line, the footer's, closes the page; its room stays, nothing moves */
.folds:has(.chev[aria-expanded="true"]){border-bottom-color:transparent}
.fold-r{display:flex;align-items:flex-start;gap:6px;padding:7px 0;cursor:pointer}
.prose h2.fold-h{display:block;flex:1;min-width:0;margin:0;font-size:inherit;line-height:inherit;letter-spacing:0;font-weight:inherit;text-wrap:pretty}  /* a row that wraps does not leave one word on its last line */
/* the chevron's box is one line high, so it stands at the first line of a row that wraps */
.chev{appearance:none;flex:none;width:24px;height:1lh;display:grid;place-items:center;margin:0;padding:0;border:0;border-radius:6px;background:none;font:inherit;color:inherit;cursor:pointer;transition:background-color .35s var(--soft),border-color .35s var(--soft)}
/* the glyph is the text colour, a little lighter at rest */
.chev svg{display:block;width:15.6px;height:15.6px;fill:none;stroke:currentColor;stroke-width:1.5385;stroke-linecap:round;stroke-linejoin:round;opacity:.75;transition:transform .6s var(--spring),opacity .35s var(--soft)}
.chev[aria-expanded="true"] svg{transform:rotate(90deg)}
/* the box follows the section, not the focus: no fill while folded; the menu's selected tint while open, whatever the focus and the pointer do;
   under the pointer, folded or open, the menu item's hover tint. The mark is the text colour, lighter at rest and full under the pointer or the keyboard's focus,
   as the book's menu chevron; the keyboard's focus shows as the ring alone */
.chev[aria-expanded="true"]{background:var(--home-sel)}
@media (hover:hover){
  .fold-r:hover .chev{background:var(--home-hov)}
  .fold-r:hover .chev svg,.chev:focus-visible svg{opacity:1}
}
/* no hover to announce it, so the chevron is drawn as a button, as in the book's menu: a box of 28 by 27.2px, grey when folded,
   the selected tint when open (as the book's current chapter), one step denser when pressed. A row is 44px high at least, and the whole of it takes the tap */
@media (hover:none){
  .fold-r{padding-block:10px}
  .chev{box-sizing:border-box;width:28px;height:calc(12px * 1.6 + 8px);margin:calc((1lh - 12px * 1.6 - 8px) / 2) 0;border:1px solid var(--line);background:var(--line)}
  .chev[aria-expanded="true"]{background:var(--home-sel);border-color:var(--home-live)}
  .fold-r:active .chev{background:var(--home-live);border-color:var(--home-deep)}
  .fold-r:active .chev svg{opacity:1}
}
/* the body starts where the row's text does; 4px of room on the sides, so a focus ring inside is not cut */
.fold-c{block-size:0;overflow:hidden;margin:0 -4px 0 26px;padding:0 4px;transition:block-size .45s var(--soft),content-visibility .45s allow-discrete}
.fold-c:not([hidden]){block-size:auto}
.fold-c>:first-child{margin-top:16px}.fold-c>:last-child{margin-bottom:32px}
@media (hover:none){.fold-c{margin-left:30px}}
/* the row folds by script: without it the sections stand open and the row is a heading */
html:not(.js) .fold-r{cursor:auto}html:not(.js) .chev{display:none}

/* the page's top. The accents are Notion's scale in the book's type: one large heading (the book's h1), a bold line larger than the text,
   then everything at the text's size, where only bold marks what matters */
.hero{padding:0 0 8px}
.hero h1{margin:0 0 11px}
.hero-s{font-size:24px;line-height:1.3;letter-spacing:-.01em;font-weight:650;margin:0 0 16px}
/* the distances are the owner's, measured between cap tops: 34 from the header to the heading, 54 to the bold line; then Notion's: 46, 46 to the avatar, 33.5 from it to the text */
.main:has(>.hero){padding-top:24.5px}
/* the credentials: italic, the text's size; the dots between them are the book's quote red */
.hero-c{font-style:italic;margin:0}
.hero-c .dot{font-style:normal;color:var(--quote);margin:0 .25em}

/* About */
/* the top: the photo and, beside it, where to go from here and who this is. The gap to the text is Notion's 63px.
   Folded, the photo is seen through a round window of --d that shows the person waist-up. The photo is drawn at .39 of the source (1799 by 874), 701.61px wide,
   as Notion's 195px circle drew its 500px square; the window is 190px, the largest whose hover size (4px more on every side) still ends inside the photo,
   which reaches 194.79px below the window's top. So the window shows the source from 591.4 to 1078.6 across (the person's 835 in the middle) and from 374 down,
   and the photo stands 591.4 * .39 = 230.65px to the left and 374 * .39 = 145.86px up.
   Opened, the photo is as wide as the column and stands at its corner, and the text takes the row under it */
.intro{--d:190px;container-type:inline-size;display:grid;grid-template-columns:var(--d) minmax(0,1fr);gap:20px 63px;align-items:start;margin-top:20px;margin-bottom:28px}
.intro-t>:first-child{margin-top:0}.intro-t>:last-child{margin-bottom:0}
/* the list is tight: its lines stand as the text's do */
.intro-k{margin-bottom:0}.intro-t ul{margin-top:0}.intro-t li+li{margin-top:0}
.intro+p{margin-top:0}
/* the list's bullets are drawn, so they can answer the pointer: a 5px dot where the browser's stood; the link pointed at or focused, its dot grows to 1.3.
   With reduced motion neither the dot nor the arrow after the link changes size or place; colours still change */
.intro-t ul{list-style:none}
.intro-t li{position:relative}
.intro-t li::before{content:"";position:absolute;left:-17px;top:calc(.5lh - 2px);width:5px;height:5px;border-radius:50%;background:currentColor;transition:transform .5s var(--spring)}
@media (prefers-reduced-motion:no-preference){
  @media (hover:hover){.intro-t li:has(a:hover)::before{transform:scale(1.3)}}
  .intro-t li:has(a:focus-visible)::before{transform:scale(1.3)}
}
/* a link that leaves the site is followed by the site's one mark (tools/build.py, ICON_EXT): 10px, its line 1.25px, beside the link, not in it,
   so it is neither underlined nor pressed. The link pointed at or focused, the mark grows a fifth and steps 1px up and right, on the spring
   of the book's card arrows; with reduced motion it stays as it is */
.ext{display:inline-block;flex:none;width:10px;height:10px;margin-left:4px;vertical-align:.02em;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;pointer-events:none;transition:transform .5s var(--spring)}
@media (prefers-reduced-motion:no-preference){
  @media (hover:hover){a:hover+.ext{transform:translate(1px,-1px) scale(1.2)}}
  a:focus-visible+.ext{transform:translate(1px,-1px) scale(1.2)}
}
/* .ava-w holds the place in the layout: the circle's square, or the whole photo's box. .ava-m is the photo's final box, the column wide, always:
   the mask (clip-path) is cut in it, a circle of --d at its corner or the whole of it, and the photo inside is drawn at one of its two sizes and places.
   The boxes take the proportions of the file that is drawn (1520 by 738), so the photo fills its box to the pixel; .ava-m's height is set, not left
   to its content, which is larger while the photo stands in the window.
   Clipped away, the photo takes no clicks, so the text under it can be selected and its links pressed */
.ava-w{grid-column:1;grid-row:1;position:relative;z-index:1;width:var(--d);height:var(--d);pointer-events:none}
.intro.is-open .ava-w{grid-column:1/-1;width:100%;height:auto;aspect-ratio:1520/738}
.ava-m{position:absolute;left:0;top:0;width:100cqw;height:calc(100cqw * 738 / 1520);clip-path:inset(0 calc(100% - var(--d)) calc(100% - var(--d)) 0 round calc(var(--d) / 2))}
.intro.is-open .ava-m{clip-path:inset(0 0 0 0 round 12px)}
.ava-m img{display:block;max-width:none;width:701.61px;height:auto;transform:translate(-230.65px,-145.86px)}
.intro.is-open .ava-m img{width:100%;transform:none}
/* the button is the mask's shape laid over the photo: it takes the clicks and carries the focus ring */
.ava{appearance:none;position:absolute;left:0;top:0;width:var(--d);height:var(--d);margin:0;padding:0;border:0;border-radius:calc(var(--d) / 2);background:none;cursor:pointer;pointer-events:auto}
.intro.is-open .ava{width:100cqw;height:calc(100cqw * 738 / 1520);border-radius:12px}
.intro-t{grid-column:2;grid-row:1}
.intro.is-open .intro-t{grid-column:1/-1;grid-row:2}
/* motion belongs to the click alone: the script marks the block .is-moving from a click until the move is over, and only then do the mask, the photo
   and the button have transitions. A change of layout (the menu panel, the window's width) redraws them at once.
   Opening: the mask grows from the circle to the whole box while the photo glides from the window to its place and takes its size. Both move on the soft curve,
   which never overshoots, over .41s: 90% of the way at 190ms, as the book's spring over .8s gave. On one curve the photo's far edges stay ahead of the mask's
   all the way, so the page never shows inside the mask.
   Closing: the same way back over .45s, so the mask closes on the circle and does not pass it.
   The text and what follows glide to their new places by script (app.js) */
.intro.is-moving .ava-m{transition:clip-path .45s var(--soft)}
.intro.is-moving .ava-m img{transition:width .45s var(--soft),transform .45s var(--soft)}
.intro.is-moving .ava{transition:width .45s var(--soft),height .45s var(--soft),border-radius .45s var(--soft)}
.intro.is-moving.is-open .ava-m{transition:clip-path .41s var(--soft)}
.intro.is-moving.is-open .ava-m img{transition:width .41s var(--soft),transform .41s var(--soft)}
.intro.is-moving.is-open .ava{transition:width .41s var(--soft),height .41s var(--soft),border-radius .41s var(--soft)}
/* under the pointer the circle grows 4px on every side, softly (.35s, as the book's hover fills); after a click, not until the pointer has left */
@media (hover:hover) and (prefers-reduced-motion:no-preference){
  .ava-m{transition:clip-path .35s var(--soft)}
  .intro:not(.is-open) .ava-w:has(.ava:hover:not(.pv-off)) .ava-m{clip-path:inset(-4px calc(100% - var(--d) - 4px) calc(100% - var(--d) - 4px) -4px round calc(var(--d) / 2 + 4px))}
}
/* the photo opens by script: without it it is a picture */
html:not(.js) .ava{display:none}
/* logo strip: one SVG, shown through six windows so the row can wrap.
   --x and --w are a logo's left edge and width in the SVG's own units (2820 wide);
   --u is the size of one SVG unit, set so a full row fills the strip */
.logos{container-type:inline-size;display:flex;flex-wrap:nowrap;align-items:center;justify-content:space-between;gap:20px 32px;margin-top:36px;margin-bottom:36px;padding:0;list-style:none}
/* the unit stops growing at .3053px, its size in a 688px column: in a wider column the logos keep their height (32.4px) and the room goes between them */
.logos li{--u:min(calc((100cqw - 160px) / 1730),.3053px);flex:none;overflow:hidden;width:calc(var(--w) * var(--u));height:calc(106 * var(--u))}
.logos img{display:block;max-width:none;width:calc(2820 * var(--u));height:auto;margin:calc(-78 * var(--u)) 0 0 calc(var(--x) * var(--u) * -1)}
/* the logos are drawn for a white ground: on the dark theme they keep it */
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .logos{padding:14px 16px;border-radius:12px;background:#ffffff}}
:root[data-theme="dark"] .logos{padding:14px 16px;border-radius:12px;background:#ffffff}

/* footer */
.foot{grid-column:2;grid-row:2;min-width:0;padding:0 clamp(16px,3vw,40px) 40px;color:var(--ph,#6b6b6b)}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .foot{--ph:#9b9b99}}:root[data-theme="dark"] .foot{--ph:#9b9b99}
.foot-in{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:4px 6px;max-width:var(--measure);margin:0 auto 0 max(0px,calc((100% - var(--measure)) / 2));padding-top:16px;border-top:1px solid var(--line);font-size:11px;line-height:1.5;transition:max-width .45s var(--soft),margin-left .45s var(--soft)}
.foot-g{display:flex;flex-wrap:wrap;align-items:center;gap:4px 6px;min-width:0}  /* a group that stands alone on its line starts at the left edge */
.foot-i{display:inline-flex;align-items:center;gap:6px;white-space:nowrap}
.foot a{color:inherit}
/* a sign before its word, inside the link, as the book's footer has them: 12px, 4px from the word, the line 1.5px with round ends. LinkedIn's is its "in", drawn in that line */
.foot-il{display:inline-flex;align-items:center;gap:4px}
.foot-ic{flex:none;width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:round;transition:stroke .35s var(--soft)}
/* the link pointed at or focused: LinkedIn's sign takes LinkedIn's blue, #0a66c2 on the light page and the lighter #70b5f9 on the dark one */
.foot{--in:#0a66c2}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .foot{--in:#70b5f9}}:root[data-theme="dark"] .foot{--in:#70b5f9}
@media (hover:hover){a.foot-il:hover .foot-ic{stroke:var(--in)}}
a.foot-il:focus-visible .foot-ic{stroke:var(--in)}
/* the consent button stands after LinkedIn and says what holds: "GA off" (no answer yet, or declined) or "GA on" (allowed). It brings the consent banner back.
   A button that reads as the footer's links do, its sign three bars; under the pointer it is underlined as they are. Both words lie in one cell and the one
   that does not hold is hidden, so the button is as wide as the wider, "GA off", in either state and LinkedIn does not move; the hidden word is not read out.
   The dot before it is the book's, between two items of the row. It works by script: without it the item is not shown */
.foot-b{appearance:none;margin:0;padding:0;border:0;background:none;color:inherit;font:inherit;cursor:pointer}
@media (hover:hover){.foot-b:hover{text-decoration:underline}}
/* the sign is the footer's grey while analytics is off and Google Analytics' orange while it is on; pointed at or focused it is orange either way.
   The orange is #f9ab00 at its own hue (OKLCH 76), darkened by the smallest step of lightness (.001) that gives 3:1 against the page, as the book's brick
   is solved: #c88802 on the light page (3.01, 122 steps down, L .674); on the dark page #f9ab00 itself (9.09, no step) */
.foot{--ga:#c88802}
@media (prefers-color-scheme:dark){:root:not([data-theme="light"]) .foot{--ga:#f9ab00}}:root[data-theme="dark"] .foot{--ga:#f9ab00}
.foot-b[data-ga="on"] .foot-ic,.foot-b:focus-visible .foot-ic{stroke:var(--ga)}
@media (hover:hover){.foot-b:hover .foot-ic{stroke:var(--ga)}}
.foot-bl{display:inline-grid}.foot-bl>span{grid-area:1/1}
.foot-b[data-ga="on"] [data-s="off"],.foot-b:not([data-ga="on"]) [data-s="on"]{visibility:hidden}
.foot .bul{flex:none;width:3px;height:3px;border-radius:50%;background:currentColor}
html:not(.js) .foot-js{display:none}

/* the consent banner: a bar at the window's bottom, the header's mirror: the page's ground and a hairline over it, the window wide, and its content
   between the header's own edges: the text starts where the header's name does (the bar's 20px, the menu button's 36px, the 16px after it), the last
   control ends where the theme button does. On a narrow screen, where the header's row starts at the window's 16px, so does the bar's.
   Not a dialog: nothing is dimmed, the page under it works, and the body keeps the bar's height free under the footer (--consent-h, app.js).
   It comes and goes at once, without motion. Shown by script alone: without it nothing is counted and the bar stays hidden.
   Under the menu's scrim (35), so an open drawer dims it with the page. In the page's source it follows the skip link, so the keyboard reaches its buttons before the header's */
.consent{position:fixed;left:0;right:0;bottom:0;z-index:32;background:var(--bg);border-top:1px solid var(--line);font-size:14px}
.consent[hidden]{display:none}
.consent-sh{max-width:var(--shell);margin:0 auto;padding:0 20px}
.consent-pad{min-width:0;padding:12px 0 12px 52px;container-type:inline-size}
.consent-in{position:relative;display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px 24px}
.consent-t{flex:1 1 100%}.consent-t p{margin:0}
/* room of 660px and over holds the text and the buttons in one row, the buttons (and the cross after them) at its end; narrower, the buttons stand under the text.
   The text takes all the room up to the buttons and wraps only when it does not fit */
@container (min-width:660px){.consent-in{flex-wrap:nowrap;justify-content:flex-start}.consent-t{flex:1 1 320px}.consent-in .consent-b{margin-left:auto}}
/* the state has its own line under the description; the words that carry it are bold */
.consent-t .consent-s{margin-top:6px}
.consent-s strong{font-weight:700}
.consent-b{flex:none;display:flex;gap:8px;margin:0}
/* a column too narrow for both buttons in a row (the widest pair is 295.3px: "Analytics allowed", 8px, "Decline analytics"): they stand one under the other, the column wide */
@container (max-width:306px){.consent-b{flex:1 1 100%;flex-direction:column}}
/* both answers are one button, the book's text button ("Clear history"): no fill, a 1px rule, 6px corners, weight 600. The rule is the text's colour,
   so the button's edge is seen on the page; under the pointer it takes the menu item's hover tint */
.consent-btn{appearance:none;margin:0;padding:6px 12px;border:1px solid var(--text);border-radius:6px;background:transparent;color:var(--text);font:inherit;font-weight:600;white-space:nowrap;cursor:pointer;transition:background-color .35s var(--soft)}
@media (hover:hover){.consent-btn:not([aria-disabled="true"]):hover{background:var(--home-hov)}}
/* the answer that holds is a fact, not an offer: the same box without its rule, filled with the menu's selected tint, the text's colour at weight 700; nothing under the pointer */
.consent-btn[aria-disabled="true"]{border-color:transparent;background:var(--home-sel);font-weight:700;cursor:not-allowed}
/* a finger's target: 44px high */
@media (hover:none){.consent-btn{min-height:44px}}
/* brought back from the footer, with an answer given, the bar can be closed without a new one: the book's cross (its search field's), in the column's
   top right corner. Its box is 36px and the drawn cross 16px, so the box stands 10px out of the content's edge and 8px over its top: the cross ends on that
   edge, on the text's first line, and the text beside it keeps clear of the box (--x-in, the box's part inside the column). So it stands while the buttons
   are under the text. A finger's target is 44px, 4px beyond the box on every side */
.consent{--x-in:26px}
.consent-x{position:absolute;z-index:0;top:-8px;right:-10px;width:36px;height:36px;display:grid;place-items:center;margin:0;padding:0;border:0;background:transparent;color:var(--text);cursor:pointer}
.consent-x[hidden]{display:none}
.consent-x svg{display:block;width:16px;height:16px;fill:none;stroke:currentColor;stroke-width:1.875;stroke-linecap:round;stroke-linejoin:round}
.consent-x::before{content:"";position:absolute;z-index:-1;inset:5px;border-radius:6px}
@media (hover:hover){.consent-x:hover::before{background:var(--home-live);box-shadow:inset 0 0 0 1px var(--home-deep)}}
.consent-x:focus-visible{outline:none}.consent-x:focus-visible::before{background:var(--home-live);box-shadow:inset 0 0 0 1px var(--home-deep);outline:2px solid var(--link);outline-offset:2px}
@media (hover:none){.consent{--x-in:30px}.consent-x::after{content:"";position:absolute;inset:-4px}}
.consent.can-close .consent-t{padding-right:var(--x-in)}
/* beside the text the cross is the row's last item: after the buttons, 24px from them (the row's gap), on the middle of their height */
@container (min-width:660px){.consent-x{position:relative;top:auto;right:auto;flex:none}.consent.can-close .consent-t{padding-right:0}}
/* the bar's words can be selected, the buttons' too; a drag that leaves a selection in a button is not a press (app.js) */
.consent,.consent-btn{-webkit-user-select:text;user-select:text}
.consent-x{-webkit-user-select:none;user-select:none}
body{padding-bottom:var(--consent-h,0px)}

/* responsive */
@media (max-width:1180px){.shell{grid-template-columns:var(--side-w) minmax(0,1fr)}}
@media (max-width:860px){
  .shell{grid-template-columns:minmax(0,1fr)}
  .sidebar{position:fixed;left:0;top:var(--top);bottom:0;width:min(86vw,320px);height:auto;background:var(--bg);z-index:40;transform:translateX(-102%);visibility:hidden;overscroll-behavior:contain;transition:transform .2s ease,visibility 0s .2s}
  body.nav-open .sidebar{transform:none;visibility:visible;transition:transform .2s ease,visibility 0s}
  body.nav-open{overflow:hidden}
  .ic-panel{display:none}.ic-burger{display:block}
  body.nav-open .ic-burger .l1{transform:translateY(4px) rotate(45deg)}
  body.nav-open .ic-burger .l2{opacity:0}
  body.nav-open .ic-burger .l3{transform:translateY(-4px) rotate(-45deg)}
  .scrim{position:fixed;inset:var(--top) 0 0 0;background:rgba(0,0,0,.35);z-index:35}
  .top-in{padding:0 16px;gap:10px}
  /* without script nothing can open the menu, so it stands in the page, above the text */
  html:not(.js) .sidebar{position:static;width:auto;transform:none;visibility:visible;padding:16px 16px 0}
  .main{padding:16px 16px 64px}
  .foot{grid-column:1;padding:0 16px 32px}
  .foot a,.foot-b{padding:14px 6px;margin:-14px -6px}  /* touch target: 44px tall, the line keeps its place */
  .foot-in{row-gap:28px}
  .consent-sh{padding:0 16px}.consent-pad{padding:12px 0}
}
/* the menu and theme buttons take taps 4px beyond their 36px boxes, 44x44; the drawn icons, the boxes and the focus rings keep their size */
@media (max-width:520px){.top-in{gap:8px}.menu-btn,.theme-btn{position:relative}.menu-btn::after,.theme-btn::after{content:"";position:absolute;inset:-4px}}
/* the circle stands above the text, and only the mask grows */
@media (max-width:620px){.intro{grid-template-columns:minmax(0,1fr)}.intro-t,.intro.is-open .intro-t{grid-column:1;grid-row:2}}
@media (max-width:520px){
  /* two rows of three: the wider row (Acqueon, Aptrinsic, Impekable) sets the unit */
  .logos{flex-wrap:wrap;justify-content:flex-start;gap:20px 16px}
  .logos li{--u:calc((100cqw - 32px) / 960)}
}
@media (prefers-reduced-motion:reduce){*,*::before,*::after{transition:none!important;animation:none!important;scroll-behavior:auto!important}
  /* the tooltip keeps its fade and loses its move */
  .tip,.tip.up{transform:none;transition:opacity .15s linear,visibility 0s .15s!important}.tip.on{transition:opacity .15s linear,visibility 0s!important}
  /* the theme icon keeps a fade between sun and moon and loses the morph */
  .ic-theme .th-cut{display:none}.ic-theme .th-rays,.ic-theme .th-disc{transform:none}.ic-theme *{transition:opacity .15s linear!important}}
@media print{.fold-c{block-size:auto!important;content-visibility:visible!important}.chev{display:none}.top,.sidebar,.scrim,.consent{display:none!important}body{padding-bottom:0}.shell{display:block}.main{padding:0}}
/* the menu's tints: the book's Contents blue */
:root{--home-sel:#cde4ff;--home-hov:#e5f0fe;--home-live:#b9d9ff;--home-deep:#a8d0ff;--home-line:#5f92cc}@media (prefers-color-scheme:dark){:root:not([data-theme="light"]){--home-sel:#183759;--home-hov:#152a40;--home-live:#16426e;--home-deep:#174a7e;--home-line:#3b6da3}}:root[data-theme="dark"]{--home-sel:#183759;--home-hov:#152a40;--home-live:#16426e;--home-deep:#174a7e;--home-line:#3b6da3}
