/* sethgeib.com — clean static rebuild.
   Mobile-first; expands at 720px (tablet) and 1024px (desktop).
   Aesthetic: dark, high-contrast, typography-led — matching the Claude
   Design visual brief at redesign.html (local-only). */

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

:root {
  --bg:           #0a0a0a;
  --bg-elev:      #141414;
  --bg-elev-2:    #1c1c1c;
  --fg:           #f5f5f5;
  --fg-muted:     #9ca3af;
  --fg-faint:     #6b7280;
  --accent:       #6366f1;
  --accent-soft:  #818cf8;
  --line:         #2a2a2a;
  --live:         #22c55e;

  --font-sans: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  --font-mono: ui-monospace, "SF Mono", Menlo, Consolas, monospace;

  --gutter: clamp(1.25rem, 5vw, 3rem);
  --max-w: 1200px;
  --section-y: clamp(3rem, 8vw, 6rem);

  color-scheme: dark;
}

html {
  -webkit-text-size-adjust: 100%;
  /* Match body bg so any overscroll-bounce at top/bottom doesn't reveal
     the aurora behind the sticky topbar — the visible band stays the
     same dark page color. */
  background: var(--bg);
  /* Disable elastic overscroll on the document so pull-down at top + tug
     up at bottom don't open a gap between the sticky topbar and the
     viewport edge. */
  overscroll-behavior-y: none;
  overflow-x: hidden;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 17px;
  line-height: 1.6;
  /* Transparent so the html bg (set above) shows through, and the
     body::before aurora (z-index: -1) paints over it without being
     covered by an opaque body box. Don't reintroduce a solid bg here. */
  background: transparent;
  color: var(--fg);
  position: relative;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

/* Aurora hero backdrop — sits behind everything, fades from full opacity
   at the top to transparent at 50vh, lets the dark page bg take over
   from there down. The topbar (with its backdrop-blur) reads as frosted
   glass over the image. */
body::before {
  content: "";
  position: fixed;
  /* Overshoot the viewport by the blur radius on every side so the
     filter doesn't reveal a soft un-blurred edge at the mask boundary. */
  top: -30px;
  left: -30px;
  right: -30px;
  height: calc(65vh + 60px);
  background-image: url("../assets/images/aurora_bg.jpg");
  background-size: cover;
  background-position: center center;
  background-repeat: no-repeat;
  filter: blur(9px);
  pointer-events: none;
  z-index: -1;
  -webkit-mask-image: linear-gradient(to bottom, black 0%, black 25%, transparent 100%);
          mask-image: linear-gradient(to bottom, black 0%, black 25%, transparent 100%);
}

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

a { color: var(--fg); text-decoration: none; transition: color 120ms ease; }
a:hover { color: var(--accent-soft); }

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

h1, h2, h3, h4, h5, h6, p { margin: 0 0 1em; }

/* ---------- Topbar ---------- */

.topbar {
  position: sticky;
  top: 0;
  z-index: 50;
  background: rgba(10, 10, 10, 0.85);
  backdrop-filter: saturate(150%) blur(10px);
  -webkit-backdrop-filter: saturate(150%) blur(10px);
  border-bottom: 1px solid var(--line);
  animation: hero-arrive 1000ms cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: 250ms; /* Staggers hero fade-in to start after the topbar finishes its own fade-in. */
}

.topbar__inner {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 0.875rem var(--gutter);
  display: flex;
  align-items: center;
  gap: 1.5rem;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-weight: 700;
  font-size: 0.95rem;
  white-space: nowrap;
}
.brand__name {
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.brand__avatar {
  width: 2rem;
  height: 2rem;
  border-radius: 25%;
  object-fit: cover;
  border: 1px solid var(--line);
  background: var(--bg-elev-2);
}

.topbar__cta { margin-left: auto; display: flex; align-items: center; gap: 0.75rem; }

/* Narrow-mobile (< 360px): the brand + CTA don't fit on one line, so
   stack them. Brand centers, CTA becomes full-width row underneath. */
@media (max-width: 359px) {
  .topbar__inner {
    flex-direction: column;
    align-items: stretch;
    gap: 0.75rem;
  }
  .brand {
    justify-content: center;
    width: 100%;
  }
  .topbar__cta {
    margin-left: 0;
    width: 100%;
    justify-content: center;
  }
  /* Dropdown owns the row width — the trigger inside it goes full-width. */
  .dropdown { width: 100%; }
  .dropdown__trigger { width: 100%; }
}

.status-pill {
  display: none;
  align-items: center;
  gap: 0.5rem;
  /* Match the .btn vertical padding so the pill and Get-in-touch button
     are the same height side-by-side. */
  padding: 0.75rem 1rem;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.78rem;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  line-height: 1;
}
/* When rendered as a button (clickable, opens chat), strip the default
   browser button styling + make the cursor + hover affordances match
   the rest of the UI. */
.status-pill--button {
  font-family: inherit;
  cursor: pointer;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease,
              transform 150ms ease, box-shadow 150ms ease;
}
.status-pill--button:hover {
  background: var(--bg-elev-2);
  border-color: var(--fg);
  color: var(--fg);
  transform: translateY(-2px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}
.status-pill--button:active { transform: translateY(0); box-shadow: none; }
.status-pill--button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.status-pill__dot {
  width: 0.55rem; height: 0.55rem;
  background: var(--live);
  border-radius: 50%;
  box-shadow: 0 0 0 0 rgba(34, 197, 94, 0.6);
  animation: pulse 1.8s ease-out infinite;
}
@keyframes pulse {
  0%   { box-shadow: 0 0 0 0   rgba(34, 197, 94, 0.6); }
  70%  { box-shadow: 0 0 0 8px rgba(34, 197, 94, 0); }
  100% { box-shadow: 0 0 0 0   rgba(34, 197, 94, 0); }
}

/* ---------- Buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.75rem 1.25rem;
  font-weight: 600;
  font-size: 0.9rem;
  /* All buttons render uppercase for a uniform, decisive CTA voice. */
  text-transform: uppercase;
  letter-spacing: 0.06em;
  /* Pointer cursor so <button class="btn"> reads as clickable like its
     <a class="btn"> siblings — browsers don't apply pointer to button
     elements by default. */
  cursor: pointer;
  border-radius: 0.55rem;
  border: 1px solid transparent;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease,
              transform 150ms ease, box-shadow 150ms ease;
  white-space: nowrap;
}
/* Subtle hover lift across all .btn instances — applies to primary,
   ghost, dropdown trigger, the bottom CTA pair, etc. translateY-1px
   plus a soft drop shadow reads as "responsive to interaction" without
   feeling cartoony. Reduced-motion users get color-only feedback below. */
.btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}
.btn:active { transform: translateY(0); box-shadow: none; }
.btn__suffix { opacity: 0.65; font-weight: 500; }
.btn--primary { background: var(--accent); color: var(--fg); }
.btn--primary:hover { background: var(--accent-soft); color: var(--fg); }
.btn--ghost { background: var(--bg); color: var(--fg); border-color: var(--line); }
.btn--ghost:hover { background: var(--bg-elev); border-color: var(--fg-muted); color: var(--fg); }
.btn--large { padding: 1rem 1.75rem; font-size: 1.05rem; }

/* ---------- Dropdown (Get-in-touch menu) ---------- */

.dropdown {
  position: relative;
  display: inline-block;
}
.dropdown__trigger {
  cursor: pointer;
}
.dropdown__trigger span[aria-hidden] {
  font-size: 0.7em;
  margin-left: 0.1rem;
  transition: transform 150ms ease;
}
.dropdown.is-open .dropdown__trigger span[aria-hidden] {
  transform: rotate(180deg);
}

.dropdown__menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  right: 0;
  min-width: 16rem;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 0.7rem;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.5);
  padding: 0.4rem;
  display: none;
  z-index: 60;
}
/* Invisible bridge that fills the visual gap between trigger and menu —
   keeps the hover state continuous when the cursor moves from trigger
   into the menu. Sized at 1rem (twice the 0.5rem gap) so it overlaps
   into the trigger's hover zone — important because .btn:hover lifts
   the trigger 3px, which would otherwise open a 3px unhovered strip
   between lifted-trigger-bottom and the original bridge-top. */
.dropdown__menu::before {
  content: "";
  position: absolute;
  top: -1rem;
  left: 0;
  right: 0;
  height: 1rem;
}

/* Open on hover (desktop with pointer:fine) OR when explicitly toggled
   (click/tap, which also covers touch devices). */
@media (hover: hover) and (pointer: fine) {
  .dropdown:hover .dropdown__menu { display: block; }
  .dropdown:hover .dropdown__trigger span[aria-hidden] { transform: rotate(180deg); }
}
.dropdown.is-open .dropdown__menu { display: block; }

.dropdown__item {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.65rem 0.75rem;
  border-radius: 0.5rem;
  text-decoration: none;
  color: var(--fg);
  font-size: 0.9rem;
  width: 100%;
  background: transparent;
  border: 0;
  cursor: pointer;
  text-align: left;
  transition: background 120ms ease;
}
.dropdown__item:hover,
.dropdown__item:focus-visible {
  background: var(--bg-elev-2);
  outline: 0;
}
.dropdown__icon {
  display: inline-grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  border-radius: 0.4rem;
  background: var(--bg-elev-2);
  color: var(--accent-soft);
  flex-shrink: 0;
}
.dropdown:hover .dropdown__item .dropdown__icon,
.dropdown.is-open .dropdown__item:hover .dropdown__icon {
  color: var(--accent-soft);
}
.dropdown__label {
  display: block;
  font-weight: 600;
  font-size: 0.95rem;
  margin-bottom: 0.1rem;
}
.dropdown__meta {
  display: block;
  color: var(--fg-muted);
  font-size: 0.8rem;
}

/* ---------- Section base ---------- */

main { max-width: var(--max-w); margin: 0 auto; padding: 0 var(--gutter); }

/* Uniform vertical rhythm between every section. Cards (inside .row-section)
   carry their own internal padding; non-card sections (hero, disciplines,
   cta-close) use the same external rhythm so the gap between any two
   adjacent sections is consistent down the page. */
section {
  padding: clamp(0.5rem, 1.5vw, 1rem) 0;
}

/* Hero keeps a larger top inset — it's the page-entry, deserves
   breathing room above. Bottom padding still matches the section rhythm. */
.hero {
  position: relative;
  padding-top: clamp(2.5rem, 6vw, 5rem);
  /* Pure-CSS arrival animation — runs on first paint, no JS dependency,
     no [data-reveal] gate. Using @keyframes instead of the JS-driven
     reveal system avoids the regression where the data-reveal CSS gate
     would hold the hero at opacity:0 for the 250ms transition-delay,
     making the page look like it had scrolled past the hero. */
  animation: hero-arrive 1000ms cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: 500ms; /* Staggers hero fade-in to start after the topbar finishes its own fade-in. */
}
#iama {
  animation: hero-arrive 1000ms cubic-bezier(0.22, 1, 0.36, 1) both;
  animation-delay: 750ms; /* Staggers the second section's fade-in to start after the hero finishes its fade-in, creating a smooth cascading effect on page load. */
}
@keyframes hero-arrive {
  from { opacity: 0; }
  to   { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .hero, #iama, .topbar { animation: none; }
}

/* Closing CTA keeps its generous frame — it's the page-exit equivalent. */
.cta-close {
  padding: clamp(3rem, 8vw, 6rem) 0;
}

.section-label {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 1.5rem;
  font-weight: 600;
}

.section-title {
  font-size: clamp(1.5rem, 3.5vw, 2.25rem);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -0.02em;
  margin: 0 0 1rem;
}

/* ---------- Row + Card layouts ---------- */

.row {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr;
}
@media (min-width: 900px) {
  .row--2-1 { grid-template-columns: 2fr 1fr; }
  .row--1-1 { grid-template-columns: 1fr 1fr; }
}

.card {
  position: relative;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 0.9rem;
  padding: clamp(1.5rem, 3vw, 2.25rem);
  overflow: hidden;
  --card-accent: var(--accent);
}
.card .section-label { margin-bottom: 1.25rem; }
.card > *:last-child { margin-bottom: 0; }

/* Top color-strip: thin line across the top edge of each card, in the
   card's assigned accent. */
.card::before {
  content: "";
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 2px;
  background: var(--card-accent);
  opacity: 0.85;
}

/* Glowy accent dot rendered before the section-label inside any card.
   The glow comes from a stacked box-shadow that fades outward in the
   card's accent color. */
.card .section-label::before {
  content: "";
  display: inline-block;
  width: 0.55rem;
  height: 0.55rem;
  margin-right: 0.6rem;
  vertical-align: 0.05em;
  background: var(--card-accent);
  border-radius: 50%;
  box-shadow:
    0 0 0  2px color-mix(in srgb, var(--card-accent) 25%, transparent),
    0 0 10px color-mix(in srgb, var(--card-accent) 60%, transparent);
}

/* Per-card accent assignments. Each section gets a distinct color so the
   page reads as a series of differentiated panels rather than one
   uniformly-themed slab. Order matches the process-step number rainbow
   (positions 1-7) so the eye sees a single coherent gradient across
   both surfaces:
     1 Currently  → green
     2 Numbers    → cyan
     3 About      → indigo
     4 Contact    → violet
     5 Process    → pink
     6 Stack      → amber
     7 Gallery    → emerald */
/* Card-header row — used when a card needs a label on the left and a CTA
   pill on the right (e.g. the gallery's Follow Me On Instagram link). */
.card__header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 1rem;
}
.card__header .section-label { margin: 0; }
.card__cta {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.55rem 1rem;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.85rem;
  color: var(--fg);
  text-decoration: none;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-weight: 600;
  line-height: 1;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease,
              transform 150ms ease, box-shadow 150ms ease;
}
.card__cta:hover {
  background: var(--bg-elev-2);
  border-color: var(--fg);
  color: var(--fg);
  transform: translateY(-2px);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.35);
}
.card__cta:active { transform: translateY(0); box-shadow: none; }

/* Card color order: I AM A is card 01, then the rainbow continues
   through the 7 sections. The gallery (last card) is the "extra" and
   wraps back to the same green as I AM A so the visual cycle begins
   and ends in the same family. */
.card--disciplines { --card-accent: #22c55e; } /* 1 green */
.card--currently   { --card-accent: #06b6d4; } /* 2 cyan */
.card--numbers     { --card-accent: #6366f1; } /* 3 indigo */
.card--about       { --card-accent: #a855f7; } /* 4 violet */
.card--contact     { --card-accent: #ec4899; } /* 5 pink */
.card--process     { --card-accent: #f59e0b; } /* 6 amber */
.card--stack       { --card-accent: #eab308; } /* 7 yellow */
.card--gallery     { --card-accent: #22c55e; } /* extra, wraps to green */

/* ---------- Hero ---------- */

.hero { padding-top: clamp(3rem, 10vw, 7rem); }

.eyebrow {
  display: inline-block;
  /* Match the I AM A disciplines pill: padding, font-size, bg, border,
     border-radius. Keeps eyebrow's uppercase + tracking for the
     small-caps eyebrow voice; everything else matches the pill family. */
  font-family: var(--font-mono);
  font-size: 0.9rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-muted);
  margin: 0 0 1.5rem;
  font-weight: 600;
  padding: 0.55rem 1rem;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 999px;
  line-height: 1;
}

.hero__title {
  font-size: clamp(2.5rem, 9vw, 6.5rem);
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 0.95;
  margin: 0 0 2rem;
}
.hero__title br { display: none; }
@media (min-width: 720px) {
  .hero__title br { display: inline; }
}

/* Slow rainbow gradient sweep on the middle hero line. The gradient
   ends on the same color it starts on (green → … → green) so the
   animation loops seamlessly. background-size: 200% lets us scroll
   the gradient one full pattern-width across the text. */
.gradient-text {
  background-image: linear-gradient(
    90deg,
    #22c55e 0%,
    #06b6d4 14.28%,
    #6366f1 28.57%,
    #a855f7 42.86%,
    #ec4899 57.14%,
    #f59e0b 71.43%,
    #10b981 85.71%,
    #22c55e 100%
  );
  background-size: 200% 100%;
  background-clip: text;
  -webkit-background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  animation: gradient-wave 14s linear infinite;
}
@keyframes gradient-wave {
  0%   { background-position:   0% 50%; }
  100% { background-position: -200% 50%; }
}
/* Honor reduced-motion preferences — show a single static gradient
   snapshot instead of the looping wave. */
@media (prefers-reduced-motion: reduce) {
  .gradient-text { animation: none; background-position: 0% 50%; }
}

.hero__lede {
  font-size: clamp(1.05rem, 1.6vw, 1.25rem);
  color: var(--fg-muted);
  max-width: 55ch;
  margin: 0 0 2.25rem;
  line-height: 1.55;
}
.hero__lede strong { color: var(--fg); font-weight: 700; }
.hero__lede a { text-decoration: underline; text-decoration-color: var(--accent); text-underline-offset: 3px; }

.hero__cta { display: flex; flex-wrap: wrap; gap: 0.75rem; }

/* ---------- Disciplines ---------- */

.disciplines__list { display: flex; flex-wrap: wrap; gap: 0.5rem 0.75rem; }
.disciplines__list li {
  padding: 0.55rem 1rem;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.9rem;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease,
              transform 150ms ease, box-shadow 150ms ease;
}
.disciplines__list a { color: var(--fg); text-decoration: none; }
.disciplines__list li:has(a):hover {
  border-color: var(--fg);
  background: var(--bg-elev-2);
  transform: translateY(-2px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
.disciplines__list li:has(a):hover a { color: var(--fg); }

/* ---------- Currently ---------- */

.currently__meta { color: var(--fg-muted); font-size: 0.95rem; margin: 0 0 1.75rem; }

.client-list { display: flex; flex-wrap: wrap; gap: 0.5rem 0.75rem; }
/* Client pills — same shape as I AM A disciplines / contact pills:
   rounded-full, bg-elev, line border, 0.9rem text, matched padding. */
.client-list li {
  padding: 0.55rem 1rem;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.9rem;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease,
              transform 150ms ease, box-shadow 150ms ease;
}
.client-list a { color: var(--fg); }
.client-list li:hover {
  border-color: var(--fg);
  background: var(--bg-elev-2);
  transform: translateY(-2px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
.client-list li:hover a { color: var(--fg); }
/* "+ many more" is not interactive — render it as a ghost pill at rest
   AND on hover. No border, no background, no color change, no cursor
   affordance. */
.client-list__more {
  color: var(--fg-muted);
  background: transparent;
  border-color: transparent;
  cursor: default;
}
.client-list li.client-list__more:hover {
  border-color: transparent;
  color: var(--fg-muted);
  background: transparent;
}

/* ---------- Stats ---------- */

/* minmax(0, 1fr) instead of bare 1fr forces equal columns even when
   one cell's content (e.g. "1190") is wider than the other ("18"). The
   bare 1fr default is minmax(auto, 1fr), which auto-grows the column
   to fit content — making the grid uneven. */
.stats { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 1rem; }
/* Outside-of-card stat grid expands to 4-up at tablet. */
@media (min-width: 720px) {
  .stats:not(.stats--inner) { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
/* `.stats--inner` keeps the 2x2 grid even at wider viewports (it's
   inside a 1/3-width card, alongside Currently). */
.stats--inner { grid-template-columns: repeat(2, minmax(0, 1fr)); }

.stat {
  padding: 1.5rem 1.25rem;
  background: var(--bg-elev-2);
  border: 1px solid var(--line);
  border-radius: 0.6rem;
  /* Container-query context so .stat__value can scale with this cell's
     own width via cqi (container-inline-size) instead of viewport %. */
  container-type: inline-size;
  overflow: hidden;
}
.stat__value {
  /* Font scales fluidly with the stat cell's own width:
     - 22cqi  = ~22% of the cell's inline size
     - floor  1.75rem (so it never gets unreadably small at narrow cells)
     - ceiling 3rem    (so it never overflows the cell padding on wide ones)
     Net: "18" and "1190" both render at the same comfortable size and
     never touch the right padding edge. */
  font-size: clamp(1.75rem, 22cqi, 3rem);
  font-weight: 800;
  line-height: 1;
  letter-spacing: -0.03em;
  margin: 0 0 0.4rem;
  color: var(--fg);
}
.stat__label {
  color: var(--fg-muted);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  margin: 0;
}

/* ---------- About ---------- */

.about__copy { font-size: 1.1rem; max-width: 65ch; color: var(--fg); margin: 0; }
.about__copy + .about__copy { margin-top: 1.25rem; }
.about__copy a { text-decoration: underline; text-underline-offset: 3px; }

/* ---------- Gallery ---------- */

.gallery__mount { min-height: 100px; }
.gallery__mount .placeholder {
  max-width: 50ch;
  text-align: center;
  margin: 0;
  color: var(--fg-muted);
  padding: 2rem;
  background: var(--bg-elev-2);
  border: 1px dashed var(--line);
  border-radius: 0.6rem;
}

.ig-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 0.5rem;
}
@media (min-width: 560px)  { .ig-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 900px)  { .ig-grid { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1200px) { .ig-grid { grid-template-columns: repeat(6, 1fr); } }

.ig-tile {
  position: relative;
  aspect-ratio: 1 / 1;
  border-radius: 0.5rem;
  overflow: hidden;
  background: var(--bg-elev-2);
  border: 1px solid var(--line);
  display: block;
  transition: transform 250ms ease, box-shadow 250ms ease;
}
.ig-tile img {
  width: 100%; height: 100%;
  object-fit: cover;
  /* Default 12% scale-up to crop the white border baked into some of
     Seth's IG posts. The tile's overflow:hidden clips the overage,
     so the rendered tile shows a center-cropped slice of the image
     with ~6% trimmed off each side. */
  transform: scale(1.12);
  transition: transform 400ms ease, opacity 250ms ease;
}
.ig-tile:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 24px rgba(0,0,0,0.4);
}
.ig-tile:hover img { transform: scale(1.18); }
.ig-tile__badge {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  background: rgba(0,0,0,0.6);
  color: var(--fg);
  font-size: 0.75rem;
  padding: 0.15rem 0.4rem;
  border-radius: 0.25rem;
  backdrop-filter: blur(4px);
}

/* ---------- Process ---------- */

.process__meta { color: var(--fg-muted); font-size: 0.95rem; margin: 0 0 2rem; }
.process__steps { display: grid; gap: 0.75rem; }
@media (min-width: 560px)  { .process__steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 900px)  { .process__steps { grid-template-columns: repeat(4, 1fr); } }
@media (min-width: 1200px) { .process__steps { grid-template-columns: repeat(7, 1fr); } }
.process__steps li {
  display: grid;
  grid-template-rows: auto auto auto;
  row-gap: 0.4rem;
  padding: 1rem;
  background: var(--bg-elev-2);
  border: 1px solid var(--line);
  border-radius: 0.5rem;
}
.step__num {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--accent-soft);
}
/* Per-step number color — cycles through the same palette the cards use,
   one color per step. Reads as a rainbow strip across the process row at
   desktop width. */
.process__steps li:nth-child(1) .step__num { color: #22c55e; } /* green */
.process__steps li:nth-child(2) .step__num { color: #06b6d4; } /* cyan */
.process__steps li:nth-child(3) .step__num { color: #6366f1; } /* indigo */
.process__steps li:nth-child(4) .step__num { color: #a855f7; } /* violet */
.process__steps li:nth-child(5) .step__num { color: #ec4899; } /* pink */
.process__steps li:nth-child(6) .step__num { color: #f59e0b; } /* amber */
.process__steps li:nth-child(7) .step__num { color: #eab308; } /* yellow */

.step__head { font-weight: 700; font-size: 1rem; }
.step__body { color: var(--fg-muted); font-size: 0.85rem; line-height: 1.4; }

/* ---------- Stack ---------- */

/* Below 500px → single column (one stack-card per row).
   500–719 → 2-up, 720–1023 → 3-up, 1024+ → 5-up. */
.stack__grid { display: grid; grid-template-columns: 1fr; gap: 1rem; }
@media (min-width: 500px)  { .stack__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 720px)  { .stack__grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 1024px) { .stack__grid { grid-template-columns: repeat(5, 1fr); } }
.stack__col {
  padding: 1.25rem;
  background: var(--bg-elev-2);
  border: 1px solid var(--line);
  border-radius: 0.6rem;
}
.stack__col h3 {
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-faint);
  margin: 0 0 1rem;
}
.stack__col ul li {
  padding: 0.5rem 0;
  border-top: 1px solid var(--line);
  font-size: 0.92rem;
}
.stack__col ul li:first-child { border-top: 0; padding-top: 0; }

/* ---------- Contact ---------- */

.contact__grid { display: grid; gap: 0; border-top: 1px solid var(--line); }
.contact__row {
  display: grid;
  grid-template-columns: 6rem 1fr;
  gap: 1rem;
  padding: 1.25rem 0;
  border-bottom: 1px solid var(--line);
  align-items: center;
}
/* Below 500px, stack dt over dd (label on top, value below) so the
   value pills don't get squeezed by the 8rem label column. */
@media (max-width: 499px) {
  .contact__row {
    grid-template-columns: 1fr;
    gap: 0.5rem;
    align-items: start;
  }
}
.contact__row dt {
  font-size: 0.78rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-faint);
  font-weight: 600;
}
.contact__row dd { margin: 0; }
/* Right-hand values render as pills, matching the I AM A disciplines pill
   family (padding, font-size, bg, border, border-radius). Both anchor +
   plain-text dd values get the same treatment so the column reads as a
   uniform pill stack. */
.contact__row dd > a,
.contact__row dd {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.55rem 1rem;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.9rem;
  color: var(--fg);
  text-decoration: none;
  line-height: 1;
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease,
              transform 150ms ease, box-shadow 150ms ease;
}
/* Plain-text dd (no anchor inside) — apply pill styling directly. */
.contact__row dd:not(:has(> a)) { display: inline-flex; }
/* When dd has an anchor, the dd should be a plain container — strip the
   pill styling off the dd itself so only the anchor renders as a pill. */
.contact__row dd:has(> a) {
  display: block;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
  font-size: inherit;
}
.contact__row dd > a:hover {
  border-color: var(--fg);
  color: var(--fg);
  background: var(--bg-elev-2);
  transform: translateY(-2px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
/* Multi-pill row — multiple anchor/button children live inside one dd.
   Override the single-pill dd rule above so we get a horizontal row of
   pills instead of one elongated pill that wraps the whole group. */
.contact__row dd.contact__multi {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
}
.contact__row dd.contact__multi > a,
.contact__row dd.contact__multi > button {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.55rem 1rem;
  background: var(--bg-elev);
  border: 1px solid var(--line);
  border-radius: 999px;
  font-size: 0.9rem;
  color: var(--fg);
  text-decoration: none;
  line-height: 1;
  font-family: inherit;
  cursor: pointer;
}
.contact__row dd.contact__multi > a,
.contact__row dd.contact__multi > button {
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease,
              transform 150ms ease, box-shadow 150ms ease;
}
.contact__row dd.contact__multi > a:hover,
.contact__row dd.contact__multi > button:hover {
  border-color: var(--fg);
  color: var(--fg);
  background: var(--bg-elev-2);
  transform: translateY(-2px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}

/* Social row — multiple icon-only anchors live inside one dd. Override the
   single-pill dd rule above so we get a horizontal row of small icon
   pills instead of one elongated pill containing four icons. */
.contact__row dd.contact__social {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  padding: 0;
  background: none;
  border: none;
  border-radius: 0;
}
.contact__row dd.contact__social > a {
  padding: 0.55rem;
  gap: 0;
  color: var(--fg-muted);
}
.contact__row dd.contact__social > a {
  transition: background 150ms ease, border-color 150ms ease, color 150ms ease,
              transform 150ms ease, box-shadow 150ms ease;
}
.contact__row dd.contact__social > a:hover {
  color: var(--fg);
  border-color: var(--fg);
  transform: translateY(-2px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
.contact__row dd.contact__social .social__icon {
  width: 1.1rem;
  height: 1.1rem;
  fill: currentColor;
  display: block;
}

/* ---------- Closing CTA ---------- */

.cta-close { text-align: center; padding: clamp(4rem, 10vw, 7rem) 0; }
.cta-close h2 {
  font-size: clamp(2rem, 6vw, 4rem);
  font-weight: 800;
  letter-spacing: -0.03em;
  margin: 0 0 2rem;
}
.cta-close__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
  justify-content: center;
}
.cta-close__actions .btn { display: inline-flex; align-items: center; gap: 0.5rem; }

/* ---------- Footer ---------- */

.footer { border-top: 1px solid var(--line); padding: 2.5rem 0; }
.footer__inner {
  max-width: var(--max-w);
  margin: 0 auto;
  padding: 0 var(--gutter);
  display: flex;
  flex-direction: column;
  gap: 1rem;
  align-items: flex-start;
  color: var(--fg-muted);
  font-size: 0.9rem;
}
@media (min-width: 720px) {
  .footer__inner { flex-direction: row; justify-content: space-between; align-items: center; }
}
.footer p { margin: 0; }
.footer__license {
  max-width: var(--max-w);
  margin: 1.5rem auto 0;
  padding: 0 var(--gutter);
  text-align: center;
}
.footer__license a {
  display: inline-block;
  opacity: 0.6;
  transition: opacity 150ms ease, transform 150ms ease;
}
.footer__license a:hover { opacity: 1; transform: translateY(-2px); }
.footer__license img { display: inline-block; height: auto; }
.social { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.social a {
  color: var(--fg-muted);
  font-size: 0.9rem;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem;
  border-radius: 0.4rem;
  transition: color 150ms ease, background 150ms ease,
              transform 150ms ease, box-shadow 150ms ease;
}
.social a:hover {
  color: var(--fg);
  background: var(--bg-elev);
  transform: translateY(-2px);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
}
.social a:active { transform: translateY(0); box-shadow: none; }
.social__icon {
  width: 1.25rem;
  height: 1.25rem;
  fill: currentColor;
  flex-shrink: 0;
}
.social__label {
  /* Visible alongside the icon. */
  font-size: 0.85rem;
}

/* Remove unused .topnav rules — the menu was removed from the topbar. */

/* ---------- Responsive: desktop up ---------- */
@media (min-width: 1024px) {
  .status-pill { display: inline-flex; }
}

/* ---------- Reveal-on-load + reveal-on-scroll ----------
   Pattern: elements tagged with [data-reveal] start hidden + translated
   down 16px, then fade + slide into place when (a) the page first loads
   for above-the-fold items and (b) scroll brings them into the viewport
   for below-the-fold items. JS toggles .is-visible. The html.js gate
   means no-JS users see everything at full opacity immediately. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 400ms ease-out 250ms, transform 400ms ease-out 250ms;
  will-change: opacity, transform;
}
.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

/* Reduced-motion guard: honor users who've requested less motion. We
   keep the color/border feedback (information channel) and turn off the
   translate + shadow lift (decorative motion channel). */
@media (prefers-reduced-motion: reduce) {
  /* Reveal-on-scroll falls back to plain visible — no fade, no slide. */
  .js [data-reveal],
  .js [data-reveal].is-visible {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .btn:hover,
  .btn:active,
  .card__cta:hover,
  .card__cta:active,
  .status-pill--button:hover,
  .status-pill--button:active,
  .disciplines__list li:has(a):hover,
  .client-list li:hover,
  .contact__row dd > a:hover,
  .contact__row dd.contact__multi > a:hover,
  .contact__row dd.contact__multi > button:hover,
  .contact__row dd.contact__social > a:hover,
  .social a:hover,
  .social a:active {
    transform: none;
    box-shadow: none;
  }
}
