/* =========================================================
   Abdullah Ashraf — CV site
   Blue / black system. Logical properties throughout so the
   same sheet serves RTL and LTR.
   ========================================================= */

/* ---------- tokens ---------- */
:root{
  --accent:#2E6BE6;
  --accent-lift:#5B8DF5;
  --accent-deep:#1E4FBF;
  --accent-rgb:46,107,230;

  --r-sm:10px; --r-md:14px; --r-lg:20px; --r-xl:28px;
  --wrap:1180px;
  --pad:clamp(20px,4vw,40px);
  --sec-y:clamp(72px,9vw,128px);

  --ff-ar:"IBM Plex Sans Arabic",system-ui,-apple-system,"Segoe UI",sans-serif;
  --ff-en:"Plus Jakarta Sans","IBM Plex Sans Arabic",system-ui,sans-serif;

  --ease:cubic-bezier(.22,.61,.36,1);
}

/* dark (default) */
html[data-theme="dark"]{
  --bg:#07090E;
  --bg-alt:#0B0E15;
  --surface:#101420;
  --surface-2:#141926;
  --line:#1D2333;
  --line-soft:#161B29;
  --text:#E9ECF3;
  --text-2:#B7BECD;
  --muted:#7B8399;
  --glow:rgba(var(--accent-rgb),.20);
  --card-shadow:0 22px 60px -34px rgba(0,0,0,.9);
}

/* light */
html[data-theme="light"]{
  --bg:#F4F6FA;
  --bg-alt:#EDF1F7;
  --surface:#FFFFFF;
  --surface-2:#F7F9FC;
  --line:#DFE5EF;
  --line-soft:#E9EEF5;
  --text:#0B0E16;
  --text-2:#3C4557;
  --muted:#69738A;
  --glow:rgba(var(--accent-rgb),.14);
  --card-shadow:0 18px 44px -30px rgba(11,14,22,.35);
}

/* ---------- base ---------- */
*,*::before,*::after{box-sizing:border-box}

[hidden]{display:none !important}

html{scroll-behavior:smooth; scroll-padding-block-start:96px; -webkit-text-size-adjust:100%}
@media (prefers-reduced-motion:reduce){ html{scroll-behavior:auto} }

body{
  margin:0;
  background:var(--bg);
  color:var(--text);
  font-family:var(--ff-ar);
  font-size:16px;
  line-height:1.75;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
  transition:background-color .3s var(--ease), color .3s var(--ease);
}
html[lang="en"] body{font-family:var(--ff-en); line-height:1.7}

img{max-width:100%; display:block}
a{color:inherit; text-decoration:none}
ul,ol{margin:0; padding:0; list-style:none}
h1,h2,h3{margin:0; line-height:1.25; letter-spacing:-.015em; font-weight:700}
p{margin:0}
button{font:inherit}

::selection{background:rgba(var(--accent-rgb),.28)}

:focus-visible{
  outline:2px solid var(--accent-lift);
  outline-offset:3px;
  border-radius:6px;
}

.wrap{width:min(100% - (var(--pad) * 2), var(--wrap)); margin-inline:auto}

.skip{
  position:absolute; inset-inline-start:-9999px; top:0; z-index:200;
  background:var(--accent); color:#fff; padding:12px 18px; border-radius:0 0 var(--r-sm) var(--r-sm);
}
.skip:focus{inset-inline-start:12px}

/* ---------- shared bits ---------- */
.eyebrow{
  display:inline-flex; align-items:center; gap:9px;
  font-size:.78rem; font-weight:600; letter-spacing:.08em; text-transform:uppercase;
  color:var(--accent-lift); margin:0 0 14px;
}
html[lang="ar"] .eyebrow{letter-spacing:0; text-transform:none; font-size:.85rem}

.dot{width:7px; height:7px; border-radius:50%; background:var(--accent); flex:none}

.live-dot{
  width:7px; height:7px; border-radius:50%; background:#22C55E; flex:none;
  box-shadow:0 0 0 0 rgba(34,197,94,.6); animation:pulse 2.4s infinite;
}
@keyframes pulse{
  70%{box-shadow:0 0 0 7px rgba(34,197,94,0)}
  100%{box-shadow:0 0 0 0 rgba(34,197,94,0)}
}

.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:9px;
  padding:13px 24px; border-radius:999px; border:1px solid transparent;
  font-weight:600; font-size:.94rem; cursor:pointer; white-space:nowrap;
  transition:transform .18s var(--ease), background-color .18s, border-color .18s, box-shadow .18s;
}
.btn:active{transform:translateY(1px)}
.btn-primary{
  background:var(--accent); color:#fff;
  box-shadow:0 10px 26px -12px rgba(var(--accent-rgb),.75);
}
.btn-primary:hover{background:var(--accent-lift); box-shadow:0 14px 32px -12px rgba(var(--accent-rgb),.9)}
.btn-ghost{background:transparent; color:var(--text); border-color:var(--line)}
.btn-ghost:hover{border-color:var(--accent); color:var(--accent-lift)}

.chip{
  display:inline-flex; align-items:center; gap:7px;
  padding:6px 13px; border-radius:999px; border:1px solid var(--line);
  background:var(--surface-2); color:var(--text-2);
  font-size:.8rem; font-weight:500; white-space:nowrap;
}
.chip-live{border-color:rgba(34,197,94,.35); color:var(--text)}
.chips{display:flex; flex-wrap:wrap; gap:9px}
.chips-sm .chip{font-size:.74rem; padding:5px 11px}

/* ---------- header ---------- */
.site-head{
  position:sticky; top:0; z-index:100;
  background:color-mix(in srgb, var(--bg) 78%, transparent);
  backdrop-filter:saturate(180%) blur(16px);
  -webkit-backdrop-filter:saturate(180%) blur(16px);
  border-block-end:1px solid transparent;
  transition:border-color .25s, background-color .25s;
}
.site-head.stuck{border-block-end-color:var(--line-soft)}

.head-inner{display:flex; align-items:center; gap:20px; min-height:70px}

.brand{display:flex; align-items:center; gap:11px; flex:none}
.brand-mark{
  width:38px; height:38px; border-radius:11px; flex:none;
  display:grid; place-items:center; color:#fff; font-weight:700; font-size:.86rem; letter-spacing:.02em;
  background:linear-gradient(140deg,var(--accent-lift),var(--accent-deep));
  box-shadow:0 8px 20px -10px rgba(var(--accent-rgb),.9);
}
.brand-text{display:flex; flex-direction:column; line-height:1.25}
.brand-text strong{font-size:.92rem; font-weight:600}
.brand-text small{font-size:.72rem; color:var(--muted)}

.nav{display:flex; gap:4px; margin-inline:auto}
.nav a{
  padding:8px 13px; border-radius:999px; font-size:.87rem; color:var(--text-2);
  transition:color .18s, background-color .18s;
}
.nav a:hover{color:var(--text); background:var(--surface-2)}
.nav a.active{color:var(--accent-lift); background:rgba(var(--accent-rgb),.10)}

.head-tools{display:flex; align-items:center; gap:8px; flex:none}

.pill-btn{
  width:36px; height:36px; border-radius:11px; flex:none;
  display:grid; place-items:center; cursor:pointer;
  border:1px solid var(--line); background:var(--surface); color:var(--text-2);
  font-size:.76rem; font-weight:600;
  transition:border-color .18s, color .18s, background-color .18s;
}
.pill-btn:hover{border-color:var(--accent); color:var(--accent-lift)}

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

.head-cta{padding:9px 18px; font-size:.85rem}

.burger{
  display:none; width:36px; height:36px; border-radius:11px; cursor:pointer;
  border:1px solid var(--line); background:var(--surface);
  flex-direction:column; align-items:center; justify-content:center; gap:4px;
}
.burger span{display:block; width:15px; height:1.5px; background:var(--text); transition:transform .25s var(--ease), opacity .2s}
.burger[aria-expanded="true"] span:nth-child(1){transform:translateY(5.5px) rotate(45deg)}
.burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-5.5px) rotate(-45deg)}

.scroll-bar{
  position:absolute; inset-block-end:-1px; inset-inline-start:0;
  height:2px; width:0; background:linear-gradient(90deg,var(--accent),var(--accent-lift));
  transition:width .08s linear;
}

.mobile-menu{
  position:sticky; top:70px; z-index:99;
  display:flex; flex-direction:column; padding:10px var(--pad) 18px;
  background:var(--bg); border-block-end:1px solid var(--line-soft);
}
.mobile-menu a{padding:11px 4px; font-size:.95rem; color:var(--text-2); border-block-end:1px solid var(--line-soft)}
.mobile-menu a:last-child{border-block-end:0}

/* ---------- hero ---------- */
.hero{position:relative; padding-block:clamp(48px,7vw,88px) clamp(40px,6vw,72px); overflow:hidden}
.hero-glow{
  position:absolute; inset-block-start:-260px; inset-inline-end:-140px;
  width:760px; height:760px; border-radius:50%; pointer-events:none;
  background:radial-gradient(circle, var(--glow), transparent 66%);
}
.hero-grid{
  position:relative; display:grid; gap:clamp(36px,5vw,72px);
  grid-template-columns:1.15fr .85fr; align-items:center;
}

.hero-text h1{
  font-size:clamp(2.1rem,5.4vw,3.5rem);
  letter-spacing:-.03em; margin-block-end:10px;
  text-wrap:balance;
}
html[lang="ar"] .hero-text h1{letter-spacing:0; line-height:1.35}

.hero-title{
  font-size:clamp(1.05rem,2vw,1.35rem); font-weight:600; color:var(--accent-lift);
  margin-block-end:16px;
}
.hero-tag{color:var(--text-2); font-size:1.02rem; max-width:46ch; margin-block-end:28px}

.hero-actions{display:flex; flex-wrap:wrap; gap:12px; margin-block-end:40px}

.stats{
  display:grid; grid-template-columns:repeat(4,1fr); gap:18px;
  padding-block-start:28px; border-block-start:1px solid var(--line);
}
.stat b{
  display:block; font-size:clamp(1.35rem,2.6vw,1.85rem); font-weight:700;
  color:var(--text); letter-spacing:-.02em; font-family:var(--ff-en);
}
.stat span{font-size:.79rem; color:var(--muted); line-height:1.5; display:block}

/* photo */
.hero-visual{display:flex; justify-content:center}
.photo-frame{position:relative; width:min(100%,340px); aspect-ratio:1; isolation:isolate}

/* Soft rotating halo behind the portrait — circular, so rotation reads as
   moving light rather than a spinning square. */
.photo-ring{
  position:absolute; inset:-34px; z-index:0; border-radius:50%; pointer-events:none;
  background:conic-gradient(from 0deg, var(--accent), transparent 34%, transparent 66%, var(--accent-lift));
  filter:blur(30px); opacity:.42;
  animation:spin 20s linear infinite;
}
@keyframes spin{to{transform:rotate(360deg)}}
@media (prefers-reduced-motion:reduce){ .photo-ring{animation:none} }

.photo{
  position:relative; z-index:1; width:100%; height:100%; object-fit:cover;
  border-radius:var(--r-xl); border:1px solid var(--line);
  background:var(--surface);
  box-shadow:0 30px 70px -32px rgba(0,0,0,.85);
}
.photo-fallback{
  display:grid; place-items:center;
  background:
    radial-gradient(circle at 30% 25%, rgba(var(--accent-rgb),.22), transparent 55%),
    linear-gradient(155deg, var(--surface-2), var(--surface));
}
/* Needs more contrast on light, where surface and surface-2 are both near white. */
html[data-theme="light"] .photo-fallback{
  background:
    radial-gradient(circle at 30% 25%, rgba(var(--accent-rgb),.16), transparent 58%),
    linear-gradient(155deg, #E8EDF6, #F8FAFD);
}
.photo-fallback span{
  font-family:var(--ff-en); font-size:clamp(3rem,9vw,4.6rem); font-weight:800;
  letter-spacing:-.04em;
  background:linear-gradient(140deg,var(--accent-lift),var(--accent-deep));
  -webkit-background-clip:text; background-clip:text; color:transparent;
}
.photo-badge{
  position:absolute; z-index:2; inset-block-end:-14px; inset-inline-start:50%;
  transform:translateX(50%);
  display:inline-flex; align-items:center; gap:8px; white-space:nowrap;
  padding:8px 16px; border-radius:999px;
  background:var(--surface); border:1px solid var(--line); color:var(--text-2);
  font-size:.79rem; font-weight:500; box-shadow:var(--card-shadow);
}
html[dir="ltr"] .photo-badge{transform:translateX(-50%)}

/* ---------- marquee ---------- */
.marquee{
  /* The strip is Latin tech names and its own scroll axis, so it is laid out
     LTR in both page directions; only the travel direction flips. */
  direction:ltr;
  overflow:hidden; border-block:1px solid var(--line-soft);
  background:var(--bg-alt); padding-block:14px; user-select:none;
}
.marquee-track{
  /* Laid out LTR in both directions: the track is duplicated content, so the
     translate maths stays predictable and the strip never starts off-screen. */
  direction:ltr;
  display:flex; align-items:center; gap:26px; width:max-content;
  animation:slide 46s linear infinite;
}
html[dir="rtl"] .marquee-track{animation-direction:reverse}
@keyframes slide{to{transform:translateX(-50%)}}
@media (prefers-reduced-motion:reduce){ .marquee-track{animation:none} }
.mq-item{
  font-family:var(--ff-en); font-size:.76rem; font-weight:500;
  letter-spacing:.14em; text-transform:uppercase; color:var(--muted);
}
.mq-sep{color:var(--accent); font-size:.5rem; opacity:.7}

/* ---------- sections ---------- */
.sec{padding-block:var(--sec-y)}
.sec-alt{background:var(--bg-alt); border-block:1px solid var(--line-soft)}

.sec-head{margin-block-end:clamp(34px,4vw,54px); max-width:62ch}
.sec-head h2{font-size:clamp(1.5rem,3.4vw,2.3rem); letter-spacing:-.025em; text-wrap:balance}
html[lang="ar"] .sec-head h2{letter-spacing:0; line-height:1.4}

/* about */
.about-grid{display:grid; grid-template-columns:1.6fr 1fr; gap:clamp(28px,4vw,56px); align-items:start}
.about-text{font-size:1.04rem; color:var(--text-2); line-height:1.95}

.about-side{
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:24px; box-shadow:var(--card-shadow);
}
.fact-list li{
  display:flex; align-items:center; gap:12px; padding-block:12px;
  border-block-end:1px solid var(--line-soft); font-size:.9rem; color:var(--text-2);
}
.fact-list li:last-child{border-block-end:0}
.fact-list svg{color:var(--accent-lift); flex:none}
.fact-list a:hover{color:var(--accent-lift)}

/* timeline */
.timeline{position:relative; display:grid; gap:22px}
.timeline::before{
  content:""; position:absolute; inset-block:14px 14px; inset-inline-start:11px;
  width:1px; background:linear-gradient(var(--accent), var(--line) 45%, transparent);
}
.tl-item{position:relative; padding-inline-start:44px}
.tl-marker{position:absolute; inset-inline-start:0; inset-block-start:26px}
.tl-marker span{
  display:block; width:23px; height:23px; border-radius:50%;
  border:1px solid var(--line); background:var(--surface);
  position:relative;
}
.tl-marker span::after{
  content:""; position:absolute; inset:6px; border-radius:50%; background:var(--accent);
}
.tl-card{
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:clamp(20px,2.6vw,30px);
  box-shadow:var(--card-shadow);
  transition:border-color .2s, transform .2s var(--ease);
}
.tl-card:hover{border-color:rgba(var(--accent-rgb),.42); transform:translateY(-2px)}

.tl-top{display:flex; flex-wrap:wrap; gap:12px; align-items:flex-start; justify-content:space-between; margin-block-end:16px}
.tl-top h3{font-size:1.1rem}
.tl-role{font-size:.88rem; color:var(--accent-lift); font-weight:500; margin-block-start:3px}

.tl-bullets{display:grid; gap:10px}
.tl-bullets li{
  position:relative; padding-inline-start:20px; font-size:.92rem;
  color:var(--text-2); line-height:1.8;
}
.tl-bullets li::before{
  content:""; position:absolute; inset-inline-start:0; inset-block-start:.72em;
  width:6px; height:6px; border-radius:2px; background:var(--accent); opacity:.75;
}

/* skills */
.skill-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:20px}
.skill-card{
  position:relative; background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:clamp(22px,2.6vw,30px); box-shadow:var(--card-shadow);
  transition:border-color .2s, transform .2s var(--ease);
}
.skill-card:hover{border-color:rgba(var(--accent-rgb),.42); transform:translateY(-3px)}
.card-num{
  position:absolute; inset-block-start:18px; inset-inline-end:20px;
  font-family:var(--ff-en); font-size:.82rem; font-weight:600; color:var(--muted); opacity:.6;
}
.skill-card h3{font-size:1.02rem; color:var(--accent-lift); margin-block-end:16px; padding-inline-end:34px}
.skill-card ul{display:grid; gap:11px}
.skill-card li{
  position:relative; padding-inline-start:19px; font-size:.89rem; color:var(--text-2); line-height:1.7;
}
.skill-card li::before{
  content:""; position:absolute; inset-inline-start:0; inset-block-start:.68em;
  width:6px; height:6px; border-radius:50%; border:1.5px solid var(--accent);
}

.chips-block{margin-block-start:28px; padding-block-start:26px; border-block-start:1px solid var(--line)}
.chips-label{font-size:.82rem; color:var(--muted); margin-block-end:14px}

/* projects */
.proj-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(290px,1fr)); gap:20px}
.proj-card{
  display:flex; flex-direction:column; gap:12px;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:clamp(22px,2.6vw,28px); box-shadow:var(--card-shadow);
  transition:border-color .2s, transform .2s var(--ease);
}
.proj-card:hover{border-color:rgba(var(--accent-rgb),.42); transform:translateY(-3px)}
.proj-top{display:flex; align-items:center; justify-content:space-between; gap:12px}
.proj-type{
  font-size:.72rem; font-weight:600; letter-spacing:.06em; text-transform:uppercase;
  color:var(--accent-lift);
}
html[lang="ar"] .proj-type{letter-spacing:0; text-transform:none; font-size:.78rem}
.proj-link{
  width:32px; height:32px; border-radius:9px; display:grid; place-items:center;
  border:1px solid var(--line); color:var(--muted); transition:all .18s;
}
.proj-link:hover{border-color:var(--accent); color:var(--accent-lift); background:rgba(var(--accent-rgb),.10)}
.proj-card h3{font-size:1.06rem}
.proj-card p{font-size:.9rem; color:var(--text-2); line-height:1.8; flex:1}

/* education */
.edu-grid{display:grid; gap:20px}
.edu-card{
  display:flex; gap:20px; align-items:flex-start;
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:clamp(22px,2.6vw,30px); box-shadow:var(--card-shadow);
}
.edu-icon{
  width:44px; height:44px; border-radius:13px; flex:none; display:grid; place-items:center;
  background:rgba(var(--accent-rgb),.12); color:var(--accent-lift);
  border:1px solid rgba(var(--accent-rgb),.24);
}
.edu-body{flex:1; min-width:0}

/* languages */
.lang-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(280px,1fr)); gap:20px}
.lang-card{
  background:var(--surface); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:24px; box-shadow:var(--card-shadow);
}
.lang-top{display:flex; flex-wrap:wrap; gap:8px; align-items:baseline; justify-content:space-between; margin-block-end:16px}
.lang-top strong{font-size:1rem}
.lang-top span{font-size:.82rem; color:var(--muted)}
.meter{height:6px; border-radius:999px; background:var(--surface-2); border:1px solid var(--line-soft); overflow:hidden}
.meter i{
  display:block; height:100%; width:0; border-radius:999px;
  background:linear-gradient(90deg,var(--accent-deep),var(--accent-lift));
  transition:width 1.1s var(--ease);
}
.lang-card.in .meter i{width:var(--pct)}

/* contact */
.cta{
  position:relative; overflow:hidden;
  border:1px solid var(--line); border-radius:var(--r-xl);
  background:
    radial-gradient(700px 340px at 50% 0%, rgba(var(--accent-rgb),.14), transparent 70%),
    var(--surface);
  padding:clamp(34px,5vw,64px) clamp(24px,4vw,56px);
  box-shadow:var(--card-shadow);
}
.cta-inner{max-width:760px; margin-inline:auto; text-align:center}
.cta-inner .eyebrow{justify-content:center}
.cta-inner h2{font-size:clamp(1.5rem,3.4vw,2.2rem); margin-block-end:14px}
.cta-note{color:var(--text-2); margin-block-end:32px; font-size:1rem}

.contact-links{
  display:grid; grid-template-columns:repeat(auto-fit,minmax(248px,1fr));
  gap:12px; margin-block-end:32px; text-align:start;
}
.contact-link{
  display:flex; align-items:center; gap:13px; padding:14px 16px;
  border:1px solid var(--line); border-radius:var(--r-md); background:var(--surface-2);
  transition:border-color .18s, transform .18s var(--ease), background-color .18s;
  min-width:0;
}
.contact-link:hover{border-color:var(--accent); transform:translateY(-2px)}
.ci{
  width:38px; height:38px; border-radius:11px; flex:none; display:grid; place-items:center;
  background:rgba(var(--accent-rgb),.12); color:var(--accent-lift);
}
.cl-body{display:flex; flex-direction:column; min-width:0; line-height:1.45}
.cl-body small{font-size:.73rem; color:var(--muted)}
/* Long values (emails, profile URLs) wrap instead of being clipped. */
.cl-body b{font-size:.85rem; font-weight:500; overflow-wrap:anywhere; text-align:start}

.cta-btn{margin-inline:auto}

/* footer */
.site-foot{border-block-start:1px solid var(--line); background:var(--bg-alt); padding-block:26px}
.foot-inner{
  display:flex; flex-wrap:wrap; gap:10px; align-items:center; justify-content:space-between;
  font-size:.82rem; color:var(--muted);
}

/* floating whatsapp */
.fab{
  position:fixed; inset-block-end:22px; inset-inline-end:22px; z-index:90;
  width:52px; height:52px; border-radius:50%; display:grid; place-items:center;
  background:#25D366; color:#fff;
  box-shadow:0 14px 30px -12px rgba(37,211,102,.8);
  transition:transform .2s var(--ease);
}
.fab:hover{transform:scale(1.08)}

/* ---------- reveal ---------- */
.reveal{opacity:0; transform:translateY(18px); transition:opacity .55s var(--ease), transform .55s var(--ease)}
.reveal.in{opacity:1; transform:none}
@media (prefers-reduced-motion:reduce){
  .reveal{opacity:1; transform:none; transition:none}
}


/* =========================================================
   MOTION LAYER
   Everything below animates transform / opacity / filter only,
   and every piece switches itself off under reduced-motion.
   ========================================================= */

/* ---------- hero entrance (plays on load, not on scroll) ---------- */
.enter{
  opacity:0;
  transform:translateY(22px);
  animation:enterUp .8s var(--ease) forwards;
  animation-delay:var(--d, 0s);
}
@keyframes enterUp{to{opacity:1; transform:none}}

/* Heading words fly in one after another. */
.split-words .w{
  display:inline-block;
  opacity:0;
  transform:translateY(.5em) rotate(2deg);
  animation:wordIn .7s var(--ease) forwards;
  animation-delay:calc(var(--wd, 0s) + (var(--wi, 0) * .055s));
}
@keyframes wordIn{to{opacity:1; transform:none}}
/* Section headings hold their words until the section scrolls into view. */
.sec-head h2.split-words:not(.in) .w{animation-play-state:paused}

/* ---------- rotating job title ---------- */
.role-rot{
  display:inline-block; position:relative; vertical-align:bottom;
  /* Reserve the widest role so the paragraph below never jumps —
     but never wider than the column itself. */
  min-width:min(var(--rw, 0px), 100%);
  max-width:100%;
}
html[dir="rtl"] .role-rot{text-align:right}
.role-text{
  display:inline-block; white-space:nowrap; overflow:hidden;
  vertical-align:bottom; max-width:100%;
  border-inline-end:2px solid var(--accent);
  padding-inline-end:3px;
  animation:caret 1s steps(1) infinite;
}
@keyframes caret{50%{border-color:transparent}}
@media (prefers-reduced-motion:reduce){ .role-text{animation:none; border-color:transparent} }

/* ---------- hero atmosphere ---------- */
.blobs{position:absolute; inset:0; overflow:hidden; pointer-events:none; z-index:0}
.blob{
  position:absolute; display:block; border-radius:50%;
  filter:blur(70px); opacity:.30;
  will-change:transform;
}
.b1{
  width:420px; height:420px; inset-block-start:-90px; inset-inline-end:6%;
  background:var(--accent); animation:drift1 22s ease-in-out infinite;
}
.b2{
  width:330px; height:330px; inset-block-end:-70px; inset-inline-start:12%;
  background:var(--accent-lift); opacity:.18; animation:drift2 27s ease-in-out infinite;
}
.b3{
  width:250px; height:250px; inset-block-start:38%; inset-inline-start:44%;
  background:var(--accent-deep); opacity:.22; animation:drift3 19s ease-in-out infinite;
}
@keyframes drift1{50%{transform:translate3d(-60px,50px,0) scale(1.14)}}
@keyframes drift2{50%{transform:translate3d(70px,-40px,0) scale(.88)}}
@keyframes drift3{50%{transform:translate3d(-40px,-60px,0) scale(1.2)}}
/* On the light theme the same opacities read as a heavy blue wash. */
html[data-theme="light"] .b1{opacity:.16}
html[data-theme="light"] .b2{opacity:.10}
html[data-theme="light"] .b3{opacity:.11}
@media (prefers-reduced-motion:reduce){ .blob{animation:none} }

/* Cursor-follow light in the hero. */
.hero-spot{
  position:absolute; inset:0; z-index:0; pointer-events:none; opacity:0;
  transition:opacity .5s var(--ease);
  background:radial-gradient(340px circle at var(--sx,50%) var(--sy,50%), rgba(var(--accent-rgb),.16), transparent 62%);
}
.hero.lit .hero-spot{opacity:1}
.hero-grid,.hero-text,.hero-visual{position:relative; z-index:1}

/* ---------- scroll cue ---------- */
/* Centred with auto margins, not a transform, so the .enter keyframe
   (which resets transform) cannot knock it off-centre. */
.scroll-cue{
  position:absolute; inset-block-end:20px; inset-inline:0;
  margin-inline:auto; width:-moz-fit-content; width:fit-content; z-index:2;
  display:grid; place-items:center; opacity:0;
  animation:enterUp .8s var(--ease) forwards; animation-delay:var(--d,.8s);
}
.mouse{
  width:24px; height:38px; border-radius:14px; border:1.5px solid var(--line);
  display:grid; justify-items:center; padding-block-start:7px;
  transition:border-color .2s;
}
.scroll-cue:hover .mouse{border-color:var(--accent)}
.mouse i{
  width:3px; height:7px; border-radius:2px; background:var(--accent);
  animation:wheel 1.9s var(--ease) infinite;
}
@keyframes wheel{
  0%{opacity:0; transform:translateY(-3px)}
  35%{opacity:1}
  75%{opacity:0; transform:translateY(11px)}
  100%{opacity:0}
}
@media (max-width:900px){ .scroll-cue{display:none} }
@media (prefers-reduced-motion:reduce){ .mouse i{animation:none} }

/* ---------- cards: cursor spotlight + 3D tilt ---------- */
.spot{position:relative; isolation:isolate}
.spot::before{
  content:""; position:absolute; inset:0; border-radius:inherit;
  z-index:-1; opacity:0; transition:opacity .35s var(--ease);
  background:radial-gradient(320px circle at var(--mx,50%) var(--my,50%), rgba(var(--accent-rgb),.13), transparent 60%);
}
.spot:hover::before{opacity:1}

.tilt{
  transform-style:preserve-3d;
  transition:transform .35s var(--ease), border-color .2s, box-shadow .3s;
  will-change:transform;
}
.tilt.tilting{transition:transform .08s linear, border-color .2s, box-shadow .3s}
/* JS owns the transform on tilt cards, so drop the CSS hover lift for them. */
.skill-card.tilt:hover,.proj-card.tilt:hover{transform:none}
.tilt:hover{box-shadow:0 34px 70px -40px rgba(var(--accent-rgb),.55)}

/* ---------- magnetic buttons ---------- */
.mag{will-change:transform}

/* Light sweep across primary buttons on hover. */
.btn-primary{position:relative; overflow:hidden; isolation:isolate}
.btn-primary::after{
  content:""; position:absolute; inset:0; z-index:-1;
  background:linear-gradient(115deg, transparent 30%, rgba(255,255,255,.32) 50%, transparent 70%);
  transform:translateX(-140%);
  transition:transform .75s var(--ease);
}
.btn-primary:hover::after{transform:translateX(140%)}
@media (prefers-reduced-motion:reduce){ .btn-primary::after{display:none} }

/* ---------- nav underline ---------- */
.nav a{position:relative}
.nav a::after{
  content:""; position:absolute; inset-block-end:2px; inset-inline:13px;
  height:1.5px; border-radius:2px; background:var(--accent);
  transform:scaleX(0); transform-origin:center;
  transition:transform .3s var(--ease);
}
.nav a:hover::after,.nav a.active::after{transform:scaleX(1)}

/* ---------- portrait interaction ---------- */
.photo-frame .photo{transition:transform .5s var(--ease), box-shadow .4s var(--ease)}
.photo-frame:hover .photo{transform:scale(1.03)}
.photo-frame:hover ~ * .photo-ring,.photo-frame:hover .photo-ring{opacity:.62}
.photo-ring{transition:opacity .5s var(--ease)}

/* ---------- timeline rail draws itself ---------- */
.timeline::before{transform-origin:top; transform:scaleY(0); transition:transform 1.4s var(--ease)}
.timeline.in::before{transform:scaleY(1)}
.tl-marker span{transition:transform .3s var(--ease), border-color .2s}
.tl-item:hover .tl-marker span{transform:scale(1.22); border-color:var(--accent)}
@media (prefers-reduced-motion:reduce){ .timeline::before{transform:none; transition:none} }

/* ---------- meters & chips ---------- */
.chip{transition:transform .2s var(--ease), border-color .2s, color .2s}
.chips .chip:hover{transform:translateY(-2px); border-color:var(--accent); color:var(--text)}

.meter i{position:relative; overflow:hidden}
.meter i::after{
  content:""; position:absolute; inset:0;
  background:linear-gradient(90deg, transparent, rgba(255,255,255,.4), transparent);
  transform:translateX(-100%);
  animation:sheen 2.6s var(--ease) 1.2s infinite;
}
@media (prefers-reduced-motion:reduce){ .meter i::after{display:none} }
@keyframes sheen{to{transform:translateX(100%)}}

/* ---------- marquee pauses when you look at it ---------- */
.marquee:hover .marquee-track{animation-play-state:paused}
.mq-item{transition:color .25s}
.marquee:hover .mq-item{color:var(--text-2)}

/* ---------- back to top with progress ring ---------- */
.to-top{
  position:fixed; z-index:90; inset-block-end:84px; inset-inline-end:24px;
  width:44px; height:44px; border-radius:50%; cursor:pointer; padding:0;
  display:grid; place-items:center;
  border:1px solid var(--line); background:var(--surface); color:var(--text-2);
  opacity:0; visibility:hidden; transform:translateY(12px) scale(.9);
  transition:opacity .3s var(--ease), transform .3s var(--ease), visibility .3s, border-color .2s, color .2s;
}
.to-top.on{opacity:1; visibility:visible; transform:none}
.to-top:hover{border-color:var(--accent); color:var(--accent-lift)}
.to-top .ring{position:absolute; inset:-1px; width:44px; height:44px; transform:rotate(-90deg)}
html[dir="rtl"] .to-top .ring{transform:rotate(-90deg) scaleY(-1)}
.ring circle{fill:none; stroke-width:2}
.ring-bg{stroke:var(--line-soft)}
.ring-fg{
  stroke:var(--accent);
  stroke-linecap:round;
  stroke-dasharray:126;
  stroke-dashoffset:calc(126 - (126 * var(--p, 0)));
  transition:stroke-dashoffset .12s linear;
}
.to-top .arrow{position:relative}
@media (max-width:640px){ .to-top{inset-block-end:74px; inset-inline-end:16px; width:40px; height:40px} }

/* ---------- film grain for depth ---------- */
.grain{
  position:fixed; inset:0; z-index:95; pointer-events:none;
  opacity:.035; mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation:grainShift 700ms steps(4) infinite;
}
html[data-theme="light"] .grain{opacity:.024; mix-blend-mode:multiply}
@keyframes grainShift{
  0%{transform:translate(0,0)}   25%{transform:translate(-4%,3%)}
  50%{transform:translate(3%,-4%)} 75%{transform:translate(-3%,-2%)}
  100%{transform:translate(0,0)}
}
@media (prefers-reduced-motion:reduce){ .grain{animation:none} }
@media print{ .grain,.to-top,.scroll-cue,.blobs,.hero-spot{display:none !important} }

/* ---------- global reduced-motion brake ---------- */
@media (prefers-reduced-motion:reduce){
  .enter,.split-words .w{opacity:1 !important; transform:none !important; animation:none !important}
  .tilt{transform:none !important}
  .spot::before{display:none}
}

/* ---------- responsive ---------- */
@media (max-width:1080px){
  .nav{display:none}
  .burger{display:flex}
}
@media (max-width:900px){
  .hero-grid{grid-template-columns:1fr; text-align:start}
  .hero-visual{order:-1}
  .photo-frame{width:min(100%,250px)}
  .about-grid{grid-template-columns:1fr}
  .brand-text small{display:none}
}
@media (max-width:640px){
  body{font-size:15.5px}
  .head-cta span{display:none}
  .head-cta{padding:9px 12px}
  .stats{grid-template-columns:repeat(2,1fr); gap:20px 14px}
  .edu-card{flex-direction:column; gap:16px}
  .tl-item{padding-inline-start:34px}
  .tl-marker span{width:19px; height:19px}
  .timeline::before{inset-inline-start:9px}
  .foot-inner{justify-content:center; text-align:center}
  .fab{inset-block-end:16px; inset-inline-end:16px; width:48px; height:48px}
}
@media (max-width:420px){
  .brand-text{display:none}
}

/* ---------- print ---------- */
@media print{
  :root{--sec-y:18px}
  html[data-theme]{--bg:#fff; --bg-alt:#fff; --surface:#fff; --surface-2:#fff;
    --text:#000; --text-2:#222; --muted:#555; --line:#ccc; --line-soft:#e5e5e5; --card-shadow:none}
  .site-head,.mobile-menu,.marquee,.fab,.hero-actions,.hero-glow,.photo-ring,.skip,.cta-btn{display:none !important}
  .sec{padding-block:16px; break-inside:avoid}
  .sec-alt{border:0}
  .tl-card,.skill-card,.proj-card,.edu-card,.lang-card,.cta,.about-side{
    box-shadow:none; break-inside:avoid; border-color:#ddd;
  }
  .reveal{opacity:1 !important; transform:none !important}
  a{text-decoration:none; color:#000}
}
