  *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

  :root {
    --bg:      #ffffff;
    --s1:      #f4f4f5;
    --s2:      #e4e4e7;
    --line:    rgba(228,228,231,.6);
    --line-2:  rgba(228,228,231,.8);
    --hover:   rgba(250,250,250,.6);
    --t1:      #09090b;
    --t2:      #3f3f46;
    --t3:      #52525b;
    --t4:      #a1a1aa;
    --inv-bg:  #09090b;
    --inv-tx:  #fafafa;
    --dot:     #0a0a0a38;
    --dot-op:  .5;
    --live:    #16a34a;

    --sans:  'Geist', 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --mono:  'Geist Mono', 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
    --serif: 'Source Serif 4', Georgia, serif;
  }

  html[data-theme="dark"] {
    --bg:      #09090b;
    --s1:      #202024;
    --s2:      #27272a;
    --line:    rgba(39,39,42,.6);
    --line-2:  rgba(39,39,42,.8);
    --hover:   rgba(24,24,27,.3);
    --t1:      #fafafa;
    --t2:      #d4d4d8;
    --t3:      #a1a1aa;
    --t4:      #71717a;
    --inv-bg:  #fafafa;
    --inv-tx:  #09090b;
    --dot:     #f4f4f533;
    --dot-op:  .25;
    --live:    #4ade80;
  }

  html {
    scroll-behavior: smooth;
    background: var(--bg);
    overflow-x: clip;
    width: 100%;
    /* keeps the scrollbar's space reserved, so locking scroll for a
       modal doesn't shift the whole layout sideways as it disappears */
    scrollbar-gutter: stable;
  }

  body {
    background: var(--bg);
    color: var(--t1);
    font-family: var(--sans);
    font-size: 16px;
    line-height: 1.6;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    overflow-x: clip;
    width: 100%;
    max-width: 100vw;
    transition: background-color .2s, color .2s;
  }

  ::selection { background: var(--t1); color: var(--bg); }
  a { color: inherit; }
  img { max-width: 100%; }

  /* ── fixed halftone corner ornaments ── */
  .ht {
    position: fixed;
    background-image: radial-gradient(var(--dot) 1px, transparent 1px);
    background-size: 9px 9px;
    pointer-events: none;
    user-select: none;
    z-index: 0;
    opacity: var(--dot-op);
  }

  .ht-tr {
    top: 0; right: 0; width: 420px; height: 420px;
    -webkit-mask-image: radial-gradient(circle at 100% 0, #000 20%, transparent 70%);
    mask-image: radial-gradient(circle at 100% 0, #000 20%, transparent 70%);
  }

  .ht-bl {
    bottom: 0; left: 0; width: 360px; height: 360px;
    -webkit-mask-image: radial-gradient(circle at 0 100%, #000 20%, transparent 70%);
    mask-image: radial-gradient(circle at 0 100%, #000 20%, transparent 70%);
  }

  @media (max-width: 640px) {
    .ht-tr { width: 200px; height: 200px; }
    .ht-bl { width: 180px; height: 180px; }
  }

  .progress { position: fixed; top: 0; left: 0; height: 1px; width: 0; background: var(--t3); z-index: 120; transition: width .1s linear; }

  .cur {
    position: fixed; z-index: 130; pointer-events: none;
    width: 7px; height: 7px; border-radius: 50%;
    background: var(--t1);
    transform: translate(-50%, -50%);
    transition: width .18s, height .18s, opacity .18s;
    opacity: 0; display: none;
  }

  .cur.on { opacity: .8; }
  .cur.big { width: 30px; height: 30px; opacity: .16; }
  @media (min-width: 641px) and (hover: hover) { .cur { display: block; } }

  .cursor-tail {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 129;
    width: var(--tail-size);
    height: var(--tail-size);
    border-radius: 50%;
    background: var(--live);
    box-shadow: 0 0 12px color-mix(in srgb, var(--live) 70%, transparent);
    pointer-events: none;
    opacity: 0;
    transition: opacity .18s ease;
    will-change: transform;
  }

  .cursor-tail.on { opacity: calc(.62 - var(--tail-index) * .07); }
  @media (max-width: 640px), (hover: none) { .cursor-tail { display: none; } }

  /* ── PAGE SHELL: narrow centred column ── */
  .shell {
    position: relative;
    z-index: 1;
    max-width: 768px;
    width: 100%;
    margin: 0 auto;
    padding: 78px 32px 56px;
    display: flex;
    flex-direction: column;
  }

  @media (min-width: 768px) { .shell { padding: 84px 60px 64px; } }

  /* reserves space above every section's anchor-scroll target so it
     doesn't land tucked under (or inconsistently offset from) the
     fixed 54px nav bar when a nav link is clicked */
  .sec { padding: 24px 0; position: relative; scroll-margin-top: 96px; }

  /* ── SECTION HEADER ── */
  .shead {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
    border-bottom: 1px solid var(--line-2);
    padding-bottom: 12px;
    margin-bottom: 16px;
  }

  /* nudge the right-side label down to sit on the heading's first
     line instead of the flex box's very top edge */
  .shead-a { margin-top: 2px; }

  .shead-t { font-family: var(--mono); font-size: 16px; font-weight: 400; color: var(--t3); letter-spacing: -0.02em; }
  .shead-t b { color: var(--t1); font-weight: 700; }

  .shead-a {
    font-family: var(--mono);
    font-size: 11px;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--t4);
    text-decoration: none;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    background: none;
    border: none;
    cursor: pointer;
    transition: color .16s;
    white-space: nowrap;
  }

  .shead-a:hover { color: var(--t1); }
  .shead-a svg { width: 12px; height: 12px; transition: transform .18s; }

  /* on small screens the Stack heading wraps and pushes against this
     note, and the Résumé shortcut here is redundant with the one in
     the nav/hero — simplest fix is to just not show either below 640px */
  @media (max-width: 640px) {
    #stack .shead-a, #cvPill2, #credentials .shead-a, #gallery .shead-a { display: none; }
  }
  .shead-a:hover svg { transform: translateX(2px); }
  .shead-a.diag:hover svg { transform: translate(2px, -2px); }

  /* ── FEATURED CASE STUDY ── */
  /* pulled out of the plain row list so the flagship project reads as
     something to open, not just another line item among equals */
  .featured {
    border: 1px solid var(--line-2);
    border-radius: 14px;
    padding: 6px 8px 10px;
    margin-bottom: 22px;
  }

  .featured-kicker {
    display: flex;
    align-items: center;
    gap: 7px;
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--t1);
    padding: 10px 10px 2px;
  }

  .featured-kicker svg { width: 13px; height: 13px; color: var(--live); }

  .featured .row:hover { background: var(--s1); }

  .also-built {
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--t4);
    margin-bottom: 10px;
  }

  /* ── DIVIDED ROW LIST ── */
  .rows { display: flex; flex-direction: column; }
  .rows > * + * { border-top: 1px solid var(--line); }

  .row {
    padding: 18px 10px;
    border-radius: 12px;
    transition: background .18s;
    display: flex;
    flex-direction: column;
    gap: 10px;
    text-align: left;
    width: 100%;
    background: none;
    border: none;
    font-family: inherit;
    color: inherit;
  }

  .row:hover { background: var(--hover); }
  .row[data-case] { cursor: pointer; }

  /* the project title is the card's real button (the whole card is
     clickable through script.js); it looks like plain heading text */
  .row-open { all: unset; cursor: pointer; }
  .row:has(.row-open:focus-visible) { outline: 2px solid var(--t3); outline-offset: 2px; }

  /* "tap to view case study" — on hover-capable devices this is
     replaced by a label that follows the cursor (see .hover-tip);
     touch devices have no hover, so they get this static hint instead */
  .row-more {
    display: none;
    align-items: center;
    gap: 5px;
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.13em;
    color: var(--t2);
    background: var(--s1);
    border: 1px solid var(--line-2);
    border-radius: 5px;
    padding: 4px 8px;
    margin-top: -2px;
    margin-left: -8px;
    align-self: flex-start;
    width: fit-content;
  }

  .row-more svg { width: 11px; height: 11px; }

  /* real touch devices report hover:none; the width check is a fallback
     for environments (like DevTools' device emulation) that don't
     always flip the hover media feature even while simulating a phone —
     it also matches the width the cursor tooltip already turns off at */
  @media (hover: none), (max-width: 640px) {
    .row-more { display: inline-flex; }
  }

  /* floating label that tracks the cursor while hovering a project row */
  .hover-tip {
    position: fixed;
    top: 0; left: 0;
    z-index: 140;
    display: none;
    align-items: center;
    gap: 6px;
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--inv-tx);
    background: var(--inv-bg);
    border-radius: 100px;
    padding: 7px 12px;
    pointer-events: none;
    opacity: 0;
    transform: translate(18px, 22px);
    transition: opacity .15s ease;
    white-space: nowrap;
  }

  .hover-tip.on { opacity: 1; }
  .hover-tip svg { width: 11px; height: 11px; flex-shrink: 0; }

  @media (min-width: 641px) and (hover: hover) { .hover-tip { display: inline-flex; } }

  /* ── HERO ── */
  .hero { padding-top: 0; padding-bottom: 0; }

  .hero-main {
    display: flex;
    flex-direction: column;
    gap: 24px;
    align-items: center;
    text-align: center;
  }

  @media (min-width: 640px) {
    .hero-main { flex-direction: row; gap: 28px; align-items: flex-start; text-align: left; }
  }

  .ava {
    position: relative;
    width: 144px; height: 144px;
    flex-shrink: 0;
    border-radius: 14px;
    overflow: hidden;
    border: 1px solid var(--line-2);
    cursor: zoom-in;
    background: var(--s1);
  }

  @media (max-width: 380px) { .ava { width: 116px; height: 116px; } }
  @media (min-width: 640px) { .ava { width: 160px; height: 160px; } }

  .ava img {
    width: 100%; height: 100%;
    object-fit: cover;
    object-position: 48% 24%;
    display: block;
    filter: grayscale(1) contrast(1.3);
    transition: transform .5s, filter .4s;
  }

  .ava::after {
    content: '';
    position: absolute; inset: 0;
    background-image: radial-gradient(var(--dot) 1.1px, transparent 1.1px);
    background-size: 4px 4px;
    mix-blend-mode: overlay;
    pointer-events: none;
    transition: opacity .4s;
  }

  .ava:hover img { transform: scale(1.05); filter: grayscale(0) contrast(1.02); }
  .ava:hover::after { opacity: 0; }

  .hero-body { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; }

  .avail {
    display: inline-flex;
    align-items: center;
    gap: 7px;
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--t3);
    margin-bottom: 10px;
    align-self: center;
  }

  @media (min-width: 640px) { .avail { align-self: flex-start; } }

  .pip { width: 5px; height: 5px; border-radius: 50%; background: var(--live); animation: soft 2.4s ease infinite; flex-shrink: 0; }
  @keyframes soft { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }

  h1 {
    font-family: var(--mono);
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.04em;
    line-height: 1.15;
    margin-bottom: 4px;
    color: var(--t1);
  }

  @media (min-width: 640px) { h1 { font-size: 30px; } }

  .hero-role {
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.13em;
    text-transform: uppercase;
    color: var(--t4);
    margin-bottom: 14px;
  }

  .hero-bio { display: flex; flex-direction: column; gap: 8px; }
  .hero-bio p { font-size: 14px; line-height: 1.75; color: var(--t3); }
  .hero-bio strong { color: var(--t2); font-weight: 600; }
  .hero-bio .se { font-family: var(--serif); font-style: italic; color: var(--t2); }

  .pills {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 16px;
    font-family: var(--mono);
    font-size: 11.5px;
    justify-content: center;
  }

  @media (min-width: 640px) { .pills { justify-content: flex-start; } }

  /* line breaks inside the button row: résumé / contact + github /
     linkedin + facebook, the same on every screen width */
  .pills-break { flex-basis: 100%; height: 0; }

  .pill {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    padding: 5px 9px;
    border-radius: 6px;
    background: var(--s1);
    color: var(--t2);
    text-decoration: none;
    border: none;
    cursor: pointer;
    font-family: var(--mono);
    font-size: 11.5px;
    font-weight: 500;
    overflow-wrap: anywhere;
    transition: background .16s, color .16s;
  }

  .pill:hover { background: var(--s2); color: var(--t1); }
  .pill svg { width: 12px; height: 12px; flex-shrink: 0; }
  .pill-solid { background: var(--inv-bg); color: var(--inv-tx); }
  .pill-solid:hover { background: var(--inv-bg); color: var(--inv-tx); opacity: .85; }

  /* stat strip */
  .stats {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
    margin-top: 22px;
  }

  .stat {
    padding: 20px 14px;
    border-right: 1px solid var(--line);
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 8px;
  }

  .stat:last-child { border-right: none; }
  .stat-n { font-family: var(--mono); font-size: 26px; font-weight: 700; letter-spacing: -0.05em; line-height: 1; font-variant-numeric: tabular-nums; }
  .stat-l { font-family: var(--mono); font-size: 10px; font-weight: 600; color: var(--t4); letter-spacing: 0.11em; text-transform: uppercase; line-height: 1.6; }

  /* the one stat that proves it's real, not just built — same signal
     colour as the "Available" pip and the project "Live" badges */
  .stat-hi .stat-l { color: var(--live); }

  /* narrow phones: 2x2 instead of 4-across, so a longer label
     (e.g. "Roles — sole IT support") has room to breathe */
  @media (max-width: 420px) {
    .stats { grid-template-columns: repeat(2, 1fr); }
    .stat:nth-child(2n) { border-right: none; }
    .stat:nth-child(-n+2) { border-bottom: 1px solid var(--line); }
    .stat { padding: 16px 10px; }
  }

  /* ── PROJECT ROW ── */
  .prow-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
  .prow-l { display: flex; align-items: flex-start; gap: 10px; min-width: 0; }

  .picon {
    width: 32px; height: 32px;
    border-radius: 9px;
    background: var(--s1);
    display: grid;
    place-items: center;
    flex-shrink: 0;
    color: var(--t2);
    font-family: var(--mono);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: -0.03em;
  }

  .picon svg { width: 15px; height: 15px; }

  /* a project's own logo in place of the initials; the round logos
     stand on their own, a bare mark gets the usual tile behind it */
  .picon-img { width: 40px; height: 40px; border-radius: 50%; background: none; overflow: hidden; box-shadow: 0 0 0 1px var(--line-2); }
  .picon-img img { width: 100%; height: 100%; object-fit: contain; display: block; }
  .picon-tile { border-radius: 10px; background: var(--s1); padding: 5px; box-shadow: none; }

  .prow-txt { display: flex; flex-direction: column; min-width: 0; }
  .prow-t { display: block; font-family: var(--mono); font-size: 15px; font-weight: 700; line-height: 1.3; letter-spacing: -0.03em; color: var(--t1); }
  .prow-m { display: block; font-family: var(--mono); font-size: 11px; color: var(--t4); margin-top: 4px; letter-spacing: -0.01em; }

  .icon-link {
    padding: 4px;
    border-radius: 6px;
    color: var(--t4);
    flex-shrink: 0;
    transition: color .16s;
    display: inline-grid;
    place-items: center;
    text-decoration: none;
  }

  .icon-link:hover { color: var(--t1); background: var(--s1); }
  .icon-link svg { width: 14px; height: 14px; }

  /* badge + launch button, right-aligned in a project row */
  .prow-act { display: inline-flex; align-items: center; gap: 6px; flex-shrink: 0; }

  .badge-off {
    color: var(--t4);
    border: 1px solid var(--line-2);
    border-radius: 5px;
    padding: 3px 8px;
  }

  .prow-d { font-size: 14.5px; line-height: 1.72; color: var(--t2); }
  .prow-d strong { color: var(--t2); font-weight: 600; }

  .chips { display: flex; flex-wrap: wrap; gap: 5px; font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.1em; }
  .chip { background: var(--s1); color: var(--t3); padding: 2px 7px; border-radius: 4px; font-weight: 500; }

  .badge {
    display: inline-flex;
    align-items: center;
    gap: 5px;
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--t4);
    white-space: nowrap;
  }

  .badge-live { color: var(--live); }
  .badge-live::before { content: ''; width: 4px; height: 4px; border-radius: 50%; background: var(--live); animation: soft 2.4s ease infinite; }

  /* ── EXPERIENCE ROW ── */
  .erow { padding: 16px 10px; border-radius: 12px; transition: background .18s; display: flex; flex-direction: column; gap: 6px; }
  .erow:hover { background: var(--hover); }
  .erow-top { display: flex; flex-direction: column; gap: 3px; }

  @media (min-width: 640px) { .erow-top { flex-direction: row; align-items: baseline; justify-content: space-between; gap: 12px; } }

  .erow-r { font-size: 15px; font-weight: 700; line-height: 1.35; color: var(--t1); }
  .erow-when { font-family: var(--mono); font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.14em; color: var(--t4); flex-shrink: 0; }
  .erow-mid { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-family: var(--mono); font-size: 13px; }
  .erow-co { color: var(--t3); }
  .erow-type { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.12em; color: var(--t4); flex-shrink: 0; }
  .erow-d { font-size: 14.5px; line-height: 1.72; color: var(--t2); margin-top: 2px; }
  .erow-d strong { color: var(--t2); font-weight: 600; }

  /* ── STACK ── */
  .stack-grid { display: grid; grid-template-columns: 1fr; gap: 12px; }
  @media (min-width: 640px) { .stack-grid { grid-template-columns: 1fr 1fr; } }

  /* Each desktop pair shares a row height, so the grid reads as a calm,
     intentional two-column system instead of uneven floating cards. */
  .scard { border: 1px solid var(--line-2); border-radius: 12px; padding: 16px 18px 18px; }
  .scard-k { font-family: var(--mono); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.14em; color: var(--t4); margin-bottom: 12px; padding-bottom: 8px; border-bottom: 1px solid var(--line); }
  .skills { display: flex; flex-wrap: wrap; gap: 6px; font-family: var(--mono); font-size: 11px; }
  .skill { display: inline-flex; align-items: center; gap: 7px; background: var(--s1); color: var(--t2); padding: 5px 10px 5px 6px; border-radius: 7px; font-weight: 500; transition: background .16s; }
  .skill:hover { background: var(--s2); }

  /* Tech stickers: a small tile holding the brand's own glyph. --tc is
     set per sticker, so one rule covers every tool; the glyph is mixed
     toward the text colour so pale brands stay readable in light mode. */
  .ti { display: inline-grid; place-items: center; width: 22px; height: 22px; flex-shrink: 0; border-radius: 6px; background: var(--bg); color: color-mix(in srgb, var(--tc, var(--t3)) 62%, var(--t1)); }
  .ti svg { width: 14px; height: 14px; display: block; }
  /* in dark mode the brand colour is mixed toward white instead, so
     near-black brands (Next.js, Railway, GitHub) stay visible */
  html[data-theme="dark"] .ti { color: color-mix(in srgb, var(--tc, var(--t3)) 45%, #fafafa); }
  .skill-hi { border: 1px solid var(--t4); background: transparent; color: var(--t1); font-weight: 600; }

  /* ── GITHUB CONTRIBUTIONS ── */
  .contrib-chart {
    margin-top: 18px;
    border: 1px solid #243447;
    border-radius: 12px;
    padding: 16px 18px 18px;
    max-width: 100%;
    overflow: hidden;
    background: var(--bg);
    box-shadow: inset 0 1px 0 rgba(255,255,255,.05), 0 12px 32px rgba(0,0,0,.16);
  }

  .contrib-chart-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 12px; }
  .contrib-chart-k { font-family: var(--mono); font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .14em; color: var(--live); }
  .contrib-chart-n { font-size: 13px; color: var(--t3); }
  .contrib-chart-n b { font-size: 18px; font-weight: 700; color: var(--t1); font-variant-numeric: tabular-nums; margin-right: 2px; }
  .contrib-chart img { display: block; width: 100%; max-width: 100%; min-width: 0; height: auto; }
  .contrib-chart-dark { display: none !important; }
  html[data-theme="dark"] .contrib-chart-light { display: none !important; }
  html[data-theme="dark"] .contrib-chart { background: #050505; }
  html[data-theme="dark"] .contrib-chart-dark { display: block !important; filter: invert(1); }

  /* ── CREDENTIALS GRID ── */
  .cert-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
  @media (min-width: 640px) { .cert-grid { grid-template-columns: repeat(3, 1fr); } }

  .cert {
    border: 1px solid var(--line-2);
    border-radius: 12px;
    padding: 14px;
    text-align: left;
    background: none;
    cursor: pointer;
    font-family: inherit;
    color: inherit;
    text-decoration: none;
    display: flex;
    flex-direction: column;
    min-width: 0;
    transition: background .18s, border-color .18s;
  }

  .cert:hover { background: var(--hover); border-color: var(--t4); }
  .cert-k { font-family: var(--mono); font-size: 10px; text-transform: uppercase; letter-spacing: 0.15em; color: var(--t4); margin-bottom: 7px; }
  @media (min-width: 640px) { .cert-k { font-size: 10.5px; } }
  .cert-t { font-size: 12px; font-weight: 700; line-height: 1.35; letter-spacing: -0.02em; color: var(--t1); margin-bottom: 3px; }
  @media (min-width: 640px) { .cert-t { font-size: 14px; } }
  .cert-s { font-family: var(--mono); font-size: 10.5px; color: var(--t4); margin-top: auto; padding-top: 8px; overflow-wrap: anywhere; }

  /* certificate card: caption + highlighted "tap to view" pill, stacked
     and pinned to the bottom of the card as one group */
  .cert-foot { margin-top: auto; padding-top: 8px; display: flex; flex-direction: column; gap: 7px; min-width: 0; }
  .cert-foot .cert-s { margin-top: 0; padding-top: 0; }

  /* same pattern as .row-more: hover-capable desktops get the cursor
     tooltip instead (see .hover-tip), touch/narrow gets this static hint */
  .cert-more {
    display: none;
    align-items: center;
    gap: 5px;
    font-family: var(--mono);
    font-size: 10.5px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.13em;
    color: var(--t2);
    background: var(--s1);
    border: 1px solid var(--line-2);
    border-radius: 5px;
    padding: 4px 8px;
    width: fit-content;
    max-width: 100%;
    overflow-wrap: anywhere;
  }

  .cert-more svg { width: 11px; height: 11px; }

  @media (hover: none), (max-width: 640px) {
    .cert-more { display: inline-flex; }
  }

  /* ── GALLERY SLIDESHOW ── */
  .car {
    position: relative;
    overflow: hidden;
  }

  .car-track {
    width: 100%;
  }

  /* prev / next */
  .car-btn {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    width: 34px; height: 34px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    border: 1px solid var(--line-2);
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: var(--t2);
    cursor: pointer;
    z-index: 4;
    opacity: 0;
    transition: opacity .22s, color .16s, border-color .16s, background .16s;
  }

  .car:hover .car-btn, .car:focus-within .car-btn { opacity: 1; }
  .car-btn:hover { color: var(--t1); border-color: var(--t4); background: var(--bg); }
  .car-btn svg { width: 15px; height: 15px; }
  .car-prev { left: 10px; }
  .car-next { right: 10px; }

  /* no hover on touch — keep the arrows visible there */
  @media (hover: none) { .car-btn { opacity: 1; } }

  .car-group { display: grid; }

  .car-slide {
    position: relative;
    grid-area: 1 / 1;
    width: 100%;
    aspect-ratio: 16/10;
    border: 1px solid var(--line-2);
    border-radius: 10px;
    overflow: hidden;
    background: var(--s1);
    cursor: zoom-in;
    padding: 0;
    display: block;
    opacity: 0;
    pointer-events: none;
    transform: scale(.985);
    transition: opacity .45s ease, transform .45s ease, border-color .18s;
  }

  .car-slide.active { opacity: 1; pointer-events: auto; transform: none; }

  .car-slide:hover { border-color: var(--t4); transform: translateY(-2px); }
  .car-slide img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
    filter: grayscale(1) contrast(1.06);
    transition: transform .5s, filter .45s;
  }

  .car-slide:hover img { transform: scale(1.05); filter: grayscale(0) contrast(1); }

  .car-slide::after {
    content: '';
    position: absolute;
    inset: 0;
    background: rgba(0,0,0,.14);
    transition: background .35s;
    pointer-events: none;
  }

  .car-slide:hover::after { background: rgba(0,0,0,0); }

  .car-n {
    position: absolute;
    left: 6px; bottom: 6px;
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: #fff;
    background: rgba(0,0,0,.62);
    border-radius: 4px;
    padding: 2px 6px;
    pointer-events: none;
    z-index: 1;
  }

  /* "click to view" hint, revealed on hover while the strip is paused */
  .car-hint {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    opacity: 0;
    transition: opacity .22s;
    pointer-events: none;
    z-index: 2;
  }

  .car-hint span {
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: #fff;
    background: rgba(0,0,0,.7);
    border-radius: 100px;
    padding: 6px 12px;
  }

  .car-slide:hover .car-hint { opacity: 1; }

  .car-ph {
    position: absolute; inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 5px;
    padding: 12px;
    font-family: var(--mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--t4);
    text-align: center;
    background-image: radial-gradient(var(--dot) 1px, transparent 1px);
    background-size: 9px 9px;
  }

  .car-ph b { color: var(--t3); font-weight: 600; text-transform: none; letter-spacing: 0; font-size: 11px; }
  .car-slide.empty img, .car-slide.empty .car-n, .car-slide.empty .car-hint { display: none; }
  .car-slide.empty::after { display: none; }
  .car-slide.empty { cursor: default; }
  .car-slide.empty:hover { border-color: var(--line-2); transform: none; }
  .car-slide:not(.empty) .car-ph { display: none; }

  .car-cap {
    font-family: var(--mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    color: var(--t4);
    line-height: 1.5;
    margin-top: 14px;
  }

  /* no motion: hold still, arrows still work */
  @media (prefers-reduced-motion: reduce) {
    .car-btn { opacity: 1; }
  }

  /* ── NAV BAR ── */
  nav {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 110;
    height: 54px;
    background: color-mix(in srgb, var(--bg) 88%, transparent);
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border-bottom: 1px solid var(--line);
  }

  .nav-in {
    max-width: 768px;
    margin: 0 auto;
    height: 100%;
    padding: 0 32px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 14px;
  }

  @media (min-width: 768px) { .nav-in { padding: 0 60px; } }

  .brand { font-family: var(--mono); font-size: 15px; font-weight: 700; letter-spacing: -0.05em; text-decoration: none; color: var(--t1); }
  .brand i { font-style: normal; color: var(--t4); font-weight: 400; }

  .nav-right { display: flex; align-items: center; gap: 5px; }

  /* inline section links — desktop only */
  .nav-links { display: none; align-items: center; gap: 2px; list-style: none; margin-right: 6px; }

  .nav-links a {
    font-family: var(--mono);
    font-size: 11px;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--t4);
    text-decoration: none;
    padding: 7px 8px;
    border-radius: 6px;
    transition: color .16s, background .16s;
    white-space: nowrap;
  }

  .nav-links a:hover { color: var(--t1); background: var(--s1); }
  .nav-links a.active { color: var(--t1); }

  @media (min-width: 860px) {
    .nav-links { display: flex; }
    #burger { display: none; }
    .nav-in { max-width: 1000px; }
  }

  .ibtn {
    width: 31px; height: 31px;
    display: grid; place-items: center;
    border: 1px solid var(--line-2);
    background: transparent;
    border-radius: 7px;
    cursor: pointer;
    color: var(--t4);
    transition: color .16s, border-color .16s;
    flex-shrink: 0;
  }

  .ibtn:hover { color: var(--t1); border-color: var(--t4); }
  .ibtn svg { width: 14px; height: 14px; }

  /* Focus blur only exists in the wide, three-panel desktop layout. */
  .unblur-btn { display: none; }

  .sun { display: none; }
  .moon { display: block; }
  html[data-theme="dark"] .sun { display: block; }
  html[data-theme="dark"] .moon { display: none; }

  /* fullscreen sheet menu */
  .sheet {
    position: fixed;
    inset: 0;
    z-index: 105;
    background: color-mix(in srgb, var(--bg) 92%, transparent);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 0 32px;
    opacity: 0;
    pointer-events: none;
    transition: opacity .25s ease;
  }

  .sheet.open { opacity: 1; pointer-events: all; }

  .sheet a {
    display: flex;
    align-items: baseline;
    gap: 14px;
    font-family: var(--mono);
    font-size: 22px;
    font-weight: 700;
    letter-spacing: -0.045em;
    color: var(--t1);
    text-decoration: none;
    padding: 13px 0;
    border-bottom: 1px solid var(--line);
    transition: opacity .16s;
  }

  .sheet a:hover { opacity: .55; }
  .sheet a span { font-family: var(--mono); font-size: 11px; font-weight: 600; letter-spacing: 0.14em; color: var(--t4); }

  /* ── FOOTER ── */
  footer { border-top: 1px solid var(--line-2); margin-top: 8px; padding-top: 20px; display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; font-family: var(--mono); font-size: 11px; text-transform: uppercase; letter-spacing: 0.13em; color: var(--t4); }
  .foot-links { display: flex; gap: 14px; }
  .foot-links a { text-decoration: none; transition: color .16s; }
  .foot-links a:hover { color: var(--t1); }

  /* ── BACK TO TOP ── */
  .top {
    position: fixed;
    bottom: 20px; right: 20px;
    width: 34px; height: 34px;
    border-radius: 8px;
    background: var(--inv-bg);
    color: var(--inv-tx);
    border: none;
    cursor: pointer;
    display: grid;
    place-items: center;
    opacity: 0;
    visibility: hidden;
    transform: translateY(8px);
    transition: opacity .3s, visibility .3s, transform .3s;
    z-index: 99;
  }

  .top.on { opacity: 1; visibility: visible; transform: none; }
  .top:hover { opacity: .82; }
  .top svg { width: 14px; height: 14px; }

  /* ── REVEAL ── */
  .rv { opacity: 0; transform: translateY(12px); transition: opacity .6s ease, transform .6s ease; }
  .rv.on { opacity: 1; transform: none; }

  @media (prefers-reduced-motion: reduce) {
    .rv { opacity: 1; transform: none; transition: none; }
    *, *::before, *::after { animation: none !important; scroll-behavior: auto !important; }
  }

  /* ── MODALS ── */
  .ov {
    position: fixed;
    inset: 0;
    background: rgba(0,0,0,.6);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    z-index: 200;
    display: flex;
    align-items: center;
    justify-content: center;
    opacity: 0;
    pointer-events: none;
    transition: opacity .2s ease;
    padding: 16px;
  }

  .ov.open { opacity: 1; pointer-events: all; }

  .modal {
    background: var(--bg);
    border: 1px solid var(--line-2);
    border-radius: 14px;
    width: 100%;
    max-width: 440px;
    padding: 26px;
    position: relative;
    max-height: 90vh;
    overflow-y: auto;
  }

  .modal-wide { max-width: 720px; }

  .modal-x {
    position: absolute;
    top: 13px; right: 13px;
    background: none;
    border: none;
    cursor: pointer;
    color: var(--t4);
    padding: 5px;
    border-radius: 6px;
    line-height: 0;
    transition: color .16s;
    z-index: 2;
  }

  .modal-x:hover { color: var(--t1); }
  .modal-k { font-family: var(--mono); font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.15em; color: var(--t4); margin-bottom: 8px; display: block; }
  .modal-t { font-family: var(--mono); font-size: 19px; font-weight: 700; letter-spacing: -0.04em; margin-bottom: 4px; line-height: 1.25; }
  .modal-m { font-family: var(--mono); font-size: 11px; color: var(--t4); margin-bottom: 18px; letter-spacing: -0.01em; }

  .fg { margin-bottom: 12px; }
  .fg label { display: block; margin-bottom: 5px; }

  .fi {
    width: 100%;
    background: var(--bg);
    border: 1px solid var(--line-2);
    border-radius: 7px;
    padding: 9px 11px;
    font-family: var(--sans);
    font-size: 14.5px;
    color: var(--t1);
    outline: none;
    transition: border-color .16s;
  }

  .fi:focus { border-color: var(--t4); }
  .fi::placeholder { color: var(--t4); }
  textarea.fi { resize: vertical; min-height: 90px; }
  .fa { display: flex; gap: 8px; margin-top: 16px; }
  .fa .pill { flex: 1; justify-content: center; padding: 10px; min-width: 0; }
  .fnote { font-family: var(--mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--t4); margin-top: 11px; }

  /* inline PDF viewer — the modal itself never scrolls, only the PDF does */
  .modal-doc {
    max-width: 820px;
    height: min(92vh, 900px);
    max-height: none;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    padding-bottom: 20px;
  }

  .modal-doc .modal-m { margin-bottom: 14px; }

  .pdf-frame {
    position: relative;
    width: 100%;
    flex: 1;
    min-height: 0;
    border: 1px solid var(--line-2);
    border-radius: 10px;
    overflow: hidden;
    background: var(--s1);
  }

  .modal-doc .fa { margin-top: 14px; flex-shrink: 0; }

  .pdf-frame iframe { position: relative; z-index: 1; width: 100%; height: 100%; border: 0; display: block; background: #fff; }

  .pdf-fallback {
    position: absolute;
    inset: 0;
    z-index: 0;
    display: grid;
    place-items: center;
    text-align: center;
    padding: 20px;
    font-family: var(--mono);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--t4);
    line-height: 2;
  }

  .pdf-fallback b { color: var(--t2); }

  /* certificate image inside a modal */
  .cert-view {
    width: 100%;
    border: 1px solid var(--line-2);
    border-radius: 10px;
    overflow: hidden;
    background: var(--s1);
    display: block;
    padding: 0;
    cursor: zoom-in;
    position: relative;
    min-height: 220px;
  }

  .cert-view img { width: 100%; display: block; }

  .cert-view-ph {
    position: absolute;
    inset: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 7px;
    font-family: var(--mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--t4);
    text-align: center;
    padding: 20px;
    background-image: radial-gradient(var(--dot) 1px, transparent 1px);
    background-size: 9px 9px;
  }

  .cert-view-ph b { color: var(--t3); font-weight: 600; text-transform: none; letter-spacing: 0; font-size: 11.5px; }
  .cert-view.empty img { display: none; }
  .cert-view.empty { cursor: default; }
  .cert-view:not(.empty) .cert-view-ph { display: none; }

  /* case-study modal: 6-up screenshot grid */
  .cs-grid {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 8px;
    margin-bottom: 8px;
  }

  @media (max-width: 520px) { .cs-grid { grid-template-columns: repeat(2, 1fr); } }

  .cs-thumb {
    position: relative;
    aspect-ratio: 16/10;
    border: 1px solid var(--line-2);
    border-radius: 8px;
    overflow: hidden;
    background: var(--s1);
    display: block;
    padding: 0;
    cursor: zoom-in;
    transition: border-color .18s, transform .18s;
  }

  .cs-thumb:hover { border-color: var(--t4); transform: translateY(-1px); }
  .cs-thumb img { width: 100%; height: 100%; object-fit: cover; object-position: top left; display: block; transition: transform .5s; }
  .cs-thumb:hover img { transform: scale(1.06); }

  .cs-thumb-n {
    position: absolute;
    left: 5px; bottom: 5px;
    font-family: var(--mono);
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.1em;
    color: #fff;
    background: rgba(0,0,0,.62);
    border-radius: 4px;
    padding: 2px 5px;
    pointer-events: none;
  }

  .cs-thumb-ph {
    position: absolute; inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--mono);
    font-size: 10px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--t4);
    text-align: center;
    padding: 8px;
    background-image: radial-gradient(var(--dot) 1px, transparent 1px);
    background-size: 9px 9px;
  }

  .cs-thumb.empty img, .cs-thumb.empty .cs-thumb-n { display: none; }
  .cs-thumb.empty { cursor: default; }
  .cs-thumb.empty:hover { transform: none; border-color: var(--line-2); }
  .cs-thumb:not(.empty) .cs-thumb-ph { display: none; }

  /* shown when a project has no screenshots at all */
  .cs-none {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 34px 20px;
    margin-bottom: 18px;
    border: 1px solid var(--line-2);
    border-radius: 10px;
    text-align: center;
    font-family: var(--mono);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--t4);
    line-height: 1.7;
    background-image: radial-gradient(var(--dot) 1px, transparent 1px);
    background-size: 9px 9px;
  }

  .cs-none svg { width: 22px; height: 22px; color: var(--t4); opacity: .65; }
  .cs-none b { color: var(--t3); font-weight: 700; font-size: 12px; letter-spacing: 0.08em; }

  .cs-grid-cap {
    font-family: var(--mono);
    font-size: 10.5px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: var(--t4);
    margin-bottom: 18px;
    line-height: 1.6;
  }

  .cs-pbr { border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); margin-bottom: 16px; }
  .cs-pbr > div { padding: 14px 0; }
  .cs-pbr > div + div { border-top: 1px solid var(--line); }
  .cs-k { font-family: var(--mono); font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.15em; color: var(--t4); display: block; margin-bottom: 7px; }
  .cs-pbr p { font-size: 14px; line-height: 1.7; color: var(--t3); }
  .cs-pbr p strong { color: var(--t2); font-weight: 600; }

  .cs-list { list-style: none; margin-top: 4px; }

  .cs-list li {
    position: relative;
    padding-left: 16px;
    margin-bottom: 11px;
    color: var(--t3);
    font-size: 14px;
    line-height: 1.72;
  }

  .cs-list li::before { content: ''; position: absolute; left: 1px; top: 9px; width: 3px; height: 3px; border-radius: 50%; background: var(--t4); }
  .cs-list strong { color: var(--t2); font-weight: 600; }
  /* a list under one of the problem / built / result paragraphs */
  .cs-pbr .cs-list { margin-top: 10px; }
  .cs-pbr .cs-list li:last-child { margin-bottom: 0; }

  .n { font-family: var(--mono); font-size: .92em; font-weight: 600; color: var(--t1); background: var(--s1); padding: 1px 5px; border-radius: 3px; font-variant-numeric: tabular-nums; white-space: nowrap; }

  /* lightbox */
  #lb .lb-img { max-width: 92vw; max-height: 86vh; border-radius: 8px; object-fit: contain; }

  .lb-nav {
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    padding: 9px;
    border-radius: 50%;
    background: rgba(0,0,0,.6);
    color: #fff;
    border: none;
    cursor: pointer;
    display: grid;
    place-items: center;
    transition: background .16s;
    z-index: 2;
  }

  .lb-nav:hover { background: rgba(0,0,0,.85); }
  .lb-nav svg { width: 17px; height: 17px; }
  .lb-prev { left: 8px; }
  .lb-next { right: 8px; }

  @media (min-width: 700px) { .lb-prev { left: 24px; } .lb-next { right: 24px; } }

  .lb-cap {
    position: absolute;
    bottom: 18px; left: 50%;
    transform: translateX(-50%);
    font-family: var(--mono);
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.12em;
    color: rgba(255,255,255,.75);
    background: rgba(0,0,0,.55);
    padding: 6px 13px;
    border-radius: 100px;
    white-space: nowrap;
    max-width: 88vw;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  @media (max-width: 480px) { .sheet a { font-size: 19px; } .modal { padding: 22px 18px; } }

  /* ══════════ WIDE DESKTOP: FIXED SIDE LAYOUT ══════════
     Hero locked left, nav locked right, only the middle column
     scrolls. Mobile and medium-desktop are untouched below this
     breakpoint - everything above still uses the normal top nav
     and single-column flow.

     The side columns are position: fixed rather than sticky so they
     never move at all - sticky still starts in flow and drifts once
     it runs out of room near the end of the page. Being fixed also
     gives them a full-height box, which is what lets their divider
     borders run the whole viewport and the sidebar's carousel sit
     properly at the bottom.

     They're offset with max(gutter, calc(50% - (max-width/2 - gutter)))
     so they line up with the centred .shell's content edges at any
     window size. 50% of a fixed element resolves against the viewport
     minus the scrollbar, which is exactly what .shell is centred in -
     100vw would include the scrollbar and sit a few px off. */

  .side-nav { display: none; }

  @media (min-width: 1280px) {
    .unblur-btn { display: grid; }

    /* the top bar is fully replaced by the side nav at this width */
    body > nav { display: none; }

    .shell {
      display: block;
      max-width: 1520px;
      padding: 24px 48px 64px;
    }

    .hero {
      position: fixed;
      top: 24px;
      bottom: 24px;
      left: max(48px, calc(50% - 712px));
      width: 400px;
      padding: 0 32px 0 0;
      border-right: 1px solid var(--line-2);
      overflow-y: auto;
      scrollbar-width: none;
      display: flex;
      flex-direction: column;
    }

    /* only ever scrolls on very short windows, and a scrollbar inside
       the pinned panel would read as a second page scroller */
    .hero::-webkit-scrollbar { display: none; }

    /* still not wide enough for the avatar-beside-text row the ≥640px
       breakpoint normally enables - fall back to the stacked layout
       mobile already uses, just in a narrower column */
    .hero .hero-main {
      flex-direction: column;
      align-items: flex-start;
      text-align: left;
      gap: 20px;
    }

    .hero .avail { align-self: center; }
    .hero .ava { align-self: center; }
    .hero .hero-body h1 { text-align: center; }
    .hero .hero-role { text-align: center; }

    /* the stat strip sits in the hero at this width, in the room left
       below the pills. The column is a fixed, full-height panel, so
       everything that takes real vertical space is sized against the
       viewport height rather than a fixed pixel budget - that way it
       fits short windows without the panel scrolling internally, and
       still reaches its full size on tall ones. */
    .hero .ava {
      width: min(180px, 20vh);
      height: min(180px, 20vh);
    }

    /* flex children of the panel - neither may be squeezed below its
       natural height, or the text inside gets clipped rather than the
       panel simply scrolling on a very short window */
    .hero .hero-main, .hero .stats { flex-shrink: 0; }

    .hero .hero-main { gap: clamp(8px, 1.8vh, 22px); }
    .hero .avail { margin-bottom: clamp(4px, 1vh, 10px); }
    .hero .hero-body h1 { font-size: clamp(22px, 3.6vh, 30px); }
    .hero .hero-role { margin-bottom: clamp(6px, 1.4vh, 14px); }
    .hero .hero-bio { gap: clamp(6px, 1.1vh, 11px); }
    .hero .hero-bio p { font-size: clamp(14px, 2.3vh, 18px); line-height: 1.6; }

    /* deliberately NOT margin-top: auto. Pinning the strip to the
       panel's bottom edge clips it whenever that edge isn't actually
       visible - a browser window sized past the taskbar is the common
       case, and CSS can't detect it. Letting the strip sit just after
       the pills leaves any slack at the bottom instead, where an
       obstruction like that covers nothing. */
    .hero .stats {
      grid-template-columns: repeat(2, 1fr);
      margin-top: clamp(12px, 2vh, 20px);
    }

    .hero .stat { padding: clamp(8px, 1.6vh, 15px) 8px; gap: clamp(3px, 0.7vh, 7px); }
    .hero .stat:nth-child(2n) { border-right: none; }
    .hero .stat:nth-child(-n+2) { border-bottom: 1px solid var(--line); }
    .hero .stat-n { font-size: clamp(17px, 2.9vh, 23px); }
    .hero .stat-l { font-size: clamp(8.5px, 1.3vh, 10px); letter-spacing: 0.07em; line-height: 1.45; }

    /* the only column that actually scrolls with the page - the fixed
       side columns are out of flow, so it reserves their space with
       margins (column width + a 48px gutter on each side) */
    .middle {
      min-width: 0;
      margin-left: 448px;
      margin-right: 328px;
    }

    /* no fixed top nav to clear at this width, so the sections'
       anchor-scroll offset only needs to match the shell's top gap */
    .sec { scroll-margin-top: 24px; }

    /* fixed right column, replaces the old top-bar nav links */
    .side-nav {
      position: fixed;
      top: 24px;
      bottom: 24px;
      right: max(48px, calc(50% - 712px));
      width: 280px;
      display: flex;
      flex-direction: column;
      padding-left: 32px;
      border-left: 1px solid var(--line-2);
    }

    /* controls + nav + actions belong together, so they share one
       modest rhythm rather than the column's larger section spacing */
    .side-nav-top {
      display: flex;
      flex-direction: column;
      gap: 24px;
    }


    .side-nav ul {
      list-style: none;
      display: flex;
      flex-direction: column;
      gap: 2px;
    }

    /* scoped to the nav list on purpose - the relocated button row also
       lives in this column, and its links must stay pills rather than
       picking up the nav's block/uppercase treatment */
    .side-nav ul a {
      display: block;
      font-family: var(--mono);
      font-size: 15px;
      font-weight: 600;
      text-transform: uppercase;
      letter-spacing: 0.09em;
      color: var(--t4);
      text-decoration: none;
      padding: 11px 14px;
      border-radius: 7px;
      transition: color .16s, background .16s;
    }

    .side-nav ul a:hover { color: var(--t1); background: var(--s1); }
    .side-nav ul a.active { color: var(--t1); }

    /* the hero's button row, relocated here by script.js */
    .side-nav-pills .pills {
      margin-top: 0;
      justify-content: flex-start;
      gap: 7px;
      padding-left: 14px;
    }

    .side-nav-icons { display: flex; gap: 8px; padding-left: 14px; }
    .side-nav-icons .ibtn { width: 36px; height: 36px; }
    .side-nav-icons .ibtn svg { width: 16px; height: 16px; }
    /* Hovering a panel makes it the clear visual priority. */
    .hero, .middle, .side-nav-gallery { transition: filter .28s ease, opacity .28s ease; }
    .side-nav ul, .side-nav-pills, .side-nav-icons { transition: filter .28s ease, opacity .28s ease; }

    /* Idle desktop: no panel is selected, so all panels recede until the
       cursor enters one of the three column zones. */
    body:not(.focus-hero):not(.focus-middle):not(.focus-nav):not(.focus-carousel) .hero,
    body:not(.focus-hero):not(.focus-middle):not(.focus-nav):not(.focus-carousel) .middle,
    body:not(.focus-hero):not(.focus-middle):not(.focus-nav):not(.focus-carousel) .side-nav ul,
    body:not(.focus-hero):not(.focus-middle):not(.focus-nav):not(.focus-carousel) .side-nav-pills,
    body:not(.focus-hero):not(.focus-middle):not(.focus-nav):not(.focus-carousel) .side-nav-icons,
    body:not(.focus-hero):not(.focus-middle):not(.focus-nav):not(.focus-carousel) .side-nav-gallery { filter: blur(5px); opacity: .20; }

    /* Left panel: leave résumé, theme and focus controls sharp and green. */
    body.focus-hero .middle, body.focus-hero .side-nav ul,
    body.focus-hero .side-nav-pills, body.focus-hero .side-nav-gallery,
    body.focus-middle .hero, body.focus-middle .side-nav-gallery,
    body.focus-nav .hero,
    body.focus-nav .side-nav-gallery,
    body.focus-carousel .hero, body.focus-carousel .middle,
    body.focus-carousel .side-nav ul, body.focus-carousel .side-nav-pills { filter: blur(5px); opacity: .20; }

    /* The primary reading column must always stay crisp when it is the
       active panel, including when the adjacent navigation is hovered. */
    body.focus-middle .middle, body.focus-nav .middle { filter: none; opacity: 1; }

    .side-nav-icons .ibtn { color: var(--live); border-color: var(--live); }
    html.focus-unblur .hero, html.focus-unblur .middle, html.focus-unblur .side-nav ul,
    html.focus-unblur .side-nav-pills, html.focus-unblur .side-nav-icons,
    html.focus-unblur .side-nav-gallery { filter: none !important; opacity: 1 !important; }

    /* the carousel is relocated in here by script.js at this width, so
       the section it normally lives in has nothing left to show */
    #gallery { display: none; }

    /* the gallery is the column's "extra" block, so it gets a rule and
       a deliberately larger gap to sit apart from the group above.

       Deliberately NOT margin-top: auto - pinning it to the panel's
       bottom edge clips it whenever that edge isn't actually visible,
       and a browser window sized past the taskbar is the common case.
       A fixed gap keeps the separation intentional and lets any slack
       fall harmlessly at the bottom instead. */
    .side-nav-gallery {
      flex: 1 1 auto;
      margin-top: 40px;
      padding-top: 28px;
      border-top: 1px solid var(--line);
      min-height: 0;
      overflow: hidden;
    }

    /* sized to the 248px of content width this column has.
       .car-track is width: max-content, so these have to be lengths -
       a percentage would resolve against a container sized by its own
       contents and blow each slide up to the image's intrinsic width */
    .side-nav-gallery .car-slide { width: 100%; }
    /* the 10px gap stays as-is - script.js hardcodes GAP = 10 for both
       its seamless-wrap measurement and its arrow step */

    .side-nav-gallery .car-btn { width: 30px; height: 30px; }
    .side-nav-gallery .car-btn svg { width: 13px; height: 13px; }
    .side-nav-gallery .car-prev { left: 6px; }
    .side-nav-gallery .car-next { right: 6px; }

    .side-nav-gallery .car-cap { margin-top: 12px; font-size: 10px; line-height: 1.55; }
  }

  /* Two trim tiers for short windows. The bio stays eight lines however
     small its font gets, so the panel can't shrink itself indefinitely.

     The budget also has to assume the bottom of the window may not be
     visible: a browser sized past the taskbar reports a viewport ~44px
     taller than what's actually on screen, and nothing in CSS can see
     that. So these thresholds leave that much in hand rather than
     filling the height the browser claims to have. */
  @media (min-width: 1280px) and (max-height: 820px) {
    .hero .ava { width: min(150px, 19vh); height: min(150px, 19vh); }
    .hero .hero-bio p { font-size: 16.5px; line-height: 1.55; }
    .hero .stat { padding: clamp(8px, 1.4vh, 12px) 8px; }
  }

  @media (min-width: 1280px) and (max-height: 740px) {
    .hero .ava { width: min(130px, 18vh); height: min(130px, 18vh); }
    .hero .hero-bio p { font-size: 14.5px; line-height: 1.5; }
    .hero .stat { padding: 8px; gap: 3px; }
    .hero .stat-n { font-size: 18px; }

    /* the side column runs out of room at the same point the hero does */
    .side-nav-top { gap: 18px; }
    .side-nav ul a { padding: 8px 14px; }
    .side-nav-gallery { margin-top: 24px; padding-top: 20px; }
    .side-nav-gallery .car-slide { width: 200px; }
  }

