/* page chrome (oct 20 2026, master): scrollbars, the shared edge fade, and the page's top and bottom fades, on
   every page. linked after the menu css by tools/site_menu.py, with page_vN.js (the drawn scrollbars). colors are each page's own --bg / --line, so light
   and dark mode follow the page.

   scrollbars: every one on the site (the page, the menu panel, anything else that scrolls) is a flat
   rectangle in --line, the horizontal rules' color, on a clear track. they show the way each platform
   shows them (master: no forcing them on): classic and always there on the desktop, an overlay only
   while scrolling for the page on Android, where Chrome keeps its own thin bar for the root and these
   styles don't reach it. ::-webkit-scrollbar does the styling in Chromium and Safari; scrollbar-color
   is only for browsers without it (Firefox), because Chrome drops the ::-webkit-scrollbar styles from
   any element that has scrollbar-color set. Firefox draws its own thumb shape. */
::-webkit-scrollbar{width:8px;height:8px}
::-webkit-scrollbar-track,::-webkit-scrollbar-corner{background:transparent}
::-webkit-scrollbar-thumb{background:var(--line);border:0;border-radius:0}
::-webkit-scrollbar-button{display:none;width:0;height:0}
@supports not selector(::-webkit-scrollbar){*{scrollbar-color:var(--line) transparent;scrollbar-width:thin}}

/* the edge fade (master, oct 20 2026): every faded edge on the site, the nav conveyor's left and right and
   the page's top and bottom, uses this one length and this one curve, so they can't drift apart.
   --edge-fade is the length (12px). --edge-ease is the curve: alpha stops for a smoothstep, t²(3−2t),
   sampled every twelfth of the length, from clear at the edge to opaque at --edge-fade. eased, not
   linear (master's pick B of six, oct 20 2026): a straight ramp shows a line where the fade starts; the
   S-curve starts and ends softly, so neither end shows a line, in the same 12px (the header stays crisp
   and the phone nav strip keeps its width). the curve is symmetric, v(1−t) = 1 − v(t), so the same stops
   serve every edge: the conveyor's sides (a clear-at-the-edge mask) and, read from the other end, the page's
   top and bottom bands (opaque at the edge). */
:root{--edge-fade:12px;--edge-ease:rgba(0,0,0,0) calc(var(--edge-fade)*0), rgba(0,0,0,0.02) calc(var(--edge-fade)*0.0833), rgba(0,0,0,0.074) calc(var(--edge-fade)*0.1667), rgba(0,0,0,0.156) calc(var(--edge-fade)*0.25), rgba(0,0,0,0.259) calc(var(--edge-fade)*0.3333), rgba(0,0,0,0.376) calc(var(--edge-fade)*0.4167), rgba(0,0,0,0.5) calc(var(--edge-fade)*0.5), rgba(0,0,0,0.624) calc(var(--edge-fade)*0.5833), rgba(0,0,0,0.741) calc(var(--edge-fade)*0.6667), rgba(0,0,0,0.844) calc(var(--edge-fade)*0.75), rgba(0,0,0,0.926) calc(var(--edge-fade)*0.8333), rgba(0,0,0,0.98) calc(var(--edge-fade)*0.9167), rgba(0,0,0,1) calc(var(--edge-fade)*1)}

/* top and bottom fades: the window scrolls (master, oct 20 2026: back from the page scroller, so the URL bar
   hides on scroll and pull-to-refresh works again), and content under the viewport's top and bottom edges
   fades out like the conveyor's edges: two fixed, click-through bands of the page's own --bg, --edge-fade
   tall, masked by --edge-ease. on our flat backgrounds that's the same pixels as masking the content
   (measured: at most 2/255 apart). the top band is shallower than the header's 18px top padding, so the
   header is crisp at the top of the page; the menu panel (z-index 20) and the drawn scrollbar sit above
   them. scroll-padding lands anchor targets clear of the bands. */
html{scroll-padding-top:var(--edge-fade);scroll-padding-bottom:var(--edge-fade)}
body::before,body::after{content:"";position:fixed;left:0;right:0;height:var(--edge-fade);z-index:10;pointer-events:none;background:var(--bg)}
body::before{top:0;-webkit-mask-image:linear-gradient(to top,var(--edge-ease));mask-image:linear-gradient(to top,var(--edge-ease))}
body::after{bottom:0;-webkit-mask-image:linear-gradient(to bottom,var(--edge-ease));mask-image:linear-gradient(to bottom,var(--edge-ease))}

/* drawn scrollbars (master, oct 20 2026): the page's and the menu panel's scrollbars are ours, drawn by
   page_vN.js, not the browser's: a thin flat --line thumb (4px, no rounded ends) that overlays the content
   (takes no width, so the column never shifts), sits above the edge fades, shows while scrolling and fades
   out after a short idle. it's the same on every platform, Android included, where the browser's own bar
   for the window can't be styled. click-through except the thumb, which drags (mouse, pen, finger). the
   native bars of the window and the panel are hidden, so nothing takes width. other scrollers (wide tables,
   code blocks) keep the styled native bar above. */
html{scrollbar-width:none}html::-webkit-scrollbar{display:none;width:0;height:0}
.menu-panel{scrollbar-width:none}.menu-panel::-webkit-scrollbar{display:none;width:0;height:0}
.ovsb{position:fixed;top:0;right:0;bottom:0;width:4px;z-index:15;pointer-events:none;opacity:0;transition:opacity .3s ease}
.ovsb.on,.ovsb.drag{opacity:1;transition-duration:.1s}
.ovsb.panel{position:absolute;bottom:auto;z-index:21;width:3px}.ovsb.panel .thumb{width:3px} /* the menu panel's bar is 3px, the window's 4px (master, oct 20 2026) */
.ovsb .thumb{position:absolute;top:0;left:0;width:4px;background:var(--line);border-radius:0;will-change:transform;pointer-events:none;touch-action:none}
.ovsb.on .thumb,.ovsb.drag .thumb{pointer-events:auto;cursor:default}
/* an easier target than 4px: the thumb's hit area reaches 10px further in, invisibly */
.ovsb .thumb::before{content:"";position:absolute;top:0;bottom:0;right:0;width:14px}
@media print{body::before,body::after,.ovsb{display:none}}
/* the LinkedIn placeholder (about/'s Find Us) is not a link yet, so no underline (master, oct 20 2026) */
a[aria-disabled="true"]{text-decoration:none;cursor:default}
