/* ==========================================================================
   shariq.ai — stylesheet
   --------------------------------------------------------------------------
   Design language: light canvas, large rounded cards, monospace micro-labels,
   centred section headings, generous vertical rhythm. Dark mode is a full
   inversion rather than an afterthought.

   Sections:
     1. Design tokens (colours, type, spacing)
     2. Reset & base elements
     3. Layout primitives
     4. Header / navigation
     5. Buttons, tags, links
     6. Hero
     7. Cards & grids
     8. Timeline
     9. Now / log entries
    10. Projects grid + filters
    11. Footer
    12. Utilities, motion, print
   ========================================================================== */


/* ==========================================================================
   1. DESIGN TOKENS
   ========================================================================== */

:root {
  --font-sans: "Figtree", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
    Helvetica, Arial, sans-serif;
  --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, "SF Mono",
    Menlo, Consolas, monospace;

  /* Fluid type scale */
  --fs-xs: 0.6875rem;
  --fs-sm: 0.875rem;
  --fs-base: clamp(0.9375rem, 0.9rem + 0.2vw, 1.0625rem);
  --fs-md: clamp(1rem, 0.95rem + 0.3vw, 1.125rem);
  --fs-lg: clamp(1.125rem, 1rem + 0.6vw, 1.375rem);
  --fs-xl: clamp(1.375rem, 1.1rem + 1.2vw, 1.875rem);
  --fs-2xl: clamp(1.875rem, 1.4rem + 2.2vw, 3rem);
  --fs-3xl: clamp(2.5rem, 1.5rem + 4.6vw, 4.75rem);

  /* Spacing */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4.5rem;
  --sp-9: 7rem;
  --sp-10: 9rem;

  /* Structure */
  --measure: 66ch;
  --container: 1180px;
  --container-narrow: 720px;
  --radius-sm: 8px;
  --radius: 16px;
  --radius-lg: 24px;
  --radius-xl: 32px;

  /* Custom curves. The built-in CSS easings are too weak to read as
     intentional. Never ease-in on UI — it delays the first frame, which is
     exactly the moment the eye is watching most closely. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --ease: var(--ease-out);

  /* Durations matched to what each thing is doing. Everything interactive
     stays under 300ms; only content entering on scroll runs longer. */
  --dur-press: 140ms;
  --dur-fast: 180ms;
  --dur: 220ms;
  --dur-reveal: 480ms;
}

/* ---- Light theme (default) ---- */
:root,
[data-theme="light"] {
  color-scheme: light;

  --bg: #ffffff;
  --bg-subtle: #fafaf8;
  --surface: #f4f4f1;
  --surface-hover: #ecece8;
  --border: #e6e6e0;
  --border-strong: #d4d4cc;

  --text: #0c0d0e;
  --text-muted: #5f656d;
  --text-faint: #8b9099;

  --accent: #0f766e;
  --accent-strong: #115e56;
  --accent-soft: rgba(15, 118, 110, 0.08);
  --accent-line: rgba(15, 118, 110, 0.28);

  /* Solid dark used for the hero card and primary buttons */
  --ink: #0b0c0d;
  --on-ink: #ffffff;

  --btn-fill: #0c0d0e;
  --btn-ink: #ffffff;
  --btn-chip: rgba(255, 255, 255, 0.16);

  --shadow: 0 1px 2px rgba(12, 13, 14, 0.04),
    0 12px 32px rgba(12, 13, 14, 0.06);
}

/* ---- Dark theme ---- */
[data-theme="dark"] {
  color-scheme: dark;

  --bg: #0a0b0c;
  --bg-subtle: #0e0f11;
  --surface: #151719;
  --surface-hover: #1b1e21;
  --border: #23262a;
  --border-strong: #32363c;

  --text: #f2f3f4;
  --text-muted: #9aa1aa;
  --text-faint: #6b727b;

  --accent: #5eead4;
  --accent-strong: #2dd4bf;
  --accent-soft: rgba(94, 234, 212, 0.1);
  --accent-line: rgba(94, 234, 212, 0.3);

  --ink: #101315;
  --on-ink: #ffffff;

  --btn-fill: #f2f3f4;
  --btn-ink: #0a0b0c;
  --btn-chip: rgba(10, 11, 12, 0.14);

  --shadow: 0 1px 2px rgba(0, 0, 0, 0.5), 0 12px 32px rgba(0, 0, 0, 0.34);
}


/* ==========================================================================
   2. RESET & BASE
   ========================================================================== */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 6rem;
}

body {
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  overflow-x: hidden;
}

img,
svg,
video {
  display: block;
  max-width: 100%;
  height: auto;
}

h1,
h2,
h3,
h4 {
  line-height: 1.12;
  letter-spacing: -0.028em;
  font-weight: 500;
  text-wrap: balance;
}

h1 { font-size: var(--fs-3xl); }
h2 { font-size: var(--fs-2xl); }
h3 { font-size: var(--fs-lg); }
h4 { font-size: var(--fs-md); }

p { text-wrap: pretty; }

a {
  color: inherit;
  text-decoration: none;
}

ul, ol {
  padding: 0;
  list-style: none;
}

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

::selection {
  background: var(--text);
  color: var(--bg);
}


/* ==========================================================================
   3. LAYOUT PRIMITIVES
   ========================================================================== */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--sp-4);
}

@media (min-width: 720px) {
  .container { padding-inline: var(--sp-6); }
}

.narrow { max-width: var(--container-narrow); }

main { flex: 1 0 auto; }

.section { padding-block: var(--sp-8); }

@media (min-width: 900px) {
  .section { padding-block: var(--sp-9); }
}

/* Centred section heading block — mono eyebrow, large title, centred lede */
.section-head {
  text-align: center;
  max-width: 740px;
  margin-inline: auto;
  margin-bottom: var(--sp-7);
}

.eyebrow {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 400;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: var(--sp-4);
}

.lede {
  color: var(--text-muted);
  font-size: var(--fs-md);
  max-width: var(--measure);
  margin-top: var(--sp-4);
}

.section-head .lede,
.center .lede {
  margin-inline: auto;
}

.center .lede { margin-bottom: var(--sp-6); }

.stack > * + * { margin-top: var(--sp-4); }

.prose {
  max-width: var(--measure);
  color: var(--text-muted);
  font-size: var(--fs-md);
}

.prose p + p { margin-top: var(--sp-4); }

.prose strong {
  color: var(--text);
  font-weight: 600;
}

.link {
  color: var(--text);
  border-bottom: 1px solid var(--accent-line);
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}

.link:hover {
  color: var(--accent);
  border-bottom-color: var(--accent);
}


/* ==========================================================================
   4. HEADER / NAVIGATION
   ========================================================================== */

.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: var(--sp-4);
  z-index: 100;
  padding: var(--sp-2) var(--sp-4);
  background: var(--btn-fill);
  color: var(--btn-ink);
  border-radius: 999px;
  font-weight: 600;
  font-size: var(--fs-sm);
  transform: translateY(-200%);
  transition: transform var(--dur) var(--ease);
}

.skip-link:focus { transform: translateY(0); }

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 84%, transparent);
  backdrop-filter: saturate(160%) blur(14px);
  -webkit-backdrop-filter: saturate(160%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--dur) var(--ease);
}

.site-header[data-scrolled="true"] { border-bottom-color: var(--border); }

.site-header .container {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  height: 4.5rem;
}

.wordmark {
  display: inline-flex;
  align-items: baseline;
  gap: 0.4rem;
  font-weight: 600;
  font-size: 1.0625rem;
  letter-spacing: -0.02em;
  white-space: nowrap;
}

.wordmark .dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
  display: inline-block;
  transform: translateY(-1px);
}

.wordmark .tld {
  color: var(--text-faint);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 400;
}

.nav {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}

.nav-links {
  display: none;
  align-items: center;
  gap: var(--sp-1);
  background: var(--surface);
  border-radius: 999px;
  padding: 4px;
}

@media (min-width: 760px) {
  .nav-links { display: flex; }
}

.nav-link {
  padding: 0.4rem 0.9rem;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--text-muted);
  border-radius: 999px;
  transition: color var(--dur) var(--ease),
    background-color var(--dur) var(--ease);
}

.nav-link:hover { color: var(--text); }

.nav-link[aria-current="page"] {
  color: var(--text);
  background: var(--bg);
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.06);
}

.icon-btn {
  display: inline-grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: transparent;
  color: var(--text-muted);
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    background-color var(--dur-fast) var(--ease),
    transform var(--dur-press) var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .icon-btn:hover {
    color: var(--text);
    border-color: var(--border-strong);
    background: var(--surface);
  }
}

.icon-btn:active { transform: scale(0.94); }

.icon-btn svg { width: 17px; height: 17px; }

.menu-btn { display: inline-grid; }

@media (min-width: 760px) {
  .menu-btn { display: none; }
}

[data-theme="dark"] .icon-sun { display: block; }
[data-theme="dark"] .icon-moon { display: none; }
[data-theme="light"] .icon-sun { display: none; }
[data-theme="light"] .icon-moon { display: block; }
:root:not([data-theme]) .icon-sun { display: none; }
:root:not([data-theme]) .icon-moon { display: block; }

.mobile-menu {
  display: none;
  border-top: 1px solid var(--border);
  background: var(--bg);
  padding: var(--sp-3) 0 var(--sp-5);
}

.mobile-menu[data-open="true"] { display: block; }

@media (min-width: 760px) {
  .mobile-menu[data-open="true"] { display: none; }
}

.mobile-menu a {
  display: block;
  padding: var(--sp-3) 0;
  font-size: var(--fs-md);
  font-weight: 500;
  color: var(--text-muted);
  border-bottom: 1px solid var(--border);
}

.mobile-menu a:last-child { border-bottom: 0; }
.mobile-menu a[aria-current="page"] { color: var(--accent); }


/* ==========================================================================
   5. BUTTONS, TAGS, LINKS
   ========================================================================== */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  padding: 0.5rem 0.65rem 0.5rem 1.25rem;
  min-height: 2.875rem;
  border-radius: 999px;
  border: 1px solid transparent;
  font-size: var(--fs-sm);
  font-weight: 600;
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
  transition: transform var(--dur-press) var(--ease),
    background-color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}

/* Buttons with no trailing icon get symmetrical padding */
.btn:not(:has(svg)) { padding-inline: 1.25rem; }

/* Scale, not nudge. Pressing should feel like the surface gave way under the
   finger — instant physical confirmation the interface heard you. */
.btn:active { transform: scale(0.97); }

.btn-primary {
  background: var(--btn-fill);
  color: var(--btn-ink);
}

.btn-primary:hover { background: var(--accent); color: #fff; }

/* The chevron sits in its own rounded chip, inset into the pill */
.btn-primary svg {
  width: 14px;
  height: 14px;
  padding: 7px;
  box-sizing: content-box;
  border-radius: 10px;
  background: var(--btn-chip);
}

.btn-ghost {
  border-color: var(--border-strong);
  color: var(--text);
  padding: 0.6rem 1.25rem;
  gap: 0.5rem;
}

.btn-ghost:hover {
  background: var(--surface);
  border-color: var(--text-faint);
}

.btn-ghost svg { width: 15px; height: 15px; }

/* Solid brand marks read heavier than the stroked icons, so size them down
   slightly to sit level with the others. */
.btn .icon-brand { width: 13px; height: 13px; }

/* Icon-only pill, used for the social profile links. Keeps the action buttons
   and the "where else to find me" links visually distinct, and means adding
   another profile never pushes the row onto a second line. */
.btn-icon {
  padding: 0;
  /* Matches the text buttons' height so the row sits on one baseline. */
  width: 2.875rem;
  height: 2.875rem;
  flex-shrink: 0;
  border-color: var(--border-strong);
  color: var(--text);
}

.btn-icon:hover {
  background: var(--surface);
  border-color: var(--text-faint);
}

.btn-icon .icon-brand { width: 16px; height: 16px; }

.btn-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
}

.center .btn-row { justify-content: center; }

.tag {
  display: inline-flex;
  align-items: center;
  padding: 0.25rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-muted);
  background: var(--bg);
  white-space: nowrap;
}

.tag-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--text);
  transition: color var(--dur-fast) var(--ease);
}

.arrow-link svg {
  width: 14px;
  height: 14px;
  /* Transform, not gap: gap forces layout on every frame, transform is
     composited on the GPU. */
  transition: transform var(--dur-fast) var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .arrow-link:hover { color: var(--accent); }
  .arrow-link:hover svg { transform: translateX(4px); }
}

.section-cta {
  margin-top: var(--sp-6);
  text-align: center;
}


/* ==========================================================================
   6. HERO
   ========================================================================== */

/* Hero: type on the page background, portrait alongside. No panel, no fill. */
.hero { padding-block: var(--sp-7) var(--sp-7); }

@media (min-width: 900px) {
  .hero { padding-block: var(--sp-8) var(--sp-8); }
}

.hero-split {
  display: grid;
  gap: var(--sp-5);
  align-items: center;
}

/* On a phone the portrait sits above the name, kept small so the name and
   role still land near the top of the screen. */
.hero-portrait {
  order: -1;
  margin: 0;
  width: 132px;
}

@media (min-width: 880px) {
  .hero-split {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 0.8fr);
    gap: var(--sp-8);
  }

  .hero-portrait {
    order: 0;
    width: 100%;
    max-width: 300px;
    justify-self: end;
  }
}

/* Source image is 400x400, so it is never displayed above 300px. */
.hero-portrait img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-xl);
  background: var(--surface);
}

.hero-name {
  font-size: var(--fs-3xl);
  font-weight: 500;
  letter-spacing: -0.04em;
  margin-top: var(--sp-5);
  line-height: 1;
}

.hero-bio {
  margin-top: var(--sp-5);
  max-width: 62ch;
  color: var(--text-muted);
  font-size: var(--fs-md);
}

.hero-bio strong {
  color: var(--text);
  font-weight: 600;
}

.hero-actions { margin-top: var(--sp-6); }

.hero-meta {
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}

.hero-meta dt {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--text-faint);
  margin-bottom: var(--sp-2);
}

.hero-meta dd {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--text);
  font-weight: 500;
}

/* Interior page headers (About / Projects / Now / 404) */
.page-header {
  text-align: center;
  max-width: 760px;
  margin-inline: auto;
  padding-block: var(--sp-8) var(--sp-6);
}

.page-title {
  font-size: var(--fs-2xl);
  margin-top: var(--sp-2);
}

.page-header .lede { margin-inline: auto; }

/* Body copy that sits centred on the page but stays left-aligned to read */
.prose-centered {
  margin-inline: auto;
  text-align: left;
}

/* Portrait beside the About intro. Stacks on narrow screens. */
.about-intro {
  display: grid;
  gap: var(--sp-6);
  max-width: 920px;
  margin-inline: auto;
  justify-items: center;
}

@media (min-width: 840px) {
  .about-intro {
    grid-template-columns: 260px 1fr;
    gap: var(--sp-7);
    align-items: start;
    justify-items: stretch;
  }
}

.about-photo {
  margin: 0;
  width: 100%;
  max-width: 240px;
}

/* The source image is 400x400, so it is capped well below that to stay sharp. */
.about-photo img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius-lg);
  background: var(--surface);
}


/* ==========================================================================
   7. CARDS & GRIDS
   ========================================================================== */

.grid {
  display: grid;
  gap: var(--sp-4);
}

.grid-2 { grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(270px, 1fr)); }

.card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--sp-6);
  background: var(--surface);
  border: 1px solid transparent;
  border-radius: var(--radius-lg);
  transition: background-color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease),
    box-shadow var(--dur-fast) var(--ease);
}

.card:hover { background: var(--surface-hover); }

/* A single featured project. Left in a multi-column grid it would sit in one
   slot with dead space beside it, which reads as "something is missing"; sized
   to a comfortable measure and centred, it reads as deliberate. */
.project-solo {
  max-width: 760px;
  margin-inline: auto;
}

/* Touch devices fire :hover on tap and leave it stuck there, so the lift is
   gated to devices with a real pointer. */
@media (hover: hover) and (pointer: fine) {
  .card-link:hover {
    transform: translateY(-3px);
    box-shadow: var(--shadow);
  }

  /* Presses back down from the lifted state. Only meaningful where a hover
     lift exists — on touch there is nothing to press down from. */
  .card-link:active { transform: translateY(-1px); }
}

/* Affordance for a card that links off-site: the title carries a small
   external-link arrow and shifts colour on hover, so it is obvious the whole
   card is clickable rather than only the heading. */
.card-title .ext {
  width: 13px;
  height: 13px;
  display: inline-block;
  vertical-align: -1px;
  margin-left: 6px;
  color: var(--text-faint);
  transition: color var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .card-link:hover .card-title { color: var(--accent); }
  .card-link:hover .card-title .ext {
    color: var(--accent);
    transform: translate(2px, -2px);
  }
}

.card-link .card-title a::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
}

.card-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-3);
}

.card-title {
  font-size: var(--fs-lg);
  font-weight: 600;
  letter-spacing: -0.02em;
}

.card-meta {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-faint);
  white-space: nowrap;
  flex-shrink: 0;
  padding-top: 0.35rem;
}

.card-body {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  flex: 1;
}

.card-body p + p { margin-top: var(--sp-3); }

/* Sub-headings inside a long write-up. Same mono micro-label treatment as the
   section eyebrows, so a detailed card stays scannable instead of becoming a
   wall of paragraphs. */
.card-body h4 {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--text-faint);
  margin-top: var(--sp-6);
  margin-bottom: var(--sp-3);
}

.card-body > h4:first-child { margin-top: 0; }

/* Aside within a card — e.g. why there's no public source link */
.note-line {
  color: var(--text-faint);
  border-left: 2px solid var(--border-strong);
  padding-left: var(--sp-4);
}

.card-body strong {
  color: var(--text);
  font-weight: 600;
}

.card-foot {
  margin-top: var(--sp-5);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
}

.card-links {
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-5);
}

/* "Currently" three-up and skill groups */
.current-card {
  padding: var(--sp-6);
  border-radius: var(--radius-lg);
  background: var(--surface);
}

.current-card h3 {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--text-faint);
  margin-bottom: var(--sp-4);
}

.current-card p {
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

.current-card p strong {
  color: var(--text);
  font-weight: 600;
}

.current-card p + p { margin-top: var(--sp-2); }

.status {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-faint);
  margin-left: auto;
}

.status::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--text-faint);
}

.status-active::before { background: var(--accent); }


/* ==========================================================================
   8. TIMELINE
   ========================================================================== */

.timeline {
  position: relative;
  padding-left: var(--sp-5);
  max-width: 880px;
  margin-inline: auto;
}

.timeline::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.6rem;
  bottom: 0.6rem;
  width: 1px;
  background: var(--border);
}

.timeline-item {
  position: relative;
  padding-bottom: var(--sp-7);
}

.timeline-item:last-child { padding-bottom: 0; }

.timeline-item::before {
  content: "";
  position: absolute;
  left: calc(-1 * var(--sp-5) - 4px);
  top: 0.5rem;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--bg);
  border: 1.5px solid var(--border-strong);
}

.timeline-item[data-current="true"]::before {
  background: var(--accent);
  border-color: var(--accent);
}

.timeline-date {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-faint);
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.timeline-title {
  font-size: var(--fs-lg);
  font-weight: 600;
  margin-top: var(--sp-2);
  letter-spacing: -0.02em;
}

.timeline-org {
  color: var(--accent);
  font-size: var(--fs-sm);
  font-weight: 500;
  margin-top: 0.2rem;
}

.timeline-body {
  margin-top: var(--sp-3);
  color: var(--text-muted);
  font-size: var(--fs-sm);
  max-width: var(--measure);
}

.timeline-body ul {
  margin-top: var(--sp-3);
  display: grid;
  gap: var(--sp-2);
}

.timeline-body li {
  position: relative;
  padding-left: var(--sp-4);
}

.timeline-body li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.68em;
  width: 6px;
  height: 1px;
  background: var(--text-faint);
}


/* ==========================================================================
   9. NOW / LOG ENTRIES
   ========================================================================== */

@media (min-width: 840px) {
  }


/* ==========================================================================
   10. PROJECTS FILTERS
   ========================================================================== */

.filters {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-7);
}

.filter-btn {
  padding: 0.45rem 1rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  background: var(--bg);
  color: var(--text-muted);
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  cursor: pointer;
  /* Never `all` — it animates properties you didn't intend and costs layout. */
  transition: color var(--dur-fast) var(--ease),
    background-color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    transform var(--dur-press) var(--ease);
}

.filter-btn:active { transform: scale(0.97); }

.filter-btn:hover {
  color: var(--text);
  border-color: var(--border-strong);
}

.filter-btn[aria-pressed="true"] {
  background: var(--btn-fill);
  border-color: var(--btn-fill);
  color: var(--btn-ink);
}

.project-card[hidden] { display: none; }

.empty-state {
  padding: var(--sp-7) 0;
  text-align: center;
  color: var(--text-faint);
  font-size: var(--fs-sm);
}


/* ==========================================================================
   11. FOOTER
   ========================================================================== */

/* The footer's .container doubles as the rounded card: the footer supplies the
   outer gutter, the container's own inline padding becomes the card's padding. */
.site-footer {
  margin-top: var(--sp-8);
  flex-shrink: 0;
  padding-inline: var(--sp-4);
  padding-bottom: var(--sp-5);
}

@media (min-width: 720px) {
  .site-footer { padding-inline: var(--sp-6); }
}

.site-footer > .container {
  background: var(--surface);
  border-radius: var(--radius-xl);
  padding: clamp(1.75rem, 4vw, 3.25rem);
}

.footer-grid {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: 1fr;
}

@media (min-width: 760px) {
  .footer-grid {
    grid-template-columns: 1.6fr 1fr 1fr;
    gap: var(--sp-7);
  }
}

.footer-tagline {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  max-width: 34ch;
  margin-top: var(--sp-3);
}

.footer-col h4 {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  font-weight: 400;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--text-faint);
  margin-bottom: var(--sp-4);
}

.footer-col li + li { margin-top: var(--sp-2); }

.footer-col a {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  transition: color var(--dur) var(--ease);
}

.footer-col a:hover { color: var(--accent); }

.footer-bottom {
  margin-top: var(--sp-7);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3);
  justify-content: space-between;
  align-items: center;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  color: var(--text-faint);
}


/* ==========================================================================
   12. UTILITIES, MOTION, PRINT
   ========================================================================== */

.visually-hidden {
  position: absolute !important;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.text-muted { color: var(--text-muted); }
.mono { font-family: var(--font-mono); }
.center { text-align: center; }

.error-page {
  display: grid;
  place-items: center;
  text-align: center;
  padding-block: var(--sp-9);
  min-height: 55vh;
}

.error-code {
  font-family: var(--font-mono);
  font-size: var(--fs-2xl);
  color: var(--text-faint);
  letter-spacing: 0.1em;
  margin-bottom: var(--sp-3);
}

.js .reveal {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity var(--dur-reveal) var(--ease),
    transform var(--dur-reveal) var(--ease);
}

.js .reveal.is-visible {
  opacity: 1;
  transform: none;
}

/* A revealed grid doesn't fade as one block — its children cascade instead,
   which reads as content arriving rather than a panel switching on. The grid
   itself is therefore exempt from the fade above. */
.js .reveal.grid {
  opacity: 1;
  transform: none;
  transition: none;
}

.js .reveal.grid > * { opacity: 0; }

/* The entrance is a keyframe animation, not a transition, for one specific
   reason: setting `transition` here would overwrite the card's own hover
   transition and break the lift. An animation runs alongside it instead.
   `backwards` fill covers the stagger delay; crucially there is no `forwards`,
   so once it finishes the animation stops asserting `transform` and hover
   takes over cleanly. A one-shot entrance is also the case where keyframes
   are the right tool — nothing interrupts it, and it runs off the main
   thread. */
.js .reveal.grid.is-visible > * {
  opacity: 1;
  animation: reveal-rise var(--dur-reveal) var(--ease) backwards;
}

@keyframes reveal-rise {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Short delays only. Past roughly 80ms a step this stops reading as a cascade
   and starts reading as a slow page. */
.js .reveal.grid.is-visible > *:nth-child(2) { animation-delay: 60ms; }
.js .reveal.grid.is-visible > *:nth-child(3) { animation-delay: 120ms; }
.js .reveal.grid.is-visible > *:nth-child(4) { animation-delay: 180ms; }
.js .reveal.grid.is-visible > *:nth-child(5) { animation-delay: 240ms; }
.js .reveal.grid.is-visible > *:nth-child(6) { animation-delay: 300ms; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  /* Reduced motion means fewer and gentler animations, not none. Opacity and
     colour still carry meaning and stay; movement is what causes trouble, so
     transforms are what go. */
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-property: opacity, color, background-color, border-color !important;
    transition-duration: 200ms !important;
  }

  .js .reveal,
  .js .reveal.grid > *,
  .js .reveal.grid.is-visible > * {
    opacity: 1;
    transform: none;
    animation: none !important;
    transition-delay: 0ms !important;
  }
}

@media print {
  .site-header,
  .site-footer,
  .btn-row,
  .filters { display: none !important; }

  body { background: #fff; color: #000; font-size: 11pt; }

  .section { padding-block: 1rem; }
  a { text-decoration: underline; }
}
