/* ============================================================
   components.css — buttons, cards, diagrams, modal, keyframes
   ============================================================ */

/* ---------------- Buttons ---------------- */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--font-display);
  font-weight: 500; font-size: var(--fs-sm);
  padding: 0.7rem 1.35rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  transition: transform var(--dur-fast) var(--ease-spring),
              background var(--dur-fast) var(--ease-out-expo),
              border-color var(--dur-fast) var(--ease-out-expo),
              box-shadow var(--dur-fast) var(--ease-out-expo),
              color var(--dur-fast) var(--ease-out-expo);
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn--solid { background: var(--accent); color: #04121a; }
.btn--solid:hover { background: var(--accent-bright); box-shadow: 0 8px 30px -8px var(--accent-glow); }
.btn--ghost { border-color: var(--hairline-strong); color: var(--text); background: transparent; }
.btn--ghost:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-faint); }

/* ---------------- About ---------------- */
.about { display: grid; grid-template-columns: 1.3fr 0.9fr; gap: clamp(2rem, 6vw, 5rem); align-items: start; }
.about__lead { font-size: var(--fs-h3); font-family: var(--font-display); line-height: 1.3; margin-bottom: 1.75rem; letter-spacing: -0.01em; }
.about__lead .em { color: var(--accent); }
.about__text p { color: var(--text-soft); margin-bottom: 1.1rem; max-width: 60ch; }
.about__facts { border-top: 1px solid var(--hairline); }
.about__fact {
  display: flex; justify-content: space-between; gap: 1rem;
  padding: 0.85rem 0;
  border-bottom: 1px solid var(--hairline);
  font-size: var(--fs-sm);
}
.about__fact dt { color: var(--text-mute); font-family: var(--font-mono); letter-spacing: 0.04em; }
.about__fact dd { color: var(--text); text-align: right; font-weight: 500; }

/* ---------------- Skills ---------------- */
.skills { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 1px; background: var(--hairline); border: 1px solid var(--hairline); }
.skill-group { background: var(--bg); padding: 1.5rem; transition: background var(--dur) var(--ease-out-expo); }
.skill-group:hover { background: var(--bg-1); }
.skill-group__name {
  font-family: var(--font-mono); font-size: var(--fs-xs);
  text-transform: uppercase; letter-spacing: 0.2em; color: var(--text-mute);
  margin-bottom: 1.1rem; display: flex; align-items: center; gap: 0.5rem;
}
.skill-group__name::before { content: ""; width: 6px; height: 6px; background: var(--accent); display: inline-block; }
.skill-group__list { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.chip {
  font-size: var(--fs-sm);
  padding: 0.35rem 0.7rem;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  color: var(--text-soft);
  transition: border-color var(--dur-fast) var(--ease-out-expo),
              color var(--dur-fast) var(--ease-out-expo),
              background var(--dur-fast) var(--ease-out-expo),
              transform var(--dur-fast) var(--ease-spring);
}
.chip:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-faint); transform: translateY(-2px); }

/* ---------------- Experience ---------------- */
.exp-item {
  display: grid; grid-template-columns: 220px 1fr; gap: clamp(1rem,4vw,3rem);
  padding: clamp(1.5rem, 4vw, 2.5rem) 0;
  border-top: 1px solid var(--hairline);
}
.exp-item:last-child { border-bottom: 1px solid var(--hairline); }
.exp-item__meta { font-family: var(--font-mono); }
.exp-item__period { color: var(--accent); font-size: var(--fs-sm); letter-spacing: 0.05em; }
.exp-item__loc { color: var(--text-mute); font-size: var(--fs-xs); margin-top: 0.35rem; }
.exp-item__role { font-size: var(--fs-h3); font-family: var(--font-display); }
.exp-item__company { color: var(--accent); font-weight: 500; }
.exp-item__summary { color: var(--text); margin: 0.5rem 0 1rem; max-width: 60ch; }
.exp-item__points { list-style: none; display: grid; gap: 0.7rem; }
.exp-item__points li { position: relative; padding-left: 1.4rem; color: var(--text-soft); font-size: var(--fs-sm); max-width: 68ch; }
.exp-item__points li::before { content: "▹"; position: absolute; left: 0; color: var(--accent); }

/* ---------------- Projects ---------------- */
/* .projects-rail-wrap grid and .projects-cards are in components.css */
.project {
  position: relative;
  display: grid;
  grid-template-columns: 1.05fr 1fr;
  gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--surface);
  padding: clamp(1.5rem, 4vw, 2.75rem);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease-out-expo),
              transform var(--dur) var(--ease-out-expo),
              box-shadow var(--dur) var(--ease-out-expo);
}
.project::before {
  content: ""; position: absolute; inset: 0;
  background: radial-gradient(80% 120% at 100% 0%, var(--accent-faint), transparent 60%);
  opacity: 0; transition: opacity var(--dur) var(--ease-out-expo); pointer-events: none;
}
.project:hover { border-color: var(--hairline-strong); transform: translateY(-4px); box-shadow: 0 24px 60px -30px rgba(0,0,0,0.9); }
.project:hover::before { opacity: 1; }
.project:nth-child(even) .project__body { order: 2; }

.project__index {
  position: absolute; top: 1rem; right: 1.25rem;
  font-family: var(--font-mono); font-size: var(--fs-xs);
  color: var(--text-faint); letter-spacing: 0.2em;
}
.project__year { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--accent); letter-spacing: 0.2em; text-transform: uppercase; }
.project__name { font-size: var(--fs-h3); margin: 0.5rem 0 0.35rem; }
.project__tagline { color: var(--text); font-weight: 500; margin-bottom: 0.9rem; }
.project__blurb { color: var(--text-soft); font-size: var(--fs-sm); margin-bottom: 1.25rem; max-width: 52ch; }
.project__stack { display: flex; flex-wrap: wrap; gap: 0.4rem; margin-bottom: 1.35rem; }
.project__stack .chip { font-size: var(--fs-xs); padding: 0.25rem 0.55rem; }
.project__actions { display: flex; gap: 0.75rem; flex-wrap: wrap; }
.project__link {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-family: var(--font-mono); font-size: var(--fs-sm);
  color: var(--text-soft); border-bottom: 1px solid transparent; padding-bottom: 2px;
  transition: color var(--dur-fast) var(--ease-out-expo), border-color var(--dur-fast) var(--ease-out-expo);
}
.project__link:hover { color: var(--accent); border-color: var(--accent); }
.project__link .live-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 8px var(--accent-glow); animation: pulse 2s infinite; }

/* Diagram frame */
.project__figure {
  position: relative;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background:
    linear-gradient(0deg, var(--bg-1), var(--bg-1)),
    repeating-linear-gradient(0deg, transparent, transparent 23px, rgba(255,255,255,0.02) 23px, rgba(255,255,255,0.02) 24px),
    repeating-linear-gradient(90deg, transparent, transparent 23px, rgba(255,255,255,0.02) 23px, rgba(255,255,255,0.02) 24px);
  aspect-ratio: 4 / 3;
  overflow: hidden;
}
.project__figure svg { width: 100%; height: 100%; display: block; }
.project__figure-label {
  position: absolute; bottom: 0; left: 0; right: 0;
  display: flex; justify-content: space-between; align-items: center;
  padding: 0.5rem 0.75rem;
  border-top: 1px solid var(--hairline);
  font-family: var(--font-mono); font-size: 0.68rem; letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--text-faint);
  background: rgba(8,9,11,0.7);
  backdrop-filter: blur(4px);
}
.project__figure-detail {
  color: var(--accent);
  text-transform: none;
  letter-spacing: 0.02em;
  font-family: var(--font-body);
  font-size: 0.72rem;
  opacity: 0.9;
  min-height: 1em;
  text-align: right;
  max-width: 52%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ---- Animated diagram primitives ---- */
/* Edges draw in via stroke-dashoffset */
.dgm-edge {
  stroke: var(--accent-dim); stroke-width: 1.6; fill: none;
  stroke-dasharray: var(--len, 300); stroke-dashoffset: var(--len, 300);
  transition: stroke-dashoffset 1.1s var(--ease-in-out-quint);
}
.draw .dgm-edge { stroke-dashoffset: 0; }

/* Nodes stagger in */
.dgm-node {
  fill: var(--bg-2); stroke: var(--hairline-strong); stroke-width: 1;
  opacity: 0; transform: scale(0.88); transform-box: fill-box; transform-origin: center;
  transition: opacity 0.5s var(--ease-out-expo), transform 0.5s var(--ease-spring), stroke 0.3s, filter 0.3s;
}
.draw .dgm-node { opacity: 1; transform: scale(1); }
.dgm-node--accent { stroke: var(--accent); }

/* Hover glow on node groups */
.dgm-nodeg { cursor: pointer; }
.dgm-nodeg:hover .dgm-node { stroke: var(--accent-bright); filter: drop-shadow(0 0 8px var(--accent-glow)); }

/* Key node continuous pulse (on-chain / live users) */
.dgm-keypulse {
  transform-box: fill-box; transform-origin: center;
  animation: none;
}
.draw .dgm-keypulse { animation: keypulse 2.4s ease-in-out infinite; }

/* Labels fade in */
.dgm-lbl {
  fill: var(--text-soft); font-family: var(--font-mono); font-size: 11px;
  opacity: 0; transition: opacity 0.6s var(--ease-out-expo) 0.3s;
}
.dgm-lbl--bold { fill: var(--text); font-size: 13px; font-weight: 700; }
.dgm-lbl--sm { font-size: 9.5px; fill: var(--text-mute); }
.draw .dgm-lbl { opacity: 1; }
.dgm-sub { fill: var(--text-mute); font-family: var(--font-mono); font-size: 9.5px; opacity: 0; transition: opacity 0.6s var(--ease-out-expo) 0.35s; }
.draw .dgm-sub { opacity: 1; }
.dgm-caption { fill: var(--text-mute); font-family: var(--font-mono); font-size: 9px; opacity: 0; transition: opacity 0.6s var(--ease-out-expo) 0.5s; }
.draw .dgm-caption { opacity: 1; }

/* Flowing dashes — appear after edge draws in (1.2s delay) */
.dgm-flow {
  fill: none; stroke: var(--accent); stroke-width: 1.6;
  stroke-dasharray: 3 9; stroke-linecap: round;
  opacity: 0;
}
.draw .dgm-flow {
  opacity: 0.75;
  animation: flowDash 1.1s linear 1.2s infinite;
}

/* Data packet */
.dgm-packet { fill: var(--accent-bright); filter: drop-shadow(0 0 6px var(--accent)); }

/* Anomaly pulse dots */
.dgm-pulse-dot { fill: var(--accent); animation: none; }
.draw .dgm-pulse-dot { animation: pulseDot 1.8s ease-in-out infinite; }

/* ---- Skill Rail ---- */
.projects-rail-wrap {
  display: grid;
  grid-template-columns: 200px 1fr;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  align-items: start;
}
.skill-rail {
  position: sticky;
  top: calc(var(--nav-h) + 1.5rem);
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  padding: 1.1rem 1rem;
  background: rgba(255,255,255,0.012);
  backdrop-filter: blur(6px);
}
.skill-rail__head {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-mute);
  margin-bottom: 0.85rem;
  padding-bottom: 0.6rem;
  border-bottom: 1px solid var(--hairline);
}
.skill-rail__chips { display: flex; flex-direction: column; gap: 0; }
.skill-rail__chip {
  display: flex; align-items: center; gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--text-faint);
  padding: 0.3rem 0;
  transition: color 0.35s var(--ease-out-expo), opacity 0.35s var(--ease-out-expo);
  cursor: default;
  white-space: nowrap;
}
.skill-rail__led {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--text-faint);
  flex-shrink: 0;
  transition: background 0.35s var(--ease-out-expo), box-shadow 0.35s var(--ease-out-expo);
}
.skill-rail__chip--on {
  color: var(--accent);
}
.skill-rail__chip--on .skill-rail__led {
  background: var(--accent);
  box-shadow: 0 0 8px var(--accent-glow);
}
.skill-rail__chip--dim {
  opacity: 0.25;
}
.projects-cards {
  display: grid;
  gap: clamp(1.5rem, 4vw, 2.5rem);
}

/* ---------------- Contact ---------------- */
.section--contact { text-align: left; }
.contact__title { font-size: var(--fs-h2); margin-bottom: 1.25rem; }
.contact__lead { color: var(--text-soft); font-size: var(--fs-lead); max-width: 46ch; margin-bottom: 2.5rem; }
.contact__grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 1px; background: var(--hairline); border: 1px solid var(--hairline); }
.contact__card {
  background: var(--bg); padding: 1.5rem;
  display: flex; flex-direction: column; gap: 0.4rem;
  position: relative; transition: background var(--dur) var(--ease-out-expo);
}
.contact__card:hover { background: var(--bg-1); }
.contact__card .label { font-family: var(--font-mono); font-size: var(--fs-xs); letter-spacing: 0.2em; text-transform: uppercase; color: var(--text-mute); }
.contact__card .value { color: var(--text); font-weight: 500; word-break: break-word; }
.contact__card:hover .value { color: var(--accent); }
.contact__card .arrow { position: absolute; top: 1.25rem; right: 1.25rem; color: var(--text-faint); transition: transform var(--dur-fast) var(--ease-spring), color var(--dur-fast); }
.contact__card:hover .arrow { transform: translate(3px,-3px); color: var(--accent); }
.contact__card.is-primary { border-left: 2px solid var(--accent); }
.contact__card .needs-input { color: var(--text-faint); font-size: var(--fs-xs); font-family: var(--font-mono); }

/* ---------------- Modal ---------------- */
.modal { position: fixed; inset: 0; z-index: var(--z-modal); display: grid; place-items: center; padding: 1.25rem; visibility: hidden; }
.modal.is-open { visibility: visible; }
.modal__backdrop { position: absolute; inset: 0; background: rgba(2,3,4,0.75); backdrop-filter: blur(6px); opacity: 0; transition: opacity var(--dur) var(--ease-out-expo); }
.modal.is-open .modal__backdrop { opacity: 1; }
.modal__panel {
  position: relative; z-index: 2;
  width: min(760px, 100%); max-height: 88vh; overflow-y: auto;
  background: var(--bg-1); border: 1px solid var(--hairline-strong);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 4vw, 2.75rem);
  transform: translateY(24px) scale(0.98); opacity: 0;
  transition: transform var(--dur) var(--ease-out-expo), opacity var(--dur) var(--ease-out-expo);
}
.modal.is-open .modal__panel { transform: none; opacity: 1; }
.modal__close {
  position: absolute; top: 0.75rem; right: 0.9rem;
  background: none; border: none; color: var(--text-mute);
  font-size: 1.8rem; line-height: 1; cursor: pointer; padding: 0.25rem 0.5rem;
  transition: color var(--dur-fast), transform var(--dur-fast) var(--ease-spring);
}
.modal__close:hover { color: var(--accent); transform: rotate(90deg); }
.modal__year { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--accent); letter-spacing: 0.2em; text-transform: uppercase; }
.modal__title { font-size: var(--fs-h3); margin: 0.4rem 0 0.75rem; }
.modal__section { margin-top: 1.5rem; }
.modal__section h4 { font-family: var(--font-mono); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.2em; color: var(--text-mute); margin-bottom: 0.6rem; }
.modal__section p { color: var(--text-soft); font-size: var(--fs-sm); }
.modal__list { list-style: none; display: grid; gap: 0.6rem; }
.modal__list li { position: relative; padding-left: 1.4rem; color: var(--text-soft); font-size: var(--fs-sm); }
.modal__list li::before { content: "▹"; position: absolute; left: 0; color: var(--accent); }
.modal__actions { display: flex; gap: 0.75rem; margin-top: 1.75rem; flex-wrap: wrap; }

/* ---------------- Keyframes ---------------- */
@keyframes pulse { 0%,100% { box-shadow: 0 0 0 0 var(--accent-glow); } 50% { box-shadow: 0 0 0 6px transparent; } }
@keyframes blink { 0%,50% { opacity: 1; } 50.01%,100% { opacity: 0; } }
@keyframes scrollLine { 0% { transform: translateX(-100%);} 100% { transform: translateX(250%);} }
@keyframes flowDash { to { stroke-dashoffset: -24; } }
@keyframes keypulse { 0%,100% { filter: drop-shadow(0 0 0 var(--accent-glow)); } 50% { filter: drop-shadow(0 0 14px var(--accent-glow)); } }
@keyframes pulseDot { 0%,100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.5; transform: scale(1.5); } }
