:root{
  --bg:#0a0a0c;
  --bg-soft:#101014;
  --fg:#f2f2f0;
  --fg-dim:#8a8a92;
  --accent:#7dffb3;
  --accent-dim:#3a5c48;
  --line:#232329;
  --spot-x:50%;
  --spot-y:40%;
}
*{box-sizing:border-box; margin:0; padding:0;}
html, body{height:100%; overflow-x:hidden;}
body{
  background:var(--bg);
  color:var(--fg);
  font-family:'Inter', sans-serif;
  cursor:none;
}
/* links/cards have a browser-default pointer cursor of their own, which
   otherwise wins over the inherited body cursor */
a, .card{cursor:inherit;}
.snap-wrap{
  height:100vh;
  overflow-y:scroll;
}
@media (pointer:coarse){
  body{cursor:auto;}
  .cursor-dot,.cursor-ring{display:none;}
}
h1,h2,h3,.brand{font-family:'Space Grotesk', sans-serif;}

/* background spotlight that follows the cursor */
.spotlight{
  position:fixed; inset:0; z-index:0; pointer-events:none;
  background: radial-gradient(600px circle at var(--spot-x) var(--spot-y), rgba(125,255,179,0.08), transparent 60%);
  transition:background 0.05s linear;
}
.grain{
  position:fixed; inset:0; z-index:1; pointer-events:none; opacity:0.035;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* custom cursor */
.cursor-dot,.cursor-ring{
  position:fixed; top:0; left:0; z-index:999; pointer-events:none;
  border-radius:50%;
  transform:translate(-50%,-50%);
}
.cursor-dot{width:6px; height:6px; background:var(--accent);}
.cursor-ring{width:32px; height:32px; border:1px solid var(--accent-dim); transition:width .2s, height .2s, border-color .2s;}
.cursor-ring.hover{width:56px; height:56px; border-color:var(--accent);}

/* side nav dots */
nav.dots{
  position:fixed; right:2.5rem; top:50%; transform:translateY(-50%);
  z-index:50; display:flex; flex-direction:column; gap:1rem;
}
nav.dots a{
  width:8px; height:8px; border-radius:50%; background:var(--line);
  display:block; position:relative; transition:background .3s;
}
nav.dots a.active{background:var(--accent);}
nav.dots a span{
  position:absolute; right:1.4rem; top:50%; transform:translateY(-50%);
  font-size:.7rem; color:var(--fg-dim); white-space:nowrap;
  opacity:0; transition:opacity .2s; letter-spacing:.05em;
}
nav.dots a:hover span{opacity:1;}
@media (max-width:800px){ nav.dots{display:none;} }

section{
  position:relative; z-index:2;
  min-height:100vh;
  display:flex; flex-direction:column; justify-content:center;
  padding:6vh 8vw;
}

/* hero */
#hero{align-items:flex-start;}
.eyebrow{
  color:var(--accent); font-size:.85rem; letter-spacing:.15em; text-transform:uppercase;
  margin-bottom:1.2rem;
}
.name{
  font-size:clamp(3rem, 10vw, 7.5rem); font-weight:700; line-height:0.95;
  letter-spacing:-.02em;
}
.role{
  font-size:clamp(1.1rem, 2.5vw, 1.6rem); color:var(--fg-dim); margin-top:1.4rem;
}
.scroll-hint{
  position:absolute; bottom:3rem; left:8vw; font-size:.75rem; color:var(--fg-dim);
  letter-spacing:.1em; display:flex; align-items:center; gap:.6rem;
}
.scroll-hint::before{
  content:''; width:1px; height:28px; background:var(--fg-dim);
  animation:scrollLine 1.8s ease-in-out infinite;
}
@keyframes scrollLine{0%{transform:scaleY(0); transform-origin:top;} 50%{transform:scaleY(1); transform-origin:top;} 51%{transform-origin:bottom;} 100%{transform:scaleY(0); transform-origin:bottom;}}

/* generic section heading */
.tag{color:var(--accent); font-size:.85rem; letter-spacing:.15em; text-transform:uppercase; margin-bottom:1rem;}
h2.title{font-size:clamp(2rem,5vw,3rem); font-weight:700; margin-bottom:2.5rem; letter-spacing:-.01em;}

.reveal{opacity:0; transform:translateY(24px); transition:opacity .7s ease, transform .7s ease;}
.reveal.visible{opacity:1; transform:translateY(0);}

/* about */
#about p{
  max-width:640px; font-size:clamp(1.05rem,2vw,1.3rem); line-height:1.7; color:var(--fg-dim);
}
#about p strong{color:var(--fg); font-weight:500;}

/* projects */
.projects-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:1.2rem; width:100%;}
.card{
  border:1px solid var(--line); border-radius:14px;
  background:var(--bg-soft); text-decoration:none; color:inherit;
  transition:transform .3s ease, border-color .3s ease;
  display:block; overflow:hidden;
}
.card:hover{transform:translateY(-6px); border-color:var(--accent-dim);}

/* thumbnail placeholder: fixed 16:9 box so layout doesn't jump once a real
   screenshot is dropped in — just swap the <div class="card-thumb"> for an
   <img class="card-thumb" src="..."> later, same class handles both */
.card-thumb{
  width:100%; aspect-ratio:16/9; display:block; object-fit:cover;
  background:
    linear-gradient(135deg, var(--bg-soft) 25%, transparent 25%) -10px 0/20px 20px,
    linear-gradient(225deg, var(--bg-soft) 25%, transparent 25%) -10px 0/20px 20px,
    linear-gradient(315deg, var(--bg-soft) 25%, transparent 25%) 0px 0/20px 20px,
    linear-gradient(45deg, var(--bg-soft) 25%, #17171c 25%) 0px 0/20px 20px;
  border-bottom:1px solid var(--line);
}
.card-body{padding:1.8rem;}
.card .num{color:var(--accent); font-family:'Space Grotesk',sans-serif; font-size:.85rem;}
.card h3{margin:.8rem 0 .6rem; font-size:1.25rem;}
.card p{color:var(--fg-dim); font-size:.92rem; line-height:1.55;}
.card .tags{margin-top:1.2rem; display:flex; gap:.5rem; flex-wrap:wrap;}
.card .tags span{
  font-size:.72rem; color:var(--fg-dim); border:1px solid var(--line);
  padding:.2rem .6rem; border-radius:999px;
}

/* contact */
#contact .links{display:flex; flex-direction:column; gap:.4rem; margin-top:1rem;}
#contact a.big-link{
  font-family:'Space Grotesk',sans-serif;
  font-size:clamp(1.6rem,4vw,2.6rem); color:var(--fg); text-decoration:none;
  width:fit-content; position:relative;
}
#contact a.big-link::after{
  content:''; position:absolute; left:0; bottom:-4px; width:0; height:2px; background:var(--accent);
  transition:width .3s ease;
}
#contact a.big-link:hover::after{width:100%;}
#contact a.big-link:hover{color:var(--accent);}
footer{margin-top:4rem; font-size:.8rem; color:var(--fg-dim);}

/* ============================================
   PROJECT DETAIL PAGES (project-*.html)
   Plain top-to-bottom scroll — deliberately NOT using .snap-wrap/.reveal,
   since a long detail page with galleries/diagrams reads better scrolling
   normally than snapping section-by-section like the one-page home does.
   ============================================ */
.detail-body{overflow-y:auto; cursor:auto;}
.detail-body .cursor-dot,.detail-body .cursor-ring,.detail-body nav.dots{display:none;}

.detail-wrap{max-width:1040px; margin:0 auto; padding:8vh 6vw 10vh;}

.back-link{
  display:inline-flex; align-items:center; gap:.5rem;
  color:var(--fg-dim); text-decoration:none; font-size:.85rem;
  letter-spacing:.03em; margin-bottom:3rem;
}
.back-link:hover{color:var(--accent);}

.detail-hero .num{color:var(--accent); font-family:'Space Grotesk',sans-serif; font-size:.9rem;}
.detail-hero h1{
  font-family:'Space Grotesk',sans-serif; font-weight:700;
  font-size:clamp(2rem,5vw,3.2rem); margin:.6rem 0 1rem; letter-spacing:-.01em;
}
.detail-hero .summary{color:var(--fg-dim); font-size:1.1rem; line-height:1.7; max-width:640px;}
.detail-hero .tags{margin-top:1.4rem; display:flex; gap:.5rem; flex-wrap:wrap;}
.detail-hero .tags span{
  font-size:.75rem; color:var(--fg-dim); border:1px solid var(--line);
  padding:.25rem .7rem; border-radius:999px;
}
.detail-hero .meta{
  margin-top:2rem; display:flex; gap:2.5rem; flex-wrap:wrap;
  font-size:.85rem; color:var(--fg-dim); border-top:1px solid var(--line);
  padding-top:1.4rem;
}
.detail-hero .meta strong{display:block; color:var(--fg); font-weight:500; margin-bottom:.2rem;}

.detail-section{margin-top:8rem;}
.detail-section h2{
  font-family:'Space Grotesk',sans-serif; font-size:1.5rem; font-weight:700;
  margin-bottom:1.4rem;
}
.detail-section p{color:var(--fg-dim); line-height:1.75; margin-bottom:1rem;}
.detail-section p strong{color:var(--fg); font-weight:500;}

/* screenshot carousel: one photo at a time, dots below to jump between them.
   Swap each placeholder <div class="shot"></div> for <img class="shot" src="...">
   when real screenshots are ready — sizing stays the same either way. */
.carousel{margin-top:1.5rem; position:relative;}
.carousel-viewport{overflow:hidden; border-radius:10px; border:1px solid var(--line);}
.carousel-track{display:flex; transition:transform .5s ease;}
.carousel-slide{flex:0 0 100%; min-width:0;}
.carousel-slide .shot{
  width:100%; height:auto; display:block;
  background:
    linear-gradient(135deg, var(--bg-soft) 25%, transparent 25%) -10px 0/20px 20px,
    linear-gradient(225deg, var(--bg-soft) 25%, transparent 25%) -10px 0/20px 20px,
    linear-gradient(315deg, var(--bg-soft) 25%, #17171c 25%) 0px 0/20px 20px,
    linear-gradient(45deg, var(--bg-soft) 25%, #17171c 25%) 0px 0/20px 20px;
}
div.carousel-slide .shot{aspect-ratio:16/10;} /* placeholder-only sizing */
.carousel-slide .shot-caption{
  font-size:.85rem; color:var(--fg-dim); text-align:center; padding:.9rem 1rem;
}
.carousel-arrow{
  position:absolute; top:50%; transform:translateY(-50%); z-index:2;
  width:38px; height:38px; border-radius:50%;
  display:flex; align-items:center; justify-content:center;
  background:rgba(10,10,12,.6); border:1px solid var(--line); color:var(--fg);
  font-size:1.2rem; line-height:1; cursor:pointer;
  transition:background .2s, border-color .2s, color .2s;
}
.carousel-arrow:hover{background:rgba(10,10,12,.85); border-color:var(--accent); color:var(--accent);}
.carousel-arrow.prev{left:12px;}
.carousel-arrow.next{right:12px;}
.carousel-dots{display:flex; justify-content:center; gap:.5rem; margin-top:1rem;}
.carousel-dots button{
  width:8px; height:8px; border-radius:50%; background:var(--line);
  border:none; padding:0; cursor:pointer; transition:background .3s, width .3s;
}
.carousel-dots button.active{background:var(--accent); width:22px; border-radius:4px;}

/* old grid layout, kept in case a project ever wants a plain grid instead */
.shot-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(380px,1fr)); gap:1.2rem; margin-top:1.5rem;}
.shot{
  width:100%; height:auto; display:block; border-radius:10px;
  border:1px solid var(--line);
  background:
    linear-gradient(135deg, var(--bg-soft) 25%, transparent 25%) -10px 0/20px 20px,
    linear-gradient(225deg, var(--bg-soft) 25%, transparent 25%) -10px 0/20px 20px,
    linear-gradient(315deg, var(--bg-soft) 25%, #17171c 25%) 0px 0/20px 20px,
    linear-gradient(45deg, var(--bg-soft) 25%, #17171c 25%) 0px 0/20px 20px;
}
div.shot{aspect-ratio:16/10;}
.shot-caption{font-size:.8rem; color:var(--fg-dim); margin-top:.5rem;}

/* architecture diagram: same placeholder trick, wider aspect ratio.
   Swap the .diagram div's background for an <img class="diagram" src="..."> ,
   or replace its contents with an inline <svg> when the real one is ready. */
.diagram{
  width:100%; min-height:320px; border-radius:12px; margin-top:1.5rem;
  border:1px dashed var(--line); background:var(--bg-soft);
  display:flex; align-items:center; justify-content:center;
  color:var(--fg-dim); font-size:.85rem; text-align:center; padding:2rem;
}
.diagram.has-svg{
  border-style:solid; padding:2.2rem 1.6rem; display:block;
  overflow-x:auto; -webkit-overflow-scrolling:touch;
}
.diagram svg{width:100%; height:auto; display:block; margin:0 auto;}
.diagram svg text{font-family:'Inter',sans-serif;}
.diagram svg .box-label{font-size:16px; font-weight:700; fill:var(--fg);}
.diagram svg .box-sub{font-size:12.5px; fill:var(--fg-dim);}
.diagram svg .flow-label{font-size:11.5px; fill:var(--fg-dim); font-weight:500;}
@media (max-width:700px){
  /* below this width, shrinking the diagram to fit would make the text
     illegible — instead give it a floor width and let just this box
     scroll sideways, so desktop-quality legibility carries over to mobile */
  .diagram svg{min-width:620px;}
}
.diagram svg .box{fill:var(--bg); stroke:var(--line); stroke-width:1.6;}
.diagram svg .box.accent{stroke:var(--accent-dim); stroke-width:2;}
.diagram svg line, .diagram svg path.arrow{stroke:var(--fg-dim); stroke-width:2; fill:none;}
.diagram svg path.arrow.hi{stroke:var(--accent); stroke-width:2.6;}
.diagram svg polygon.arrowhead{fill:var(--fg-dim);}
.diagram svg polygon.arrowhead.hi{fill:var(--accent);}

.problem-solution{margin-top:1.5rem; display:flex; flex-direction:column; gap:1.2rem;}
.ps-row{
  display:grid; grid-template-columns:1fr 1fr;
  border:1px solid var(--line); border-radius:12px;
  background:var(--bg-soft); overflow:hidden;
}
.ps-row > div{padding:1.6rem 1.8rem;}
.ps-row > div + div{border-left:1px solid var(--line);}
@media (max-width:700px){
  .ps-row{grid-template-columns:1fr;}
  .ps-row > div + div{border-left:none; border-top:1px solid var(--line);}
}
.ps-row h3{
  font-size:.8rem; letter-spacing:.08em; text-transform:uppercase;
  color:var(--accent); margin-bottom:.8rem;
}
.ps-row p{margin-bottom:0;}

.detail-links{
  margin-top:5rem; padding-top:2.5rem; border-top:1px solid var(--line);
  display:flex; gap:1.2rem; flex-wrap:wrap;
}
.detail-links a{
  font-family:'Space Grotesk',sans-serif; font-size:1.1rem; color:var(--fg);
  text-decoration:none; border:1px solid var(--line); border-radius:999px;
  padding:.7rem 1.4rem; transition:border-color .2s, color .2s;
}
.detail-links a:hover{border-color:var(--accent); color:var(--accent);}
