/* ------------------------------------------------------------------
     Design read: developer / security portfolio for recruiters and
     prospective agent clients. Restrained dark-technical language.
     DESIGN_VARIANCE 6 | MOTION_INTENSITY 5 | VISUAL_DENSITY 4
     Single locked accent, one radius scale, one theme. No external
     resources of any kind: the _headers CSP is default-src 'self'.
     ------------------------------------------------------------------ */
  :root{
    color-scheme: dark;
    --bg:#0b0b0c; --panel:#151517; --panel-2:#0f0f11; --line:#26262a;
    --line-soft:#1d1d21;
    --text:#f2f2f4; --muted:#9a9aa3; --dim:#6e6e78;
    /* ONE accent for the whole page. The previous blue -> purple gradient
       pair was the single most generic thing on the site. */
    --accent:#b6ff3a; --accent-ink:#0d1103; --accent-soft:rgba(182,255,58,.10);
    /* one radius scale */
    --r-sm:10px; --r-md:14px; --r-lg:20px; --r-pill:999px;
    --ease:cubic-bezier(.4,0,.2,1);
  }
  *{box-sizing:border-box}
  html{scroll-behavior:smooth;overflow-x:clip}
  body{margin:0;color:var(--text);
    background:
      radial-gradient(75% 38% at 50% -2%, color-mix(in srgb,var(--accent) 11%, transparent), transparent 68%),
      var(--bg);
    background-attachment:fixed;
    font:16px/1.65 -apple-system,BlinkMacSystemFont,"Segoe UI",system-ui,sans-serif;
    -webkit-font-smoothing:antialiased;overflow-x:clip}
  .wrap{max-width:70rem;margin:0 auto;padding:0 1.75rem}
  a{color:var(--accent)}
  /* display type needs its own leading: body line-height 1.65 makes multi-line
     headings look like paragraphs */
  h1,h2,h3{letter-spacing:-.028em;font-weight:650;line-height:1.16}

  /* ---------- header ---------- */
  header{position:sticky;top:0;z-index:20;border-bottom:1px solid var(--line-soft);
    background:color-mix(in srgb,var(--bg) 82%,transparent);backdrop-filter:blur(12px)}
  nav{display:flex;justify-content:space-between;align-items:center;gap:1rem;
    height:64px;flex-wrap:nowrap}
  .brand{font-weight:700;letter-spacing:-.02em;white-space:nowrap}
  nav ul{display:flex;gap:1.4rem;list-style:none;margin:0;padding:0}
  nav a{color:var(--muted);text-decoration:none;font-size:.9rem;transition:color .15s;
    display:inline-flex;align-items:center;min-height:44px;padding:0 .2rem}
  /* 44px is the Apple/Google minimum tap target. min-height guarantees it
     regardless of font metrics. */
  nav a:hover{color:var(--text)}
  @media (max-width:680px){ nav ul{display:none} }

  /* ---------- hero: asymmetric split, no centred glow ---------- */
  .hero{display:grid;grid-template-columns:1.15fr .85fr;gap:clamp(2rem,5vw,4.5rem);
    align-items:center;padding:clamp(3rem,7vw,5.5rem) 0 clamp(2.5rem,5vw,4rem)}
  /* Not a flex row. The dot is placed on the text's own baseline instead, which
     is the one vertical reference every browser and platform agrees on. Flex
     centring used the font's box, and that box is measured differently on macOS
     and Windows, so the dot drifted. */
  .eyebrow{display:inline-block;font-size:.8rem;color:var(--muted);
    border:1px solid var(--line);border-radius:var(--r-pill);padding:.35rem .85rem;margin-bottom:1.5rem}
  /* the one dot on the page, and it carries real state: availability.
     vertical-align is measured up from the baseline, so .07em lands it on the
     middle of the lowercase wherever it renders. */
  .dot{display:inline-block;width:.5rem;height:.5rem;border-radius:50%;
    background:#3fb950;vertical-align:.055em;margin-right:.55rem;
    /* Lit, not printed. A radial core so the top-left reads as the bright
       point of the lamp, then two blurred halos: a tight hot one and a wider
       faint one. That layering is what makes a light look like it is emitting
       rather than like a circle with a ring drawn round it. */
    background:radial-gradient(circle at 50% 36%, #86ffa0, #3fdc63 45%, #2ea44f 100%);
    box-shadow:
      0 0 4px 1px rgba(74,222,110,.75),
      0 0 10px 3px rgba(63,200,90,.45),
      0 0 18px 6px rgba(63,185,80,.20)}
  .hero h1{font-size:clamp(2.3rem,5.4vw,3.75rem);line-height:1.04;margin:0 0 1.15rem;max-width:16ch}
  .hero h1 em{font-style:normal;color:var(--accent)}
  .hero .lede{font-size:clamp(1.02rem,1.7vw,1.16rem);color:var(--muted);max-width:34rem;margin:0 0 2rem}
  .cta{display:flex;gap:.7rem;flex-wrap:wrap}
  .btn{display:inline-flex;align-items:center;justify-content:center;gap:.55rem;
    padding:.8rem 1.35rem;border:0;border-radius:var(--r-sm);text-decoration:none;
    font-weight:600;font-size:.94rem;white-space:nowrap;
    transition:transform .12s var(--ease),background .15s,box-shadow .15s}
  .btn:hover{transform:translateY(-1px)}
  /* solid accent with ink-dark label: 8.9:1, no gradient, no glow */
  .btn-primary{background:var(--accent);color:var(--accent-ink)}
  .btn-primary:hover{background:#68b1ff}
  /* inset shadow instead of a border: same look, zero layout impact, so the
     two buttons match height without a transparent border hack. */
  .btn-ghost{box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--text) 26%,transparent);color:var(--text)}
  .btn-ghost:hover{box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--text) 45%,transparent)}
  .btn svg{width:1.1em;height:1.1em;fill:currentColor;flex:none}

  /* portrait: a photo print on a dark page. The white background is the
     point, so it gets a quiet frame rather than a glow. */
  .portrait{position:relative;justify-self:end;width:100%;max-width:23rem}
  .portrait img{display:block;width:100%;height:auto;border-radius:var(--r-lg);
    border:1px solid var(--line);box-shadow:0 24px 60px -30px rgba(0,0,0,.9)}

  /* ---------- stats ---------- */
  .stats{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line-soft);
    border:1px solid var(--line-soft);border-radius:var(--r-md);overflow:hidden}
  .stat{background:var(--panel);padding:1.15rem 1.3rem}
  .stat b{display:block;font-size:1.4rem;letter-spacing:-.03em;font-variant-numeric:tabular-nums}
  .stat span{font-size:.82rem;color:var(--muted)}

  /* ---------- sections ---------- */
  section{padding:clamp(3rem,6vw,5rem) 0;border-top:1px solid var(--line-soft);scroll-margin-top:4.5rem}
  #contact{scroll-margin-top:4.5rem}
  .sec-head{margin-bottom:2.25rem;max-width:44rem}
  .sec-head h2{font-size:clamp(1.6rem,3.1vw,2.05rem);margin:0 0 .55rem}
  .sec-head p{color:var(--muted);margin:0}
  .kicker{display:inline-block;font-size:.73rem;letter-spacing:.11em;text-transform:uppercase;
    color:var(--accent);font-weight:700;margin-bottom:.7rem}

  /* ---------- agents: bento with rhythm, not three equal cards ---------- */
  .agent-top{max-width:46rem;margin-bottom:2rem}
  .agent-top h2{font-size:clamp(1.55rem,3.1vw,2.05rem);margin:0 0 .7rem;max-width:20ch}
  .agent-top p{color:var(--muted);margin:0}
  .bento{display:grid;grid-template-columns:repeat(3,1fr);gap:1rem}
  .cell{background:var(--panel);border:1px solid var(--line-soft);border-radius:var(--r-md);
    padding:1.5rem 1.6rem}
  .cell h3{margin:0 0 .5rem;font-size:1.02rem}
  .cell p{margin:0;color:var(--muted);font-size:.93rem}
  /* two cells carry a tint so the grid has visual variation, not six
     identical text boxes */
  .cell.lead{grid-column:span 2;background:
    linear-gradient(135deg,var(--accent-soft),transparent 62%),var(--panel)}
  .cell.lead h3{font-size:1.18rem}
  .cell.wide{grid-column:span 3;background:
    linear-gradient(100deg,var(--panel-2),var(--panel) 70%)}
  .cell.wide .inner{display:grid;grid-template-columns:minmax(0,22ch) 1fr;gap:.4rem 2.5rem;align-items:baseline}
  @media (max-width:900px){
    .bento{grid-template-columns:repeat(2,1fr)}
    .cell.lead,.cell.wide{grid-column:span 2}
    .cell.wide .inner{grid-template-columns:1fr}
  }
  @media (max-width:600px){
    .bento{grid-template-columns:1fr}
    .cell.lead,.cell.wide{grid-column:span 1}
  }

  /* ---------- experience ---------- */
  .roles{display:grid;gap:.75rem}
  .role{border:1px solid var(--line-soft);border-radius:var(--r-md);background:var(--panel);overflow:hidden}
  .role summary{list-style:none;cursor:pointer;padding:1.35rem 1.5rem;display:grid;
    grid-template-columns:1fr auto;gap:.75rem 1rem;align-items:start}
  .role summary::-webkit-details-marker{display:none}
  .role summary:hover{background:var(--panel-2)}
  .role h3{margin:0;font-size:1.04rem}
  .role .org{color:var(--accent);font-size:.92rem;margin:.15rem 0 0}
  .role .meta{color:var(--muted);font-size:.85rem;text-align:right;white-space:nowrap}
  .role .chev{color:var(--dim);font-size:.75rem;margin-left:.5rem;
    display:inline-block;transition:transform .3s var(--ease)}
  .role[open] .chev{transform:rotate(180deg)}
  .role-body{overflow:hidden;transition:height .3s var(--ease)}
  .role ul{margin:0;padding:0 1.5rem 1.5rem 2.6rem;color:var(--muted);font-size:.92rem}
  .role li{margin:.5rem 0}
  @media (max-width:600px){
    .role summary{grid-template-columns:1fr;padding:1.15rem}
    .role .meta{text-align:left;white-space:normal;order:-1;font-size:.8rem}
    .role ul{padding:0 1.15rem 1.25rem 2.1rem}
  }

  /* ---------- skills ---------- */
  /* align-items:start so a 4-chip card does not stretch to match a 9-chip one
     and end up mostly empty */
  .skills{display:grid;gap:1rem;grid-template-columns:repeat(auto-fit,minmax(17rem,1fr));align-items:start}
  .sk{border:1px solid var(--line-soft);border-radius:var(--r-md);padding:1.4rem;background:var(--panel)}
  .sk h4{margin:0 0 .75rem;font-size:.73rem;letter-spacing:.11em;color:var(--dim);font-weight:700}
  .chips{display:flex;flex-wrap:wrap;gap:.4rem}
  .chip{font-size:.85rem;padding:.3rem .68rem;border:1px solid var(--line);border-radius:var(--r-sm);color:var(--muted)}

  /* ---------- education ---------- */
  .edu{border:1px solid var(--line-soft);border-radius:var(--r-md);padding:1.6rem;background:var(--panel);
    display:flex;justify-content:space-between;gap:1rem;flex-wrap:wrap;align-items:flex-start}
  .edu h3{margin:0 0 .3rem;font-size:1.08rem}
  .edu p{margin:.1rem 0;color:var(--muted);font-size:.93rem}
  .edu .when{text-align:right;color:var(--muted);font-size:.9rem;white-space:nowrap}

  /* ---------- contact ---------- */
  .contact{text-align:center;padding:clamp(3.5rem,7vw,5.5rem) 0}
  .contact h2{font-size:clamp(1.7rem,3.4vw,2.3rem);margin:0 0 .7rem}
  .contact p{color:var(--muted);max-width:34rem;margin:0 auto 1.9rem}
  .contact .cta{justify-content:center;margin-top:1.75rem}

  /* ---------- contact form ----------
     Posts same-origin to /api/contact, which is why the CSP needs no change:
     form-action and connect-src both stay 'self'. */
  .cform{max-width:34rem;margin:0 auto;text-align:left;display:grid;gap:1rem}
  .cform .row{display:grid;grid-template-columns:1fr 1fr;gap:1rem}
  .field{display:grid;gap:.4rem;min-width:0}
  .field label{font-size:.85rem;font-weight:600;color:var(--muted)}
  .field input,.field textarea{
    width:100%;font:inherit;font-size:.95rem;color:var(--text);
    background:var(--panel-2);border:1px solid var(--line);border-radius:var(--r-sm);
    padding:.72rem .85rem;transition:border-color .15s,box-shadow .15s}
  .field textarea{resize:vertical;min-height:8.5rem;line-height:1.55}
  .field input:hover,.field textarea:hover{border-color:#2b3846}
  /* Labels do the work, so there are no placeholders to fail contrast. */
  .field input:focus-visible,.field textarea:focus-visible{
    outline:none;border-color:var(--accent);
    box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 25%,transparent)}
  .cform button{justify-self:start;min-width:11rem}
  .cform[data-busy] button{opacity:.55;pointer-events:none}
  /* Scoped to .contact so it outranks `.contact p`, which would otherwise add
     its own 1.9rem bottom margin and open a hole under the button. */
  .contact .cform-status{margin:0;font-size:.9rem;min-height:1.4em;color:var(--muted);max-width:none}
  .contact .cform-status.ok{color:#3fb950}
  .contact .cform-status.err{color:#ff7b72}
  /* Honeypot. Offscreen rather than display:none, because a bot that reads the
     CSS will skip a hidden field but happily fill this one. */
  .hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
  @media (max-width:560px){
    .cform .row{grid-template-columns:1fr}
    .cform button{justify-self:stretch;width:100%}
  }

  /* Visible keyboard focus. Anyone navigating by Tab could not see where they were. */
  a:focus-visible, summary:focus-visible, .btn:focus-visible{
    outline:3px solid var(--accent); outline-offset:3px; border-radius:6px}
  summary:focus-visible{outline-offset:-3px}
  a:focus:not(:focus-visible), summary:focus:not(:focus-visible){outline:none}

  footer{border-top:1px solid var(--line-soft);padding:2rem 0 3rem;color:var(--dim);
    font-size:.87rem;text-align:center}

  /* ---------- scroll reveal (MOTION_INTENSITY 5) ----------
     Entrance only, once, to give the page a reading order on first scroll.
     Everything is visible by default so a failed observer degrades to static. */
  @media (prefers-reduced-motion: no-preference){
    .reveal{opacity:0;transform:translateY(14px);
      transition:opacity .55s var(--ease),transform .55s var(--ease)}
    .reveal.in{opacity:1;transform:none}
  }

  /* ---------- phone ---------- */
  @media (max-width:820px){
    .hero{grid-template-columns:1fr;gap:2.5rem;padding-top:2.75rem}
    .portrait{justify-self:start;max-width:17rem;order:-1}
    .hero h1{max-width:none}
  }
  @media (max-width:520px){
    .wrap{padding:0 1.15rem}
    .hero h1{font-size:clamp(2rem,9vw,2.5rem)}
    .btn{flex:1 1 100%}
    .stats{grid-template-columns:1fr 1fr}
    .stat:last-child{grid-column:1 / -1}   /* 3 stats in 2 cols would leave a hole */
    .stat{padding:1rem}
    .stat b{font-size:1.25rem}
    .cell{padding:1.25rem}
    .sk{padding:1.2rem}
    .edu{padding:1.3rem}
    .edu .when{text-align:left}
  }
  /* The availability pill is a fixed-width string. On a 360px Android it would
     wrap inside its own border, which looks broken. Shrink it instead. */
  @media (max-width:400px){
    .eyebrow{font-size:.72rem;padding:.3rem .7rem;gap:.4rem}
  }

/* ---------- standalone pages (contact) ---------- */
.page{max-width:38rem;margin:0 auto;padding:clamp(2.5rem,6vw,4.5rem) 0 clamp(3rem,6vw,5rem)}
.page h1{font-size:clamp(1.9rem,4vw,2.6rem);margin:0 0 .8rem}
.page-lede{color:var(--muted);margin:0 0 2.25rem;max-width:34rem}
.page .cform{max-width:none;margin:0}
.page .cform-status{margin:0;font-size:.9rem;min-height:1.4em;color:var(--muted)}
.page .cform-status.ok{color:#3fb950}
.page .cform-status.err{color:#ff7b72}
.page-alt{margin:2.25rem 0 0;font-size:.9rem;color:var(--dim)}
/* The wordmark is the way back to the home page, so it has to read as a link
   on hover even though it is not styled like one.
   font-size and padding are reset explicitly: on the home page the wordmark is
   a <span>, here it is an <a>, so it was picking up `nav a`'s .9rem and coming
   out visibly smaller than the same wordmark one page over. */
a.brand{color:var(--text);text-decoration:none;transition:color .15s;
  font-size:1rem;letter-spacing:-.02em;padding:0}
a.brand:hover{color:var(--accent)}
/* Current page (contact) and current section while scrolling (home) get the
   same treatment, so the nav behaves the same way across both pages. */
nav a[aria-current="page"],nav a.is-active{color:var(--text)}


/* ------------------------------------------------------------------
   MATERIAL DEPTH
   Flat fills read as paint. These give surfaces a light source: brighter
   along the top edge, deeper at the bottom, a hairline where the light
   lands. Every gradient here runs inside ONE hue. A gradient across two
   hues (the old blue into purple) is the thing that looks generated.
   ------------------------------------------------------------------ */
.btn-primary{
  background:linear-gradient(180deg,
    color-mix(in srgb,var(--accent) 82%, white),
    var(--accent) 52%,
    color-mix(in srgb,var(--accent) 86%, black));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.5),
    0 8px 20px -10px color-mix(in srgb,var(--accent) 75%, transparent),
    0 1px 2px rgba(0,0,0,.55);
}
.btn-primary:hover{background:linear-gradient(180deg,
    color-mix(in srgb,var(--accent) 74%, white),
    var(--accent) 52%,
    color-mix(in srgb,var(--accent) 92%, black));}
.btn-ghost{
  background:linear-gradient(180deg, rgba(255,255,255,.045), rgba(255,255,255,.012));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.10),
             inset 0 0 0 1px color-mix(in srgb,var(--text) 20%,transparent),
             0 1px 2px rgba(0,0,0,.45);
}
.cell,.stat,.role,.sk,.edu,.field input,.field textarea{
  background:linear-gradient(180deg, color-mix(in srgb,var(--panel) 94%, white), var(--panel));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05), 0 1px 3px rgba(0,0,0,.35);
}
.cell.lead{
  background:
    linear-gradient(135deg, var(--accent-soft), transparent 62%),
    linear-gradient(180deg, color-mix(in srgb,var(--panel) 92%, white), var(--panel));
}
.eyebrow{
  background:linear-gradient(180deg, rgba(255,255,255,.05), rgba(255,255,255,.01));
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07);
}
.portrait img{box-shadow:0 30px 70px -32px rgba(0,0,0,.95), 0 0 0 1px var(--line)}

/* Fine grain over everything. Invisible on its own, and without it flat dark
   surfaces go back to looking like paint. Non-interactive. */
body::after{
  content:"";position:fixed;inset:0;pointer-events:none;z-index:9999;opacity:.05;
  background-image:url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='3' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='140' height='140' filter='url(%23n)'/></svg>");
}


/* ------------------------------------------------------------------
   LABEL LEFT, CONTENT RIGHT
   Replaces three equal boxes of chips. The boxes were forced to matching
   heights, so the shortest category carried a large empty hole. Rows have
   no height to match. The monospace label separates itself from the
   content by typeface, which is what lets the borders come out.
   ------------------------------------------------------------------ */
.skill-rows{display:grid;gap:0}
.srow{display:grid;grid-template-columns:minmax(0,11rem) 1fr;gap:.9rem 2.5rem;
  padding:1.45rem 0;align-items:start}
.slabel{font:500 .72rem/1.5 ui-monospace,SFMono-Regular,Menlo,"Cascadia Mono",monospace;
  letter-spacing:.13em;text-transform:uppercase;color:var(--dim);padding-top:.4rem}
.srow .chips{gap:.45rem}
/* stats: label above in mono, number below and larger, so the number is the
   thing you read and the label explains it rather than competing */
.stat .slabel{display:block;padding-top:0;margin-bottom:.4rem}
.stat b{font-size:1.5rem}
@media (max-width:700px){
  .srow{grid-template-columns:1fr;gap:.7rem;padding:1.15rem 0}
  .slabel{padding-top:0}
}


/* ==================================================================
   EDITORIAL TYPOGRAPHY
   Newsreader for anything you read, IBM Plex Mono for the small
   uppercase labels. Both are served from this domain, not Google:
   the CSP is font-src 'self', and self-hosting is faster and stops a
   third party logging every visitor anyway. Both are OFL licensed.
   ================================================================== */
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:400;font-display:swap;
  src:url('/fonts/IBMPlexMono-normal-400.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'IBM Plex Mono';font-style:normal;font-weight:500;font-display:swap;
  src:url('/fonts/IBMPlexMono-normal-500.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Newsreader';font-style:italic;font-weight:300 500;font-display:swap;
  src:url('/fonts/Newsreader-italic-300_500.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}
@font-face{font-family:'Newsreader';font-style:normal;font-weight:300 600;font-display:swap;
  src:url('/fonts/Newsreader-normal-300_600.woff2') format('woff2');unicode-range:U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;}

body{font-family:'Newsreader',Georgia,'Times New Roman',serif;font-size:17px;line-height:1.62}
h1,h2,h3{font-family:'Newsreader',Georgia,serif;font-weight:500;letter-spacing:-.012em}
.hero h1{font-weight:500;letter-spacing:-.018em}
.hero h1 em{font-style:italic;font-weight:500}
.brand,a.brand{font-family:'Newsreader',Georgia,serif;font-style:italic;font-weight:600;font-size:1.15rem}
.slabel,.kicker,.chip,nav a,.stat b,.role .meta,.edu .when,.btn{
  font-family:'IBM Plex Mono',ui-monospace,SFMono-Regular,Menlo,monospace}
.chip{font-size:.78rem;letter-spacing:.01em}
nav a{font-size:.76rem;letter-spacing:.09em;text-transform:uppercase}
.stat b{font-weight:500;letter-spacing:-.01em}
.role .meta,.edu .when{font-size:.75rem;letter-spacing:.04em}
/* Buttons keep the mono texture but stay in sentence case: shouting at the
   reader was not the point of the typeface. */
.btn{font-size:.86rem;letter-spacing:.02em;font-weight:500;text-transform:none}

/* Vertical centring inside the pill was depending on the font's ascent and
   descent metrics, and those are read differently on macOS and Windows for the
   same font file, so the same CSS centred here and sat low there. text-box trims
   the line box to cap-height and baseline, which removes the metrics from the
   calculation entirely: the pill now centres on the letterforms themselves.
   line-height:1 stays as the fallback for browsers without text-box support. */
.eyebrow{line-height:1.5;padding:.5rem .95rem .3rem}

/* LinkedIn's mark in LinkedIn's blue. Inheriting the text colour made it read
   as a broken icon rather than a brand. */
.btn-linkedin svg,.btn svg{fill:#4a9eff}
.btn-linkedin:hover svg,.btn:hover svg{fill:#7bb8ff}

/* Active section: full-strength text, heavier, and an accent rule under it.
   Grey-to-white alone was a difference you had to hunt for. */
nav a[aria-current="page"],nav a.is-active{
  color:var(--text);font-weight:500;
  box-shadow:inset 0 -2px 0 0 var(--accent);
}
