/* ==============================================
   Jad Hunaidi Portfolio - Design System
   ============================================== */

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

html {
  scroll-behavior: smooth;
  scrollbar-width: thin;
  scrollbar-color: rgba(59,130,246,0.4) transparent;
}
::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(59,130,246,0.4); border-radius: 3px; }
::-webkit-scrollbar-thumb:hover { background: rgba(59,130,246,0.6); }

body {
  background: #050505;
  margin: 0;
  min-height: 100vh;
  overflow-x: hidden;
}

/* ---- Visually-hidden utility (screen-reader only) ---- */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---- Skip Link ---- */
.skip-link {
  position: absolute;
  left: -999px;
  top: 16px;
  z-index: 9999;
  padding: .6rem 1.2rem;
  background: #3b82f6;
  color: #fff;
  border-radius: 8px;
  font-weight: 600;
  text-decoration: none;
  font-family: system-ui, sans-serif;
  transition: none;
}
.skip-link:focus { left: 16px; }

/* ---- Animated Background Orbs ---- */
body::before, body::after {
  content: '';
  position: fixed;
  border-radius: 50%;
  filter: blur(50px);
  z-index: -1;
  pointer-events: none;
  will-change: transform;
}
body::before {
  width: 650px; height: 650px;
  background: hsla(262,78%,42%,0.52);
  top: -12%; left: -8%;
  animation: orbA 25s ease-in-out infinite alternate;
}
body::after {
  width: 550px; height: 550px;
  background: hsla(217,88%,40%,0.50);
  bottom: -12%; right: -8%;
  animation: orbB 30s ease-in-out infinite alternate;
}

@keyframes orbA {
  0%{transform:translate(0,0) scale(1)}
  50%{transform:translate(80px,60px) scale(1.1)}
  100%{transform:translate(-40px,120px) scale(.95)}
}
@keyframes orbB {
  0%{transform:translate(0,0) scale(1)}
  50%{transform:translate(-60px,-80px) scale(1.15)}
  100%{transform:translate(50px,-40px) scale(.9)}
}
@keyframes orbC {
  0%{transform:translate(-50%,-50%) scale(1)}
  50%{transform:translate(-40%,-60%) scale(1.1)}
  100%{transform:translate(-60%,-40%) scale(.95)}
}

/* ---- Design Tokens ---- */
.jh-wrap {
  --jh-fg: #f3f4f6;
  --jh-muted: #9ca3af;
  --jh-card: rgba(20,20,25,0.45);
  --jh-acc: #3b82f6;
  --jh-line: rgba(255,255,255,0.08);
  --jh-chip: rgba(255,255,255,0.05);
  --jh-radius: 16px;
  --jh-pad: 32px;
  --jh-space: 24px;
  --jh-space-sm: 12px;
  --jh-font-heading: 'Sora','Outfit',system-ui,sans-serif;
  --jh-font-body: 'Outfit',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;
  --jh-font-mono: 'JetBrains Mono','Fira Code',monospace;
  --jh-purple: #8b5cf6;

  font: 400 15.5px/1.6 var(--jh-font-body);
  color: var(--jh-fg);
  background: transparent;
  padding: var(--jh-pad);
  border-radius: var(--jh-radius);
  max-width: 1100px;
  margin-inline: auto;
  text-align: left;
}

.jh-wrap * { box-sizing:border-box; margin:0; padding:0; }
.jh-wrap p { margin-bottom: 1rem; }
.jh-wrap a { color:inherit; text-decoration:none; transition: color .2s; }
.jh-wrap a:hover { color:var(--jh-acc); }
.jh-wrap ul { padding-left: 1.5rem; margin: .5rem 0 1rem; }
.jh-wrap li { margin-bottom: .5rem; }
.jh-wrap details summary { cursor:pointer; color:var(--jh-muted); font-size:.9rem; transition: color .2s; }
.jh-wrap details summary:hover { color: var(--jh-fg); }
.jh-wrap details summary::marker { color:var(--jh-acc); }
.jh-wrap details[open] { border-top:1px dashed var(--jh-line); margin-top:8px; padding-top:8px; }

/* ---- Layout ---- */
.jh-wrap .grid { display:grid; gap:var(--jh-space); }
.jh-wrap .row { display:flex; gap:var(--jh-space-sm); flex-wrap:wrap; align-items:center; }
.jh-wrap .split { display:grid; grid-template-columns:1.1fr .9fr; gap:var(--jh-space); }
@media(max-width:860px){ .jh-wrap .split { grid-template-columns:1fr; } }

/* ---- Glassmorphism Cards ---- */
.jh-wrap .card {
  background: var(--jh-card);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--jh-line);
  border-radius: var(--jh-radius);
  padding: 24px;
  margin-bottom: 24px;
  box-shadow: 0 4px 30px rgba(0,0,0,0.1);
  transition: transform .35s cubic-bezier(.22,1,.36,1), border-color .35s ease, box-shadow .35s ease;
}
.jh-wrap .card:hover {
  transform: translateY(-3px);
  border-color: rgba(255,255,255,0.12);
  box-shadow: 0 12px 40px rgba(0,0,0,0.25);
}

/* ---- Typography ---- */
.jh-wrap .h1 {
  font: 700 clamp(1.6rem,2.5vw+1rem,2.2rem)/1.35 var(--jh-font-heading);
  margin:0; padding-bottom:4px; letter-spacing:-.3px; color:#fff;
}
.jh-wrap .h2 { font:600 1.25rem/1.3 var(--jh-font-heading); margin:0 0 .15rem; letter-spacing:-.2px; color:#fff; }
.jh-wrap .sub { font-size:1.05rem; color:var(--jh-muted); margin-top:-8px; margin-bottom:1rem; }
.jh-wrap .muted { color:var(--jh-muted); }

/* About paragraph — fluid font-size so the text scales with viewport instead
   of looking cramped on wide screens. clamp() locks the bounds so it stays
   readable on narrow phones and never gets oversized on huge desktops. */
#about .card > p.muted {
  font-size: clamp(1rem, 0.85rem + 0.65vw, 1.25rem);
  line-height: 1.7;
}
.jh-wrap .divider {
  height:1px; margin:16px 0 20px; width:100%;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.18), transparent);
  border:none;
}

/* ---- Pills & Tags ---- */
.jh-wrap .pill {
  background:var(--jh-chip); color:#d1d5db;
  border:1px solid var(--jh-line); border-radius:999px;
  padding:.3rem .8rem; font-size:.85rem; font-weight:500;
  display:inline-block;
  transition: background .2s, border-color .2s;
}
.jh-wrap .pill:hover { background:rgba(255,255,255,0.08); border-color:rgba(255,255,255,0.15); }
.jh-wrap .tagset { display:flex; flex-wrap:wrap; gap:8px; }

/* ---- Buttons ---- */
.jh-wrap .btn {
  display:inline-flex; align-items:center; gap:.5rem;
  padding:.6rem 1rem; border-radius:10px;
  background:rgba(59,130,246,0.15); color:#60a5fa;
  border:1px solid rgba(59,130,246,0.3);
  font:600 .9rem var(--jh-font-body); cursor:pointer;
  transition: all .2s;
  /* `manipulation` disables double-tap-to-zoom on the button itself (each
     tap registers immediately) but leaves pinch-zoom elsewhere on the page
     untouched. `user-select: none` stops the long-press text-select on
     mobile. -webkit-tap-highlight-color suppresses the grey iOS tap flash
     so taps feel snappy. */
  touch-action: manipulation;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.jh-wrap .btn:hover { background:rgba(59,130,246,0.25); transform:translateY(-1px); border-color:rgba(59,130,246,0.5); }
.jh-wrap .btn:active { transform:translateY(0) scale(.97); }
.jh-wrap .btn svg { width:1rem; height:1rem; flex-shrink:0; }
.jh-wrap .btn.secondary { background:var(--jh-chip); color:var(--jh-fg); border:1px solid var(--jh-line); }
.jh-wrap .btn.secondary:hover { background:rgba(255,255,255,0.1); border-color:rgba(255,255,255,0.2); }

.jh-wrap .btn.purple { background:rgba(139,92,246,0.15); color:#a78bfa; border:1px solid rgba(139,92,246,0.3); }
.jh-wrap .btn.purple:hover { background:rgba(139,92,246,0.25); border-color:rgba(139,92,246,0.5); }

/* Material Preset Button Group */
.jh-wrap .btn-group { display:flex; gap:0; }
.jh-wrap .btn-group .btn {
  border-radius:0; border-right-width:0;
  font-size:.82rem; padding:.45rem .75rem;
}
.jh-wrap .btn-group .btn:first-child { border-radius:10px 0 0 10px; }
.jh-wrap .btn-group .btn:last-child { border-radius:0 10px 10px 0; border-right-width:1px; }
.jh-wrap .btn-group .btn.active {
  background:rgba(59,130,246,0.3); color:#93bbfd;
  border-color:rgba(59,130,246,0.5);
}

/* Preset row */
.jh-wrap .preset-row { display:flex; gap:8px; flex-wrap:wrap; margin-top:14px; margin-bottom:16px; }
.jh-wrap .preset-row .btn { font-size:.82rem; padding:.4rem .7rem; }

/* ---- Projects ---- */
.jh-wrap .project-grid { display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:24px; }
.jh-wrap .project-card { position:relative; overflow:hidden; background:rgba(0,0,0,0.15); }
.jh-wrap .project-card img {
  width:100%; height:auto; object-fit:contain;
  border-radius:10px; border:1px solid var(--jh-line);
  background:rgba(0,0,0,0.4); aspect-ratio:16/9; display:block;
  transition: transform .4s ease;
  cursor:zoom-in;
}
.jh-wrap .project-card:hover img { transform:scale(1.02); }
.jh-wrap .project-details { margin-top:14px; padding-top:14px; border-top:1px dashed var(--jh-line); }

/* ---- Gallery ---- */
.jh-wrap .gallery-grid { display:grid; grid-template-columns:repeat(auto-fill,minmax(220px,1fr)); gap:20px; }
.jh-wrap .gallery-item { margin:0; }
.jh-wrap .gallery-item img {
  width:100%; height:auto; border-radius:10px;
  border:1px solid var(--jh-line); aspect-ratio:4/3;
  object-fit:cover; background:var(--jh-chip);
  transition: transform .4s cubic-bezier(.22,1,.36,1), box-shadow .4s ease;
  display:block; cursor:zoom-in;
}
.jh-wrap .gallery-item img:hover {
  transform:scale(1.04);
  box-shadow: 0 8px 30px rgba(0,0,0,0.3);
}
.jh-wrap .gallery-caption { font-size:.85rem; color:var(--jh-muted); margin-top:10px; line-height:1.4; display:block; }

/* ---- Experience ---- */
.jh-wrap .exp-item { display:flex; gap:16px; padding:16px 0; }
.jh-wrap .exp-item > div:nth-child(2) { flex:1; min-width:0; }
.jh-wrap .exp-item+.exp-item { border-top:1px dashed var(--jh-line); }
.jh-wrap .exp-dot { width:10px; height:10px; border-radius:50%; background:var(--jh-acc); margin-top:6px; box-shadow:0 0 0 4px rgba(59,130,246,.2); flex-shrink:0; }
.jh-wrap .exp-role { font:600 1.05rem var(--jh-font-heading); margin:0; color:#fff; }
.jh-wrap .exp-org { color:var(--jh-acc); font-weight:600; font-size:.95rem; display:block; margin-top:2px; }
.jh-wrap .exp-date { font-size:.85rem; color:var(--jh-muted); margin:4px 0 8px; display:block; }
.jh-wrap .exp-tags { display:flex; flex-wrap:wrap; gap:6px; margin-top:12px; }
.jh-wrap .exp-tags .pill { font-size:.8rem; padding:.2rem .55rem; margin:0; }

/* ---- Contact ---- */
.jh-wrap .copyfield { display:flex; gap:8px; align-items:center; flex-wrap:wrap; }
.jh-wrap .copyfield input {
  width:260px; max-width:100%; padding:.6rem .8rem;
  background:rgba(0,0,0,0.2); border:1px solid var(--jh-line);
  border-radius:10px; color:var(--jh-fg); font-size:.9rem;
  font-family:var(--jh-font-mono);
  outline:none; transition: border-color .2s;
}
.jh-wrap .copyfield input:focus { border-color:var(--jh-acc); }


/* ---- Tool Canvas ---- */
.jh-wrap .tool-canvas {
  width:100%; height:380px; border-radius:12px;
  border:1px solid var(--jh-line); background:rgba(0,0,0,0.2);
  cursor:crosshair; display:block;
}

/* ---- Custom Range Sliders ---- */
input[type=range] {
  -webkit-appearance:none; appearance:none;
  width:100%; height:6px; border-radius:3px;
  background:rgba(255,255,255,0.08);
  outline:none; cursor:pointer;
  /* Disable the iOS/Android 300 ms double-tap-zoom delay on the slider area
     so first contact registers as a thumb grab instead of a zoom gesture. */
  touch-action: pan-y;
}
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance:none; appearance:none;
  width:18px; height:18px; border-radius:50%;
  background:var(--jh-acc,#3b82f6);
  border:2px solid rgba(255,255,255,0.2);
  box-shadow:0 0 10px rgba(59,130,246,0.4);
  transition: box-shadow .2s, transform .15s;
  cursor:grab;
}
input[type=range]::-webkit-slider-thumb:hover {
  box-shadow:0 0 16px rgba(59,130,246,0.6);
  transform:scale(1.15);
}
input[type=range]::-webkit-slider-thumb:active { cursor:grabbing; transform:scale(1.05); }
input[type=range]::-moz-range-thumb {
  width:18px; height:18px; border-radius:50%;
  background:var(--jh-acc,#3b82f6);
  border:2px solid rgba(255,255,255,0.2);
  box-shadow:0 0 10px rgba(59,130,246,0.4);
  cursor:grab;
}

/* On coarse-pointer / touch devices: enlarge the visible track and the
   thumb. The thumb itself is the primary touch target (32 px); the
   thicker track gives extra "click bleed" area since clicking anywhere
   on the track scrubs the value. WCAG 2.5.5 / 2.2 target-size met
   by the 32 px thumb alone.
   (Earlier attempt used `padding` + `background-clip: content-box` to
   inflate the box invisibly — Webkit on iOS doesn't render the visible
   track inside the padded area, so the bar disappeared entirely.) */
@media (hover: none) and (pointer: coarse) {
  input[type=range] {
    height: 12px;
    border-radius: 6px;
  }
  input[type=range]::-webkit-slider-thumb {
    width: 32px; height: 32px;
    box-shadow: 0 0 14px rgba(59,130,246,0.5);
    border-width: 3px;
  }
  input[type=range]::-moz-range-thumb {
    width: 32px; height: 32px;
    border-width: 3px;
  }
  input[type=range]::-moz-range-track {
    height: 12px;
    border-radius: 6px;
  }
  /* Add 8 px vertical "click bleed" via the surrounding row, so taps
     slightly above or below the bar still register on the input. */
  .tool03-sliders > div,
  .tool-sliders > div {
    padding: 6px 0;
  }
}
input[type=range]::-moz-range-track {
  height:6px; border-radius:3px;
  background:rgba(255,255,255,0.08); border:none;
}

/* ---- Peak Deviation Badge ---- */
.jh-wrap .deviation-badge {
  display:inline-flex; align-items:center; gap:8px;
  margin-top:16px; padding:.5rem 1rem;
  background:rgba(0,0,0,0.25); border:1px solid var(--jh-line);
  border-radius:10px; font-size:.88rem;
}
.jh-wrap .deviation-badge .val {
  font-family:var(--jh-font-mono); font-weight:600; color:#60a5fa;
}
.jh-wrap .deviation-badge.good .val { color:#10b981; }
.jh-wrap .deviation-badge.warn .val { color:#f59e0b; }
.jh-wrap .deviation-badge.bad .val { color:#ef4444; }

/* ---- Sticky Nav ---- */
.sticky-nav {
  position:fixed; top:0; left:0; right:0; z-index:1000;
  background:rgba(10,10,15,0.75);
  backdrop-filter:blur(16px); -webkit-backdrop-filter:blur(16px);
  border-bottom:1px solid rgba(255,255,255,0.06);
  padding:0 24px; height:52px;
  display:flex; align-items:center; justify-content:center;
  transform:translateY(-100%);
  transition: transform .4s cubic-bezier(.22,1,.36,1);
}
.sticky-nav.visible { transform:translateY(0); }
.sticky-nav-inner {
  max-width:1100px; width:100%;
  display:flex; align-items:center; gap:8px;
}
.sticky-nav .brand {
  font:700 1rem 'Outfit',system-ui,sans-serif;
  color:#fff; margin-right:auto; cursor:pointer;
  text-decoration:none;
  transition: color .2s;
}
.sticky-nav .brand:hover { color:#60a5fa; }
.sticky-nav a:not(.brand) {
  color:#9ca3af; font-size:.85rem; font-weight:500; font-family:'Outfit',system-ui,sans-serif;
  padding:.35rem .6rem; border-radius:8px;
  text-decoration:none; transition: color .2s, background .2s;
}
.sticky-nav a:not(.brand):hover { color:#f3f4f6; background:rgba(255,255,255,0.06); }
.sticky-nav a:not(.brand).active { color:#60a5fa; }

/* ---- Lightbox ---- */
/* Body scroll-lock while the lightbox is open. JS adds .lightbox-open to
   document.body on open and removes it on close. `overscroll-behavior` stops
   touch scroll inside the lightbox from chaining to the body underneath
   (iOS rubber-banding otherwise still scrolls the page even with
   overflow:hidden on body). */
body.lightbox-open {
  overflow: hidden;
  overscroll-behavior: none;
  touch-action: none;
}
.lightbox {
  position:fixed; inset:0; z-index:2000;
  background:rgba(0,0,0,0.85);
  backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
  display:flex; align-items:center; justify-content:center;
  opacity:0; visibility:hidden;
  transition: opacity .35s ease, visibility .35s ease;
  cursor:zoom-out;
  touch-action: none;        /* swipes inside the lightbox don't scroll anything */
}
.lightbox.open { opacity:1; visibility:visible; }
.lightbox img {
  max-width:90vw; max-height:88vh;
  border-radius:12px; object-fit:contain;
  box-shadow:0 20px 60px rgba(0,0,0,0.5);
  transform:scale(.92); transition: transform .35s cubic-bezier(.22,1,.36,1);
}
.lightbox.open img { transform:scale(1); }
.lightbox-close {
  position:absolute; top:20px; right:24px;
  width:44px; height:44px; border-radius:50%;
  background:rgba(255,255,255,0.1); border:1px solid rgba(255,255,255,0.15);
  color:#fff; font-size:1.3rem; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  transition: background .2s;
  appearance:none; -webkit-appearance:none;
  touch-action: manipulation;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
  font-family:inherit; line-height:1;
}
.lightbox-close:hover { background:rgba(255,255,255,0.2); }

/* ---- Footer ---- */
.site-footer {
  max-width:1100px; margin:0 auto;
  padding:32px; margin-top:0;
  border-top:1px solid rgba(255,255,255,0.06);
  display:flex; align-items:center; justify-content:space-between;
  flex-wrap:wrap; gap:16px;
  color:#9ca3af; font-size:.85rem;
}
.site-footer a {
  color:#9ca3af; text-decoration:none; transition: color .2s;
}
.site-footer a:hover { color:#60a5fa; }

/* ---- Scroll Reveal ---- */
.reveal {
  opacity:0; transform:translateY(28px);
  transition: opacity .7s cubic-bezier(.22,1,.36,1), transform .7s cubic-bezier(.22,1,.36,1);
}
.reveal.visible { opacity:1; transform:translateY(0); }

/* ---- Header Stagger Animation ---- */
.stagger { opacity:0; transform:translateY(18px); animation: staggerUp .65s ease forwards; }
@keyframes staggerUp { to { opacity:1; transform:translateY(0); } }

/* ---- Responsive ---- */
@media(max-width:640px){
  .jh-wrap { padding:18px; }
  .sticky-nav a:not(.brand) { font-size:.78rem; padding:.3rem .4rem; }
  .jh-wrap .project-grid { grid-template-columns:1fr; }
  .jh-wrap .gallery-grid { grid-template-columns:repeat(auto-fill,minmax(160px,1fr)); }
  .site-footer { flex-direction:column; text-align:center; }
}

/* ---- Reduced Motion ----
   Scope the override to *decorative* motion (scroll-reveal, magnetic CTAs,
   background orbs, card glow). UI feedback transitions (button hover, focus,
   lightbox fade, slider thumb scale) stay because they're short, useful, and
   communicate state rather than just decorating. WCAG "reduce", not "remove".
   (Phase 14 audit A10) */
@media (prefers-reduced-motion: reduce) {
  .reveal,
  .stagger { opacity: 1; transform: none; animation: none; transition: none; }
  body::before, body::after, .bg-orb { animation-play-state: paused; }
  /* Magnetic CTAs + scroll-progress bar — pure decoration */
  .scroll-progress { display: none; }
  .jh-wrap header .btn { transform: none !important; }
}

/* ==============================================
   Phase 2 - Aesthetic Upgrades
   ============================================== */

/* ---- Selection ---- */
::selection { background: rgba(59,130,246,0.35); color: #fff; }

/* ---- Focus rings (accessibility + polish) ---- */
.jh-wrap a:focus-visible,
.jh-wrap button:focus-visible,
.jh-wrap input:focus-visible,
.sticky-nav a:focus-visible,
.lightbox-close:focus-visible,
.skip-link:focus-visible,
.gallery-img:focus-visible {
  outline: 2px solid #60a5fa;
  outline-offset: 3px;
  border-radius: 6px;
}

/* ---- SVG Grain Overlay ---- */
.grain {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: -1;
  opacity: 0.045;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)'/></svg>");
}

/* ---- Scroll Progress Bar ---- */
.scroll-progress {
  position: fixed;
  top: 0; left: 0; right: 0;
  height: 2px;
  z-index: 1500;
  background: linear-gradient(90deg, #3b82f6, #8b5cf6);
  transform: scaleX(0);
  transform-origin: left;
  will-change: transform;
  pointer-events: none;
}

/* ---- Hero name (large title — matches section h1 typography) ---- */
.jh-wrap .hero-name {
  font-family: var(--jh-font-heading);
  font-size: clamp(3rem, 8vw + 0.5rem, 5.25rem);
  font-weight: 700;
  margin: 6px 0 12px;
  letter-spacing: -0.3px;
  line-height: 1.35;
  color: #fff;
  padding-bottom: 0.05em;
}

/* ---- Hero Stats Strip ---- */
.jh-wrap .hero-stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 16px;
  margin-top: 16px;
  padding: 16px 0 4px;
  border-top: 1px dashed var(--jh-line);
}
.jh-wrap .hero-stats > div {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 0.92rem;
  color: var(--jh-fg);
  font-weight: 500;
  line-height: 1.3;
}
.jh-wrap .hero-stats span {
  font-family: var(--jh-font-mono);
  font-size: 0.65rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--jh-muted);
  font-weight: 500;
}
@media (max-width: 640px) {
  .jh-wrap .hero-stats { grid-template-columns: 1fr; gap: 10px; padding: 12px 0 0; }
}

/* ---- Section Numbers (CSS counter) ---- */
body { counter-reset: section; }
.jh-wrap .section-title { display: flex; align-items: baseline; gap: 0.6em; margin: 0; }
.jh-wrap .section-title::before {
  counter-increment: section;
  content: counter(section, decimal-leading-zero);
  font-family: var(--jh-font-mono);
  font-size: 0.65em;
  font-weight: 500;
  color: #60a5fa;
  letter-spacing: 0.05em;
  opacity: 0.85;
}
.jh-wrap .section-title.tools-title {
  text-align: center;
  font-size: 2rem;
  margin-bottom: 2rem;
  justify-content: center;
}

/* ---- Animated Nav Underlines ---- */
.sticky-nav a:not(.brand) { position: relative; }
.sticky-nav a:not(.brand)::after {
  content: '';
  position: absolute;
  left: 0.6rem; right: 0.6rem;
  bottom: 0.18rem;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s cubic-bezier(0.22, 1, 0.36, 1);
}
.sticky-nav a:not(.brand):hover::after,
.sticky-nav a:not(.brand).active::after { transform: scaleX(1); }

/* ---- Skill Groups with category tinting ---- */
.jh-wrap .skill-groups { display: flex; flex-direction: column; gap: 18px; }
.jh-wrap .skill-cat {
  font: 500 0.68rem var(--jh-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--jh-muted);
  margin-bottom: 8px;
}
.jh-wrap .skill-group[data-cat="software"] .pill {
  background: rgba(59,130,246,0.10);
  border-color: rgba(59,130,246,0.25);
  color: #93bbfd;
}
.jh-wrap .skill-group[data-cat="software"] .pill:hover {
  background: rgba(59,130,246,0.18);
  border-color: rgba(59,130,246,0.4);
}
.jh-wrap .skill-group[data-cat="hardware"] .pill {
  background: rgba(139,92,246,0.10);
  border-color: rgba(139,92,246,0.25);
  color: #c4b5fd;
}
.jh-wrap .skill-group[data-cat="hardware"] .pill:hover {
  background: rgba(139,92,246,0.18);
  border-color: rgba(139,92,246,0.4);
}
.jh-wrap .skill-group[data-cat="standards"] .pill {
  background: rgba(16,185,129,0.10);
  border-color: rgba(16,185,129,0.25);
  color: #86efac;
}
.jh-wrap .skill-group[data-cat="standards"] .pill:hover {
  background: rgba(16,185,129,0.18);
  border-color: rgba(16,185,129,0.4);
}

/* ---- Mouse-aware Card Glow ---- */
.jh-wrap .card { position: relative; overflow: hidden; }
.jh-wrap .card > * { position: relative; z-index: 1; }
.jh-wrap .card::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: radial-gradient(
    500px circle at var(--mx, 50%) var(--my, 50%),
    rgba(96, 165, 250, 0.10),
    transparent 45%
  );
  opacity: 0;
  transition: opacity 0.4s ease;
  pointer-events: none;
  z-index: 0;
}
.jh-wrap .card:hover::before { opacity: 1; }

/* ---- Project Card Arrow ---- */
.jh-wrap .project-card .card-arrow {
  position: absolute;
  bottom: 18px;
  right: 22px;
  font-size: 1.3rem;
  color: #60a5fa;
  opacity: 0.45;
  transition: transform 0.35s cubic-bezier(0.22,1,0.36,1), opacity 0.3s;
  font-family: var(--jh-font-mono);
  line-height: 1;
}
.jh-wrap .project-card:hover .card-arrow {
  transform: translateX(5px);
  opacity: 1;
}

/* ---- Tool Header Labels ---- */
.jh-wrap .tool-header {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 12px;
}
.jh-wrap .tool-label {
  font: 500 0.68rem var(--jh-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: #60a5fa;
  opacity: 0.75;
}
.jh-wrap .tool-title { color: #fff; margin: 0; }

/* ---- Footer Meta ---- */
.site-footer .footer-meta {
  font-family: var(--jh-font-mono);
  font-size: 0.74rem;
  color: #4b5563;
  letter-spacing: 0.03em;
}

/* ---- Hero CTA refinement (hover lift) ---- */
.jh-wrap header .row .btn:hover {
  transform: translateY(-2px) scale(1.02);
  box-shadow: 0 10px 28px rgba(59,130,246,0.18);
}
.jh-wrap header .row .btn.resume:hover {
  box-shadow: 0 10px 28px rgba(255,255,255,0.18);
}
.jh-wrap header .row .btn.purple:hover {
  box-shadow: 0 10px 28px rgba(139,92,246,0.22);
}

/* Make hero buttons honour magnetic JS without conflicting transitions */
.jh-wrap header .row .btn { transition: background .25s, color .25s, border-color .25s, box-shadow .25s, transform .25s ease-out; }

/* On mouseleave the magnetic JS adds .is-resetting then clears the inline transform.
   This swaps the snappy ease-out for a slightly longer cubic-bezier so the button
   glides back to identity instead of snapping. The class is removed once the
   transition finishes. */
.jh-wrap header .row .btn.is-resetting {
  transition: transform .35s cubic-bezier(.22, 1, .36, 1);
}

/* ==============================================
   Tool 03 — Scan-to-CAD Metrology
   ============================================== */

/* ---- HUD overlay ---- */
#tool03-hud {
  position: absolute;
  top: 12px;
  left: 12px;
  z-index: 10;
  background: rgba(5, 5, 10, 0.78);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  border-radius: 10px;
  padding: 10px 14px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.72rem;
  pointer-events: none;
  min-width: 162px;
}

.hud-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  line-height: 2;
}

.hud-label {
  font-size: 0.63rem;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: #4b5563;
  font-weight: 500;
}

.hud-val {
  color: #e5e7eb;
  font-weight: 600;
}

.hud-sep {
  height: 1px;
  background: rgba(255, 255, 255, 0.07);
  margin: 5px 0;
}

/* ---- Orbit hint ---- */
.tool03-hint {
  position: absolute;
  bottom: 10px;
  left: 0;
  right: 0;
  text-align: center;
  margin: 0;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.63rem;
  letter-spacing: 0.1em;
  color: rgba(156, 163, 175, 0.4);
  pointer-events: none;
}
/* Pointer-aware hint copy: mouse users see "SCROLL TO ZOOM", touch users
   see "PINCH TO ZOOM". Default to the mouse string; flip on coarse pointer. */
.tool03-hint .hint-mouse { display: inline; }
.tool03-hint .hint-touch { display: none; }
@media (hover: none) and (pointer: coarse) {
  .tool03-hint .hint-mouse { display: none; }
  .tool03-hint .hint-touch { display: inline; }
}

/* ---- Tool 03 — viewport container & canvas ---- */
#tool03-container {
  position: relative;
  height: 340px;
  width: 100%;
  border-radius: 12px;
  overflow: hidden;
  border: 1px solid rgba(255,255,255,0.07);
  background: rgba(0,0,0,0.3);
}
/* touch-action: none lets the canvas capture all touch gestures (rotate, pinch)
   without the JS having to preventDefault touchstart on every contact, which
   would also block any incidental taps that just happened to land here. Users
   scroll past Tool 03 by touching outside the canvas (the surrounding card has
   ample padding). */
#tool03-canvas { display: block; touch-action: none; }

/* hud-pct initial state; JS overrides color dynamically via element.style */
#hud-pct { font-weight: 700; color: #10b981; font-size: 0.82rem; }

/* ---- Tool 03 — description ---- */
.tool03-desc { margin-bottom: 20px; font-size: 1.05rem; line-height: 1.6; }
.tool03-desc strong { color: #fff; }
.tool03-desc a { color: var(--jh-acc); text-decoration: none; }
.tool03-desc a:hover { color: #fff; }
.legend-green   { color: #10b981; font-weight: 600; }
.legend-red     { color: #ef4444; font-weight: 600; }
.legend-missing { color: #e6a413; font-weight: 600; }

/* ---- Tool 03 — sliders ---- */
.tool03-sliders { display: grid; gap: 20px; margin-top: 24px; }
.sl-row { display: flex; justify-content: space-between; margin-bottom: 8px; }
.sl-label { font-weight: 600; color: var(--jh-fg, #f3f4f6); font-size: 0.9rem; }
.tool03-sliders .pill { font-family: var(--jh-font-mono, 'JetBrains Mono', monospace); font-size: 0.85rem; }

/* ---- Header layout variants ---- */
.jh-wrap header.card.grid.stagger { gap: 12px; }
.jh-wrap .row-spread { justify-content: space-between; width: 100%; }
.jh-wrap .hero-desc { max-width: 720px; margin: 0; }
.jh-wrap .hero-cta-row { margin-top: 8px; }

/* ---- Experience colour variants ---- */
.jh-wrap .exp-dot.exp-dot-green  { background: #10b981; box-shadow: 0 0 0 4px rgba(16,185,129,.2); }
.jh-wrap .exp-dot.exp-dot-amber  { background: #f59e0b; box-shadow: 0 0 0 4px rgba(245,158,11,.2); }
.jh-wrap .exp-dot.exp-dot-purple { background: var(--jh-purple); box-shadow: 0 0 0 4px rgba(139,92,246,.2); }
.jh-wrap .exp-org.exp-org-green  { color: #10b981; }
.jh-wrap .exp-org.exp-org-amber  { color: #f59e0b; }
.jh-wrap .exp-org.exp-org-purple { color: var(--jh-purple); }
.jh-wrap .exp-list { margin: 6px 0 0; font-size: .9rem; padding-left: 1.2rem; }

/* ---- Projects ---- */
.jh-wrap .project-title { font-size: 1.05rem; margin-top: 16px; }
.jh-wrap .project-card .tagset { margin-top: 12px; }
.jh-wrap .project-list { font-size: .9rem; }

/* ---- Tool 01 & 02 — shared layout ---- */
.tool-desc { margin-bottom: 20px; font-size: 1.05rem; line-height: 1.6; }
.tool-desc strong { color: #fff; }
.tool-canvas-300 { position: relative; height: 300px; width: 100%; }
.tool-canvas-300 canvas { width: 100%; height: 100%; display: block; cursor: crosshair; }
.tool-canvas-180 { position: relative; height: 180px; width: 100%; margin-bottom: 12px; }
.tool-canvas-180 canvas { width: 100%; height: 100%; display: block; }
.tool-sliders { display: grid; gap: 20px; margin-top: 24px; }
.tool-sliders .pill { font-family: var(--jh-font-mono, 'JetBrains Mono', monospace); font-size: 0.85rem; }

/* ---- Tool 01 — view-mode toggle ---- */
.t03-view-toggle {
  display: inline-flex;
  gap: 0;
  margin-bottom: 14px;
  border: 1px solid rgba(255,255,255,0.10);
  border-radius: 10px;
  overflow: hidden;
  background: rgba(255,255,255,0.03);
}
.t03-view-btn {
  background: transparent;
  border: 0;
  color: var(--jh-muted, #9ca3af);
  font: 600 0.78rem var(--jh-font-body, 'Outfit', system-ui, sans-serif);
  letter-spacing: 0.04em;
  padding: 0.5rem 0.95rem;
  cursor: pointer;
  transition: background 0.15s ease, color 0.15s ease;
  touch-action: manipulation;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.t03-view-btn + .t03-view-btn { border-left: 1px solid rgba(255,255,255,0.08); }
.t03-view-btn:hover { color: var(--jh-fg, #f3f4f6); background: rgba(255,255,255,0.05); }
.t03-view-btn.is-active {
  background: rgba(59,130,246,0.18);
  color: var(--jh-fg, #f3f4f6);
}
.t03-view-btn:focus-visible {
  outline: 2px solid var(--jh-acc, #3b82f6);
  outline-offset: -2px;
}

/* ---- Tool 02 — play/pause button ---- */
.t02-play-btn { min-width: 86px; }
.t02-play-btn[aria-pressed="false"] { background: rgba(59,130,246,0.18); }

/* ==============================================
   Hamburger Nav (mobile)
   ============================================== */
.nav-links {
  display: flex;
  align-items: center;
  gap: 8px;
}
.nav-toggle {
  display: none;
  background: transparent;
  border: 1px solid rgba(255,255,255,0.1);
  border-radius: 8px;
  width: 44px;
  height: 44px;
  padding: 0;
  cursor: pointer;
  position: relative;
  flex-shrink: 0;
  touch-action: manipulation;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.nav-toggle:hover { background: rgba(255,255,255,0.06); }
.nav-toggle span {
  position: absolute;
  left: 12px;
  right: 12px;
  height: 2px;
  background: #f3f4f6;
  border-radius: 1px;
  transition: transform .25s ease, opacity .2s ease, top .25s ease;
}
.nav-toggle span:nth-child(1) { top: 14px; }
.nav-toggle span:nth-child(2) { top: 21px; }
.nav-toggle span:nth-child(3) { top: 28px; }
.sticky-nav.nav-open .nav-toggle span:nth-child(1) { top: 21px; transform: rotate(45deg); }
.sticky-nav.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
.sticky-nav.nav-open .nav-toggle span:nth-child(3) { top: 21px; transform: rotate(-45deg); }

@media (max-width: 600px) {
  .nav-toggle { display: block; }
  .sticky-nav .nav-links {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: stretch;
    gap: 2px;
    padding: 10px;
    background: rgba(10,10,15,0.95);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    border-bottom: 1px solid rgba(255,255,255,0.06);
    transform: translateY(-8px);
    opacity: 0;
    visibility: hidden;
    transition: opacity .2s ease, transform .2s ease, visibility .2s ease;
  }
  .sticky-nav.nav-open .nav-links {
    opacity: 1;
    transform: translateY(0);
    visibility: visible;
  }
  .sticky-nav .nav-links a:not(.brand) {
    padding: .7rem 1rem;
    font-size: .95rem;
    border-radius: 6px;
  }
  .sticky-nav .nav-links a:not(.brand)::after { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .nav-toggle span,
  .sticky-nav .nav-links { transition: none; }
}

/* ==============================================
   Contact Form (mailto)
   ============================================== */
.jh-wrap .contact-divider {
  height: 1px;
  margin: 24px 0;
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.12), transparent);
}
.jh-wrap .contact-form {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.jh-wrap .contact-form-hint {
  margin: 0 0 4px;
  font-size: .9rem;
}
.jh-wrap .form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 12px;
}
@media (max-width: 540px) {
  .jh-wrap .form-grid { grid-template-columns: 1fr; }
}
.jh-wrap .contact-form label {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.jh-wrap .form-label {
  font: 500 0.68rem var(--jh-font-mono);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--jh-muted);
}
.jh-wrap .contact-form input,
.jh-wrap .contact-form textarea {
  padding: .65rem .8rem;
  background: rgba(0,0,0,0.22);
  border: 1px solid var(--jh-line);
  border-radius: 10px;
  color: var(--jh-fg);
  font: 400 .95rem var(--jh-font-body);
  outline: none;
  transition: border-color .2s, background .2s;
}
.jh-wrap .contact-form textarea {
  resize: vertical;
  min-height: 100px;
  font-family: var(--jh-font-body);
}
.jh-wrap .contact-form input:focus,
.jh-wrap .contact-form textarea:focus {
  border-color: var(--jh-acc);
  background: rgba(0,0,0,0.3);
}
.jh-wrap .contact-form input:invalid:not(:placeholder-shown),
.jh-wrap .contact-form textarea:invalid:not(:placeholder-shown) {
  border-color: rgba(245,158,11,0.5);
}
.jh-wrap .contact-form button[type="submit"] {
  align-self: flex-start;
  margin-top: 4px;
}

/* Mailto fallback panel — revealed after submit so users without a configured
   mail client can copy the composed message manually. */
.jh-wrap .mailto-fallback {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 16px;
  padding: 14px;
  background: rgba(0, 0, 0, 0.18);
  border: 1px dashed var(--jh-line);
  border-radius: 10px;
}
.jh-wrap .mailto-fallback[hidden] { display: none; }
.jh-wrap .mailto-fallback textarea {
  resize: vertical;
  min-height: 140px;
  padding: .65rem .8rem;
  background: rgba(0, 0, 0, 0.22);
  border: 1px solid var(--jh-line);
  border-radius: 10px;
  color: var(--jh-fg);
  font: 400 .9rem var(--jh-font-mono);
  outline: none;
}
.jh-wrap .mailto-fallback textarea:focus { border-color: var(--jh-acc); }
.jh-wrap .mailto-fallback button { align-self: flex-start; }

/* ============================================================================
 * ARCHIVED: Reach Envelope styles — referenced only by the commented-out HTML
 * block in index.html. Kept here so uncommenting the tool restores its full
 * visual treatment without further work.
 * ============================================================================
.tool-canvas-380 { position: relative; height: 380px; width: 100%; }
.reach-legend { display: flex; gap: 16px; flex-wrap: wrap; margin-top: 14px; font-size: .85rem; color: var(--jh-muted); }
.legend-dot { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 6px; vertical-align: middle; }
.legend-dot-comfort  { background: rgba(16,185,129,0.8); box-shadow: 0 0 8px rgba(16,185,129,0.6); }
.legend-dot-extended { background: rgba(245,158,11,0.8);  box-shadow: 0 0 8px rgba(245,158,11,0.4); }
.legend-dot-steering { background: rgba(96,165,250,0.8);  box-shadow: 0 0 8px rgba(96,165,250,0.6); }
 * ============================================================================ */

/* ==============================================
   Tool 03 — Mobile viewport controls
   ============================================== */
.tool03-controls {
  position: absolute;
  bottom: 10px;
  right: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  z-index: 10;
}
.tool03-ctrl-btn {
  width: 44px;
  height: 44px;
  border-radius: 8px;
  background: rgba(5, 5, 10, 0.78);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: #e5e7eb;
  font: 600 1.15rem 'JetBrains Mono', monospace;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background .15s;
  appearance: none;
  -webkit-appearance: none;
  line-height: 1;
  /* Prevent double-tap-zoom on the page when the user rapidly hits zoom-in
     to keep zooming into the scene — without this, the browser interprets
     two fast taps as a zoom gesture on the whole page. */
  touch-action: manipulation;
  user-select: none; -webkit-user-select: none;
  -webkit-tap-highlight-color: transparent;
}
.tool03-ctrl-btn:hover { background: rgba(255, 255, 255, 0.12); }
.tool03-ctrl-btn:active { transform: scale(0.93); }
.tool03-ctrl-btn:focus-visible {
  outline: 2px solid #60a5fa;
  outline-offset: 2px;
}

/* ==============================================
   Mobile — gate hover transforms so touch-tap
   doesn't cause cards / images to jump
   ============================================== */
@media (hover: none) {
  .jh-wrap .card:hover {
    transform: none;
  }
  .jh-wrap .project-card:hover img {
    transform: none;
  }
  .jh-wrap .gallery-item img:hover {
    transform: none;
  }
}

/* Ensure no horizontal overflow on narrow viewports */
html { overflow-x: hidden; }
