/* =========================================================================
   Ahmed Hassini — portfolio
   Carbon theme · Network ground · Spotlight cards · Thread layout

   One rule to keep in mind when editing: never put a CSS transition on a
   property whose value comes from a colour token (background-color, color,
   border-color).  Chromium does not repaint a transitioned property when the
   custom property behind it changes, so the old paint stays on screen.
   Hover effects here transition opacity, transform and shadow only.
   ========================================================================= */

:root {
  --bg: #0f0f0f;
  --bg2: #090909;
  --card: #191919;
  --card2: #212121;
  --btn: #2b2b2b;
  --ink: #f0efec;
  --ink2: #b9b8b4;
  --dim: #8b8a86;
  --faint: #5f5e5b;
  --line: rgba(255, 255, 255, .1);
  --line2: rgba(255, 255, 255, .19);
  --dot: rgba(255, 255, 255, .12);           /* the network ground reads this */
  --ac: #e3b64a;                             /* …and this */
  --onAc: #07090e;
  --shadow: 0 12px 34px rgba(0, 0, 0, .55);
  --r: 20px;
  --gap: 14px;
  --pad: 24px;
  color-scheme: dark;
  font-family: 'Hanken Grotesk', ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
}

/* pseudo-elements too: the thread's knots and end rings have borders, and
   their centring maths assumes the border sits inside the stated width */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body { margin: 0; background-color: var(--bg); color: var(--ink); font-size: 16px; line-height: 1.5; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; text-align: left; padding: 0; }
:focus-visible { outline: 2px solid var(--ac); outline-offset: 3px; border-radius: 6px; }
/* visually hidden, still read aloud */
.vh { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
.kick { font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--faint); }

/* ---- the ground: a drifting network, drawn by assets/site.js ------------- */
#field { position: fixed; inset: 0; z-index: 0; pointer-events: none; }

/* ---- shell ---------------------------------------------------------------- */
.wrap { position: relative; z-index: 1; max-width: 1280px; margin: 0 auto;
        padding: 26px clamp(18px, 3.5vw, 40px) 60px; }
nav { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.pills { margin-left: auto; display: flex; gap: 7px; flex-wrap: wrap; align-items: center; }
.pill { background-color: var(--card); border-radius: 99px; padding: 8px 16px; font-size: 13.5px;
        border: 1px solid var(--line); color: var(--ink2); transition: transform .16s; }
.pill:hover { border-color: var(--line2); transform: translateY(-1px); }
.pill.dark { background-color: var(--ink); color: var(--bg); border-color: var(--ink); }

.grid { max-width: 1080px; margin: 18px auto 0; }

/* ---- cards ------------------------------------------------------------------ */
.t { position: relative; background-color: var(--card); border-radius: var(--r); padding: var(--pad);
     border: 1px solid var(--line); overflow: hidden;
     transition: box-shadow .2s, transform .2s; }
/* spotlight: each card lights where the cursor is (--cx/--cy set by site.js) */
.t::before { content: ""; position: absolute; inset: 0; pointer-events: none; opacity: 0; border-radius: inherit;
  transition: opacity .3s;
  background: radial-gradient(360px circle at var(--cx, 50%) var(--cy, 50%),
    color-mix(in srgb, var(--ac) 13%, transparent), transparent 60%); }
.t:hover::before { opacity: 1; }
.t.click { cursor: pointer; }
.t.click:hover { border-color: var(--line2); transform: translateY(-2px); box-shadow: var(--shadow); }
.t > * { position: relative; z-index: 1; }

h1 { font-size: clamp(30px, 4.2vw, 46px); line-height: 1.08; letter-spacing: -.028em; margin: 12px 0 0; font-weight: 700; }
h1 em { font-style: normal; color: var(--ac); }
.lede { color: var(--ink2); margin-top: 12px; font-size: 15.5px; max-width: 46ch; }
.btns { display: flex; gap: 9px; margin-top: 20px; flex-wrap: wrap; }
.btn { border-radius: 99px; padding: 11px 20px; font-size: 14px; font-weight: 500; background-color: var(--btn);
       color: var(--ink); border: 1px solid transparent; transition: transform .16s; display: inline-block; }
.btn:hover { border-color: var(--line2); transform: translateY(-1px); }
.btn.p { background-color: var(--ac); color: var(--onAc); }

.big { font-size: clamp(34px, 4.6vw, 50px); font-weight: 700; letter-spacing: -.03em; line-height: 1; color: var(--ac); }
.big.ink { color: var(--ink); }
.sub { color: var(--dim); font-size: 13.5px; margin-top: 8px; }

.t h3 { font-size: 21px; margin: 7px 0 0; letter-spacing: -.015em; line-height: 1.25; }
.t .meta { font-size: 13px; color: var(--dim); margin-top: 4px; }
.t p.d { font-size: 14px; color: var(--ink2); margin: 10px 0 0; }
.metric { font-size: 30px; font-weight: 700; letter-spacing: -.02em; line-height: 1; color: var(--ac); }
.metric small { display: block; font-size: 11.5px; font-weight: 400; letter-spacing: 0; color: var(--dim); margin-top: 5px; }
.out { padding-top: 16px; }
.lk { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 13px; }
.lk a, .lk span { font-size: 11.5px; border-radius: 99px; padding: 5px 11px; border: 1px solid var(--line2);
  color: var(--dim); display: inline-flex; align-items: center; gap: 5px; transition: transform .16s; }
.lk a { color: var(--ac); border-color: color-mix(in srgb, var(--ac) 42%, transparent); }
.lk a:hover { transform: translateY(-1px); }
.lk span.priv { color: var(--faint); border-style: dashed; }
.open-cs { margin-top: 12px; font-size: 12px; color: var(--ac); font-weight: 500; display: inline-flex; gap: 6px; }
.tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
.tag { border: 1px solid var(--line2); border-radius: 7px; padding: 3px 9px; font-size: 11.5px; color: var(--dim); }
/* the tools on each card, set like the education coursework */
.stack { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-top: 14px; }
.stack .kick { margin-right: 4px; }
.bl { display: flex; gap: 10px; margin-top: 9px; font-size: 14px; color: var(--ink2); line-height: 1.55; }
.bl i { color: var(--ac); font-style: normal; flex: none; }

/* ---- intro: hero beside education ------------------------------------------ */
.intro { display: grid; grid-template-columns: 1.3fr 1fr; gap: var(--gap); }
.hero, .edu { align-self: stretch; }
.edu { display: flex; flex-direction: column; }
.edustats { display: flex; gap: 34px; margin-top: 18px; }
.edu .bl { margin-top: 16px; }
.edufoot { margin-top: auto; padding-top: 18px; }
.edufoot .tags { margin-top: 8px; }

/* =========================================================================
   THE THREAD
   The work hangs from a centre spine.  Cards alternate sides and interlock;
   each is tied in by a string that bends into the spine, fastened by a knot.
   The spine fills gold as you read down it (--fill, set by site.js), a spark
   rides the leading edge, and knots light as you pass them.
   ========================================================================= */
.shead { display: flex; justify-content: center; align-items: center; margin: 54px 0 0; }
.shead h2 { margin: 0; border: 1px solid var(--line2); border-radius: 99px; padding: 7px 16px; background-color: var(--card);
  color: var(--ink); font-size: 11px; line-height: 1.5; letter-spacing: .18em; text-transform: uppercase; font-weight: 500; }
/* the capsule lights once the reading line reaches it, like the knots below it */
.shead h2.reached { background-color: var(--ac); border-color: var(--ac); color: var(--onAc);
  box-shadow: 0 0 14px 1px color-mix(in srgb, var(--ac) 45%, transparent); }

.tiles { position: relative; padding: 30px 0 46px; }
.spine { position: absolute; left: calc(50% - 1px); top: 0; bottom: 12px; width: 2px; border-radius: 2px;
  background: linear-gradient(to bottom, transparent, var(--line2) 26px); }
.spine b { position: absolute; left: 0; top: 0; width: 100%; height: var(--fill, 0%); border-radius: 2px;
  background: linear-gradient(to bottom, transparent, var(--ac) 26px);
  box-shadow: 0 0 6px color-mix(in srgb, var(--ac) 70%, transparent),
              0 0 18px 2px color-mix(in srgb, var(--ac) 30%, transparent); }
.spine b::after { content: ""; position: absolute; left: 50%; bottom: -4px; width: 8px; height: 8px; margin-left: -4px;
  border-radius: 50%; background-color: var(--ac); opacity: 0;
  box-shadow: 0 0 10px 3px color-mix(in srgb, var(--ac) 65%, transparent),
              0 0 26px 8px color-mix(in srgb, var(--ac) 25%, transparent); }
.tiles.started:not(.done) .spine b::after { opacity: 1; }
/* the end of each thread */
.tiles::after { content: ""; position: absolute; left: calc(50% - 7px); bottom: 0; width: 14px; height: 14px;
  border-radius: 50%; border: 2px solid var(--line2); background-color: var(--bg); }
.tiles.done::after { border-color: var(--ac); background-color: var(--ac);
  box-shadow: 0 0 12px 2px color-mix(in srgb, var(--ac) 55%, transparent); }

.tiles .t { width: calc(50% - 50px); margin-bottom: 26px; overflow: visible; }
.tiles .t:nth-child(even) { margin-left: calc(50% + 50px); }
.tiles .t + .t { margin-top: -116px; }            /* the two sides interlock */

/* node = the string.  Its width is the gap to the spine plus the card's 1px
   border plus half the string, so the string's centreline lands exactly on
   the spine's.  Offsets inside it are measured from inside its own border. */
.t > .node { position: absolute; top: 31px; width: 51.75px; height: 24px; z-index: 2;
  border: 0 solid var(--line2); border-top-width: 1.5px; }
.t:nth-child(odd) > .node { left: 100%; border-right-width: 1.5px; border-top-right-radius: 24px; }
.t:nth-child(even) > .node { right: 100%; border-left-width: 1.5px; border-top-left-radius: 24px; }
.t > .node::after { content: ""; position: absolute; bottom: -4px; width: 8px; height: 8px; border-radius: 50%;
  border: 1.5px solid var(--line2); background-color: var(--bg); }
.t:nth-child(odd) > .node::after { right: -4.75px; }
.t:nth-child(even) > .node::after { left: -4.75px; }
.t.lit > .node { border-color: var(--ac); filter: drop-shadow(0 0 3px color-mix(in srgb, var(--ac) 60%, transparent)); }
.t.lit > .node::after { border-color: var(--ac); background-color: var(--ac); }
/* the current role keeps a slow pulse on its knot */
.t[data-now] > .node::before { content: ""; position: absolute; bottom: -4px; width: 8px; height: 8px; border-radius: 50%;
  border: 1px solid var(--ac); animation: ping 2.4s cubic-bezier(.2, .7, .3, 1) infinite; }
.t[data-now]:nth-child(odd) > .node::before { right: -4.75px; }
.t[data-now]:nth-child(even) > .node::before { left: -4.75px; }
@keyframes ping { from { transform: scale(1); opacity: .9; } to { transform: scale(3.2); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .t[data-now] > .node::before { animation: none; opacity: 0; } }

/* ---- résumé: a printed document ------------------------------------------- */
.more { margin-top: 50px; }
.rz { display: grid; grid-template-columns: 250px 1fr; gap: 26px; }
.rz h3 { font-size: 26px; }
.sheet { background: #fbfaf7; border: 1px solid rgba(30, 30, 25, .14); border-radius: 13px; max-height: 620px;
  overflow-y: auto; padding: 36px 40px; font-family: Charter, "Bitstream Charter", Cambria, Georgia, serif;
  font-size: 12.6px; line-height: 1.42; color: #15150f; }
.sheet h4 { text-align: center; font-size: 24px; margin: 0; letter-spacing: .04em; font-variant: small-caps; font-weight: 700; }
.sheet .em { text-align: center; color: #3a3a31; font-size: 11.5px; margin-top: 3px; }
.sheet .em a { text-decoration: underline; }
.sh { font-variant: small-caps; font-size: 15px; border-bottom: 1px solid #15150f; margin: 16px 0 5px; letter-spacing: .03em; }
.rw { display: flex; justify-content: space-between; gap: 14px; margin-top: 7px; }
.rw b { font-weight: 700; }
.rw .it, .it { font-style: italic; color: #2d2d26; font-size: 11.6px; }
/* \emph inside \textit sets the role upright, as the PDF does */
.it .up { font-style: normal; }
.sheet ul { margin: 3px 0 0; padding-left: 17px; }
.sheet li { margin-top: 2px; }
.sheet li b, .sheet p b { font-weight: 700; }
.sheet p { margin: 3px 0 0; }

/* ---- case study overlay ---------------------------------------------------- */
#cs { position: fixed; inset: 0; z-index: 40; background-color: var(--bg2); overflow-y: auto; visibility: hidden;
  transform: translateY(101%); transition: transform .5s cubic-bezier(.16, 1, .3, 1), visibility 0s .5s; }
#cs.on { transform: none; visibility: visible; transition: transform .5s cubic-bezier(.16, 1, .3, 1), visibility 0s; }
.cswrap { max-width: 1040px; margin: 0 auto; padding: 40px clamp(16px, 4vw, 26px) 80px; }
.cshead { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px;
  border-bottom: 2px solid var(--ink); padding-bottom: 16px; }
.cshead h2 { font-size: clamp(26px, 4vw, 38px); margin: 8px 0 0; letter-spacing: -.025em; line-height: 1.15; }
.cshead .meta { font-size: 13px; color: var(--dim); margin-top: 6px; }
.csx { border: 1px solid var(--line2); border-radius: 99px; padding: 7px 15px; font-size: 12px;
  background-color: var(--card); flex: none; color: var(--ink); }
.csgrid { display: grid; grid-template-columns: 1.15fr .85fr; gap: 34px; margin-top: 26px; }
.csq { margin-top: 20px; }
.csq h3 { font-size: 10px; letter-spacing: .2em; color: var(--ac); margin: 0 0 7px; text-transform: uppercase; }
.csq p { margin: 0; font-size: 14.5px; line-height: 1.62; color: var(--ink2); }
.csside { background-color: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 20px; align-self: start; }
.csnav { display: flex; justify-content: space-between; gap: 10px; margin-top: 34px; padding-top: 18px;
  border-top: 1px solid var(--line); }
.csnav button { font-size: 12.5px; color: var(--dim); }
.csnav button:hover { color: var(--ink); }
.flow { display: grid; grid-template-columns: repeat(auto-fit, minmax(142px, 1fr)); gap: 8px; margin-top: 14px; }
.fstep { position: relative; border: 1px solid var(--line2); border-radius: 10px; overflow: hidden;
  padding: 11px 12px; font-size: 11.5px; line-height: 1.35; color: var(--ink2); background-color: var(--card2); }
.fstep b { display: block; font-size: 9px; letter-spacing: .14em; color: var(--faint); font-weight: 500; margin-bottom: 4px; }
.fpulse { position: absolute; left: 0; right: 0; bottom: -1px; height: 2px; border-radius: 2px; background-color: var(--ac);
  transform: scaleX(0); transform-origin: left; animation: pulse 4.4s ease-in-out infinite; }
@keyframes pulse { 0%, 100% { transform: scaleX(0); } 8% { transform: scaleX(1); } 38% { transform: scaleX(1); } 46% { transform: scaleX(0); } }
@media (prefers-reduced-motion: reduce) { .fpulse { animation: none; transform: scaleX(1); opacity: .5; } }
.shots { display: flex; gap: 9px; margin-top: 14px; }
.shots img { width: 100%; height: auto; border-radius: 9px; border: 1px solid var(--line2); display: block; min-width: 0; }

footer { max-width: 1080px; margin: 60px auto 0; padding-top: 18px; border-top: 1px solid var(--line);
  display: flex; justify-content: space-between; flex-wrap: wrap; gap: 8px; font-size: 12px; color: var(--faint); }
footer a:hover { color: var(--ink2); }

/* ---- narrow screens: one column, the thread runs down the left -------------- */
@media (max-width: 1000px) {
  .intro, .rz, .csgrid { grid-template-columns: 1fr; }
  .shead { justify-content: flex-start; }
  .spine { left: 23px; }
  .tiles::after { left: 17px; }
  .tiles .t, .tiles .t:nth-child(even) { width: auto; margin-left: 62px; }
  .tiles .t + .t { margin-top: 0; }
  .t:nth-child(odd) > .node, .t:nth-child(even) > .node { left: auto; right: 100%; width: 39.75px;
    border-right-width: 0; border-left-width: 1.5px; border-top-right-radius: 0; border-top-left-radius: 24px; }
  .t:nth-child(odd) > .node::after, .t:nth-child(odd) > .node::before,
  .t:nth-child(even) > .node::after { left: -4.75px; right: auto; }
}
@media (max-width: 620px) {
  .tiles .t, .tiles .t:nth-child(even) { margin-left: 44px; }
  .spine { left: 13px; }
  .tiles::after { left: 7px; }
  .t:nth-child(odd) > .node, .t:nth-child(even) > .node { width: 31.75px; }
  .sheet { padding: 24px 20px; font-size: 12px; }
  .rw { flex-wrap: wrap; gap: 0 14px; }
  .edustats { gap: 24px; }
  .shots { flex-direction: column; max-width: 260px; }
}
