/* SlantUI, sober: ink and teal. The one sheet of the site, identical on all eight pages.
   Linked BEFORE the <style> of a page, so a page's own rules (the ones no other page needs)
   win at equal specificity without heavier selectors.
   Two vocabularies, as in SlantUI: roles (the only place a colour is written) and metrics
   (lengths, type, times). Every rule below :root names a role or a metric, never a value.
   Every edge is a step between two fills: no border, outline or ring appears on hover.
   A hover, a press or a focus is a colour change of 120 ms; the one motion is Federico's
   exception to SlantUI: a rectangle that can be pressed grows a little from its centre
   under the pointer or the keyboard ("the one motion", below). A window opens and closes
   in one frame. Reference: drafts/slant/SPEC.md (local, not published). */

:root{
  color-scheme:dark;

  /* ---- roles. Neutrals: SlantUI green-dark (= gold-dark). Accent: teal-dark, the only hue. ---- */
  --surface-0:#0D0D0F;              /* the page, the stage of a window */
  --surface-1:#101013;              /* a band fixed to an edge: the status bars */
  --surface-2:#121216;              /* a strip inside a window: the toolbar */
  --control:#1E1E24;                /* resting fill: the bands, the rows, Back, the cards */
  --control-hover:#33333B;          /* the same under the pointer */
  --control-active:#26262B;         /* the same while pressed */
  --text-1:#E6E6EC;                 /* titles, the name, a hovered label */
  --text-2:#C8C8D0;                 /* body copy, a resting label */
  --text-3:#A0A0AA;                 /* captions, the role line, status bar links */
  --text-4:#80808A;                 /* labels only, never a sentence */
  --accent:#3FBFB0;                 /* teal-dark: the dot of a row, the primary button, selection */
  --accent-hover:#55D1C1;
  --accent-active:#14A697;
  --on-accent:#0D0D0F;
  --accent-text:#3FBFB0;            /* the accent as ink, and the focus ring */
  --accent-surface:#1D2428;         /* a surface tinted toward the accent: what is current */
  --accent-surface-hover:#202C2F;
  --veil:#0D0D0FE6;                 /* surface-0 at 90%: the screen behind a window */
  --shadow:#00000099;               /* the one shadow: the home disc, raised (SPEC 4.4) */

  /* ---- metrics: type. SlantUI 0.3.0 as it is (metrics.css:37-64): the platform's face,
         five sizes and no sixth, two weights and no third ---- */
  --font:'Segoe UI',system-ui,-apple-system,sans-serif;
  /* the name on the band, nothing else */
  --font-brand:'Abadi','Abadi MT Std','Segoe UI Variable Display','Selawik','Segoe UI',system-ui,sans-serif;
  --fs-xs:10px;                     /* section label */
  --fs-sm:11.5px;                   /* notes, status bars, ghost buttons, a window's counter */
  --fs:12.5px;                      /* body, rows, Back, card names, a window's title */
  --fs-lg:13.5px;                   /* SlantUI's panel title: the page title, a figure of a spec */
  --fs-brand:14.5px;                /* the name on the band */
  --w:400;                          /* text that is not strong, every pressable label */
  --w-strong:600;                   /* a label that heads something, a title */
  --lh:1.45;                        /* labels, controls, titles */
  --lh-prose:1.7;                   /* running text: SlantUI's .sheet-body (components.css:824) */
  --ls-brand:.15px;
  --ls-strong:.4px;
  --ls-label:.8px;                  /* the section label (base.css:79) */

  /* ---- metrics: space. 4 / 8 / 12 / 16 inside a component, slot and block between them ---- */
  --sp-1:4px;
  --sp-2:8px;
  --sp-3:12px;
  --sp-4:16px;
  --slot:32px;
  --slot-2:64px;
  --block:96px;
  --edge:calc((var(--tbar-h) - var(--tbar-mark)) / 2);  /* 11: the mark's inset, and the
                                       inline padding of every bar, so all of them share one edge */
  --measure:720px;                  /* the reading column (mesh-field.js reads it too) */
  --prose:520px;                    /* line length of a paragraph inside the column: SlantUI's
                                       --sheet-w, the width of its one reading surface */

  /* ---- metrics: radii, one per role ---- */
  --r-xs:4px;                       /* a toolbar button, a photo inside a pane */
  --r:5px;                          /* the home button, a ghost button, anything pressed that is not a row */
  --r-lg:7px;                       /* a pane: a window, a card, a photo button */
  --pill:999px;                     /* the rows, Back and the PDF button, as on the live site */
  --round:50%;                      /* the site's disc, the avatar, the portrait */

  /* ---- metrics: the title band, SlantUI library values (SPEC 2.1) ---- */
  --tbar-h:44px;                    /* thick end, under the mark and the name */
  --tbar-thin:28px;                 /* thin end, to the right edge */
  --tbar-slant:38px;                /* horizontal run of the oblique */
  --tbar-join:8px;                  /* rounding of its two vertices */
  --tbar-mark:22px;                 /* the site's disc (/assets/icon.svg), centred on the thick end */
  --tbar-ring:4px;                  /* the raised disc of the home button around it: 30 px */
  --tbar-lift:1px;                  /* its shadow, offset and blur (SlantUI layout.css) */
  --tbar-lift-blur:3px;
  --tbar-mark-gap:14px;             /* disc to name */
  --tbar-name-end:16px;             /* end of the name to the head of the oblique */
  /* the taper piece, 38 + 2 x 8 = 54 px wide; rewrite it if one of the four numbers above changes */
  --tbar-taper:path("M0 0 H54 V28 Q46 28 38.63 31.1 L15.37 40.9 Q8 44 0 44 Z");

  /* ---- metrics: a window. Its title bar is the band at k = .75 (SPEC 2.5): 33 / 21 / 28.5 / 6,
         the same angle and the same proportions; the shell below it is SlantUI's (SPEC 4.3) ---- */
  --win-h:33px;                     /* thick end, under the title: the height of a row */
  --win-thin:21px;                  /* thin end, under the counter */
  --win-slant:28.5px;
  --win-join:6px;
  /* the taper piece, 28.5 + 2 x 6 = 40.5 px wide */
  --win-taper:path("M0 0 H40.5 V21 Q34.5 21 28.97 23.33 L11.53 30.67 Q6 33 0 33 Z");
  --win-w:880px;                    /* a model window, at most */
  --stage-h:min(56vh,560px);        /* the model inside it */
  --shot:calc((var(--stage-h) - 2 * var(--sp-1)) / 3);  /* a photo beside the model: three
                                       squares exactly as tall as the model */
  --shot-sm:72px;                   /* the same photo in the row above the model, narrow screens */
  --toolbar:32px;
  --ct:24px;                        /* a toolbar button, square */
  --ct-glyph:14px;                  /* its icon, on a 24-unit grid */
  --ct-stroke:1.8;                  /* one stroke for every icon */
  --rail:42px;                      /* the least height of a status bar */

  /* ---- metrics: rows, buttons, cards ---- */
  --row-h:33px;                     /* the live geometry (SPEC 6.7): one line, never taller */
  --row-w:360px;
  --row-pad-r:16px;
  --row-pad-l:32px;
  --dot:8px;                        /* the flat mark on the left cap */
  --ctl-h:31px;                     /* a strip of --fs text: SlantUI .btn (SPEC 4.3), a card's name */
  --btn-sm-h:27px;                  /* a strip of --fs-sm text: SlantUI .btn-sm, a ghost button,
                                       a row of a legend */
  --card-min:200px;                 /* the narrowest a card gets before the grid drops a column */
  --ring:2px;                       /* focus ring, inset, keyboard only */

  /* ---- metrics: time. A hover is a colour change, plus the one motion ---- */
  --t:120ms;
  --grow:1.025;                     /* the one motion: a card, a row, Back, a legend row */
  --grow-ct:1.1;                    /* the same on a 24 px toolbar button, where 1.025 is half a pixel */
  --t-grow:240ms;                   /* in and out alike */
  --ease-grow:cubic-bezier(.2,.8,.2,1);  /* soft, no overshoot */

  /* ---- the models: every material gets its colour and its finish once, at load, from
         /assets/js/model-tone.js, which reads the four tokens below. The photos of the
         models (cards, front, side, iso) are rendered from the same viewers and need no
         filter. Greys and whites keep their colour ---- */
  --tone-chroma:.7;                 /* OKLCH chroma of a coloured material, times this */
  --tone-lmax:.62;                  /* and its OKLCH lightness at most this: deep, not pastel */
  --metal-grey:.56;                 /* a grey metal reflects at least this much (linear) */
  --tone-white:.45;                 /* a white that is not a metal at most this (linear): no burn-out */

  /* ---- the names mesh-field.js reads on :root. It parses #rrggbb only;
         var() is substituted before it reads, so these resolve to the hex above. ---- */
  --bg:var(--surface-0);
  --text:var(--text-1);
}

/* ---------------------------------------------------------------- base */

*,*::before,*::after{box-sizing:border-box}

html{
  background:var(--surface-0);
  scrollbar-color:var(--control) transparent;
  -webkit-text-size-adjust:100%;
}

body{
  margin:0;
  min-height:100vh;
  display:flex;
  flex-direction:column;
  background:var(--surface-0);
  color:var(--text-2);
  font-family:var(--font);
  font-size:var(--fs);
  font-weight:var(--w);
  line-height:var(--lh-prose);
  -webkit-font-smoothing:antialiased;
}

h1,h2,h3,p,ul,ol,figure{margin:0}
h2,h3{font:inherit}
ul,ol{padding:0;list-style:none}
img{display:block;max-width:100%}
a{color:inherit;text-decoration:none}
button{margin:0;padding:0;border:0;background:none;font:inherit;color:inherit;cursor:pointer}
/* hidden means gone, whatever display a class gives the element */
[hidden]{display:none !important}

::selection{background:var(--accent);color:var(--on-accent)}

/* keyboard focus only: the inset ring, never an outline or a glow */
:focus-visible{outline:none;box-shadow:inset 0 0 0 var(--ring) var(--accent-text)}

.skip{
  position:absolute;
  top:var(--edge);
  left:var(--edge);
  z-index:5;
  padding:var(--sp-1) var(--sp-3);
  border-radius:var(--r);
  background:var(--accent-surface);
  color:var(--accent-text);
  font-size:var(--fs-sm);
  font-weight:var(--w);
  line-height:var(--lh);
}
.skip:not(:focus){left:-100vw}

/* ---------------------------------------------------------------- the title band
   One shape from three fills of the same role, no script:
   ::before is the thin band across the whole width, .tbar-brand is the thick end
   (as wide as the name, measured by layout), ::after is the taper hung on its right edge.
   The pieces overlap where they meet, so no seam can open between them. Under the thin
   end the band leaves 16 px of page: that strip has no colour of its own.
   Markup, the same on every page (the page word is left out on the home):
     <header class="titlebar"><div class="tbar-brand">
       <a class="tbar-logo-btn" href="/" aria-label="Home"><img class="tbar-logo" src="/assets/icon.svg" alt="" width="22" height="22"></a>
       <span class="tbar-name"><b>Federico Salerno</b><span class="tbar-page">Page</span></span>
     </div></header> */

.titlebar{
  position:relative;
  flex:none;
  height:var(--tbar-h);
  display:flex;
  align-items:flex-start;
  overflow:hidden;
}
.titlebar::before{
  content:"";
  position:absolute;
  inset:0 0 auto 0;
  height:var(--tbar-thin);
  background:var(--control);
}
.tbar-brand{
  position:relative;
  flex:none;
  height:var(--tbar-h);
  display:flex;
  align-items:center;
  padding:0 var(--tbar-name-end) 0 var(--edge);
  background:var(--control);
}
.tbar-brand::after{
  content:"";
  position:absolute;
  top:0;
  left:calc(100% - var(--tbar-join));
  width:calc(var(--tbar-slant) + 2 * var(--tbar-join));
  height:var(--tbar-h);
  background:var(--control);
  clip-path:var(--tbar-taper);
}
/* the home button, SlantUI's .tbar-logo-btn (SPEC 2.3, layout.css): the site's own disc,
   /assets/icon.svg in its colours (the icon Google shows beside the name), 22 px where
   SlantUI puts the brand mark, 11 px from the left, the top and the bottom of the thick end,
   14 px before the name; around it a round disc of 30 px in relief, the one thing on the
   site that casts a shadow (SPEC 4.4). Its negative margins give back exactly the room it
   takes: the mark does not move and the brand block keeps its width. Three states (SPEC 2.3):
   control-hover and the 1 px shadow at rest, accent-surface-hover under the pointer and on
   keyboard focus, accent-surface and no shadow while pressed. It does not grow. On every
   page, the home included: Federico's exception, the disc is always a button. */
.tbar-logo{
  flex:none;
  display:block;
  width:var(--tbar-mark);
  height:var(--tbar-mark);
  margin-right:var(--tbar-mark-gap);
  border-radius:var(--round);
}
.tbar-logo-btn{
  flex:none;
  display:flex;
  align-items:center;
  justify-content:center;
  width:calc(var(--tbar-mark) + 2 * var(--tbar-ring));
  height:calc(var(--tbar-mark) + 2 * var(--tbar-ring));
  margin:calc(0px - var(--tbar-ring)) calc(var(--tbar-mark-gap) - var(--tbar-ring))
         calc(0px - var(--tbar-ring)) calc(0px - var(--tbar-ring));
  border-radius:var(--round);
  background:var(--control-hover);
  box-shadow:0 var(--tbar-lift) var(--tbar-lift-blur) var(--shadow);
  transition:background-color var(--t),color var(--t),box-shadow var(--t);
}
.tbar-logo-btn > .tbar-logo{margin-right:0}
.tbar-logo-btn:hover,
.tbar-logo-btn:focus-visible{background:var(--accent-surface-hover);color:var(--accent-text)}
/* the keyboard ring, inset in the 4 px of disc around the mark, over the same shadow */
.tbar-logo-btn:focus-visible{
  box-shadow:inset 0 0 0 var(--ring) var(--accent-text),
             0 var(--tbar-lift) var(--tbar-lift-blur) var(--shadow);
}
.tbar-logo-btn:active{background:var(--accent-surface);box-shadow:none}
/* cap height to baseline: the name centres on its capitals and not on a line box, so it
   sits on the axis of the disc (where text-box is supported) */
.tbar-name{
  text-box:trim-both cap alphabetic;
  font-family:var(--font-brand);
  font-size:var(--fs-brand);
  font-weight:var(--w);
  letter-spacing:var(--ls-brand);
  line-height:var(--lh);
  color:var(--text-2);
  white-space:nowrap;
}
.tbar-name b{
  font-weight:var(--w-strong);
  letter-spacing:var(--ls-strong);
  color:var(--text-1);
}
.tbar-page{margin-left:var(--sp-3)}

/* ---------------------------------------------------------------- the column and the page head
   Under the band one block of air, then the page head (SPEC 6.10): h1, the lede, an
   optional note; then one .block per section, each opened by a .sec-lbl. */

.wrap{
  flex:1 0 auto;
  width:100%;
  max-width:calc(var(--measure) + 2 * var(--slot));
  margin:0 auto;
  padding:var(--block) var(--slot) var(--slot-2);
}

h1{
  font-size:var(--fs-lg);
  font-weight:var(--w-strong);
  line-height:var(--lh);
  color:var(--text-1);
}

.lede{margin-top:var(--sp-3);max-width:var(--prose)}
.note{
  margin-top:var(--sp-3);
  font-size:var(--fs-sm);
  line-height:var(--lh);
  color:var(--text-3);
}
.block{margin-top:var(--block)}
.group + .group{margin-top:var(--slot)}

.sec-lbl{
  font-size:var(--fs-xs);
  font-weight:var(--w-strong);
  letter-spacing:var(--ls-label);
  line-height:var(--lh);
  text-transform:uppercase;
  color:var(--text-4);
}

/* ---------------------------------------------------------------- rows, Back, PDF
   The live pill, unchanged in shape (SPEC 6.7); only the fills are SlantUI roles.
   Always one line and one row tall: a label too long for its pill ends in an ellipsis, as
   a SlantUI button's does (SPEC 6.4), it never makes the pill fatter.
   Hover and focus: one fill step, the label one step brighter, and the one motion.
   .list holds the rows of an index (the home, Biomedical research). .back is the way out
   of a page, as wide as its label, at the right of the column. .pdf is the one primary
   action of a page (the CV): the accent fill, the dot in on-accent. */

.list{margin-top:var(--block);display:grid;gap:var(--sp-3)}

.row,
.back,
.pdf{
  position:relative;
  display:block;
  width:min(100%,var(--row-w));
  height:var(--row-h);
  padding:0 var(--row-pad-r) 0 var(--row-pad-l);
  overflow:hidden;
  border-radius:var(--pill);
  background:var(--control);
  color:var(--text-2);
  font-size:var(--fs);
  font-weight:var(--w);
  line-height:var(--row-h);
  text-align:left;
  white-space:nowrap;
  text-overflow:ellipsis;
  transition:background-color var(--t),color var(--t),transform var(--t-grow) var(--ease-grow);
}
.row::before,
.back::before,
.pdf::before{
  content:"";
  position:absolute;
  top:50%;
  left:calc((var(--row-h) - var(--dot)) / 2);
  width:var(--dot);
  height:var(--dot);
  border-radius:50%;
  background:var(--accent);
  transform:translateY(-50%);
}
.row:hover,
.row:focus-visible,
.back:hover,
.back:focus-visible{
  background:var(--control-hover);
  color:var(--text-1);
}
.row:active,
.back:active{background:var(--control-active)}
.row[aria-current="page"]{
  background:var(--accent-surface);
  color:var(--accent-text);
  font-weight:var(--w-strong);
}

.back,
.pdf{width:fit-content;max-width:100%}
.back{
  margin-top:var(--block);
  margin-left:auto;
}

.pdf{
  background:var(--accent);
  color:var(--on-accent);
  font-weight:var(--w-strong);
}
.pdf::before{background:var(--on-accent)}
.pdf:hover,
.pdf:focus-visible{background:var(--accent-hover)}
.pdf:active{background:var(--accent-active)}
/* accent-text is the fill itself: the ring is drawn in on-accent */
.pdf:focus-visible{box-shadow:inset 0 0 0 var(--ring) var(--on-accent)}

/* ---------------------------------------------------------------- cards
   A card is a pane like a window, at r-lg, without a title bar: a photo on top on the
   page's fill, the name under it on the control fill. No border at rest or under the
   pointer: hover, focus and press step the fill and brighten the name, as on a row.
   Never oblique. .grid lays cards out in columns of at least --card-min. */

.grid{
  margin-top:var(--sp-3);
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(var(--card-min),1fr));
  gap:var(--sp-3);
}
.card{
  position:relative;
  display:flex;
  flex-direction:column;
  width:100%;
  height:100%;
  border-radius:var(--r-lg);
  overflow:hidden;
  background:var(--control);
  color:var(--text-2);
  font-weight:var(--w);
  text-align:left;
  transition:background-color var(--t),color var(--t),transform var(--t-grow) var(--ease-grow);
}
.card img{
  width:100%;
  height:auto;
  aspect-ratio:1;
  object-fit:cover;
  background:var(--surface-0);
}
/* the name: a strip as tall as a SlantUI button (SPEC 4.3), its padding and its type, one
   line whatever the name, so every card in a row is the same height; a long name ends in
   an ellipsis and is read whole in the title of the window it opens */
.card-name{
  display:block;
  height:var(--ctl-h);
  padding:0 var(--sp-3);
  overflow:hidden;
  font-size:var(--fs);
  line-height:var(--ctl-h);
  white-space:nowrap;
  text-overflow:ellipsis;
}
a.card:hover,
button.card:hover,
.card:focus-visible{background:var(--control-hover);color:var(--text-1)}
a.card:active,
button.card:active{background:var(--control-active)}
/* a photo covers its own fill, so the keyboard ring is drawn on a layer above the photo
   instead of under it. Mouse focus shows nothing. */
.card::after{
  content:"";
  position:absolute;
  inset:0;
  border-radius:inherit;
  pointer-events:none;
}
.card:focus-visible::after{box-shadow:inset 0 0 0 var(--ring) var(--accent-text)}

/* ---------------------------------------------------------------- windows
   Every box that opens over the page is one SlantUI window, built from the same pieces in
   the same order: the title bar (the band at k = .75, title on the thick end, counter on the
   thin end), the toolbar, the stage, the status bar. A window with no command leaves the
   last two out. The <dialog class="veil"> is the screen behind it; it opens and closes in
   one frame, nothing moves.
     <dialog class="veil" aria-labelledby="..."><div class="win">
       <div class="win-bar"><div class="win-head"><h2 class="win-name" id="...">Title</h2></div>
         <p class="win-count" aria-hidden="true">1 of 19</p></div>
       <div class="win-tools"><div class="ct-set"><button class="ct">..</button></div>
         <div class="ct-set ct-end">..close..</div></div>
       <div class="win-stage">..</div>
       <div class="win-status"><p class="status-text">..</p><a class="ghost">..</a></div>
     </div></dialog> */

.veil{
  position:fixed;
  inset:0;
  width:100%;
  height:100%;
  max-width:none;
  max-height:none;
  margin:0;
  padding:var(--sp-4);
  border:0;
  background:var(--veil);
  color:var(--text-2);
  overflow:hidden;
}
.veil[open]{display:grid;place-items:center}
.veil::backdrop{background:none}
.veil:focus-visible{box-shadow:none}
/* a window that holds a model keeps the page behind it still */
html:has(.viewer[open]){overflow:hidden}

.win{
  display:flex;
  flex-direction:column;
  width:min(100%,var(--win-w));
  max-height:100%;
  border-radius:var(--r-lg);
  overflow:hidden;
  background:var(--surface-0);
}

/* the title bar: the page band's recipe at k = .75. The strip under the thin end has no
   fill of its own: it is the toolbar's when one follows, the stage's when none does */
.win-bar{
  position:relative;
  flex:none;
  display:flex;
  align-items:flex-start;
  height:var(--win-h);
  overflow:hidden;
  background:var(--surface-0);
}
.win-bar:has(+ .win-tools){background:var(--surface-2)}
.win-bar::before{
  content:"";
  position:absolute;
  inset:0 0 auto 0;
  height:var(--win-thin);
  background:var(--control);
}
.win-head{
  position:relative;
  flex:0 1 auto;
  min-width:0;
  height:var(--win-h);
  display:flex;
  align-items:center;
  padding:0 var(--sp-3) 0 var(--edge);   /* 12 = the band's 16 at k = .75 */
  background:var(--control);
}
.win-head::after{
  content:"";
  position:absolute;
  top:0;
  left:calc(100% - var(--win-join));
  width:calc(var(--win-slant) + 2 * var(--win-join));
  height:var(--win-h);
  background:var(--control);
  clip-path:var(--win-taper);
}
.win-name{
  overflow:hidden;
  font-size:var(--fs);
  font-weight:var(--w-strong);
  line-height:var(--lh);
  color:var(--text-1);
  white-space:nowrap;
  text-overflow:ellipsis;
}
/* the counter keeps the taper's width clear on its left, so a long title shrinks first */
.win-count{
  position:relative;
  flex:none;
  height:var(--win-thin);
  display:flex;
  align-items:center;
  margin-left:auto;
  padding:0 var(--edge) 0 calc(var(--win-slant) + var(--win-join));
  font-size:var(--fs-sm);
  line-height:1;
  color:var(--text-3);
  font-variant-numeric:tabular-nums;
  white-space:nowrap;
}

/* the toolbar (SPEC 6.3): a 32 px strip, buttons 24 px square, 4 apart, groups 12 apart.
   Icons are stroked on a 24-unit grid, one stroke for all. Hover and focus: the control fill
   and the glyph one step brighter. A switch that is on (aria-pressed) keeps the control fill
   and takes the accent ink. A button that cannot act keeps its place in text-4. */
.win-tools{
  flex:none;
  display:flex;
  align-items:center;
  gap:var(--sp-3);
  height:var(--toolbar);
  padding:0 var(--edge);
  background:var(--surface-2);
}
.ct-set{display:flex;gap:var(--sp-1)}
.ct-end{margin-left:auto}
.ct{
  flex:none;
  display:grid;
  place-items:center;
  width:var(--ct);
  height:var(--ct);
  border-radius:var(--r-xs);
  color:var(--text-3);
  transition:background-color var(--t),color var(--t),transform var(--t-grow) var(--ease-grow);
}
.ct svg{
  width:var(--ct-glyph);
  height:var(--ct-glyph);
  fill:none;
  stroke:currentColor;
  stroke-width:var(--ct-stroke);
  stroke-linecap:round;
  stroke-linejoin:round;
}
.ct:hover,
.ct:focus-visible{background:var(--control);color:var(--text-1)}
.ct:active{background:var(--control-active)}
.ct[aria-pressed="true"]{background:var(--control);color:var(--accent-text)}
.ct[aria-pressed="true"]:hover{background:var(--control-hover)}
.ct[aria-disabled="true"]{background:none;color:var(--text-4);cursor:default}

/* the stage: the page's own fill. When something in it has the keyboard focus the ring is
   drawn on a layer above it, since a model's canvas covers anything drawn under it */
.win-stage{
  position:relative;
  flex:1 1 auto;
  min-height:0;
  display:flex;
  justify-content:center;
  overflow:hidden;
  background:var(--surface-0);
}
.win-stage::after{
  content:"";
  position:absolute;
  inset:0;
  pointer-events:none;
}
.win-stage:has(model-viewer:focus-visible)::after{box-shadow:inset 0 0 0 var(--ring) var(--accent-text)}

/* ---------------------------------------------------------------- a model and its photos
   model-viewer stands on the page's fill. .mv-split is a model with its three photos
   (front, side, isometric) in a column on its right, three squares as tall as the model;
   under 600 px they become a row above it. Every photo is a button, built around the img
   by the page's script: a pane at r-lg whose 4 px of fill around the picture is the
   control's, control-hover under the pointer, the accent tint (accent-surface) on the photo
   whose view the model is showing (li.is-current). Markup:
     <div class="mv-split"><model-viewer ...></model-viewer>
       <ul class="shots"><li><img ...></li> x 3</ul></div> */

model-viewer{
  display:block;
  background-color:var(--surface-0);
  --poster-color:transparent;
}
.mv-poster{
  display:flex;
  align-items:center;
  justify-content:center;
  width:100%;
  height:100%;
  font-size:var(--fs-sm);
  color:var(--text-3);
}
.win-stage > model-viewer{
  flex:1 1 auto;
  width:100%;
  height:var(--stage-h);
  max-height:100%;
}

.mv-split{
  flex:1 1 auto;
  min-width:0;
  display:flex;
  gap:var(--sp-1);
  padding:var(--sp-1);
}
.mv-split model-viewer{
  flex:1 1 auto;
  min-width:0;
  height:var(--stage-h);
}
.shots{
  flex:none;
  display:flex;
  flex-direction:column;
  gap:var(--sp-1);
  width:var(--shot);
}
.shots li{flex:1 1 0;min-height:0}
.shots img{
  width:100%;
  height:100%;
  object-fit:cover;
  border-radius:var(--r-xs);
}
.shots button{
  display:block;
  width:100%;
  height:100%;
  padding:var(--sp-1);
  border-radius:var(--r-lg);
  background:var(--control);
  transition:background-color var(--t),transform var(--t-grow) var(--ease-grow);
}
.shots button:hover,
.shots button:focus-visible{background:var(--control-hover)}
.shots button:active{background:var(--control-active)}
.shots li.is-current button{background:var(--accent-surface)}
.shots li.is-current button:hover{background:var(--accent-surface-hover)}

/* ---------------------------------------------------------------- status bars
   SlantUI has no footer: the page's is its rail mirrored at the bottom, full bleed on
   surface-1, and a window ends on the same bar. The step from the fill above to surface-1 is
   the only edge. On the left a line of text (text-3), on the right ghost buttons (SPEC 6.4):
   no fill at rest, the control fill under the pointer. A window's sentence never gets
   narrower than a row, so on a narrow screen its button drops under it instead of squeezing it. */

.foot{flex:none;background:var(--surface-1)}
.foot-inner,
.win-status{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  justify-content:space-between;
  gap:var(--sp-1) var(--sp-4);
  min-height:var(--rail);
  padding:var(--sp-1) var(--edge);
}
.win-status{flex:none;background:var(--surface-1)}
.copy,
.status-text{
  order:-1;
  font-size:var(--fs-sm);
  line-height:var(--lh);
  color:var(--text-3);
}
.status-text{flex:1 1 0;min-width:min(100%,var(--row-w))}
.contacts{display:flex;flex-wrap:wrap;gap:var(--sp-1)}
.contacts a,
.ghost{
  display:inline-flex;
  align-items:center;
  height:var(--btn-sm-h);
  padding:0 var(--sp-3);
  border-radius:var(--r);
  font-size:var(--fs-sm);
  font-weight:var(--w);
  line-height:var(--lh);
  color:var(--text-3);
  white-space:nowrap;
  transition:background-color var(--t),color var(--t),transform var(--t-grow) var(--ease-grow);
}
.contacts a:hover,
.contacts a:focus-visible,
.ghost:hover,
.ghost:focus-visible{background:var(--control);color:var(--text-1)}
.contacts a:active,
.ghost:active{background:var(--control-active)}

/* ---------------------------------------------------------------- the one motion
   Federico's one exception to SlantUI, which never scales a control (SPEC 7): a rectangle
   that can be pressed grows a little from its own centre while the pointer is on it or
   the keyboard has chosen it, and goes back the same way, over --t-grow on --ease-grow.
   transform alone, so it runs on the compositor and nothing around it moves; the fill
   steps as before. Under the pointer only where there is a real hover; nothing at all
   under prefers-reduced-motion. The home disc keeps its three states and does not grow.
   A page's own pressable rectangles (the CV's papers, the switches of the biomedical
   pages) take the same two tokens in that page. */

@media (hover:hover) and (prefers-reduced-motion:no-preference){
  a.card:hover,
  button.card:hover,
  .row:hover,
  .back:hover,
  .pdf:hover,
  .links a:hover,
  .legend button:hover,
  .shots button:hover,
  .contacts a:hover,
  .ghost:hover{transform:scale(var(--grow))}
  .ct:not([aria-disabled="true"]):hover{transform:scale(var(--grow-ct))}
}
@media (prefers-reduced-motion:no-preference){
  .card:focus-visible,
  .row:focus-visible,
  .back:focus-visible,
  .pdf:focus-visible,
  .links a:focus-visible,
  .legend button:focus-visible,
  .shots button:focus-visible,
  .contacts a:focus-visible,
  .ghost:focus-visible{transform:scale(var(--grow))}
  .ct:not([aria-disabled="true"]):focus-visible{transform:scale(var(--grow-ct))}
}

/* ---------------------------------------------------------------- narrow screens */

@media (max-width:600px){
  :root{--stage-h:min(48vh,360px)}
  .wrap{padding:var(--slot-2) var(--sp-4)}
  .list,
  .block,
  .back{margin-top:var(--slot-2)}
  .grid{grid-template-columns:repeat(2,minmax(0,1fr))}
  /* the photos leave the column for a row of small squares above the model */
  .mv-split{flex-direction:column}
  .shots{order:-1;flex-direction:row;width:auto}
  .shots li{flex:none;width:var(--shot-sm);height:var(--shot-sm)}
  /* once the buttons sit under the text, their labels line up with it */
  .contacts,
  .win-status .ghost{margin-left:calc(-1 * var(--sp-3))}
}

/* under 420 px the band keeps the strong name only, so the taper stays on screen */
@media (max-width:420px){
  .tbar-page{display:none}
}

@media (prefers-reduced-motion:reduce){
  .tbar-logo-btn,
  .row,
  .back,
  .pdf,
  .card,
  .ct,
  .shots button,
  .contacts a,
  .ghost{transition:none}
}

/* ---- passata 2: biomedical ----
   What the two work pages (biomedical-artifact.html, biomedical-platform.html) share and no
   other page has. A model on a work page is not opened: it stands in the column as a window,
   the same pieces in the same order as the model window of My projects (title bar at
   k = .75, toolbar, stage, status bar), the photos beside it and the lists of the model
   under it. Around it the paper: a head, the stages on a rail, the cards under a stage,
   the equations, the links to the paper. Fills only; what moves is the colour of a control
   and the one motion. Rules of one page only stay in that page. */

:root{
  --surface-3:#16161B;              /* a card in the flow: the object under a stage */
  --pin:15px;                       /* a numbered marker on a model or in a drawn figure */
  --pin-fs:9px;                     /* its digit: a glyph inside the marker, not a size of text */
  --rail-x:var(--sp-4);             /* the rail of the stages hangs this far left of the column */
  --rail-w:3px;
  --rail-dot:11px;
}

/* ---------------------------------------------------------------- the head of a work */

.works{margin-top:var(--block)}
.kind{
  font-size:var(--fs-xs);
  font-weight:var(--w-strong);
  letter-spacing:var(--ls-label);
  line-height:var(--lh);
  text-transform:uppercase;
  color:var(--text-4);
}
.feature h2{
  margin-top:var(--sp-2);
  font-size:var(--fs);
  font-weight:var(--w-strong);
  line-height:var(--lh);
  color:var(--text-1);
}
.dek,
.dek-q{max-width:var(--prose);color:var(--text-2)}
.dek{margin-top:var(--sp-3)}
.meta{
  margin-top:var(--sp-2);
  font-size:var(--fs-sm);
  line-height:var(--lh);
  color:var(--text-3);
}
.feature-grid{
  margin-top:var(--slot);
  display:grid;
  grid-template-columns:minmax(0,1fr);
  gap:var(--slot-2);
}
.feature-media,
.feature-text{min-width:0}

/* ---------------------------------------------------------------- a window in the column
   .win > .win-bar + .win-tools + .win-stage.stage + .win-status. The page's script wraps
   the model in .mv-wrap and puts its commands (.mv-zoom, a .ct-set of .ct) in .win-tools;
   without the script the toolbar is empty and is not drawn. */

.win-tools:empty{display:none}
.win-bar:has(+ .win-tools:empty){background:var(--surface-0)}
.win-stage.stage{flex-direction:column;justify-content:flex-start}
.mv-wrap{position:relative;display:block}
.win-stage > .mv-wrap,
.mv-split > .mv-wrap{flex:1 1 auto;min-width:0}
.mv-wrap > model-viewer{width:100%;height:var(--stage-h)}

/* the list of what the model is made of, under it: rows of text with no fill at rest, the
   control fill under the pointer, the accent tint on the one that is chosen. One line as
   tall as a SlantUI .btn-sm, the end of a long name in an ellipsis */
.legend button{
  display:flex;
  align-items:center;
  gap:var(--sp-2);
  width:100%;
  height:var(--btn-sm-h);
  padding:0 var(--sp-2);
  overflow:hidden;
  white-space:nowrap;
  border-radius:var(--r-xs);
  font-size:var(--fs-sm);
  line-height:var(--lh);
  color:var(--text-2);
  text-align:left;
  transition:background-color var(--t),color var(--t),transform var(--t-grow) var(--ease-grow);
}
.legend button > span{min-width:0;overflow:hidden;text-overflow:ellipsis}
.legend button:hover,
.legend button:focus-visible{background:var(--control);color:var(--text-1)}
.legend button:active{background:var(--control-active)}
.legend button[aria-pressed="true"]{background:var(--accent-surface);color:var(--accent-text)}
.legend button[aria-pressed="true"]:hover{background:var(--accent-surface-hover)}

/* ---------------------------------------------------------------- the stages of the paper
   One line naming the stages, then the stages on a rail hung left of the column: the track
   in control, filled in accent as the block is read (the page's script writes --p), one dot
   per stage, accent on the stage being read. */

.phases{
  margin-top:var(--slot);
  font-size:var(--fs-sm);
  line-height:var(--lh-prose);
  color:var(--text-3);
}
.phases span{white-space:nowrap;transition:color var(--t)}
.phases b{margin-right:var(--sp-1);font-weight:var(--w-strong);font-variant-numeric:tabular-nums}
.phases i{margin:0 var(--sp-2);font-style:normal;color:var(--text-4)}
.phases span.on{color:var(--text-1)}

.steps-wrap{position:relative;margin-top:var(--slot-2)}
.steps-wrap::before,
.steps-wrap::after{
  content:"";
  position:absolute;
  top:calc(var(--fs-sm) * var(--lh) / 2);
  bottom:0;
  left:calc(-1 * var(--rail-x));
  width:var(--rail-w);
  border-radius:var(--pill);
}
.steps-wrap::before{background:var(--control)}
.steps-wrap::after{
  background:var(--accent);
  transform:scaleY(var(--p,0));
  transform-origin:top;
}
.step{position:relative;padding-bottom:var(--slot-2)}
.step:last-child{padding-bottom:0}
.step::before{
  content:"";
  position:absolute;
  top:calc((var(--fs-sm) * var(--lh) - var(--rail-dot)) / 2);
  left:calc(var(--rail-w) / 2 - var(--rail-dot) / 2 - var(--rail-x));
  width:var(--rail-dot);
  height:var(--rail-dot);
  border-radius:var(--round);
  background:var(--control-hover);
  transition:background-color var(--t);
}
.step:hover::before,
.step.is-active::before{background:var(--accent)}
.step-n{
  font-size:var(--fs-sm);
  line-height:var(--lh);
  color:var(--text-4);
  font-variant-numeric:tabular-nums;
  transition:color var(--t);
}
.step.is-active .step-n{color:var(--accent-text)}
.step h3{
  margin-top:var(--sp-1);
  font-size:var(--fs);
  font-weight:var(--w-strong);
  line-height:var(--lh);
  color:var(--text-1);
}
.step .lead{
  margin-top:var(--sp-2);
  max-width:var(--prose);
  color:var(--text-3);
  transition:color var(--t);
}
.step.is-active .lead{color:var(--text-2)}

/* the object of a stage: a card of the surface-3 fill, its caption under it */
.obj{
  margin-top:var(--sp-4);
  padding:var(--sp-4);
  border-radius:var(--r-lg);
  background:var(--surface-3);
}
.obj-t{
  margin-bottom:var(--sp-3);
  font-size:var(--fs-sm);
  font-weight:var(--w-strong);
  line-height:var(--lh);
  color:var(--text-1);
}
.obj-cap{
  margin-top:var(--sp-2);
  max-width:var(--prose);
  font-size:var(--fs-sm);
  line-height:var(--lh-prose);
  color:var(--text-3);
}
.spec{
  display:grid;
  grid-template-columns:repeat(auto-fit,minmax(var(--block),1fr));
  gap:var(--sp-4);
}
.spec b{
  display:block;
  font-size:var(--fs-lg);
  font-weight:var(--w-strong);
  line-height:var(--lh);
  color:var(--text-1);
  font-variant-numeric:tabular-nums;
}
.spec span{
  display:block;
  margin-top:var(--sp-1);
  font-size:var(--fs-sm);
  line-height:var(--lh);
  color:var(--text-3);
}
.pair,
.pair dd{margin:0}
.pair dt{
  margin-top:var(--sp-4);
  font-size:var(--fs-sm);
  font-weight:var(--w-strong);
  line-height:var(--lh);
  color:var(--text-1);
}
.pair dt:first-of-type{margin-top:0}
.pair dd{
  margin-top:var(--sp-1);
  font-size:var(--fs-sm);
  line-height:var(--lh-prose);
  color:var(--text-3);
}

/* equations: native MathML in the browser's math face. One equation is a line with its
   number at the right; a run of them is one grid with the signs on one vertical. Neither
   ever shows a scroll bar. */
.eq{
  display:flex;
  align-items:center;
  justify-content:space-between;
  gap:var(--sp-4);
  overflow-x:auto;
  overflow-y:hidden;
  scrollbar-width:none;
  text-align:left;
}
.eq::-webkit-scrollbar,
.eqs::-webkit-scrollbar{display:none}
.eq math,
.eqs math{
  padding:var(--sp-1) 0;
  font-size:var(--fs-lg);
  font-weight:var(--w);
  color:var(--text-1);
}
.eqs{
  display:grid;
  grid-template-columns:0 auto auto auto 1fr auto;
  align-items:center;
  row-gap:var(--sp-4);
  overflow-x:auto;
  overflow-y:hidden;
  scrollbar-width:none;
}
.eqs math{font-size:var(--fs)}
.eqs .eq-r{display:contents}
.eqs .lhs{grid-column:2;justify-self:end}
.eqs .rel{grid-column:3;justify-self:center;padding-inline:var(--sp-1)}
.eqs .rhs{grid-column:4;justify-self:start}
.eq .num,
.eqs .num{
  flex:none;
  font-family:var(--font);
  font-size:var(--fs-sm);
  color:var(--text-3);
  font-variant-numeric:tabular-nums;
}
.eqs .num{grid-column:6;justify-self:end;padding-left:var(--sp-4)}
.key{
  margin-top:var(--sp-4);
  font-size:var(--fs-sm);
  line-height:var(--lh-prose);
  color:var(--text-3);
}
.key b{font-weight:var(--w-strong);font-style:italic;color:var(--text-1)}

/* the paper and its data: the site's own pill, as Back, the dot on the left cap, one line */
.links{display:flex;flex-wrap:wrap;gap:var(--sp-3);margin-top:var(--slot)}
.links li{min-width:0;max-width:100%}
.links a{
  position:relative;
  display:block;
  height:var(--row-h);
  padding:0 var(--row-pad-r) 0 var(--row-pad-l);
  overflow:hidden;
  border-radius:var(--pill);
  background:var(--control);
  color:var(--text-2);
  font-weight:var(--w);
  line-height:var(--row-h);
  white-space:nowrap;
  text-overflow:ellipsis;
  transition:background-color var(--t),color var(--t),transform var(--t-grow) var(--ease-grow);
}
.links a::before{
  content:"";
  position:absolute;
  top:50%;
  left:calc((var(--row-h) - var(--dot)) / 2);
  width:var(--dot);
  height:var(--dot);
  border-radius:var(--round);
  background:var(--accent);
  transform:translateY(-50%);
}
.links a:hover,
.links a:focus-visible{background:var(--control-hover);color:var(--text-1)}
.links a:active{background:var(--control-active)}

@media (max-width:600px){
  :root{--rail-x:var(--sp-3)}
  .works{margin-top:var(--slot-2)}
  .feature-grid{gap:var(--slot)}
  .step{padding-bottom:var(--slot)}
  .eq math{font-size:var(--fs)}
  /* the widest run, the root of eq. 11 of the artifact, fits a 343 px column at this size */
  .eqs math{font-size:var(--fs-xs)}
  .eqs{row-gap:var(--sp-2)}
  .eqs .num{padding-left:var(--sp-2)}
}

@media (prefers-reduced-motion:reduce){
  .legend button,
  .phases span,
  .step::before,
  .step-n,
  .step .lead,
  .links a{transition:none}
}
