/* Shehab Hassani — site styles. Shared by index.html and projects/*.html.
   Colour, type and plate rules are the Lambda Research system; see DESIGN-NOTES.md. */

/* ───────────────────────────────────────────────────────────────
   TYPE — the Lambda Research faces, OFL, served locally.
   Didot = display only.  STIX Two Text = body, figures, maths.
   Plex Sans = drafting annotations only.
   Copied from lambda-research-website/index.html; keep in step.
   ─────────────────────────────────────────────────────────────── */
@font-face{font-family:"LR Didot";src:url(fonts/didot-400-latin.woff2) format("woff2");font-weight:400;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+2212}
@font-face{font-family:"LR Didot";src:url(fonts/didot-400-greek.woff2) format("woff2");font-weight:400;font-display:swap;
  unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}
@font-face{font-family:"LR Stix";src:url(fonts/stix-400-latin.woff2) format("woff2");font-weight:400 700;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+2000-206F,U+20AC,U+2122,U+2212,U+2215}
@font-face{font-family:"LR Stix";src:url(fonts/stix-400-greek.woff2) format("woff2");font-weight:400 700;font-display:swap;
  unicode-range:U+0370-0377,U+037A-037F,U+0384-038A,U+038C,U+038E-03A1,U+03A3-03FF}
@font-face{font-family:"LR Plex";src:url(fonts/plex-400-latin.woff2) format("woff2");font-weight:100 700;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+2000-206F,U+2122}

/* ───────────────────────────────────────────────────────────────
   GROUND — five colours, two grounds, one system.
   Verbatim from the company site (= branding/colour/tokens.css).
   ─────────────────────────────────────────────────────────────── */
:root{
  --rail:9.25rem;
  --gutter:clamp(1.4rem,5vw,4.5rem);
  --measure:38rem;
  --ease:cubic-bezier(.22,.61,.36,1);

  --royal:#1F3BE0; --royal-lift:#7D9AFF; --paper:#F4F6FB; --navy:#0E1633; --deep:#080B1A;
  --bg:var(--paper); --fg:var(--navy); --acc:var(--royal);
  --rule:rgba(14,22,51,.16); --rule-2:rgba(14,22,51,.30);
  --dim:rgba(14,22,51,.60); --dim-2:rgba(14,22,51,.86);
  --vellum:rgba(244,246,251,.66); --vellum-edge:rgba(14,22,51,.14);
  --glow-a:rgba(31,59,224,.16); --glow-b:rgba(125,154,255,.20); --glow-c:rgba(14,22,51,.10);
  --grain:.22; --blend:multiply;
  --sheen:rgba(255,255,255,.95); --tile:rgba(14,22,51,.045);
}
/* the dot grid replaces the ruled columns on the blue grounds */

:root[data-ground="ink"]{
  --royal:#1F3BE0; --royal-lift:#7D9AFF; --paper:#F4F6FB; --navy:#0E1633; --deep:#080B1A;
  --bg:var(--deep); --fg:#E6EAF7; --acc:var(--royal-lift);
  --rule:rgba(230,234,247,.16); --rule-2:rgba(230,234,247,.30);
  --dim:rgba(230,234,247,.62); --dim-2:rgba(230,234,247,.90);
  --vellum:rgba(8,11,26,.55); --vellum-edge:rgba(230,234,247,.14);
  --glow-a:rgba(125,154,255,.18); --glow-b:rgba(31,59,224,.28); --glow-c:rgba(230,234,247,.06);
  --grain:.18; --blend:overlay;
  --sheen:rgba(230,234,247,.22); --tile:rgba(230,234,247,.04);
}

*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0; background:var(--bg); color:var(--fg);
  font-family:"LR Stix",Georgia,serif; font-size:clamp(1rem,.94rem + .28vw,1.14rem);
  line-height:1.68; font-kerning:normal; text-rendering:optimizeLegibility;
  -webkit-font-smoothing:antialiased;
  transition:background-color .7s var(--ease), color .7s var(--ease);
  overflow-x:hidden;
}
::selection{background:var(--acc); color:var(--bg)}
a{color:inherit; text-decoration:none}
h1,h2,h3{font-weight:400; margin:0}

/* ── the ground is never a flat fill ───────────────────────────── */
.ground{position:fixed; inset:0; z-index:0; pointer-events:none; overflow:hidden}
.ground__blob{position:absolute; border-radius:50%; filter:blur(80px); will-change:transform}
.b1{width:58vw; height:58vw; left:-12vw; top:-14vw;  background:radial-gradient(circle at 50% 50%,var(--glow-a),transparent 68%); animation:drift-a 64s var(--ease) infinite alternate}
.b2{width:52vw; height:52vw; right:-10vw; top:22vh;  background:radial-gradient(circle at 50% 50%,var(--glow-b),transparent 68%); animation:drift-b 78s var(--ease) infinite alternate}
.b3{width:64vw; height:64vw; left:18vw; bottom:-24vw; background:radial-gradient(circle at 50% 50%,var(--glow-c),transparent 70%); animation:drift-c 92s var(--ease) infinite alternate}
@keyframes drift-a{from{transform:translate3d(0,0,0) scale(1)}      to{transform:translate3d(9vw,7vh,0) scale(1.14)}}
@keyframes drift-b{from{transform:translate3d(0,0,0) scale(1.08)}   to{transform:translate3d(-8vw,-9vh,0) scale(.94)}}
@keyframes drift-c{from{transform:translate3d(0,0,0) scale(.96)}    to{transform:translate3d(6vw,-6vh,0) scale(1.16)}}
.ground__grain{position:absolute; inset:-50%; opacity:var(--grain); mix-blend-mode:var(--blend);
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='200' height='200' filter='url(%23n)'/%3E%3C/svg%3E");
  background-size:200px 200px}
.ground__rule{position:absolute; inset:0; opacity:.55;
  background-image:radial-gradient(circle,var(--rule) 1px,transparent 1.2px); background-size:28px 28px;
  -webkit-mask-image:linear-gradient(to bottom,transparent,#000 22%,#000 78%,transparent);
          mask-image:linear-gradient(to bottom,transparent,#000 22%,#000 78%,transparent)}

/* ── masthead: mark left, CV right, no ground of its own ───────── */
.masthead{position:fixed; top:clamp(1.5rem,3.4vh,2.4rem); left:var(--gutter); right:var(--gutter);
  z-index:45; display:flex; align-items:center; justify-content:space-between; pointer-events:none}
.masthead > *{pointer-events:auto}
.masthead__mark{display:block; color:var(--fg); opacity:.92; transition:opacity .4s var(--ease)}
.masthead__mark:hover{opacity:1}
.masthead svg{display:block; width:auto; height:clamp(20px,2.1vw,26px)}

/* ── breadcrumb: masthead right slot on every project page ───────── */
.crumbs{display:flex; align-items:center; gap:.6rem; margin-right:clamp(1.25rem,4vw,4.5rem); padding:.25rem 0;
  font-family:"LR Plex",system-ui,sans-serif; font-size:.685rem; letter-spacing:.15em; text-transform:uppercase; color:var(--dim)}
.crumbs a{color:var(--fg); transition:color .35s var(--ease)}
.crumbs a:hover,.crumbs a:focus-visible{color:var(--acc)}
.crumbs span[aria-current]{color:var(--dim)}
.crumbs i{font-style:normal; width:5px; height:5px; margin-top:-2px; border-right:1px solid var(--rule-2); border-bottom:1px solid var(--rule-2); transform:rotate(-45deg)}
@media (max-width:480px){ .crumbs{gap:.45rem; font-size:.62rem; letter-spacing:.12em} .crumbs span[aria-current]{display:none} .crumbs i:last-of-type{display:none} }

/* ── repository tile: the GitHub mark, a label, and a reflection that
      sweeps across on hover. The sweep is the Ugarit scope-of-work tile's,
      re-timed to this system's ease and coloured from its own palette. ── */
.repo{position:relative; display:inline-flex; align-items:center; gap:.9rem; overflow:hidden; max-width:100%;
  padding:.85rem 1.2rem .85rem 1rem; border:1px solid var(--rule); border-radius:2px; background:var(--tile);
  color:var(--fg); transition:border-color .45s var(--ease), transform .45s var(--ease), box-shadow .45s var(--ease)}
.repo::before{content:""; position:absolute; top:7px; left:7px; width:8px; height:8px; opacity:.5;
  border-top:1px solid var(--rule-2); border-left:1px solid var(--rule-2)}
.repo::after{content:""; position:absolute; top:-10%; bottom:-10%; left:-70%; width:45%; pointer-events:none;
  background:linear-gradient(105deg,transparent,var(--sheen),transparent); transform:skewX(-18deg);
  transition:left .7s var(--ease)}
.repo:hover,.repo:focus-visible{border-color:var(--acc); transform:translateY(-3px); box-shadow:0 12px 28px rgba(33,25,19,.10)}
.repo:hover::after,.repo:focus-visible::after{left:130%}
.repo__icon{display:grid; place-items:center; width:38px; height:38px; flex:0 0 auto; border-radius:50%; border:1px solid var(--rule-2); color:var(--fg);
  transition:transform .35s var(--ease), color .35s var(--ease), border-color .35s var(--ease)}
.repo__icon svg{width:19px; height:19px; display:block}
.repo:hover .repo__icon{transform:translateY(-2px) scale(1.08); color:var(--acc); border-color:var(--acc)}
.repo__t{display:flex; flex-direction:column; gap:.3rem; min-width:0; font-family:"LR Plex",system-ui,sans-serif; font-size:.62rem; letter-spacing:.2em; text-transform:uppercase; color:var(--dim)}
.repo__t b{font-family:"LR Stix",Georgia,serif; font-weight:400; font-size:.98rem; letter-spacing:0; text-transform:none; color:var(--fg);
  white-space:nowrap; overflow:hidden; text-overflow:ellipsis}
.repo__t b .slot{color:var(--dim)}
.repo + .repo{margin-left:.8rem}
.repos{display:flex; flex-wrap:wrap; gap:.8rem; margin-top:1.6rem}
section.pg .repos + ul{margin-top:1.4rem}
/* links inside the overview: the tile, then the rest as a short tracked list */
.links-inline{margin-top:1.8rem; max-width:52rem}
.links-inline .repos{margin-top:0}
.links-list{list-style:none; margin:1rem 0 0; padding:0; display:flex; flex-wrap:wrap; gap:.4rem 1.8rem;
  font-family:"LR Plex",system-ui,sans-serif; font-size:.62rem; letter-spacing:.2em; text-transform:uppercase; color:var(--dim)}
.links-list .slot{text-transform:none; letter-spacing:.06em}
.pg--nav{padding-top:0}
.pg--nav .pn{margin-top:0}

/* ── system design drawing ────────────────────────────────────────
      Layers as stacked bands, components as boxes, arrows along the real
      data path. Line weight and lettering after ISLR: hairlines, serif
      layer titles, small capitals for everything else. Generated by
      projects/build-arch.py. Hover a layer to light the flows touching it. */
.arch__frame{padding:clamp(.6rem,1.5vw,1.2rem) clamp(.4rem,1.2vw,1rem); overflow-x:auto}
.arch__svg{width:100%; min-width:760px; height:auto; display:block}
.arch__svg--portrait{display:none; min-width:0}
.arch__band{fill:transparent; stroke:none; transition:fill .35s var(--ease)}   /* bands separate by tint alone, no outline */
.arch__layer:nth-child(even) .arch__band{fill:var(--tile)}
.arch__layer.lit .arch__band{fill:var(--vellum)}
.arch__ln{font-family:"LR Stix",Georgia,serif; font-style:italic; font-size:15px; fill:var(--fg); transition:fill .35s var(--ease)}
.arch__lno{font-family:"LR Plex",system-ui,sans-serif; font-size:9px; letter-spacing:.22em; fill:var(--acc)}
.arch__layer.lit .arch__ln{fill:var(--acc)}
.arch__box{fill:var(--bg); stroke:var(--fg); stroke-width:1; transition:stroke .35s var(--ease)}
.arch__ic{fill:none; stroke:var(--fg); stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; transition:stroke .35s var(--ease)}
.arch__il{font-family:"LR Plex",system-ui,sans-serif; font-size:9px; letter-spacing:.12em; fill:var(--fg)}
.arch__nodes.lit .arch__box,.arch__nodes.lit .arch__ic{stroke:var(--acc)}
.arch__edges{pointer-events:none}
.arch__edge{fill:none; stroke:var(--fg); stroke-opacity:.55; stroke-width:1; transition:stroke .35s var(--ease), stroke-opacity .35s var(--ease)}
.arch__edge--dash{stroke-dasharray:3 4}
.arch__edge.lit{stroke:var(--acc); stroke-opacity:1; stroke-width:1.4}
.arch__ah{fill:var(--fg)}
.arch__el rect{fill:var(--bg); stroke:none}
.arch__el text{font-family:"LR Plex",system-ui,sans-serif; font-size:8px; letter-spacing:.14em; fill:var(--dim)}
.arch__el.lit text{fill:var(--acc)}
.arch__layer{outline:none; cursor:default}
/* reveal: bands settle in order, then the flows draw along their length */
.arch.rv .arch__layer,.arch.rv .arch__nodes{opacity:0; transition:opacity .7s var(--ease) calc(var(--i) * .1s)}
.arch.rv.in .arch__layer,.arch.rv.in .arch__nodes{opacity:1}
.arch.rv .arch__edge:not(.arch__edge--dash){stroke-dasharray:900; stroke-dashoffset:900; transition:stroke-dashoffset 1.4s var(--ease) .5s, stroke .35s var(--ease), stroke-opacity .35s var(--ease)}
.arch.rv.in .arch__edge:not(.arch__edge--dash){stroke-dashoffset:0}
.arch.rv .arch__el{opacity:0; transition:opacity .6s var(--ease) 1.4s}
.arch.rv.in .arch__el{opacity:1}

/* ── two-column sections: prose left at its measure, figure right ──
      The text column never widens past 38rem; the figure takes what is
      left and, where it is a single plate, stays in view while the text
      scrolls past it. One column again below 1080px. */
.two{display:grid; grid-template-columns:minmax(0,var(--measure)) minmax(0,1fr); gap:clamp(2rem,5vw,5rem); align-items:start}
.two__text > .plate{display:none}
.two__fig{min-width:0}
.two__fig .plate{margin-top:0}
.two__fig .plate + .plate{margin-top:clamp(2rem,4vh,3rem)}
/* the cell stretches to its row and the plate sticks inside it, so a sticky
   figure stops at the foot of the text beside it and never runs on under a
   full-width row below */
.two__fig{align-self:stretch}
.two__fig--sticky > .plate{position:sticky; top:clamp(4.5rem,10vh,7rem)}
/* a side-by-side figure is exactly as tall as the text beside it: the row's
   --fig-h is set from the text column (chrome.js), floored so the drawing stays
   legible and capped so a sticky plate never overflows the viewport */
.two__fig .plate,.hobby .plate{display:flex; flex-direction:column}
.plate__frame[data-fill]{height:var(--fig-h,auto); flex:0 0 auto}
.two__wide{grid-column:1 / -1}
.two__wide .plate{margin-top:clamp(2rem,4vh,3rem)}
.two .entries{margin-top:clamp(1.6rem,4vh,2.4rem)}
.two .strands{grid-template-columns:1fr; gap:1.4rem}
@media (max-width:1080px){
  .two{grid-template-columns:minmax(0,1fr)}   /* minmax(0): a wide drawing scrolls in its frame, not the page */
  .two__wide{min-width:0}
  .two__fig--sticky > .plate{position:static}
  .two__fig .plate{margin-top:clamp(2.5rem,6vh,4rem)}
  .plate__frame[data-fill]{height:auto}
}

/* ── hobbies: three rows, the hobby's text beside its own plate ────── */
.hobby{display:grid; grid-template-columns:minmax(0,28rem) minmax(0,1fr); gap:clamp(1.5rem,4vw,4rem); align-items:center;
  padding:clamp(1rem,2.4vh,1.6rem) 0; border-top:1px solid var(--rule-2)}
.hobby:first-of-type{margin-top:clamp(2rem,5vh,3rem)}
.hobby:last-of-type{border-bottom:1px solid var(--rule)}
.hobby__t h3{margin:0 0 .55rem}
.hobby__t p{font-size:.94em; color:var(--dim); margin:0; max-width:27rem}
.hobby .plate{margin-top:0; min-width:0}
@media (max-width:1080px){ .hobby{grid-template-columns:1fr; gap:1.4rem} .hobby .plate__frame[data-fill]{height:auto} }

/* ── the rail ──────────────────────────────────────────────────── */
.rail{position:fixed; left:var(--gutter); top:50%; transform:translateY(-50%); z-index:40; width:var(--rail)}
.rail ol{list-style:none; margin:0; padding:0}
.rail li + li{margin-top:.15rem}
.rail a{display:flex; align-items:baseline; gap:.55rem; padding:.3rem 0;
  font-family:"LR Plex",system-ui,sans-serif; font-size:.685rem; letter-spacing:.15em;
  text-transform:uppercase; color:var(--dim); font-weight:400; transition:color .35s var(--ease)}
.rail a:hover,.rail a:focus-visible{color:var(--fg)}
.rail a[aria-current="true"]{color:var(--fg); font-weight:600; letter-spacing:.142em}
.rail__n{font-size:.56rem; letter-spacing:.1em; opacity:.62; font-variant-numeric:tabular-nums; font-weight:400}
.rail a[aria-current="true"] .rail__n{color:var(--acc); opacity:1; font-weight:600}
.rail__sep{height:1px; width:2.2rem; background:var(--rule); margin:.95rem 0 .8rem}
.swap{display:flex; align-items:center; gap:.5rem; width:100%; padding:.1rem 0; border:0; background:none;
  cursor:pointer; color:var(--dim); font-family:"LR Plex",system-ui,sans-serif; font-size:.585rem;
  letter-spacing:.15em; text-transform:uppercase; transition:color .35s var(--ease)}
.swap:hover{color:var(--fg)}
.swap__dot{width:9px; height:9px; border-radius:50%; border:1px solid var(--rule-2); background:var(--ink);
  flex:0 0 auto; transition:background-color .5s var(--ease)}
:root[data-ground="ink"] .swap__dot{background:var(--fg)}
.swap + .swap{margin-top:.3rem}

/* ── scroll position, as a drafting scale on the right edge ────── */
.scale{position:fixed; right:calc(var(--gutter) * .55); top:18vh; bottom:18vh; width:1px; background:var(--rule); z-index:35}
.scale__tick{position:absolute; left:-4px; width:9px; height:1px; background:var(--acc); top:0; transition:top .12s linear}

/* ── layout ────────────────────────────────────────────────────── */
main{position:relative; z-index:10; padding-left:calc(var(--gutter) + var(--rail) + clamp(1.5rem,4vw,4rem)); padding-right:var(--gutter)}
section{max-width:80rem; padding-block:clamp(6rem,17vh,11rem)}
.hero{min-height:100svh; display:flex; flex-direction:column; justify-content:center;
  padding-top:0; padding-bottom:clamp(2.5rem,6vh,4rem); max-width:64rem}
.hero h1{font-size:clamp(3rem,8.4vw,7.2rem); letter-spacing:-.012em; max-width:none}
.hero .lede{margin-top:2rem}

/* ── profile links: icon and tracked label, no buttons ─────────── */
.links{list-style:none; margin:2.6rem 0 0; padding:0; display:flex; flex-wrap:wrap; gap:.4rem clamp(1.6rem,3vw,2.6rem)}
.links a{display:inline-flex; align-items:center; gap:.6rem; padding:.45rem 0; white-space:nowrap;
  font-family:"LR Plex",system-ui,sans-serif; font-size:.685rem; letter-spacing:.15em; text-transform:uppercase;
  color:var(--dim); border-bottom:1px solid transparent; transition:color .35s var(--ease), border-color .35s var(--ease)}
.links a:hover,.links a:focus-visible{color:var(--acc); border-color:var(--acc)}
.links a[href^="mailto:"] span{text-transform:none; letter-spacing:.06em}
.links svg{width:15px; height:15px; display:block; flex:0 0 auto}

.eyebrow{font-family:"LR Plex",system-ui,sans-serif; font-size:.66rem; letter-spacing:.26em;
  text-transform:uppercase; color:var(--dim); display:flex; align-items:center; gap:.85rem}
.eyebrow::after{content:""; height:1px; flex:1; max-width:7rem; background:var(--rule)}
.eyebrow--plain::after{content:none}   /* the opening carries no trailing rule */
h1{font-family:"LR Didot",Georgia,serif; font-size:clamp(2.6rem,6.6vw,5.9rem); line-height:1.0;
  letter-spacing:-.008em; margin:1.4rem 0 0; max-width:21ch; text-wrap:balance}
h1 em{font-style:normal; color:var(--acc)}
h2{font-family:"LR Didot",Georgia,serif; font-size:clamp(1.9rem,3.6vw,3.1rem); line-height:1.08;
  letter-spacing:-.004em; margin-top:1rem; max-width:20ch; text-wrap:balance}
h3{font-family:"LR Didot",Georgia,serif; font-size:clamp(1.15rem,1.9vw,1.55rem); line-height:1.15}
.lede{max-width:var(--measure); margin-top:1.5rem; color:var(--dim); font-size:1.06em}
p{max-width:var(--measure)}
a.t{color:var(--acc); border-bottom:1px solid var(--rule-2); transition:border-color .35s var(--ease)}
a.t:hover{border-color:var(--acc)}
.slot{color:var(--dim)}   /* bracketed placeholder text, see PLAN.md §8 */

/* ── the three strands, under the hero ─────────────────────────── */
.strands{display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:clamp(1.5rem,3vw,2.8rem); margin-top:clamp(1.8rem,4.5vh,3rem)}
.strand{border-top:1px solid var(--rule-2); padding-top:.95rem}
.strand__n{font-family:"LR Plex",system-ui,sans-serif; font-size:.6rem; letter-spacing:.22em; text-transform:uppercase; color:var(--acc); margin:0 0 .55rem}
.strand h3{margin:0 0 .55rem}
.strand p{font-size:.94em; color:var(--dim); margin:0; max-width:27rem}
@media (max-width:1080px){ .strands{grid-template-columns:repeat(2,minmax(0,1fr)); gap:clamp(1.6rem,4vw,3.6rem)} }
@media (max-width:760px){ .strands{grid-template-columns:1fr; gap:1.6rem} }

/* ── entries: experience and education ─────────────────────────── */
.entries{margin-top:clamp(2rem,5vh,3.2rem); border-top:1px solid var(--rule-2)}
.entry{display:grid; grid-template-columns:9.5rem minmax(0,1fr); gap:1.5rem clamp(1.2rem,3vw,2.6rem);
  padding:1.6rem 0; border-bottom:1px solid var(--rule)}
.entry__when{font-family:"LR Plex",system-ui,sans-serif; font-size:.62rem; letter-spacing:.2em;
  text-transform:uppercase; color:var(--dim); padding-top:.45rem; font-variant-numeric:tabular-nums}
.entry__when b{display:block; font-weight:400; color:var(--acc); margin-top:.35rem}
.entry h3{margin:0}
.entry__role{font-family:"LR Plex",system-ui,sans-serif; font-size:.62rem; letter-spacing:.2em; text-transform:uppercase; color:var(--acc); margin:.45rem 0 0 !important; max-width:none !important}
.entry p{margin:.55rem 0 0; color:var(--dim-2); font-size:.96em; max-width:34rem}
.entry ul{margin:.6rem 0 0; padding-left:1.1rem; color:var(--dim-2); font-size:.94em; max-width:34rem}
.entry li + li{margin-top:.2rem}
@media (max-width:640px){ .entry{grid-template-columns:1fr; gap:.4rem} .entry__when b{display:inline; margin-left:.8rem} }

/* ── modules: a vertical tile per class, icon above a short label, grouped ── */
.mods{margin-top:.9rem; display:grid; gap:.8rem; max-width:none}
.mods .mods__n{font-family:"LR Plex",system-ui,sans-serif; font-size:.56rem; letter-spacing:.22em; text-transform:uppercase; color:var(--acc); margin:0 0 .35rem !important; max-width:none !important}
.mods ul{list-style:none; margin:0 !important; padding:0 !important; display:flex; flex-wrap:wrap; gap:.35rem; font-size:1em !important; color:var(--fg) !important}
.mods li{display:flex; flex-direction:column; align-items:center; justify-content:flex-start; gap:.4rem; width:4.7rem; padding:.55rem .25rem .45rem;
  border:1px solid var(--rule); border-radius:2px; background:var(--tile); text-align:center;
  font-family:"LR Plex",system-ui,sans-serif; font-size:.5rem; letter-spacing:.08em; line-height:1.35; text-transform:uppercase; color:var(--dim-2); margin:0 !important;
  transition:border-color .35s var(--ease), color .35s var(--ease)}
.mods li:hover{border-color:var(--acc); color:var(--fg)}
.mods li svg{width:16px; height:16px; flex:0 0 auto}
.mods li svg path{fill:none; stroke:var(--fg); stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; transition:stroke .35s var(--ease)}
.mods li:hover svg path{stroke:var(--acc)}

/* ── skills: lanes (disciplines) across, bands (layers) down, a tile per tool ── */
.lanes__frame{padding:clamp(.6rem,1.5vw,1.2rem) clamp(.6rem,1.5vw,1.4rem); overflow-x:auto}
.lanes{display:grid; grid-template-columns:9.5rem repeat(3,minmax(0,1fr)); min-width:720px}
.lanes__corner{border-bottom:1px solid var(--rule-2)}
.lanes__lane{padding:.6rem .8rem .7rem; border-bottom:1px solid var(--rule-2); border-left:1px solid var(--rule);
  font-family:"LR Plex",system-ui,sans-serif; font-size:.62rem; letter-spacing:.2em; text-transform:uppercase; color:var(--dim); text-align:center; transition:color .35s var(--ease)}
.lanes__band{padding:.9rem .8rem .9rem 0; border-bottom:1px solid var(--rule); font-family:"LR Stix",Georgia,serif; font-style:italic; font-size:.95rem; color:var(--fg);
  display:flex; flex-direction:column; gap:.25rem; justify-content:center; transition:color .35s var(--ease)}
.lanes__band span{font-family:"LR Plex",system-ui,sans-serif; font-style:normal; font-size:.56rem; letter-spacing:.22em; color:var(--acc)}
.lanes__cell{padding:.7rem .6rem; border-bottom:1px solid var(--rule); border-left:1px solid var(--rule); transition:background-color .35s var(--ease)}
.lanes__cell ul{list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; gap:.35rem}
.lanes__cell li{display:flex; flex-direction:column; align-items:center; gap:.4rem; width:4.7rem; padding:.55rem .25rem .45rem;
  border:1px solid var(--rule); border-radius:2px; background:var(--tile); text-align:center;
  font-family:"LR Plex",system-ui,sans-serif; font-size:.5rem; letter-spacing:.08em; line-height:1.35; text-transform:uppercase; color:var(--dim-2);
  transition:border-color .35s var(--ease), color .35s var(--ease)}
.lanes__cell li svg{width:16px; height:16px; flex:0 0 auto}
.lanes__cell li svg path{fill:none; stroke:var(--fg); stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; transition:stroke .35s var(--ease)}
/* vendor marks: the same tile, the mark filled in the page's ink rather than its brand colour */
.lanes__cell li.logo svg path{fill:var(--fg); stroke:none; transition:fill .35s var(--ease)}
.lanes__cell li.logo:hover svg path{fill:var(--acc)}
.lanes__cell li.logo svg{width:17px; height:17px; opacity:.9}
.lanes__cell li:hover{border-color:var(--acc); color:var(--fg)}
.lanes__cell li:hover svg path{stroke:var(--acc)}
/* the cross-hair: a hovered cell lights its lane and its band */
.lanes__cell.lit{background:var(--vellum)}
.lanes__lane.lit,.lanes__band.lit{color:var(--acc)}

/* ── languages: a short section, tiles only ─────────────────────── */
.langs{padding-block:clamp(3rem,8vh,5rem)}
.langs .mods{margin-top:1.6rem; grid-template-columns:repeat(auto-fit,minmax(14rem,max-content)); gap:1.2rem 2.5rem; align-items:start}
.langs .mods li{width:5.2rem; height:4.9rem; justify-content:center; box-sizing:border-box}
.langs .mods li svg{width:17px; height:17px}
.langs .mods li i{font-style:normal; font-size:.46rem; letter-spacing:.14em; color:var(--acc)}
.mods li.logo svg path,.mods li.glyph svg path{fill:var(--fg); stroke:none; transition:fill .35s var(--ease)}
.mods li.logo:hover svg path,.mods li.glyph:hover svg path{fill:var(--acc)}
.langs .mods li.glyph svg{width:21px; height:21px}


/* ── the applications: cards in the plate frame, grouped ──────────── */
.apps__frame{padding:clamp(1rem,2.2vw,1.8rem) clamp(1rem,2.2vw,1.8rem) clamp(.6rem,1.5vw,1.2rem)}
.apps__g{font-family:"LR Plex",system-ui,sans-serif; font-size:.6rem; letter-spacing:.22em; text-transform:uppercase; color:var(--acc); margin:0 0 .8rem; max-width:none}
.apps__g + .apps{margin-bottom:1.6rem}
.apps{display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:.8rem}
.app{border:1px solid var(--rule); border-radius:2px; background:var(--tile); padding:.9rem 1rem 1rem; transition:border-color .35s var(--ease)}
.app:hover{border-color:var(--acc)}
.app svg{width:18px; height:18px; display:block; margin-bottom:.6rem}
.app svg path{fill:none; stroke:var(--fg); stroke-width:1.5; stroke-linecap:round; stroke-linejoin:round; transition:stroke .35s var(--ease)}
.app:hover svg path{stroke:var(--acc)}
.app h4{font-family:"LR Didot",Georgia,serif; font-weight:400; font-size:1.15rem; line-height:1.15; margin:0 0 .3rem; color:var(--fg)}
.app p.app__meta{font-family:"LR Plex",system-ui,sans-serif; font-size:.56rem; letter-spacing:.18em; text-transform:uppercase; color:var(--dim); margin:0 0 .5rem !important}
.app p{font-size:.86em; line-height:1.5; color:var(--dim-2); margin:0; max-width:none}
@media (max-width:1080px){ .apps{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (max-width:640px){ .apps{grid-template-columns:1fr} }

/* ── phones: narrower drawings and grids, tighter tiles ──────────── */
@media (max-width:640px){
  .arch__svg{display:none}
  .arch__svg--portrait{display:block}                          /* the stacked drawing, no scrolling */
  .arch__frame{overflow-x:hidden}
  /* the grid stands up: one block per layer, the three roles stacked inside it,
     each cell labelled with its role. Nothing scrolls. */
  .lanes__frame{overflow-x:hidden}
  .lanes{display:block; min-width:0}
  .lanes__corner,.lanes__lane{display:none}
  .lanes__band{flex-direction:row; align-items:baseline; gap:.6rem; padding:1rem 0 .4rem; border-bottom:0; border-top:1px solid var(--rule-2); font-size:.95rem}
  .lanes__band:first-of-type{border-top:0; padding-top:.2rem}
  .lanes__cell{border:0; padding:.35rem 0 .5rem}
  .lanes__cell--empty{display:none}
  .lanes__cell::before{content:attr(data-lane-name); display:block; margin-bottom:.4rem;
    font-family:"LR Plex",system-ui,sans-serif; font-size:.54rem; letter-spacing:.18em; text-transform:uppercase; color:var(--dim)}
  .lanes__cell.lit{background:transparent}
  .lanes__cell li,.mods li,.langs .mods li{width:4.2rem}
  .apps__frame{padding:.9rem .9rem .5rem}
  .proj__head{gap:.7rem}
  .proj__n{font-size:1.7rem}
}

/* ── figures ───────────────────────────────────────────────────── */
.plate{margin-top:clamp(2.5rem,6vh,4rem); position:relative}
.plate__frame{position:relative; border:1px solid var(--rule); border-radius:2px; overflow:hidden; background:var(--vellum);
  -webkit-backdrop-filter:blur(14px) saturate(1.04); backdrop-filter:blur(14px) saturate(1.04)}
.plate__frame::before,.plate__frame::after{content:""; position:absolute; width:9px; height:9px; opacity:.5}
.plate__frame::before{top:9px; left:9px; border-top:1px solid var(--rule-2); border-left:1px solid var(--rule-2)}
.plate__frame::after{bottom:9px; right:9px; border-bottom:1px solid var(--rule-2); border-right:1px solid var(--rule-2)}
canvas{display:block; width:100%; height:auto}
/* a live control under a plate: one parameter, in Plex, the value in the serif */
.plate__ctl{display:flex; align-items:center; gap:1rem; margin-top:.8rem; font-family:"LR Plex",system-ui,sans-serif;
  font-size:.62rem; letter-spacing:.18em; text-transform:uppercase; color:var(--dim)}
.plate__ctl label{flex:0 0 auto}
.plate__ctl .gk{font-family:"LR Stix",Georgia,serif; font-size:.95rem; letter-spacing:0; text-transform:none; color:var(--fg); margin-right:.15em}
.plate__ctl output{font-family:"LR Stix",Georgia,serif; font-size:.95rem; letter-spacing:0; text-transform:none; color:var(--acc); min-width:2.6em; font-variant-numeric:tabular-nums}
.plate__ctl input[type=range]{-webkit-appearance:none; appearance:none; flex:1 1 auto; max-width:16rem; height:1px; background:var(--rule-2); outline:none; margin:0; cursor:pointer}
.plate__ctl input[type=range]::-webkit-slider-thumb{-webkit-appearance:none; width:11px; height:11px; border-radius:50%; background:var(--bg); border:1px solid var(--acc); box-shadow:inset 0 0 0 3px var(--acc); transition:transform .3s var(--ease)}
.plate__ctl input[type=range]::-moz-range-thumb{width:9px; height:9px; border-radius:50%; background:var(--acc); border:1px solid var(--acc)}
.plate__ctl input[type=range]:focus-visible::-webkit-slider-thumb{transform:scale(1.25)}
.plate__cap{display:flex; gap:1.1rem; margin-top:.85rem; align-items:baseline;
  font-family:"LR Plex",system-ui,sans-serif; font-size:.655rem; letter-spacing:.14em; text-transform:uppercase; color:var(--dim)}
.plate__cap b{font-weight:400; color:var(--acc); flex:0 0 auto}
.plate__cap span{max-width:44ch; letter-spacing:.1em}

/* project grid: two plates side by side, each with its own heading */
.grid2{display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:clamp(1.6rem,3.5vw,3rem); margin-top:clamp(2rem,5vh,3.2rem)}
/* project number beside the title, then what it was, then what it solved */
.proj__head{display:flex; align-items:baseline; gap:1rem; margin-bottom:.7rem}
.proj__n{font-family:"LR Didot",Georgia,serif; font-size:clamp(1.9rem,3vw,2.6rem); line-height:1; color:var(--fg); letter-spacing:-.01em; font-variant-numeric:tabular-nums; flex:0 0 auto; transition:color .35s var(--ease)}
.proj__n i{font-style:normal; font-size:.42em; color:var(--dim); margin-left:.15em; letter-spacing:.02em}
.proj:hover .proj__n{color:var(--acc)}
.proj__head h3{margin:0; font-size:clamp(1.5rem,2.4vw,2.1rem)}
.proj__what{font-size:1.02em; color:var(--fg); margin:0 0 .5rem; max-width:32rem}
.proj__how{font-size:.94em; color:var(--dim-2); margin:0; max-width:32rem}
.pnum{color:var(--acc); margin-right:.35rem}
.pnum::after{content:"—"; margin-left:.35rem; color:var(--dim)}
/* each project is one link: the whole card, figure included, is the target */
/* every plate in a row starts at the same height whatever the copy above it:
   each card is a subgrid, so its five rows (number and title, what, how, plate,
   read-more) share tracks with the card beside it. The flex fallback below
   covers browsers without subgrid. */
.proj{display:flex; flex-direction:column; color:inherit; border-top:1px solid var(--rule-2); padding:.95rem 0 1rem; cursor:pointer;
  transition:border-color .45s var(--ease)}
.proj__how{flex:1 1 auto}
.proj .plate{margin-top:1.3rem}
@supports (grid-template-rows: subgrid){
  .grid2{grid-auto-rows:auto}
  .proj{display:grid; grid-template-rows:subgrid; grid-row:span 5; row-gap:0; align-content:start}   /* the card's own margins space its rows, not the grid gap */
  .proj__how{flex:none}
  .proj .plate{align-self:start}
}
.proj:hover,.proj:focus-visible{border-top-color:var(--acc)}
.proj h3{transition:color .35s var(--ease)}
.proj:hover h3,.proj:focus-visible h3{color:var(--acc)}
.proj .plate__frame{transition:border-color .45s var(--ease)}
.proj:hover .plate__frame{border-color:var(--rule-2)}
.proj__more{display:inline-flex; align-items:center; gap:.55rem; margin-top:1rem;
  font-family:"LR Plex",system-ui,sans-serif; font-size:.62rem; letter-spacing:.2em; text-transform:uppercase; color:var(--dim);
  transition:color .35s var(--ease), gap .35s var(--ease)}
.proj__more::after{content:""; width:5px; height:5px; border-right:1px solid currentColor; border-top:1px solid currentColor; transform:rotate(45deg)}
.proj:hover .proj__more,.proj:focus-visible .proj__more{color:var(--acc); gap:.85rem}
.proj h3{margin:0 0 .45rem}
.proj .plate{margin-top:1.3rem}
@media (max-width:760px){ .grid2{grid-template-columns:1fr} }

footer{position:relative; z-index:10; margin-top:2rem;
  padding:2.5rem var(--gutter) 3rem calc(var(--gutter) + var(--rail) + clamp(1.5rem,4vw,4rem));
  border-top:1px solid var(--rule); font-family:"LR Plex",system-ui,sans-serif; font-size:.64rem; letter-spacing:.15em;
  text-transform:uppercase; color:var(--dim); display:flex; justify-content:space-between; gap:1.5rem; flex-wrap:wrap}

/* ── reveal ────────────────────────────────────────────────────── */
.rv{opacity:0; transform:translateY(18px); transition:opacity .95s var(--ease), transform .95s var(--ease)}
.rv.in{opacity:1; transform:none}
.rv[data-d="1"]{transition-delay:.10s} .rv[data-d="2"]{transition-delay:.20s}
.rv[data-d="3"]{transition-delay:.30s} .rv[data-d="4"]{transition-delay:.40s}
:focus-visible{outline:1px solid var(--acc); outline-offset:3px}
/* a section receives focus after a rail click so assistive tech lands there; it is not a control and gets no ring */
main section:focus,main section:focus-visible{outline:none}
.skip{position:absolute; left:-9999px}
.skip:focus{left:var(--gutter); top:1rem; z-index:60; background:var(--bg); padding:.6rem 1rem; border:1px solid var(--rule-2)}

/* ── narrow: the rail becomes a rail, not a hamburger ──────────── */
@media (max-width:900px){
  :root{--rail:auto}
  main{padding-left:var(--gutter); padding-bottom:5.5rem}
  footer{padding-left:var(--gutter); padding-bottom:6rem}
  .rail{top:auto; bottom:0; left:0; right:0; transform:none; width:auto;
    padding:1.5rem var(--gutter) .9rem; display:flex; align-items:center; gap:.55rem;
    background:linear-gradient(to top,var(--bg) 58%,transparent)}
  /* eight sections do not fit a phone; the row scrolls and fades at its right edge so it reads as scrollable */
  .rail ol{display:flex; gap:.15rem; flex:1 1 0; min-width:0; overflow-x:auto; scrollbar-width:none;
    -webkit-mask-image:linear-gradient(to right,#000 82%,transparent); mask-image:linear-gradient(to right,#000 82%,transparent); padding-right:2rem}
  .rail ol::-webkit-scrollbar{display:none}
  .rail li + li{margin-top:0}
  .rail a{padding:.3rem .45rem; white-space:nowrap; font-size:.62rem; letter-spacing:.12em}
  .rail__n{display:none}
  .rail__sep{width:1px; height:1.4rem; margin:0 .35rem; flex:0 0 auto}
  .swap{width:auto; flex:0 0 auto}  .swap__t{display:none}
  .scale{display:none}
  .masthead{left:var(--gutter)}
  .hero{padding-top:clamp(5rem,12vh,7rem); justify-content:flex-start}
  .hero h1{font-size:clamp(2.8rem,12vw,5.9rem)}
}

/* ── motion budget ─────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  *,*::before,*::after{animation-duration:.001ms!important; animation-iteration-count:1!important; transition-duration:.001ms!important; transition-delay:0s!important}
  .rv{opacity:1; transform:none}
}

/* ── project pages ─────────────────────────────────────────────── */
.page-head{padding-top:clamp(7rem,18vh,11rem)}
.page-head h1{font-size:clamp(2.4rem,5.4vw,4.6rem); max-width:16ch}
.meta{display:grid; grid-template-columns:repeat(auto-fit,minmax(11rem,1fr)); gap:1.2rem 2rem;
  margin-top:2.2rem; padding-top:1.2rem; border-top:1px solid var(--rule-2); max-width:52rem}
.meta dt{font-family:"LR Plex",system-ui,sans-serif; font-size:.6rem; letter-spacing:.22em; text-transform:uppercase; color:var(--acc); margin:0 0 .35rem}
.meta dd{margin:0; font-size:.94em; color:var(--dim-2)}
.meta dd a{color:var(--fg); border-bottom:1px solid var(--rule-2)}
.meta dd a:hover{border-color:var(--acc); color:var(--acc)}
section.pg{padding-block:clamp(3.5rem,9vh,6rem)}
section.pg h2{font-size:clamp(1.6rem,2.8vw,2.4rem)}
section.pg h3{margin:1.8rem 0 .4rem}
section.pg p + p{margin-top:.9rem}
section.pg ul{max-width:var(--measure); padding-left:1.1rem; color:var(--dim-2)}
section.pg li + li{margin-top:.35rem}
/* results: a row of plates, each one number and its label */
.stats{display:grid; grid-template-columns:repeat(auto-fit,minmax(11rem,1fr)); gap:1rem; margin-top:2rem}
.stat{position:relative; border:1px solid var(--rule); border-radius:2px; background:var(--vellum); padding:1.3rem 1.2rem 1.1rem}
.stat::before{content:""; position:absolute; top:7px; left:7px; width:8px; height:8px; border-top:1px solid var(--rule-2); border-left:1px solid var(--rule-2); opacity:.5}
.stat b{display:block; font-weight:400; font-size:clamp(1.8rem,3vw,2.5rem); line-height:1; color:var(--fg); font-variant-numeric:tabular-nums}
.stat b em{font-style:normal; font-size:.5em; color:var(--acc); margin-left:.15em}
.stat span{display:block; margin-top:.6rem; font-family:"LR Plex",system-ui,sans-serif; font-size:.6rem; letter-spacing:.18em; text-transform:uppercase; color:var(--dim); line-height:1.5}
/* code and data, set in Plex at reduced size, never in the serif */
pre{max-width:var(--measure); overflow-x:auto; margin:1.2rem 0 0; padding:1rem 1.1rem; border:1px solid var(--rule); border-radius:2px; background:var(--vellum);
  font-family:"LR Plex",ui-monospace,SFMono-Regular,monospace; font-size:.78rem; line-height:1.6; color:var(--dim-2)}
code{font-family:"LR Plex",ui-monospace,monospace; font-size:.9em}
/* previous and next, at the foot of every project page */
.pn{display:flex; justify-content:space-between; gap:2rem; margin-top:clamp(3rem,8vh,5rem); padding-top:1.4rem; border-top:1px solid var(--rule-2); max-width:64rem}
.pn a{display:block; font-family:"LR Plex",system-ui,sans-serif; font-size:.62rem; letter-spacing:.2em; text-transform:uppercase; color:var(--dim)}
.pn a b{display:block; margin-top:.4rem; font-family:"LR Didot",Georgia,serif; font-weight:400; font-size:clamp(1.1rem,1.8vw,1.45rem); letter-spacing:0; text-transform:none; color:var(--fg)}
.pn a:hover b{color:var(--acc)}
.pn a + a{text-align:right}
