/* Page styles. Tokens live in tokens.css (from DESIGN.md). */
@font-face{font-family:"Newsreader";src:url(fonts/newsreader-latin-wght-normal.woff2) format("woff2");font-weight:200 800;font-style:normal;font-display:swap}
@font-face{font-family:"Newsreader";src:url(fonts/newsreader-latin-wght-italic.woff2) format("woff2");font-weight:200 800;font-style:italic;font-display:swap}
@font-face{font-family:"Inter";src:url(fonts/inter-latin-wght-normal.woff2) format("woff2");font-weight:100 900;font-style:normal;font-display:swap}

/* ---------- Base ---------- */
*{box-sizing:border-box}
html{scroll-padding-top:var(--header-h)}
body{margin:0;background:var(--paper);color:var(--ink);font:400 var(--step-body)/1.6 var(--font-sans);-webkit-font-smoothing:antialiased}
h1,h2,h3{font-family:var(--font-serif);font-weight:450;margin:0;text-wrap:balance}
p{margin:0;text-wrap:pretty}
a{color:inherit}
:focus-visible{outline:3px solid var(--accent);outline-offset:4px}
[hidden]{display:none!important}
.container{width:min(100% - 2*var(--gutter),var(--container));margin-inline:auto}
.sr-only{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.skip{position:absolute;left:var(--space-4);top:-100px;z-index:30;padding:var(--space-3) var(--space-4);background:var(--paper);color:var(--ink);border:2px solid var(--accent);border-radius:var(--radius-2);font:500 var(--step-small)/1.2 var(--font-sans)}
.skip:focus{top:var(--space-2)}

/* ---------- Buttons and links ---------- */
.btn{display:inline-flex;align-items:center;gap:var(--space-2);min-height:44px;padding:10px 20px;border:1px solid var(--accent);border-radius:var(--radius-2);background:transparent;color:var(--accent);font:500 var(--step-small)/1.2 var(--font-sans);text-decoration:none;cursor:pointer;transition:background var(--dur-fast),color var(--dur-fast),border-color var(--dur-fast)}
.btn:active{transform:translateY(1px)}
.btn--primary{background:var(--accent);color:var(--paper)}
.btn--primary:hover{background:var(--accent-strong);border-color:var(--accent-strong)}
.btn--secondary:hover{background:var(--mist);color:var(--accent-strong);border-color:var(--accent-strong)}
.tlink{display:inline-flex;align-items:center;min-height:44px;color:var(--accent);font:500 var(--step-small)/1.2 var(--font-sans);text-decoration:none}
.tlink:hover{color:var(--accent-strong);text-decoration:underline;text-underline-offset:.2em}
.links{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-1) var(--space-5)}

/* ---------- Header ---------- */
.site-header{position:sticky;top:0;z-index:20;height:var(--header-h);background:var(--paper);border-bottom:1px solid transparent;transition:border-color var(--dur-base)}
.site-header[data-scrolled]{border-bottom-color:var(--line)}
.header-row{height:100%;display:flex;align-items:center;justify-content:space-between;gap:var(--space-5)}
.wordmark{display:inline-flex;align-items:center;gap:10px;min-height:44px;color:var(--ink);font:500 1.125rem/1 var(--font-serif);letter-spacing:.005em;text-decoration:none}
.wordmark:hover{color:var(--accent-strong)}
.mark{width:30px;height:30px;flex:none}
.site-nav{display:flex;gap:clamp(0px,1vw,12px)}
.site-nav a{display:inline-flex;align-items:center;min-height:44px;padding-inline:12px;color:var(--ink);font:500 .9375rem/1 var(--font-sans);text-decoration:none;box-shadow:inset 0 -2px 0 transparent;transition:color var(--dur-fast),box-shadow var(--dur-fast)}
.site-nav a:hover{color:var(--accent-strong);box-shadow:inset 0 -2px 0 var(--accent-strong)}
.site-nav a[aria-current]{box-shadow:inset 0 -2px 0 var(--accent)}
.menu-button{display:none}
@media(max-width:720px){
 .menu-button{display:inline-flex}
 .js .site-nav{display:none;position:absolute;left:0;right:0;top:var(--header-h);flex-direction:column;gap:0;padding:var(--space-2) var(--gutter) var(--space-4);background:var(--paper);border-bottom:1px solid var(--line)}
 .js .site-nav[data-open]{display:flex}
 .js .site-nav a{padding-inline:0;min-height:48px;font-size:1rem}
 .site-nav{gap:0;flex-wrap:wrap}
}

/* ---------- About ---------- */
.about{padding-block:clamp(24px,4vw,48px) calc(var(--section-pad) * .5)}
.about-grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:var(--col-gap);row-gap:var(--space-6);align-items:start}
.about-id{grid-column:1/span 8;grid-row:1}
.display{font:450 var(--step-display)/1.04 var(--font-serif);letter-spacing:-.01em}
.role{margin-top:var(--space-3);font:400 var(--step-lead)/1.35 var(--font-serif);color:var(--ink-muted)}
.affiliation{margin-top:var(--space-1);color:var(--ink-muted)}
.focus{margin-top:var(--space-6);max-width:30ch;font:450 var(--step-h2)/1.15 var(--font-serif);text-wrap:balance}
.nw{white-space:nowrap}
.ext{margin-left:.3em}
.about-id .links{margin-top:var(--space-5)}
.portrait{position:relative;grid-column:9/span 4;grid-row:1;justify-self:end;width:clamp(180px,22vw,320px);margin:0}
.portrait img{display:block;width:100%;height:auto;aspect-ratio:1;border-radius:50%;object-fit:cover}
/* The one circle style: a solid ring drawn on the edge, no gap (DESIGN.md section 6). */
.portrait::after{content:"";position:absolute;inset:0;border-radius:50%;box-shadow:inset 0 0 0 var(--ring-w) var(--accent);pointer-events:none}
.about-bio{grid-column:1/-1;grid-row:2}
.about-bio p{max-width:66ch;margin:0 0 var(--space-4)}
.about-bio p:last-child{margin-bottom:0}
/* The three questions are the page's own idea ("One system. Many questions."): side by side, each under the accent rule that marks a list,
   with the question text in the Lead size, as in the work drawer. They map to the tagline: adaptive, low-carbon, data-driven. */
.about-bio .about-lead-in{margin-top:var(--space-6);margin-bottom:var(--space-3)}
.about-questions{list-style:none;margin:0 0 var(--space-6);padding:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-5) var(--col-gap)}
.about-questions li{padding-top:var(--space-3);border-top:2px solid var(--q);color:var(--q);font:450 var(--step-lead)/1.3 var(--font-serif)}
/* One colour for each question, from the chapter colours (each is at least 4.6:1 on the paper): adaptive, low-carbon, data-driven. */
.about-questions li:nth-child(1){--q:var(--ring-kf02-text)}
.about-questions li:nth-child(2){--q:var(--ring-kf04-text)}
.about-questions li:nth-child(3){--q:var(--ring-kf03-text)}
@media(max-width:1023px){.about-questions{grid-template-columns:1fr;gap:var(--space-4);max-width:66ch}}
@media(max-width:720px){
 .about-grid{grid-template-columns:1fr}
 .portrait{grid-column:1;grid-row:1;justify-self:start;width:min(56vw,220px)}
 .about-id{grid-column:1;grid-row:2}
 .about-bio{grid-column:1;grid-row:3}
}

/* ---------- Research journey (pinned stage) ---------- */
.sticky{position:sticky;top:0;height:100svh;min-height:560px;overflow:hidden}
.stage-overlay{position:absolute;inset:0;z-index:2;pointer-events:none}
.overlay-inner{position:relative;height:100%}
.heading{position:absolute;top:max(8%,calc(var(--header-h) + var(--space-4)));left:0;pointer-events:none}
.heading.is-away{opacity:0}   /* gone from sight, still in the reading order */
/* Section names (Research, NBIF, Education, Contact): a clear step up from the body text, in ink, in the heading face. */
.eyebrow{font:450 var(--step-lead)/1.2 var(--font-serif);color:var(--ink)}
.heading h2{font:450 clamp(26px,2.8vw,40px)/1.12 var(--font-serif);margin:10px 0}
#instruction{margin-top:8px;font-size:13px;color:var(--ink-muted)}
#stage{position:absolute;inset:10% max(var(--gutter),calc((100% - var(--container-wide))/2)) 5%}
#scene{position:relative;width:100%;height:100%}

/* Caption: beside the circle on a desktop (centred on it), under it on a phone. */
#content{position:absolute;left:var(--caption-x,auto);right:0;top:var(--ring-cy,50%);translate:0 -50%;width:var(--caption-w,min(360px,30%));pointer-events:auto}   /* --caption-x and --caption-w come from layout.js: a fixed gap right of the circle */
.kicker{display:flex;align-items:center;gap:10px;color:var(--ink);font:500 var(--step-small)/1.3 var(--font-sans);margin:0}
/* The caption does not repeat the chapter's number and name: the list beside the circle already shows them. The heading stays for screen readers. */
#content .kicker{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
.numeral{flex:none;display:inline-grid;place-items:center;width:28px;height:28px;border-radius:50%;border:2px solid var(--ring,var(--ink));font-size:13px;font-weight:600;font-variant-numeric:tabular-nums;color:var(--ink)}
.caption-lead{margin-top:var(--space-3);font:450 clamp(20px,1.9vw,26px)/1.25 var(--font-serif);text-wrap:balance}
#work{margin-top:var(--space-4)}

/* Chapter rail: every chapter listed by number and name in its own colour; the one on screen is larger and bolder.
   Down the left edge on a desktop (numerals only when the window is narrow or the drawer is open), along the top on a phone. */
.rail{position:absolute;left:0;top:var(--ring-cy,50%);translate:0 -50%;pointer-events:auto}
.rail ol{list-style:none;margin:0;padding:0;display:flex;flex-direction:column}
.rail[data-faded]{pointer-events:none}
.kbd .rail:focus-within{opacity:1!important;pointer-events:auto}   /* only for someone using the keyboard (pilot.js sets .kbd); a click or a script moving focus must not bring it back over the painting */
.rail-item{position:relative;display:flex;align-items:center;justify-content:flex-start;gap:10px;min-width:44px;height:48px;padding:0 10px 0 8px;border:0;background:transparent;color:var(--ink);cursor:pointer;border-radius:var(--radius-2);text-align:left;
 transform-origin:22px 50%;transition:transform var(--dur-base) var(--ease-out)}
.rail-item .numeral{transition:background var(--dur-fast),color var(--dur-fast)}
.rail-item:hover .numeral{background:var(--mist)}
.rail-item[aria-current="step"]{transform:scale(1.3)}
.rail-item[aria-current="step"] .numeral{background:var(--mist);box-shadow:inset 0 0 0 2px var(--ring);color:var(--ink)}   /* dark text on a pale fill: white on the teal ring colour is only 4.1:1 */
.rail-mark{flex:none;width:26px;height:26px;margin:1px;border-radius:50%;transition:box-shadow var(--dur-fast)}
.rail-item[aria-current="step"] .rail-mark{box-shadow:0 0 0 3px var(--mist),0 0 0 4.5px var(--accent)}   /* the overview item's "current" marker: the same heavier ring as the numerals */
.rail-label{width:max-content;max-width:150px;font:500 var(--step-small)/1.2 var(--font-sans);color:var(--ring-text,var(--ink));transition:color var(--dur-fast)}
.rail-item[aria-current="step"] .rail-label{font-weight:700}
.rail-item:hover .rail-label{text-decoration:underline;text-underline-offset:.2em}
.sticky[data-rail="narrow"] .rail-label{max-width:110px}
.rail-item[data-index="0"]{--ring-text:var(--accent)}
.rail-item[data-index="0"] .rail-label{max-width:none;white-space:nowrap;font-size:calc(var(--step-small) * 1.3);font-weight:650;line-height:1.1}   /* "Research Overview": larger than the chapter names, on one line */
.rail-item[data-index="0"][aria-current="step"]{transform:scale(1.08)}   /* already larger: it is only ever current while the rail is faded out */
.rail-item[data-index="0"] .rail-mark{width:30px;height:30px;margin:-1px}
.rail-item[data-index="1"]{--ring-text:var(--ring-kf01-text)}.rail-item[data-index="2"]{--ring-text:var(--ring-kf02-text)}.rail-item[data-index="3"]{--ring-text:var(--ring-kf03-text)}
.rail-item[data-index="4"]{--ring-text:var(--ring-kf04-text)}.rail-item[data-index="5"]{--ring-text:var(--ring-kf05-text)}.rail-item[data-index="6"]{--ring-text:var(--ring-kf06-text)}
.rail-item[data-index="7"]{--ring-text:var(--ring-kf07-text)}.rail-item[data-index="8"]{--ring-text:var(--ring-kf08-text)}
/* Numerals only: in a narrow window (layout.js sets data-rail="compact"), and while the work drawer is open (it needs the room). */
@media(min-width:901px){
 .sticky.drawer-open #content{visibility:hidden}   /* the drawer covers it; keep its overflow from showing beside the drawer */
 .sticky[data-rail="compact"] .rail-label,.sticky.drawer-open .rail-label{display:none}
 .sticky[data-rail="compact"] .rail-item,.sticky.drawer-open .rail-item{width:44px;padding:0;justify-content:center;transform-origin:center}
}

/* "Go to NBIF": bottom right of the pinned stage, shown from the first chapter on (pilot.js sets data-show), a way past the keyframes to the NBIF section. */
.stage-nbif{position:absolute;right:0;bottom:max(20px,3svh);pointer-events:auto;background:var(--paper);opacity:0;visibility:hidden;transition:opacity var(--dur-base),visibility 0s linear var(--dur-base),background var(--dur-fast),color var(--dur-fast),border-color var(--dur-fast)}
.stage-nbif[data-show]{opacity:1;visibility:visible;transition:opacity var(--dur-base),visibility 0s,background var(--dur-fast),color var(--dur-fast),border-color var(--dur-fast)}
.stage-nbif:hover{background:var(--mist)}
@media(max-width:480px){.stage-nbif{padding-inline:14px}.stage-nbif-go{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}}   /* on a phone just "NBIF ↓", so it never meets the caption's button; the spoken name stays "Go to NBIF" */
.sticky.drawer-open .stage-nbif{visibility:hidden}
html:not(.js) .stage-nbif{display:none}

/* Work drawer: the questions and papers of the current chapter. */
.drawer{position:absolute;top:var(--header-h);bottom:0;right:0;width:clamp(340px,40%,480px);display:flex;flex-direction:column;background:var(--paper);border-left:1px solid var(--line);box-shadow:-12px 0 32px rgba(40,58,71,.10);pointer-events:auto;
 visibility:hidden;transform:translateX(24px);opacity:0;transition:transform var(--dur-base) var(--ease-out),opacity var(--dur-base) var(--ease-out),visibility 0s linear var(--dur-base)}
.drawer.is-open{visibility:visible;transform:none;opacity:1;transition:transform var(--dur-base) var(--ease-out),opacity var(--dur-base) var(--ease-out),visibility 0s}
.drawer:focus{outline:none}
.drawer:focus-visible{outline:3px solid var(--accent);outline-offset:-3px}
.drawer-head{display:flex;align-items:center;justify-content:space-between;gap:var(--space-3);padding:var(--space-4) var(--space-5);border-bottom:1px solid var(--line)}
.drawer-body{flex:1;overflow:auto;overscroll-behavior:contain;padding:var(--space-5) var(--space-5) var(--space-8)}
.drawer .questions{list-style:none;margin:0;padding:0;display:grid;gap:var(--space-7)}
.drawer .q-text{font:italic 400 var(--step-lead)/1.25 var(--font-serif)}

/* Questions, findings and papers: one set of styles for the drawer and for the page without JavaScript. */
.q-finding{margin-top:var(--space-2);color:var(--ink-muted);font-size:var(--step-small);line-height:1.5}
.q-points{list-style:disc;margin:var(--space-2) 0 0;padding-left:1.2em;color:var(--ink-muted);font-size:var(--step-small);line-height:1.5}
.q-points li{margin-top:var(--space-1)}
.q-points li::marker{color:var(--ring,var(--ink-muted))}
.papers{list-style:none;margin:var(--space-3) 0 0;padding:0;display:grid;gap:var(--space-3)}
.paper{display:block;font-size:var(--step-small);line-height:1.45}
.paper-title{display:inline-block;padding-block:2px;color:var(--accent);font-weight:500;text-decoration:none}
.paper-title:hover{color:var(--accent-strong);text-decoration:underline;text-underline-offset:.2em}
.paper-meta{display:block;color:var(--ink-muted)}
.paper-meta b{font-weight:600;color:var(--ink)}

/* The same chapters as plain HTML, for visitors without JavaScript. With JavaScript they are replaced by the stage. */
.chapters-static{width:min(100% - 2*var(--gutter),var(--container));margin:0 auto;padding-block:var(--section-pad);display:grid;gap:var(--space-9);counter-reset:chapter}
.chapter{counter-increment:chapter;display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:var(--col-gap);row-gap:var(--space-4)}
.chapter>.chapter-label,.chapter>.chapter-lead{grid-column:1/span 4}
.chapter>.questions{grid-column:5/-1;grid-row:1/span 2;list-style:none;margin:0;padding:0;display:grid;gap:var(--space-7)}
.chapter-label{display:flex;align-items:center;gap:10px;margin:0;font:500 var(--step-small)/1.3 var(--font-sans)}
.chapter-label::before{content:counter(chapter);display:inline-grid;place-items:center;width:28px;height:28px;border-radius:50%;border:2px solid var(--ring,var(--ink));font-size:13px;font-weight:600;font-variant-numeric:tabular-nums}
.chapter-lead{font:450 var(--step-h3)/1.25 var(--font-serif);margin:0;text-wrap:balance}
.q-text{margin:0;font:italic 400 var(--step-h3)/1.25 var(--font-serif)}
.chapter[data-region="KF01"]{--ring:var(--ring-kf01)}.chapter[data-region="KF02"]{--ring:var(--ring-kf02)}.chapter[data-region="KF03"]{--ring:var(--ring-kf03)}
.chapter[data-region="KF04"]{--ring:var(--ring-kf04)}.chapter[data-region="KF05"]{--ring:var(--ring-kf05)}.chapter[data-region="KF06"]{--ring:var(--ring-kf06)}.chapter[data-region="KF07"]{--ring:var(--ring-kf07)}.chapter[data-region="KF08"]{--ring:var(--ring-kf08)}
@media(max-width:900px){.chapter>.chapter-label,.chapter>.chapter-lead,.chapter>.questions{grid-column:1/-1;grid-row:auto}}
.js .chapters-static{display:none}
html:not(.js) .sticky{position:static;height:auto;min-height:0;overflow:visible}
html:not(.js) .stage-overlay{position:static}
html:not(.js) .overlay-inner{height:auto;padding-top:var(--space-7)}
html:not(.js) .heading{position:static}
html:not(.js) #stage{position:static;padding-block:var(--space-6)}
html:not(.js) #scene{height:auto}
html:not(.js) .drawer,html:not(.js) #content,html:not(.js) .controls,html:not(.js) #status{display:none}
/* Without JavaScript the Menu button cannot work, so the header shows its links and wraps instead of overflowing. */
html:not(.js) .menu-button{display:none}
html:not(.js) .site-header{height:auto;position:static}
html:not(.js) .header-row{height:auto;flex-wrap:wrap;padding-block:var(--space-2)}
html:not(.js) .site-nav{flex-wrap:wrap}
.scene-fallback{display:block;width:100%;height:auto}

/* Research stage layers (see stage.js). The frame fills the stage; layout.js places the painting and the circle. */
.frame{position:absolute;inset:0;translate:var(--shift,0) 0;transition:translate var(--dur-base) var(--ease-out)}   /* slides aside when the drawer opens (pilot.js) */
.clip{position:absolute;inset:0;overflow:hidden}
.pan{position:absolute;left:0;top:0;width:1672px;height:941px;transform-origin:0 0;background-size:100% 100%}
/* The painting's border is --paper but the Research ground is --wash-research (trial, 2026-10-05), so its outer edge is feathered into the ground: a gradient of the
   ground colour over the border (about 7% top and bottom, where the painting has plain paper; 2.5% at the sides, where the river and the sea run off the edge). */
.pan::after{content:"";position:absolute;inset:0;pointer-events:none;background:linear-gradient(to bottom,var(--wash-research) 0,transparent 7%,transparent 93%,var(--wash-research) 100%),linear-gradient(to right,var(--wash-research) 0,transparent 2.5%,transparent 97.5%,var(--wash-research) 100%)}
.paint{display:block;width:1672px;height:941px;max-width:none;opacity:0;transition:opacity .45s var(--ease-out)}
.frame.loaded .paint{opacity:1}
.koi{position:absolute;left:0;top:0;width:1672px;height:941px;overflow:visible;pointer-events:none}
.weather{position:absolute;pointer-events:none}   /* rain and lightning: placed and sized in painting units by weather.js */
.ring{position:absolute;left:0;top:0;width:100%;height:100%;overflow:visible;pointer-events:none;visibility:hidden}
.pillars{position:absolute;left:0;top:0;width:100%;height:100%;overflow:visible;pointer-events:none;visibility:hidden}   /* the Sustainability rim: three arrows and three words, in the chapter's olive */
.pillars path{stroke:var(--ring-kf08);stroke-width:3px;stroke-linejoin:round}
.pillars .pillar-tail{stop-color:#dfe8a8}.pillars .pillar-head{stop-color:#98b53c}   /* the fill deepens from tail to head: two yellow-greens next to the chapter's olive outline */
.pillars text{fill:var(--ring-kf08-text);font-family:var(--font-sans);font-weight:600;letter-spacing:.02em;paint-order:stroke;stroke:var(--wash-research);stroke-width:5px;stroke-linejoin:round}   /* a halo of the ground colour keeps the words clear of the painting's edge */

/* Phone and tablet: the circle is large and centred, the caption sits under it, the chapter rail runs along the top
   and the drawer is a bottom sheet. (900px matches STACKED_MAX in layout.js.) */
@media(max-width:900px){
 #stage{inset:0}
 .heading{top:calc(var(--header-h) + 64px)}   /* below the chapter rail row */
 .heading h2{font-size:28px;max-width:340px}
 #content{top:var(--caption-top,60%);right:0;left:0;translate:none;width:auto}
 .caption-lead{font-size:clamp(19px,5vw,24px)}
 /* A phone shows only the numerals in the chapter list, so the chapter's name goes above the text, in its own colour (2026-10-05, the user's request). Screen readers have it everywhere. */
 #content .kicker{position:static;width:auto;height:auto;overflow:visible;clip-path:none;white-space:normal;margin-bottom:var(--space-2);color:var(--ring-text,var(--ink));font:600 clamp(25px,6.6vw,31px)/1.15 var(--font-sans)}   /* larger than the text under it (which is 19 to 24px) */
 #content #chapter-num{display:none}
 /* On a phone as short as most are with the browser bars showing, the caption (name, text, button) is set a little tighter so the circle can stay large. */
 @media(max-height:820px){
  #content .kicker{margin-bottom:var(--space-1);font-size:clamp(22px,5.8vw,27px)}   /* still larger than the text under it (17 to 21px) */
  .caption-lead{margin-top:var(--space-1);font-size:clamp(17px,4.6vw,21px);line-height:1.22}
  #work{margin-top:var(--space-3)}
 }
 .rail{left:0;right:0;top:calc(var(--header-h) + 8px - 0px);translate:none;display:flex;justify-content:center}
 .rail ol{flex-direction:row}
 .rail-item{width:38px;min-width:0;height:44px;padding:0;justify-content:center;transform-origin:center}
 .rail-item[aria-current="step"]{transform:scale(1.35)}
 .rail-label{display:none}
 .drawer{top:auto;bottom:0;left:calc(var(--gutter) * -1);right:calc(var(--gutter) * -1);width:auto;max-height:76svh;border-left:0;border-top:1px solid var(--line);border-radius:16px 16px 0 0;box-shadow:0 -12px 32px rgba(40,58,71,.14);transform:translateY(24px)}
 .drawer-head{padding:var(--space-3) var(--gutter)}
 .drawer-body{padding-inline:var(--gutter)}
}

/* A short fade over the page (below the header) that hides the cut when scrolling up from NBIF jumps back to the overview. */
.veil{position:fixed;inset:var(--header-h) 0 0 0;z-index:15;background:var(--wash-research);opacity:0;pointer-events:none;transition:opacity 480ms ease-out}   /* fades back out slowly */
.veil.on{opacity:1;transition-duration:260ms}   /* covers the page a little faster; pilot.js FADE_IN matches */
@media(prefers-reduced-motion:reduce){.veil{display:none}}

/* ---------- Prototype controls: only with ?dev=1 ---------- */
.controls,#instruction,#cursor-position{display:none}
body.dev .controls{display:flex;position:absolute;bottom:5%;left:var(--gutter);right:var(--gutter);align-items:center;gap:16px}
body.dev #instruction{display:block}
body.dev #cursor-position{display:block;position:absolute;z-index:4;pointer-events:none;background:rgba(255,255,255,.9);border:1px solid var(--ink);padding:2px 5px;font:11px monospace;color:var(--ink);transform:translate(10px,10px)}
.controls button{min-width:44px;min-height:44px;border:0;background:transparent;font:inherit;font-size:12px;padding:8px;cursor:pointer}
.controls input{flex:1;accent-color:var(--accent)}
.controls select{max-width:260px;min-height:44px;background:var(--paper);color:var(--ink);border:1px solid #aebdc4;font:12px var(--font-sans);padding:5px}
.controls output{font:12px monospace;min-width:4ch}
.still{font-size:11px;white-space:nowrap;display:flex;align-items:center;gap:5px}
.controls .still input{flex:none}
.fish-editor{font-size:11px;position:relative}
.fish-editor summary{cursor:pointer}
.fish-editor[open] summary{color:var(--accent)}
.fish-editor textarea{display:block;width:min(420px,42vw);font:11px/1.35 monospace;margin-top:6px}
.fish-editor button{display:inline-block;font-size:11px;padding:5px 9px;margin-top:4px;border:1px solid #aebdc4;border-radius:3px}
@media(max-width:650px){body.dev .controls{flex-wrap:wrap;gap:7px;bottom:4%}.controls input[type=range]{flex-basis:60%;min-width:80px}.controls select{max-width:calc(100% - 105px);flex:1}.still{font-size:10px;margin-left:auto}}
/* The status line is read aloud by screen readers; it is visible only in dev mode or on an error. */
#status{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
body.dev #status,#status.error{width:auto;height:auto;overflow:visible;clip-path:none;white-space:normal;bottom:0;left:var(--gutter);font-size:11px;color:var(--ink-muted)}
#status.error{font-size:14px;color:var(--ink)}
body.clean .site-header,body.clean .stage-overlay,body.clean .controls,body.clean #status{display:none!important}
body.clean #journey{height:100vh}
body.clean .sticky{min-height:0}
body.clean #stage{inset:0}

/* ---------- Bands: NBIF, Education, Contact ---------- */
.band{padding-block:var(--section-pad)}
/* Section washes (trial, 2026-10-05). Every section has its own colour (--bg) and arrives at it from the colour above (--bg-from) over --fade, eased
   (smoothstep) and mixed in OKLCH so the hue travels through the spectrum between the two instead of greying out in the middle. The Research stage stays
   on --paper: the painting's border is that colour. The intro fades down to --paper at its own bottom. Without color-mix the fade is a plain two-colour gradient. */
:root{--fade:clamp(140px,18vw,260px)}
.about,.band{background-color:var(--bg)}
.band{background-image:linear-gradient(to bottom,var(--bg-from) 0,var(--bg) var(--fade))}
.about{--bg:var(--paper);--ok:var(--ok-paper);background-image:linear-gradient(to bottom,var(--bg) calc(100% - var(--fade)),var(--wash-research) 100%)}
#journey{background-color:var(--wash-research)}
.nbif-section{--bg:var(--wash-nbif);--bg-from:var(--wash-research);--ok:var(--ok-nbif);--ok-from:var(--ok-research)}
.edu-section{--bg:var(--wash-edu);--bg-from:var(--wash-nbif);--ok:var(--ok-edu);--ok-from:var(--ok-nbif)}
.contact-section{--bg:var(--wash-contact);--bg-from:var(--wash-edu);--ok:var(--ok-contact);--ok-from:var(--ok-edu)}
@supports (background:color-mix(in oklch,red,blue)){
 .band{background-image:linear-gradient(to bottom,var(--bg-from) 0,
  color-mix(in oklch,var(--ok-from) 95.7%,var(--ok)) calc(var(--fade) * .125),color-mix(in oklch,var(--ok-from) 84.4%,var(--ok)) calc(var(--fade) * .25),
  color-mix(in oklch,var(--ok-from) 68.4%,var(--ok)) calc(var(--fade) * .375),color-mix(in oklch,var(--ok-from) 50%,var(--ok)) calc(var(--fade) * .5),
  color-mix(in oklch,var(--ok-from) 31.6%,var(--ok)) calc(var(--fade) * .625),color-mix(in oklch,var(--ok-from) 15.6%,var(--ok)) calc(var(--fade) * .75),
  color-mix(in oklch,var(--ok-from) 4.3%,var(--ok)) calc(var(--fade) * .875),var(--bg) var(--fade))}
 .about{background-image:linear-gradient(to bottom,var(--bg) calc(100% - var(--fade)),
  color-mix(in oklch,var(--ok) 95.7%,var(--ok-research)) calc(100% - var(--fade) * .875),color-mix(in oklch,var(--ok) 84.4%,var(--ok-research)) calc(100% - var(--fade) * .75),
  color-mix(in oklch,var(--ok) 68.4%,var(--ok-research)) calc(100% - var(--fade) * .625),color-mix(in oklch,var(--ok) 50%,var(--ok-research)) calc(100% - var(--fade) * .5),
  color-mix(in oklch,var(--ok) 31.6%,var(--ok-research)) calc(100% - var(--fade) * .375),color-mix(in oklch,var(--ok) 15.6%,var(--ok-research)) calc(100% - var(--fade) * .25),
  color-mix(in oklch,var(--ok) 4.3%,var(--ok-research)) calc(100% - var(--fade) * .125),var(--wash-research) 100%)}
}
.band-grid{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:var(--col-gap);row-gap:var(--space-4);align-items:start}
/* NBIF, Education and Contact use the whole container, like About and Research (2026-10-04, the user's request): the section name sits above its heading at the
   container's left edge, and the content runs the full width. */
.band-label{grid-column:1/-1;font:450 var(--step-lead)/1.2 var(--font-serif);color:var(--ink)}
.band-body{grid-column:1/-1}
.band h2{font:450 var(--step-h2)/1.15 var(--font-serif);margin-bottom:var(--space-5);max-width:30ch}
.band p{max-width:62ch}
.band .links{margin-top:var(--space-4)}
/* Contact: one ruled list; every value is set in the same size, so nothing competes with the heading above it */
.contact-lead{font:400 var(--step-lead)/1.45 var(--font-sans)}
.contact-list{margin:var(--space-7) 0 0;padding:0;border-top:2px solid var(--accent)}   /* the accent rule that marks a list, as in NBIF and Education */
.contact-list>div{display:grid;grid-template-columns:minmax(0,9rem) minmax(0,1fr);gap:var(--space-2) var(--space-5);align-items:center;padding:var(--space-2) 0;border-bottom:1px solid var(--line)}
.contact-list dt{color:var(--ink-muted);font:500 var(--step-small)/1.4 var(--font-sans)}
.contact-list dd{margin:0}
.contact-profiles{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:0 var(--space-5)}   /* four profiles as two by two, so no name is left alone on a second line */
.contact-link{display:inline-flex;align-items:center;min-height:44px;color:var(--ink);font:450 var(--step-lead)/1.2 var(--font-serif);font-variant-numeric:lining-nums tabular-nums;text-decoration:underline;text-decoration-color:var(--accent);text-decoration-thickness:1px;text-underline-offset:.22em;overflow-wrap:anywhere;transition:color var(--dur-fast)}
.contact-profiles .contact-link{justify-self:start}
.contact-link:hover{color:var(--accent-strong);text-decoration-thickness:2px}
.contact-link .ext{display:inline-block;margin-left:.3em;color:var(--accent);font-size:.7em;text-decoration:none}
@media(min-width:1024px){
 .contact-section .band-body{display:grid;grid-template-columns:repeat(12,minmax(0,1fr));column-gap:var(--col-gap);align-items:start}
 .contact-section h2,.contact-lead{grid-column:1/span 4}
 .contact-list{grid-column:5/-1;grid-row:1/span 3;margin-top:0}   /* the heading and the lead on the left, the list across the rest of the width */
}
@media(max-width:1023px){.contact-list>div{grid-template-columns:1fr;gap:0;padding-block:var(--space-3)}}   /* the label goes above its value, so the values have the width */
@media(max-width:480px){.contact-profiles{grid-template-columns:1fr}}

/* ---------- NBIF section: the message, three strands, and the 3D model with its numbered list (DESIGN.md section 7) ---------- */
.nbif-link,.inline-link{color:var(--accent);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:.2em}
.nbif-link:hover,.inline-link:hover{color:var(--accent-strong)}
.band-label .nbif-link{color:var(--ink);text-decoration:none}
.band-label .nbif-label-text{text-decoration:underline;text-decoration-color:var(--accent);text-decoration-thickness:2px;text-underline-offset:.2em}   /* the underline is under the word, not the arrow */
.band-label .nbif-link:hover{color:var(--accent-strong)}
.band-label .ext{font-size:.65em;margin-left:.25em;vertical-align:.25em}
.band-label .nbif-label{display:inline-flex;align-items:center;min-height:44px;margin-block:-10px}   /* a 44px target that takes only the text's height in the layout, so the heading below sits where it does in the other sections */
.nbif-section h2{max-width:30ch}
.nbif-lead{font:400 var(--step-lead)/1.45 var(--font-sans)}
.nbif-examples{margin:var(--space-5) 0 0}
.nbif-strands{list-style:none;margin:var(--space-3) 0 0;padding:0;display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--space-5) var(--space-6)}
.nbif-strands li{padding-top:var(--space-3);border-top:2px solid var(--accent)}   /* a rule marks each strand */
.nbif-strands h3{margin:0 0 var(--space-2);font:450 var(--step-lead)/1.2 var(--font-serif)}
.nbif-strands p{margin:0;font-size:var(--step-small);line-height:1.5}
.nbif-invite{margin-top:var(--space-6)}   /* an invitation to industry and research partners, under the strands */
.nbif-section .links{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3) var(--space-5);margin-top:var(--space-4)}
.nbif-section .btn .ext{margin-left:.3em}
@media(max-width:1023px){.nbif-strands{grid-template-columns:1fr}}

/* The figure: the model (the centrepiece) on the left and its numbered list on the right, in a raised box as tall as the model and the button
   row under it (1000px and up, with JavaScript and WebGL). Narrower windows, and browsers without JavaScript or WebGL, stack them: the same box
   below the model, in columns, with every explanation showing. The viewer (nbif-3d/nbif-viewer.js) adds the toolbar after the stage. */
.nbif-fig{margin-top:var(--space-8);display:grid;grid-template-columns:minmax(0,1fr);grid-template-areas:"stage" "toolbar" "list";
 /* The box: a darker shade of the band's own sand, lifted off the page: a soft top-to-bottom gradient, a lit top edge, a fine darker rim and
    three warm shadows (contact, body, and a long soft one). */
 --nbif-box-bg:linear-gradient(180deg,#e0dcc3 0%,#d8d3b7 100%);--nbif-box-border:1px solid rgba(84,74,34,.22);
 --nbif-box-shadow:inset 0 1px 0 rgba(255,255,255,.6),inset 0 -1px 0 rgba(84,74,34,.10),0 1px 2px rgba(64,55,20,.14),0 8px 18px -4px rgba(64,55,20,.20),0 26px 44px -14px rgba(64,55,20,.30);
 --nbif-row:30px;--nbif-detail:13px}
.nbif-fig .nbif-3d__stage{grid-area:stage}
.nbif-fig .nbif-3d__toolbar,.nbif-fig .nbif-3d__start{grid-area:toolbar}
.nbif-fig .nbif-list{grid-area:list}
/* The box, stacked: natural height, the parts in columns. */
.nbif-fig .nbif-list>ol{margin:var(--space-6) 0 0;padding:var(--space-4) var(--space-5);background:var(--nbif-box-bg);border:var(--nbif-box-border);border-radius:var(--radius-2);box-shadow:var(--nbif-box-shadow)}
.nbif-fig .nbif-3d__item{padding:4px var(--space-2);border-radius:var(--radius-1)}
.nbif-fig .nbif-3d__detail{color:rgba(40,58,71,.9)}   /* ink, not the muted grey: the muted grey is only 3.9:1 on the darker sand */
.nbif-fig .nbif-3d__item:hover{background:rgba(255,255,255,.28)}
.nbif-fig .nbif-3d__item[aria-current="true"]{background:linear-gradient(180deg,#fbf9ef,#f3f0e0);border-radius:6px;box-shadow:0 1px 2px rgba(64,55,20,.18),0 4px 10px -2px rgba(64,55,20,.20),inset 0 1px 0 #fff}   /* the chosen row is a lifted card */
/* On a mouse the buttons and the hint are small enough to share one line under the model (nbif-section.js shortens the hint to match).
   On touch screens they keep the viewer's 44px size. 28px is above WCAG 2.2's 24px target minimum (2.5.8). */
@media(hover:hover) and (pointer:fine){
 .nbif-fig .nbif-3d__toolbar,.nbif-fig .nbif-3d__group{gap:var(--space-2)}
 .nbif-fig .nbif-3d__toolbar{margin-top:var(--space-3)}
 .nbif-fig .nbif-3d__btn{min-height:28px;min-width:28px;padding:0 var(--space-3);font-size:12px;border-radius:6px}
 .nbif-fig .nbif-3d__btn--icon{padding:0;font-size:1rem}
 .nbif-fig .nbif-3d__hint{flex:0 1 auto;margin:0 0 0 var(--space-2);font-size:12px;line-height:1.3;white-space:nowrap}
}
@media(min-width:1000px){
 /* Only with JavaScript and WebGL. Without them (no script, or a browser that cannot draw the model) the list stays under the still
    image with every explanation showing, because a fixed-height box could not be scrolled from the keyboard. */
 .js .nbif-fig:not(.is-static){grid-template-columns:minmax(0,8fr) minmax(0,4fr);grid-template-areas:"stage list" "toolbar list";column-gap:var(--col-gap)}
 /* The box is as tall as the model plus the button row: the list is laid inside it, so it adds nothing to the rows' height. */
 .js .nbif-fig:not(.is-static) .nbif-list{position:relative;min-height:0}
 .js .nbif-fig:not(.is-static) .nbif-list>ol{position:absolute;inset:0;margin:0;padding:3px var(--space-3);overflow:auto;display:flex;flex-direction:column;gap:0}
 .js .nbif-fig:not(.is-static) .nbif-3d__legend li,.js .nbif-fig:not(.is-static) .nbif-3d__item{grid-template-columns:24px 1fr;column-gap:var(--space-3)}
 .js .nbif-fig:not(.is-static) .nbif-3d__legend li{border-top:1px solid rgba(84,74,34,.20);box-shadow:inset 0 1px 0 rgba(255,255,255,.42)}   /* a hairline with a light edge under it: engraved */
 .js .nbif-fig:not(.is-static) .nbif-3d__legend li:first-child{border-top:0;box-shadow:none}
 .js .nbif-fig:not(.is-static) .nbif-3d__legend>li{flex:1 0 auto;align-content:center}   /* before the 3D view loads a row is the li itself (a grid of numeral, name and explanation) */
 .js .nbif-fig.is-3d:not(.is-static) .nbif-3d__legend>li{display:flex;flex-direction:column}   /* once it runs the li holds a button, which takes the row's height */
 .js .nbif-fig.is-3d:not(.is-static) .nbif-3d__item{flex:1 1 auto;align-content:center}
 .js .nbif-fig:not(.is-static) .nbif-3d__stage{aspect-ratio:4/3}
 /* Rows as roomy as the box allows. The base row is the least a row may be (30px; 28px from 1000 to 1279px wide), which always fits fourteen rows with one
    explanation open, and is above WCAG 2.2's 24px minimum for a target (2.5.8). Whatever is left in the box is then shared out between the rows, so there is
    no empty strip at the bottom and the rows grow to about 38px on a large window. The model's frame is 4:3 from 1000px, which is what gives the box its
    height. On touch screens the rows are 44px. */
 .js .nbif-fig:not(.is-static) .nbif-3d__item{min-height:var(--nbif-row);padding:calc((var(--nbif-row) - 24px) / 2) var(--space-2);align-items:start}
 .js .nbif-fig:not(.is-static) .nbif-3d__num{width:24px;height:24px;font-size:12px}
 .js .nbif-fig:not(.is-static) .nbif-3d__name{padding-top:2px}   /* the 24px numeral and the name share a centre line, open or closed */
 .js .nbif-fig:not(.is-static) .nbif-3d__detail{display:block;margin-top:0;padding-bottom:1px;font-size:var(--nbif-detail);line-height:1.35}
 /* Only the chosen part explains itself (the first one until a part is chosen), also before the 3D view has loaded: with every explanation
    open the box would be taller than the model and would scroll by mouse only, which axe-core flags (scrollable-region-focusable). With
    no script or no WebGL the figure is `is-static` and the list stays below the still image with every explanation showing. */
 .js .nbif-fig:not(.is-static) .nbif-3d__detail{display:none}
 .js .nbif-fig:not(.is-static) .nbif-3d__item[aria-current="true"] .nbif-3d__detail{display:block}
 .js .nbif-fig:not(.is-static) .nbif-list:not(:has([aria-current="true"])) li:first-child .nbif-3d__detail{display:block}
}
/* 1000 to 1279px: the model column is narrower, so the box is shorter, and rows and text are a little smaller. */
@media(min-width:1000px) and (max-width:1279px){
 .js .nbif-fig:not(.is-static){--nbif-row:28px;--nbif-detail:12px}
}
@media(min-width:1000px) and (max-width:1279px) and (hover:hover) and (pointer:fine){
 .js .nbif-fig:not(.is-static) .nbif-3d__btn:not(.nbif-3d__btn--icon){padding:0 var(--space-2)}
}
@media(min-width:1000px) and (pointer:coarse){.js .nbif-fig:not(.is-static) .nbif-3d__item{min-height:44px}}


/* ---------- Education section: the modules taught now, and supervision by area (DESIGN.md section 7) ---------- */
.edu-section{--edu-rule:rgba(40,58,71,.2)}   /* hairlines on --mist: a tint of --ink, decorative only */
.edu-lead{font:400 var(--step-lead)/1.45 var(--font-sans)}
.edu-jump{margin-top:var(--space-5);gap:var(--space-3)}
.edu-section h3{margin:0 0 var(--space-4);font:450 var(--step-h3)/1.2 var(--font-serif)}
.edu-section h4{margin:0}
.edu-modules-block,.edu-supervision{margin-top:var(--space-8);padding-top:var(--space-4);border-top:2px solid var(--accent)}   /* each block starts with the accent rule that marks a list, across the full width */
.edu-modules{list-style:none;margin:0;padding:0;border-top:1px solid var(--edu-rule)}
.edu-module{display:flex;flex-wrap:wrap;align-items:baseline;justify-content:space-between;gap:var(--space-1) var(--space-5);padding:var(--space-4) 0;border-bottom:1px solid var(--edu-rule)}   /* title and level on one line; no description */
.edu-module h4{font:450 var(--step-lead)/1.25 var(--font-serif)}
.edu-section .edu-level{margin:0;max-width:none;color:var(--ink-muted);font-size:var(--step-small);line-height:1.5}
.edu-supervision h3{margin-bottom:var(--space-3)}
.edu-supervision h4{margin-bottom:var(--space-2);font:500 var(--step-small)/1.4 var(--font-sans);color:var(--ink-muted)}
.edu-list{list-style:none;margin:0;padding:0;border-top:1px solid var(--edu-rule);display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:var(--col-gap)}
.edu-list li{padding:8px 0;border-bottom:1px solid var(--edu-rule);line-height:1.4}
.edu-sup-cols{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:var(--col-gap);align-items:start}   /* the areas on the left, how to approach on the right */
.edu-areas .edu-list{grid-template-columns:1fr}
.edu-approach p{margin:0 0 var(--space-4)}
.edu-approach .edu-resources{margin-top:var(--space-2);margin-bottom:0}
@media(max-width:1023px){.edu-sup-cols{grid-template-columns:1fr;row-gap:var(--space-5)}.edu-areas .edu-list{grid-template-columns:repeat(2,minmax(0,1fr))}.edu-approach{margin-top:var(--space-2)}}
@media(max-width:720px){.edu-areas .edu-list{grid-template-columns:1fr}}
.edu-resources{display:flex;flex-wrap:wrap;gap:0 var(--space-5);margin-top:var(--space-2)}
.edu-resources .tlink{min-height:44px}
@media(max-width:720px){.edu-list{grid-template-columns:1fr}}

/* The 404 page (404.html): the same band as the sections, one heading and one way home */
.notfound-title{margin:0 0 var(--space-5);font:450 var(--step-h2)/1.15 var(--font-serif);max-width:22ch}
.notfound-lead{font:400 var(--step-lead)/1.45 var(--font-sans)}

/* ---------- Footer ---------- */
.site-footer{--bg-from:var(--wash-contact);--ok-from:var(--ok-contact);background-color:var(--paper);background-image:linear-gradient(to bottom,var(--bg-from),var(--paper));padding-block:var(--space-6);color:var(--ink-muted);font-size:var(--step-small)}
@supports (background:color-mix(in oklch,red,blue)){
 .site-footer{background-image:linear-gradient(to bottom,var(--bg-from) 0,color-mix(in oklch,var(--ok-from) 95.7%,var(--ok-paper)) 12.5%,color-mix(in oklch,var(--ok-from) 84.4%,var(--ok-paper)) 25%,
  color-mix(in oklch,var(--ok-from) 68.4%,var(--ok-paper)) 37.5%,color-mix(in oklch,var(--ok-from) 50%,var(--ok-paper)) 50%,color-mix(in oklch,var(--ok-from) 31.6%,var(--ok-paper)) 62.5%,
  color-mix(in oklch,var(--ok-from) 15.6%,var(--ok-paper)) 75%,color-mix(in oklch,var(--ok-from) 4.3%,var(--ok-paper)) 87.5%,var(--paper) 100%)}
}
.footer-row{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:var(--space-2) var(--space-5)}
.footer-links{display:flex;flex-wrap:wrap;gap:0 var(--space-5)}

@media(prefers-reduced-motion:reduce){.paint,.site-header,.btn,.stage-nbif,.contact-link,.site-nav a,.drawer,.drawer.is-open,.rail-item,.rail-item .numeral,.rail-label,.frame{transition:none}.drawer{transform:none}}
