/* ============================================================================
 *  MODERN DARK THEME PORTFOLIO - PROFESSIONAL DESIGN
 * =========================================================================== */

:root {
  --bg-primary: #ffffff;
  --bg-secondary: #f8fafc;
  --bg-tertiary: #f1f5f9;
  --text-primary: #0f172a;
  --text-secondary: #475569;
  --text-tertiary: #64748b;
  --accent: #2563eb;
  --accent-dark: #1e40af;
  --accent-light: #3b82f6;
  --accent-secondary: #1e3a8a;
  --accent-green: #059669;
  --accent-purple: #7c3aed;
  --accent-orange: #d97706;
  /* Pulled straight from the logo strokes so type and mark stay in step. */
  --logo-cyan: #22d3ee;
  --logo-violet: #7c3aed;
  --border: #e2e8f0;
  --shadow: 0 0 0 1px rgba(30, 41, 59, 0.08);
  --shadow-md: 0 4px 16px rgba(30, 41, 59, 0.08);
  --shadow-lg: 0 10px 32px rgba(30, 41, 59, 0.12);
  --shadow-xl: 0 20px 48px rgba(30, 41, 59, 0.15);
  --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  /* Fallbacks for the nav sizing; config.js theme overrides these at runtime. */
  --nav-font-size: clamp(0.7rem, 0.92vw, 0.85rem);
  --nav-gap: clamp(0.5rem, 1.15vw, 1.15rem);
  --nav-font-size-mobile: 0.95rem;
  /* Same arrangement for the rest of the sizing config.theme controls. */
  --hero-font-size: clamp(1.75rem, 4.4vw, 2.65rem);
  --section-subtitle-max: 760px;
  --skill-chip-size: 0.78rem;
  --skill-note-size: 0.78rem;
  --domain-chip-size: 0.82rem;
  --cta-padding: 0.78rem 1.9rem;
  --cta-font-size: 0.95rem;
}

* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
}

body {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Helvetica Neue", sans-serif;
  color: var(--text-primary);
  background: var(--bg-primary);
  background-attachment: fixed;
  line-height: 1.65;
  font-size: 17px;
}

.app-container {
  display: flex;
  flex-direction: column;
  min-height: 100vh;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 2rem;
}

/* ============================================================================
 *  NAVBAR
 * =========================================================================== */

.navbar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 1000;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
  padding: 1rem 0;
  box-shadow: 0 1px 3px rgba(30, 41, 59, 0.08);
}

.nav-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 2rem;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.nav-brand {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  cursor: pointer;
  transition: var(--transition);
}

.nav-brand:hover {
  transform: scale(1.05);
}

.logo-icon {
  width: 40px;
  height: 40px;
  filter: drop-shadow(0 2px 4px rgba(30, 41, 59, 0.1));
  transition: var(--transition);
}

.nav-brand:hover .logo-icon {
  filter: drop-shadow(0 4px 8px rgba(37, 99, 235, 0.15));
  transform: rotate(10deg);
}

.brand-copy {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}

/* Same family, weight and gradient as the brand name, so the lockup reads
   as one piece of type rather than a name with a caption stuck under it. */
.brand-tagline {
  font-size: 0.64rem;
  font-weight: 700;
  letter-spacing: 0.17em;
  text-transform: uppercase;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-light) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  white-space: nowrap;
}

/* The parent clips a gradient to the text, so the prefix has to reset the
   transparent fill before its own colour will show. */
.tagline-accent {
  background: none;
  color: var(--logo-cyan);
  -webkit-text-fill-color: var(--logo-cyan);
}

.brand-text {
  font-weight: 700;
  font-size: 1.2rem;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-light) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  letter-spacing: -0.3px;
  white-space: nowrap;
}

.nav-menu {
  display: flex;
  list-style: none;
  gap: var(--nav-gap);
  align-items: center;
  /* Nine labels in one row: never wrap, shrink the type instead. */
  flex-wrap: nowrap;
  min-width: 0;
}

.nav-link {
  text-decoration: none;
  color: var(--text-secondary);
  font-size: var(--nav-font-size);
  font-weight: 500;
  letter-spacing: 0.1px;
  white-space: nowrap;
  transition: var(--transition);
  position: relative;
  padding: 0.5rem 0;
}

.nav-link::after {
  content: '';
  position: absolute;
  bottom: -4px;
  left: 0;
  width: 0;
  height: 2px;
  background: linear-gradient(90deg, var(--accent), var(--accent-light));
  transition: width 0.3s ease;
  box-shadow: 0 0 12px rgba(59, 130, 246, 0.4);
}

.nav-link:hover,
.nav-link.active {
  color: var(--accent-light);
}

.nav-link:hover::after,
.nav-link.active::after {
  width: 100%;
}

/* The band just above the hamburger breakpoint is where nine links and the
   full brand lockup compete for the same row. "Professional Synopsis" is a
   long label, so the tagline stands down well before things get tight. */
@media (min-width: 769px) and (max-width: 1080px) {
  .brand-tagline {
    display: none;
  }

  .nav-container {
    padding: 0 1.25rem;
  }
}

/* An action, not a destination, so it reads as a button rather than another
   link in the row. Shares .nav-link sizing so the row stays on one baseline. */
.nav-action {
  display: inline-flex;
  align-items: center;
  gap: 0.32rem;
  padding: 0.32rem 0.7rem;
  border: 1px solid var(--accent);
  border-radius: 999px;
  background: none;
  color: var(--accent);
  font-family: inherit;
  cursor: pointer;
  white-space: nowrap;
}

.nav-action svg { flex-shrink: 0; }

.nav-action:hover {
  background: var(--accent);
  color: #fff;
}

/* The underline sweep belongs to the section links, not to this. */
.nav-action::after { content: none; }

.nav-action:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.nav-toggle {
  display: none;
  flex-direction: column;
  gap: 6px;
  background: none;
  border: none;
  cursor: pointer;
}

.nav-toggle span {
  width: 24px;
  height: 2px;
  background: var(--accent);
  transition: var(--transition);
  box-shadow: 0 0 8px rgba(59, 130, 246, 0.3);
}

.nav-toggle.active span:nth-child(1) {
  transform: rotate(45deg) translate(8px, 8px);
}

.nav-toggle.active span:nth-child(2) {
  opacity: 0;
}

.nav-toggle.active span:nth-child(3) {
  transform: rotate(-45deg) translate(7px, -7px);
}

/* ============================================================================
 *  MAIN CONTENT
 * =========================================================================== */

.main-content {
  flex: 1;
  margin-top: 80px;
}

/* ============================================================================
 *  HERO SECTION
 * =========================================================================== */

.hero {
  padding: 3rem 2rem 2.4rem;
  background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
  border-bottom: 1px solid var(--border);
  position: relative;
  overflow: hidden;
}

.hero::before {
  content: '';
  position: absolute;
  top: -50%;
  right: -20%;
  width: 600px;
  height: 600px;
  background: radial-gradient(circle, rgba(37, 99, 235, 0.1) 0%, transparent 70%);
  pointer-events: none;
}

/* ---------------------------------------------------------------------------
   Section backdrops. One container per section, holding whichever medium
   config asked for: a video, an image, a canvas, or nothing. Sits above the
   section background, below the content, and never intercepts clicks.
   ------------------------------------------------------------------------ */

.section-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
}

.section-media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  border: 0;
}

/* Dark wash between the medium and the text, so copy stays legible over
   footage of any brightness. */
.section-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(8, 14, 26, 0.55) 0%,
    rgba(8, 14, 26, 0.75) 60%,
    rgba(8, 14, 26, 0.9) 100%);
}

.about-section,
.experience-section,
.skills-section,
.projects-section,
.education-section,
.insights-section,
.contact-section {
  position: relative;
  overflow: hidden;
}

.about-section .container,
.experience-section .container,
.skills-section .container,
.projects-section .container,
.education-section .container,
.insights-section .container,
.contact-section .container {
  position: relative;
  z-index: 1;
}

.hero .container {
  text-align: center;
  position: relative;
  z-index: 1;
}

/* ---------------------------------------------------------------------------
   Dark landing band. Only the hero flips; the rest of the page stays light,
   which is what gives the section its contrast.
   ------------------------------------------------------------------------ */

/* Doubled class so this always outranks .section:nth-child(odd), whatever
   order the two rules end up in. */
.section--dark,
.section.section--dark {
  background: linear-gradient(160deg, #0b1220 0%, #111c30 55%, #0d1526 100%);
  border-bottom-color: #1e2b44;
}

.section--dark::before {
  background: radial-gradient(circle, rgba(56, 189, 248, 0.13) 0%, transparent 70%);
}

.section--dark .hero-title {
  background: linear-gradient(135deg, #7dd3fc 0%, #a78bfa 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.section--dark .hero-subtitle {
  color: #7dd3fc;
}

.section--dark .hero-description {
  color: #cbd5e1;
}

.section--dark .hero-avatar {
  border-color: #38bdf8;
  box-shadow: 0 0 30px rgba(56, 189, 248, 0.28);
}

.section--dark .cta-btn.secondary {
  color: #bae6fd;
  border-color: #38bdf8;
}

.section--dark .cta-btn.secondary:hover {
  background: rgba(56, 189, 248, 0.14);
}

.section--dark .social-link {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(148, 163, 184, 0.35);
  color: #bae6fd;
}

.section--dark .social-link:hover {
  background: #38bdf8;
  color: #0b1220;
  border-color: #38bdf8;
}

/* Brand marks keep their own colours, so only the plate behind them shifts. */
.section--dark .social-link[data-icon="linkedin"]:hover,
.section--dark .social-link[data-icon="github"]:hover {
  background: rgba(255, 255, 255, 0.12);
}

.section--dark .social-link::after {
  background: #e2e8f0;
  color: #0b1220;
}

.section--dark .social-link::before {
  border-top-color: #e2e8f0;
}

.section--dark .phone-menu {
  background: #111c30;
  border-color: #1e2b44;
}

.section--dark .phone-option {
  color: #e2e8f0;
}

.section--dark .phone-option:hover {
  background: rgba(56, 189, 248, 0.12);
  color: #7dd3fc;
}

.section--dark .phone-option svg {
  color: #7dd3fc;
}

.section--dark .phone-option-label {
  color: #94a3b8;
}

/* --- approach columns, sitting over the hero video --- */

/* Flex rather than grid, deliberately. With five cards an auto-fit grid fits
   four columns and strands the fifth alone on the left with three empty
   slots beside it. Wrapping flex items centre their last row instead, so an
   uneven count reads as intentional at every width. */
.approach-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 1.4rem;
  /* The bottom value is the gap above the CTA buttons, so it is the one that
     shows as dead space if it drifts up. */
  margin: 1.75rem auto 1.5rem;
  max-width: 1140px;
  text-align: left;
}

.approach-card {
  min-width: 0;
  /* Basis is under a fifth of the row so all five sit on one line on desktop,
     then wrap in centred rows as the viewport narrows. */
  flex: 1 1 195px;
  max-width: 260px;
}

/* Staggered reveal. The hidden state is scoped to .is-revealing, which the
   script adds only when the animation will actually run, so the cards are
   never left invisible if it is switched off or JS never gets there. */
.approach-grid.is-revealing .approach-card {
  opacity: 0;
  transform: translateY(var(--approach-reveal-lift, 22px));
  /* Both properties share one curve. An expo-style ease-out here would land
     in the first third and read as instant however long the duration is. */
  transition:
    opacity var(--approach-reveal-ms, 1800ms)
      var(--approach-reveal-timing, cubic-bezier(0.4, 0, 0.25, 1)),
    transform var(--approach-reveal-ms, 1800ms)
      var(--approach-reveal-timing, cubic-bezier(0.4, 0, 0.25, 1));
  /* Each card waits one stagger longer than the one before it. */
  transition-delay: calc(var(--reveal-index, 0) * var(--approach-stagger, 700ms));
}

.approach-grid.is-revealing .approach-card.is-revealed {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .approach-grid.is-revealing .approach-card {
    opacity: 1;
    transform: none;
    transition: none;
    transition-delay: 0s;
  }
}

/* Soft halo behind the glyph so it reads against moving footage. */
.approach-icon {
  display: inline-grid;
  place-items: center;
  width: 48px;
  height: 48px;
  margin-bottom: 0.8rem;
  border-radius: 50%;
  color: var(--accent);
  background: radial-gradient(circle at 50% 50%,
    rgba(37, 99, 235, 0.22) 0%,
    rgba(37, 99, 235, 0.08) 55%,
    transparent 75%);
}

.approach-title {
  font-size: 1.1rem;
  font-weight: 700;
  line-height: 1.25;
  color: var(--text-primary);
  margin-bottom: 0.5rem;
}

.approach-text {
  color: var(--text-secondary);
  font-size: 0.88rem;
  line-height: 1.55;
}

.section--dark .approach-icon {
  color: #5eead4;
  background: radial-gradient(circle at 50% 50%,
    rgba(94, 234, 212, 0.28) 0%,
    rgba(94, 234, 212, 0.10) 55%,
    transparent 75%);
}

.section--dark .approach-title {
  color: #f1f5f9;
}

.section--dark .approach-text {
  color: #b6c2d4;
}

/* --- domains section --- */

/* Wider than the hero strip: more chips per row means fewer rows, which is
   the main lever on how tall this section gets. */
.domains-section .domain-grid {
  max-width: 980px;
  margin: 0 auto;
}

/* ---------------------------------------------------------------------------
   Dark section content. Applies wherever a section is themed dark, currently
   the hero and Featured Projects. Cards are slightly translucent so the mesh
   behind them stays visible without ever getting under the text.
   ------------------------------------------------------------------------ */

.section--dark .section-title {
  color: #f1f5f9;
}

.section--dark .section-icon {
  color: #7dd3fc;
  background: linear-gradient(135deg, rgba(56, 189, 248, 0.16) 0%, rgba(167, 139, 250, 0.16) 100%);
  box-shadow: inset 0 0 0 1px rgba(148, 163, 184, 0.25);
}

.section--dark .section-subtitle {
  color: #b6c2d4;
}

.section--dark .project-card {
  background: rgba(12, 20, 36, 0.82);
  border-color: rgba(148, 163, 184, 0.22);
  backdrop-filter: blur(2px);
}

.section--dark .project-card:hover {
  border-color: #38bdf8;
  box-shadow: 0 12px 34px rgba(0, 0, 0, 0.45);
}

.section--dark .project-header {
  background: rgba(255, 255, 255, 0.04);
  border-bottom-color: rgba(148, 163, 184, 0.2);
}

.section--dark .project-name {
  color: #7dd3fc;
}

.section--dark .project-year {
  color: #94a3b8;
}

.section--dark .project-desc {
  color: #cbd5e1;
}

.section--dark .tech-tag {
  background: rgba(56, 189, 248, 0.12);
  color: #bae6fd;
  border-color: rgba(56, 189, 248, 0.3);
}

.section--dark .tech-tag:hover {
  background: #38bdf8;
  color: #0b1220;
  border-color: #38bdf8;
}

.section--dark .location-badge {
  background: rgba(56, 189, 248, 0.1);
  color: #7dd3fc;
  border-color: rgba(56, 189, 248, 0.28);
}

.section--dark .project-link {
  color: #7dd3fc;
}

.section--dark .project-link:hover {
  color: #bae6fd;
}

/* Experience uses the same one-card-at-a-time track as Projects. */
.carousel-track .experience-item {
  flex: 0 0 100%;
  scroll-snap-align: center;
  scroll-snap-stop: always;
  margin-bottom: 0;
  transform: none;
}

.carousel-track .experience-item:hover {
  transform: none;
}

/* --- dark section content, applied wherever theme is "dark" --- */

.section--dark .experience-item {
  background: rgba(12, 20, 36, 0.82);
  border-left-color: #38bdf8;
  backdrop-filter: blur(2px);
}

.section--dark .company-name { color: #f1f5f9; }
.section--dark .position { color: #7dd3fc; }
.section--dark .duration { color: #94a3b8; }
.section--dark .experience-desc { color: #cbd5e1; }
.section--dark .responsibilities li { color: #cbd5e1; }
.section--dark .responsibilities li::before { background: #38bdf8; }

.section--dark .skill-card,
.section--dark .education-item,
.section--dark .cert-item,
.section--dark .insight-card,
.section--dark .philosophy-section,
.section--dark .send-channels,
.section--dark .quick-actions,
.section--dark .about-stats--background {
  background: rgba(12, 20, 36, 0.8);
  border-color: rgba(148, 163, 184, 0.22);
  backdrop-filter: blur(2px);
}

.section--dark .skill-category { color: #7dd3fc; }
.section--dark .skill-icon {
  color: #7dd3fc;
  background: rgba(56, 189, 248, 0.14);
}
.section--dark .skill-tag {
  background: rgba(56, 189, 248, 0.12);
  color: #bae6fd;
  border-color: rgba(56, 189, 248, 0.3);
}
.section--dark .skill-tag:hover {
  background: #38bdf8;
  color: #0b1220;
}

.section--dark .institution { color: #f1f5f9; }
.section--dark .degree { color: #7dd3fc; }
.section--dark .field,
.section--dark .edu-year { color: #94a3b8; }
.section--dark .cert-name { color: #f1f5f9; }
.section--dark .cert-issuer { color: #cbd5e1; }
.section--dark .cert-year { color: #7dd3fc; }

.section--dark .insight-card h3 { color: #7dd3fc; }
.section--dark .insight-card p { color: #cbd5e1; }
.section--dark .insight-link { color: #7dd3fc; }

.section--dark .philosophy-section h3 { color: #7dd3fc; }
.section--dark .philosophy-section p { color: #cbd5e1; }
.section--dark .philosophy-section p strong { color: #f1f5f9; }

.section--dark .about-name { color: #f1f5f9; }
.section--dark .about-role { color: #7dd3fc; }
.section--dark .about-location { color: #94a3b8; }
.section--dark .about-description { color: #e2e8f0 !important; }
.section--dark .about-text p { color: #cbd5e1; }
.section--dark .about-stats--background .stat-number { color: #7dd3fc; }
.section--dark .about-stats--background .stat-label { color: #94a3b8; }

.section--dark .form-group label { color: #e2e8f0; }
.section--dark .form-group label .optional { color: #94a3b8; }
.section--dark .form-group input,
.section--dark .form-group textarea {
  background: rgba(12, 20, 36, 0.75);
  border-color: rgba(148, 163, 184, 0.3);
  color: #f1f5f9;
}
.section--dark .form-group input::placeholder,
.section--dark .form-group textarea::placeholder { color: #7d8ea6; }
/* The generic .form-group input:focus rule further down sets a near-white
   background and scores the same specificity (0,2,1) as the dark-band rule
   above, so it wins on source order. It sets no colour, which left light text
   on a light field: invisible while typing, correct again on blur. Restating
   background and colour here at (0,3,1) means the two can never disagree. */
.section--dark .form-group input:focus,
.section--dark .form-group textarea:focus {
  border-color: #38bdf8;
  background: rgba(9, 16, 30, 0.92);
  color: #f8fafc;
  box-shadow: 0 0 0 3px rgba(56, 189, 248, 0.25);
}

.section--dark .form-group input:-webkit-autofill,
.section--dark .form-group input:-webkit-autofill:focus {
  -webkit-text-fill-color: #f8fafc;
  -webkit-box-shadow: 0 0 0 1000px rgba(9, 16, 30, 0.92) inset;
}

/* Invalid fields keep the dark fill too, or the red tint would replace it and
   leave the text floating over whatever is animating behind the section. */
.section--dark .form-group input.invalid,
.section--dark .form-group textarea.invalid {
  background: rgba(60, 12, 18, 0.82);
  border-color: #f87171;
  color: #f8fafc;
}

.section--dark .form-group input.invalid:focus,
.section--dark .form-group textarea.invalid:focus {
  background: rgba(60, 12, 18, 0.92);
  border-color: #f87171;
  color: #f8fafc;
  box-shadow: 0 0 0 3px rgba(248, 113, 113, 0.25);
}

.section--dark .send-channels-title,
.section--dark .quick-actions-title { color: #f1f5f9; }
.section--dark .send-channels-hint,
.section--dark .quick-actions-sub { color: #94a3b8; }
.section--dark .send-channel {
  background: rgba(255, 255, 255, 0.05);
  border-color: rgba(148, 163, 184, 0.25);
}
.section--dark .send-channel-label { color: #f1f5f9; }
.section--dark .send-channel-hint { color: #94a3b8; }

/* ---------------------------------------------------------------------------
   Pale bands. A faint mesh runs behind these, so cards get a near-opaque
   surface and text is pinned to strong values rather than left to inherit
   anything low contrast.
   ------------------------------------------------------------------------ */

.section:not(.section--dark) .project-card,
.section:not(.section--dark) .experience-item,
.section:not(.section--dark) .skill-card,
.section:not(.section--dark) .education-item,
.section:not(.section--dark) .cert-item,
.section:not(.section--dark) .insight-card,
.section:not(.section--dark) .philosophy-section,
.section:not(.section--dark) .send-channels,
.section:not(.section--dark) .quick-actions,
.section:not(.section--dark) .about-stats--background {
  background: rgba(255, 255, 255, 0.92);
}

.section:not(.section--dark) .section-title,
.section:not(.section--dark) .company-name,
.section:not(.section--dark) .institution,
.section:not(.section--dark) .cert-name,
.section:not(.section--dark) .about-name,
.section:not(.section--dark) .quick-actions-title,
.section:not(.section--dark) .send-channels-title,
.section:not(.section--dark) .send-channel-label {
  color: #0f172a;
}

.section:not(.section--dark) .experience-desc,
.section:not(.section--dark) .project-desc,
.section:not(.section--dark) .responsibilities li,
.section:not(.section--dark) .about-text p,
.section:not(.section--dark) .insight-card p,
.section:not(.section--dark) .philosophy-section p,
.section:not(.section--dark) .cert-issuer {
  color: #334155;
}

.section:not(.section--dark) .about-description {
  color: #0f172a !important;
}

.section:not(.section--dark) .duration,
.section:not(.section--dark) .project-year,
.section:not(.section--dark) .field,
.section:not(.section--dark) .edu-year,
.section:not(.section--dark) .edu-details,
.section:not(.section--dark) .about-location,
.section:not(.section--dark) .quick-actions-sub,
.section:not(.section--dark) .send-channels-hint,
.section:not(.section--dark) .send-channel-hint,
.section:not(.section--dark) .domains-label {
  color: #475569;
}

.section:not(.section--dark) .position,
.section:not(.section--dark) .project-name,
.section:not(.section--dark) .degree,
.section:not(.section--dark) .cert-year,
.section:not(.section--dark) .about-role,
.section:not(.section--dark) .skill-category,
.section:not(.section--dark) .insight-card h3,
.section:not(.section--dark) .philosophy-section h3 {
  color: #1d4ed8;
}

.section:not(.section--dark) .form-group label {
  color: #0f172a;
}

.section:not(.section--dark) .form-group input,
.section:not(.section--dark) .form-group textarea {
  background: #ffffff;
}

/* --- hero domain chips --- */

/* Groups sit under one another separated by a rule rather than a gap, which
   reads as a deliberate divide instead of leftover space. */
.domain-group + .domain-group {
  margin-top: 1.15rem;
  padding-top: 1.15rem;
  border-top: 1px solid var(--border);
}

.section--dark .domain-group + .domain-group {
  border-top-color: rgba(148, 163, 184, 0.22);
}

.domains-label {
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-tertiary);
  /* Centred to match the chips under it; left aligned looked accidental. */
  text-align: center;
  margin: 0 0 0.6rem;
}

.section--dark .domains-label {
  color: #94a3b8;
}

.domain-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.35rem;
  /* Group spacing is handled by the divider above, so no trailing gap. */
  margin-bottom: 0;
}

.domain-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.34rem 0.75rem;
  border-radius: 999px;
  font-size: var(--domain-chip-size, 0.82rem);
  font-weight: 600;
  color: var(--text-secondary);
  background: rgba(37, 99, 235, 0.07);
  border: 1px solid rgba(37, 99, 235, 0.18);
  transition: var(--transition);
}

.domain-chip svg {
  flex-shrink: 0;
  color: var(--accent);
}

.domain-chip:hover {
  transform: translateY(-2px);
  border-color: var(--accent);
}

.section--dark .domain-chip {
  color: #dbeafe;
  background: rgba(255, 255, 255, 0.07);
  border-color: rgba(148, 163, 184, 0.3);
}

.section--dark .domain-chip svg {
  color: #7dd3fc;
}

.section--dark .domain-chip:hover {
  background: rgba(56, 189, 248, 0.16);
  border-color: #38bdf8;
}

/* --- about identity block --- */

/* Stacked and left aligned in its own column. */
.about-profile {
  text-align: left;
}

.about-avatar {
  width: 128px;
  height: 128px;
  margin-bottom: 1.25rem;
  border-radius: 50%;
  object-fit: cover;
  flex-shrink: 0;
  border: 3px solid var(--accent);
  box-shadow: 0 0 24px rgba(37, 99, 235, 0.18);
  transition: var(--transition);
}

.about-avatar:hover {
  transform: scale(1.04);
}

.about-identity {
  min-width: 0;
}

.about-name {
  font-size: 1.6rem;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.2;
}

.about-role {
  font-size: 1rem;
  font-weight: 600;
  color: var(--accent);
  margin-top: 0.15rem;
}

.about-location {
  display: inline-flex;
  /* The line is a sentence now, not a city, so it can wrap. Top aligned keeps
     the pin on the first line instead of floating beside a two-line block. */
  align-items: flex-start;
  gap: 0.4rem;
  color: var(--text-tertiary);
  font-size: 0.9rem;
  line-height: 1.45;
  margin: 0.5rem 0 0.9rem;
}

.about-location svg {
  flex-shrink: 0;
  opacity: 0.8;
  margin-top: 0.15em;
}

.about-profile .hero-socials {
  justify-content: flex-start;
}

@media (max-width: 640px) {
  .about-profile {
    flex-direction: column;
    text-align: center;
  }

  .about-profile .hero-socials {
    justify-content: center;
  }

  .about-location {
    justify-content: center;
  }
}

/* Wide enough for the four columns to sit in one row. The headline and intro
   keep their own narrower measure below, so only the cards use the full width. */
.hero-content {
  max-width: 1120px;
  margin: 0 auto;
}

.hero-avatar {
  width: 160px;
  height: 160px;
  border-radius: 50%;
  object-fit: cover;
  margin-bottom: 2rem;
  border: 3px solid var(--accent);
  box-shadow: 0 0 20px rgba(59, 130, 246, 0.2), inset 0 0 20px rgba(59, 130, 246, 0.05);
  transition: var(--transition);
}

.hero-avatar:hover {
  transform: scale(1.05);
  box-shadow: 0 0 30px rgba(59, 130, 246, 0.3), inset 0 0 20px rgba(59, 130, 246, 0.08);
}

.hero-title {
  /* Fluid, because the headline is a full sentence rather than a few words.
     The clamp keeps it to two or three lines from phone to desktop. */
  font-size: var(--hero-font-size, clamp(1.75rem, 4.4vw, 2.65rem));
  font-weight: 800;
  color: var(--text-primary);
  margin-bottom: 0.9rem;
  line-height: 1.16;
  letter-spacing: -0.6px;
  max-width: 900px;
  margin-left: auto;
  margin-right: auto;
  background: linear-gradient(135deg, var(--accent-light) 0%, var(--accent) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
}

.hero-subtitle {
  font-size: 1.3rem;
  color: var(--accent-light);
  margin-bottom: 1.5rem;
  font-weight: 600;
}

.hero-description {
  font-size: 1.02rem;
  color: var(--text-secondary);
  line-height: 1.7;
  margin-bottom: 0;
  max-width: 760px;
  margin-left: auto;
  margin-right: auto;
}

.hero-cta {
  display: flex;
  gap: 0.7rem;
  justify-content: center;
  margin-bottom: 0;
  flex-wrap: wrap;
}

.cta-btn {
  /* One of these is a <button> and the other an <a>. Without an explicit
     font-family the button falls back to the browser UI font at its own
     line-height, so the pair render at different widths and heights. Flex
     centring plus inherited type keeps them identical. */
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: inherit;
  line-height: 1.2;
  min-height: 2.85rem;
  padding: var(--cta-padding, 0.78rem 1.9rem);
  border-radius: 8px;
  font-weight: 600;
  font-size: var(--cta-font-size, 0.95rem);
  cursor: pointer;
  transition: var(--transition);
  text-decoration: none;
  border: 2px solid;
  position: relative;
  overflow: hidden;
}

.cta-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(135deg, rgba(255, 255, 255, 0.1) 0%, transparent 100%);
  opacity: 0;
  transition: opacity 0.3s ease;
}

.cta-btn:hover::before {
  opacity: 1;
}

.cta-btn.primary {
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%);
  color: #fff;
  border-color: var(--accent);
  box-shadow: 0 0 20px rgba(59, 130, 246, 0.25);
}

.cta-btn.primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 0 30px rgba(59, 130, 246, 0.4);
  border-color: var(--accent-light);
}

.cta-btn.secondary {
  background: transparent;
  color: var(--accent-light);
  border-color: var(--accent);
}

.cta-btn.secondary:hover {
  background: rgba(59, 130, 246, 0.1);
  box-shadow: 0 0 20px rgba(59, 130, 246, 0.2);
}

.hero-socials {
  display: flex;
  gap: 1rem;
  justify-content: center;
}

/* The copy button sits under its icon rather than beside it, so the row of
   social links keeps its even rhythm instead of being pushed apart. */
.social-pair {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 0.25rem;
}

/* Links without a copy button need the same top alignment as those with one,
   or the row would sit unevenly. */
.hero-socials { align-items: flex-start; }

/* Deliberately small and quiet: an accessory to the link, not a peer of it. */
.copy-btn {
  display: inline-grid;
  place-items: center;
  width: 22px;
  height: 22px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 6px;
  background: none;
  color: var(--text-tertiary);
  cursor: pointer;
  transition: color 0.2s ease, border-color 0.2s ease, background 0.2s ease;
}

.copy-btn:hover {
  color: var(--accent);
  border-color: var(--border);
  background: var(--bg-secondary);
}

.copy-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.copy-btn.is-copied {
  color: var(--accent-green);
  border-color: transparent;
  background: none;
}

.section--dark .copy-btn { color: #94a3b8; }

.section--dark .copy-btn:hover {
  color: #7dd3fc;
  border-color: rgba(148, 163, 184, 0.3);
  background: rgba(255, 255, 255, 0.06);
}

.section--dark .copy-btn.is-copied { color: #5dd6a8; }

.social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--bg-secondary);
  color: var(--accent);
  text-decoration: none;
  font-size: 1rem;
  transition: var(--transition);
  border: 1.5px solid var(--border);
}

.social-link:hover {
  background: var(--accent);
  color: var(--bg-primary);
  border-color: var(--accent);
  transform: translateY(-4px);
  box-shadow: var(--shadow-lg);
}

/* ============================================================================
 *  SECTIONS
 * =========================================================================== */

.section {
  padding: 3rem 2rem;
  border-bottom: 1px solid var(--border);
}

/* Must exclude dark sections. This selector outranks .section--dark, so
   without the :not() a dark-themed section keeps a pale background while its
   text turns light, leaving it unreadable. */
.section:nth-child(odd):not(.section--dark) {
  background: var(--bg-secondary);
}

.section-title {
  font-size: 2.5rem;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 1.75rem;
  text-align: center;
  letter-spacing: -0.5px;
  position: relative;
  padding-bottom: 0.85rem;
}

.section-title::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 60px;
  height: 4px;
  background: linear-gradient(90deg, var(--accent), var(--accent-purple));
  border-radius: 2px;
}

.section-subtitle {
  text-align: center;
  color: var(--text-secondary);
  font-size: 1.02rem;
  line-height: 1.6;
  /* Capped, so a full sentence does not run the whole 1200px container. */
  max-width: var(--section-subtitle-max, 760px);
  margin: 0 auto 1.6rem;
}

.contact-section .section-subtitle {
  margin-bottom: 1.9rem;
  font-size: 1rem;
}

/* ============================================================================
 *  ABOUT SECTION
 * =========================================================================== */

.about-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 4rem;
  align-items: center;
}

/* ---------------------------------------------------------------------------
   Two columns: identity on the left, prose on the right with the figures
   watermarked behind it.
   ------------------------------------------------------------------------ */

.about-layout {
  display: grid;
  grid-template-columns: minmax(200px, 260px) 1fr;
  gap: 2.25rem;
  align-items: start;
  margin-bottom: 2.5rem;
}

.about-body {
  position: relative;
}

.about-text {
  position: relative;
  z-index: 1;
}

@media (max-width: 900px) {
  .about-layout {
    grid-template-columns: 1fr;
    gap: 2.25rem;
  }
}

.about-text p {
  font-size: 1.05rem;
  color: var(--text-secondary);
  line-height: 1.8;
  margin-bottom: 1.5rem;
}

.about-description {
  font-size: 1.1rem !important;
  color: var(--text-primary) !important;
}

.about-stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: 2rem;
  align-items: end;
}

/* ---------------------------------------------------------------------------
   Watermark mode. The figures recede behind the section as quiet supporting
   evidence rather than competing tiles, and the row distributes evenly however
   many stats are configured.
   ------------------------------------------------------------------------ */

/* Given its own space under the prose rather than washed out behind it. A
   tinted panel keeps it clearly secondary to the paragraph while leaving the
   figures at full contrast, so they can actually be read. */
.about-stats--background {
  margin-top: 1.75rem;
  padding: 1.25rem 1.5rem;
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: 10px;
  background: linear-gradient(135deg,
    rgba(37, 99, 235, 0.05) 0%,
    rgba(34, 211, 238, 0.04) 100%);
  grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  gap: 1.25rem 1.5rem;
  align-items: start;
}

.about-stats--background .stat {
  text-align: center;
  padding: 0;
  background: none;
  border: 0;
}

/* "Multi-Million" is far longer than "17+", so allow a clean break rather
   than letting it overflow its column. */
.about-stats--background .stat-number {
  font-size: 1.6rem;
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1.1;
  color: var(--accent);
  background: none;
  -webkit-text-fill-color: currentColor;
  margin-bottom: 0.15rem;
  overflow-wrap: break-word;
  /* Digits change width as they count, so lock the glyph width or the row
     jitters for the whole animation. */
  font-variant-numeric: tabular-nums;
}

/* Hidden until observed, so the final value never flashes before counting. */
.about-stats .stat-number {
  opacity: 0;
  transform: translateY(6px);
  transition: opacity 0.4s ease, transform 0.4s ease;
}

.about-stats .stat-number.is-shown {
  opacity: 1;
  transform: none;
}

/* Figures with no digits cannot count, so they drift up and sharpen out of a
   blur over the same span the numbers spend climbing. */
.about-stats .stat-number.is-text {
  transform:
    translateY(var(--stat-reveal-lift, 12px))
    scale(var(--stat-reveal-scale, 0.96));
  filter: blur(var(--stat-reveal-blur, 10px));
  /* Fade and blur run on a steady curve. An ease-out here would clear the
     blur inside the first quarter and read as instant however long it lasts. */
  transition:
    opacity var(--stat-reveal-ms, 4500ms) var(--stat-reveal-timing, linear),
    transform var(--stat-reveal-ms, 4500ms) cubic-bezier(0.16, 1, 0.3, 1),
    filter var(--stat-reveal-ms, 4500ms) var(--stat-reveal-timing, linear);
}

.about-stats .stat-number.is-text.is-shown {
  transform: none;
  filter: blur(0);
}

@media (prefers-reduced-motion: reduce) {
  .about-stats .stat-number.is-text {
    transform: none;
    filter: none;
    transition: opacity 0.3s ease;
  }
}

.about-stats--background .stat-label {
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-secondary);
  line-height: 1.35;
}

.about-stats--background .stat:hover {
  transform: none;
  box-shadow: none;
}

/* --- original bordered tiles, kept for statsDisplay: "cards" --- */

.about-stats--cards .stat,
.about-stats:not([class*="about-stats--"]) .stat {
  text-align: center;
  padding: 2rem;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 12px;
  transition: var(--transition);
}

.stat {
  transition: var(--transition);
}

.stat:hover {
  border-color: var(--accent);
  box-shadow: 0 0 20px rgba(59, 130, 246, 0.2);
  transform: translateY(-4px);
}

.stat-number {
  font-size: 2.5rem;
  font-weight: 700;
  background: linear-gradient(135deg, var(--accent-light) 0%, var(--accent-purple) 100%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  background-clip: text;
  margin-bottom: 0.5rem;
}

.stat-label {
  color: var(--text-secondary);
  font-weight: 500;
}

.philosophy-section {
  margin-top: 1.25rem;
  padding: 1.1rem 1.3rem;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 12px;
}

/* An eyebrow rather than a second heading. The section already has its own
   h2 above, so a 1.5rem title here competed with it and cost a whole line of
   space to say something the panel's own framing already implies. */
.philosophy-section h3 {
  font-size: 0.72rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 0.7rem;
  font-weight: 700;
}

.philosophy-section p {
  color: var(--text-secondary);
  line-height: 1.62;
  margin-bottom: 0.65rem;
  font-size: 0.94rem;
}

.philosophy-section p strong {
  color: var(--text-primary);
  font-weight: 600;
}

.philosophy-section p:last-child {
  margin-bottom: 0;
}

/* ============================================================================
 *  EXPERIENCE SECTION
 * =========================================================================== */

.experience-list {
  max-width: 800px;
  margin: 0 auto;
}

.experience-item {
  padding: 1.4rem 1.6rem;
  margin-bottom: 1rem;
  background: var(--bg-primary);
  border-left: 4px solid var(--accent);
  border-radius: 8px;
  box-shadow: var(--shadow-md);
  transition: var(--transition);
  position: relative;
  overflow: hidden;
}

.experience-item::before {
  content: '';
  position: absolute;
  top: 0;
  right: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(59, 130, 246, 0.1), transparent);
  transition: right 0.5s ease;
}

.experience-item:hover::before {
  right: 100%;
}

.experience-item:hover {
  box-shadow: var(--shadow-lg);
  border-left-color: var(--accent-light);
  transform: translateX(8px);
}

.experience-header {
  display: flex;
  justify-content: space-between;
  align-items: start;
  margin-bottom: 0.6rem;
  gap: 1rem;
  position: relative;
  z-index: 1;
}

.company-name {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text-primary);
  line-height: 1.3;
}

.position {
  font-size: 0.95rem;
  color: var(--accent-light);
  font-weight: 600;
  margin-top: 0.1rem;
}

.duration {
  color: var(--text-tertiary);
  font-weight: 500;
  white-space: nowrap;
  font-size: 0.9rem;
}

.experience-desc {
  color: var(--text-secondary);
  margin-bottom: 0.65rem;
  line-height: 1.55;
  font-size: 0.95rem;
  position: relative;
  z-index: 1;
}

.responsibilities {
  list-style: none;
  padding-left: 0;
  position: relative;
  z-index: 1;
}

.responsibilities li {
  padding: 0.22rem 0 0.22rem 1.25rem;
  color: var(--text-secondary);
  position: relative;
  line-height: 1.5;
  font-size: 0.92rem;
}

.responsibilities li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.72rem;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--accent);
}

/* Single source of truth for the location pill. It was previously split across
   three rules that overrode each other, leaving a tinted pill with grey text. */
.location-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: rgba(37, 99, 235, 0.09);
  color: var(--accent);
  padding: 0.25rem 0.65rem;
  border-radius: 20px;
  font-size: 0.8rem;
  font-weight: 600;
  margin-top: 0.7rem;
  border: 1px solid rgba(37, 99, 235, 0.2);
  position: relative;
  z-index: 1;
}

.location-badge svg {
  flex-shrink: 0;
  opacity: 0.85;
}

/* ============================================================================
 *  SKILLS SECTION
 * =========================================================================== */

.skills-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.15rem;
}

.skill-card {
  padding: 1.3rem 1.4rem;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: 12px;
  transition: var(--transition);
  position: relative;
  overflow: hidden;
}

.skill-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, var(--accent), var(--accent-light), var(--accent-purple));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s ease;
}

.skill-card:hover::before {
  transform: scaleX(1);
}

.skill-card:hover {
  border-color: var(--accent);
  box-shadow: 0 0 20px rgba(59, 130, 246, 0.2);
  transform: translateY(-8px);
}

.skill-category {
  font-size: 1.2rem;
  font-weight: 700;
  color: var(--accent-light);
  margin-bottom: 0.85rem;
  display: flex;
  align-items: center;
  gap: 0.65rem;
}

.skill-category::before {
  content: '';
  display: inline-block;
  width: 4px;
  height: 24px;
  background: linear-gradient(180deg, var(--accent), var(--accent-light));
  border-radius: 2px;
}

.skill-items {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  align-items: center;
}

/* Closing line on a card, for context the chips cannot carry on their own. */
.skill-note {
  margin: 0.85rem 0 0;
  padding-top: 0.7rem;
  border-top: 1px dashed var(--border);
  font-size: var(--skill-note-size, 0.78rem);
  line-height: 1.5;
  color: var(--text-tertiary);
}

.section--dark .skill-note {
  border-top-color: rgba(148, 163, 184, 0.25);
  color: rgba(203, 213, 225, 0.85);
}

.skill-tag {
  background: rgba(59, 130, 246, 0.1);
  color: var(--accent-light);
  padding: 0.3rem 0.7rem;
  border-radius: 20px;
  font-size: var(--skill-chip-size, 0.78rem);
  font-weight: 500;
  line-height: 1.35;
  transition: var(--transition);
  border: 1px solid rgba(37, 99, 235, 0.45);
  cursor: default;
}

.skill-tag:hover {
  background: var(--accent);
  color: var(--bg-primary);
  border-color: var(--accent-light);
}

/* Chips past the cap stay in the DOM but out of the flow, so expanding is
   instant and the full list is still there for find-in-page and printing. */
.skill-tag.is-overflow {
  display: none;
}

.skill-card.is-expanded .skill-tag.is-overflow {
  display: inline-block;
}

.skill-more {
  padding: 0.3rem 0.65rem;
  border-radius: 20px;
  border: 1px dashed rgba(37, 99, 235, 0.5);
  background: none;
  color: var(--accent);
  font: inherit;
  font-size: 0.74rem;
  font-weight: 600;
  cursor: pointer;
  transition: var(--transition);
}

.skill-more:hover {
  background: rgba(37, 99, 235, 0.1);
  border-style: solid;
}

.skill-more:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.section--dark .skill-more {
  color: #7dd3fc;
  border-color: rgba(56, 189, 248, 0.5);
}

.section--dark .skill-more:hover {
  background: rgba(56, 189, 248, 0.14);
}

/* Phones get narrower cards and a tighter grid so the section stays short. */
@media (max-width: 600px) {
  .skills-grid {
    grid-template-columns: 1fr;
    gap: 0.8rem;
  }

  .skill-card {
    padding: 1rem 1.1rem;
  }

  .skill-category {
    font-size: 1rem;
    margin-bottom: 0.6rem;
  }

  .skill-icon {
    width: 32px;
    height: 32px;
  }

  .skill-tag {
    font-size: 0.74rem;
    padding: 0.26rem 0.6rem;
  }
}

/* ============================================================================
 *  PROJECTS SECTION
 * =========================================================================== */

/* ---------------------------------------------------------------------------
   Projects carousel. A snapping horizontal track with arrows and a progress
   bar. Native scrolling, trackpad swipes and arrow keys all still work, so
   the buttons are an extra rather than the only route through.
   ------------------------------------------------------------------------ */

.carousel {
  position: relative;
}

.carousel-track {
  display: flex;
  gap: 1.75rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-left: 2px;
  padding: 0.25rem 0.25rem 1rem;
  /* The custom bar below stands in for the native one. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.carousel-track::-webkit-scrollbar {
  display: none;
}

.carousel-track:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 12px;
}

/* One card fills the track; scrolling moves to the next. */
.carousel-track .project-card {
  flex: 0 0 100%;
  scroll-snap-align: center;
  scroll-snap-stop: always;
}

.carousel-controls {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  margin-top: 0.5rem;
}

.carousel-progress {
  flex: 1;
  height: 3px;
  border-radius: 3px;
  background: var(--border);
  overflow: hidden;
}

.carousel-progress-bar {
  display: block;
  height: 100%;
  width: 8%;
  border-radius: 3px;
  background: linear-gradient(90deg, var(--accent), var(--logo-cyan));
  transition: width 0.15s ease-out;
}

/* "2 of 5 · Click the arrows to browse". Sits between the progress bar and
   the buttons so the eye travels from position, to instruction, to control. */
.carousel-hint {
  flex-shrink: 0;
  margin: 0;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.01em;
  color: var(--text-tertiary);
  white-space: nowrap;
}

.section--dark .carousel-hint {
  color: rgba(203, 213, 225, 0.85);
}

.carousel-buttons {
  display: flex;
  gap: 0.6rem;
  flex-shrink: 0;
}

/* Until the track has been moved once, the forward arrow leans right on a
   loop. It stops on first use, and never starts under reduced motion. */
@keyframes carousel-nudge {
  0%, 60%, 100% { transform: translateX(0); }
  75% { transform: translateX(4px); }
  90% { transform: translateX(1px); }
}

.carousel-btn.is-nudging:not(:disabled) {
  animation: carousel-nudge var(--carousel-nudge-duration, 2.2s) ease-in-out infinite;
  border-color: var(--accent);
  box-shadow: 0 0 0 4px rgba(59, 130, 246, 0.12);
}

.carousel-btn.is-nudging:hover {
  animation: none;
}

@media (prefers-reduced-motion: reduce) {
  .carousel-btn.is-nudging:not(:disabled) {
    animation: none;
  }
}

/* On a phone the three controls will not share one row. Give the progress bar
   its own line and let the hint sit beside the buttons. */
@media (max-width: 640px) {
  .carousel-controls {
    flex-wrap: wrap;
    gap: 0.7rem 1rem;
  }

  .carousel-progress {
    order: 1;
    flex: 1 1 100%;
  }

  .carousel-hint {
    order: 2;
    flex: 1 1 auto;
    white-space: normal;
    font-size: 0.74rem;
  }

  .carousel-buttons {
    order: 3;
    margin-left: auto;
  }
}

.carousel-btn {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 1px solid var(--border);
  background: var(--bg-primary);
  color: var(--accent);
  cursor: pointer;
  transition: var(--transition);
}

.carousel-btn:hover:not(:disabled) {
  border-color: var(--accent);
  background: var(--accent);
  color: #fff;
  transform: translateY(-2px);
}

.carousel-btn:disabled {
  opacity: 0.35;
  cursor: default;
}

.carousel-btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Dark band variants. */
.section--dark .carousel-progress {
  background: rgba(148, 163, 184, 0.25);
}

.section--dark .carousel-btn {
  background: rgba(255, 255, 255, 0.06);
  border-color: rgba(148, 163, 184, 0.3);
  color: #7dd3fc;
}

.section--dark .carousel-btn:hover:not(:disabled) {
  background: #38bdf8;
  border-color: #38bdf8;
  color: #0b1220;
}


.project-card {
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: 12px;
  overflow: hidden;
  transition: var(--transition);
  box-shadow: var(--shadow-md);
  display: flex;
  flex-direction: column;
  position: relative;
}

.project-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--accent-orange), var(--accent), var(--accent-purple));
  opacity: 0;
  transition: opacity 0.3s ease;
}

.project-card:hover::before {
  opacity: 1;
}

.project-card:hover {
  border-color: var(--accent);
  box-shadow: var(--shadow-lg);
  transform: translateY(-8px);
}

.project-header {
  padding: 1.1rem 1.4rem;
  background: var(--bg-secondary);
  border-bottom: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: start;
  gap: 1rem;
}

.project-name {
  font-size: 1.3rem;
  font-weight: 700;
  color: var(--accent-light);
}

.project-year {
  color: var(--text-tertiary);
  font-weight: 600;
  font-size: 0.9rem;
  white-space: nowrap;
}

.project-body {
  padding: 1.3rem 1.4rem;
  flex: 1;
  display: flex;
  flex-direction: column;
}

.project-desc {
  color: var(--text-secondary);
  margin-bottom: 1.5rem;
  line-height: 1.7;
  flex: 1;
}

.project-tech {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: 1rem;
}

.tech-tag {
  background: rgba(59, 130, 246, 0.15);
  color: var(--accent);
  padding: 0.4rem 0.8rem;
  border-radius: 6px;
  font-size: 0.8rem;
  font-weight: 500;
  border: 1px solid rgba(59, 130, 246, 0.3);
  transition: var(--transition);
}

.tech-tag:hover {
  background: var(--accent);
  color: var(--bg-primary);
  border-color: var(--accent-light);
}

.project-link {
  color: var(--accent-light);
  text-decoration: none;
  font-weight: 600;
  transition: var(--transition);
  display: inline-block;
  align-self: flex-start;
}

.project-link:hover {
  color: var(--accent-orange);
  text-decoration: underline;
  transform: translateX(4px);
}

/* ============================================================================
 *  GIT-INSIGHTS SECTION
 * =========================================================================== */

.insights-section {
  background: linear-gradient(135deg, rgba(59, 130, 246, 0.03) 0%, rgba(211, 157, 255, 0.02) 100%);
  position: relative;
  overflow: hidden;
}

.password-overlay {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  background: rgba(255, 255, 255, 0.95);
  backdrop-filter: blur(4px);
  align-items: center;
  justify-content: center;
  z-index: 1000;
  border-radius: 0;
  padding: 2rem;
}

.password-overlay:not(.hidden-overlay) {
  display: flex;
}

.password-overlay.hidden-overlay {
  display: none;
  pointer-events: none;
}

.password-prompt {
  background: var(--bg-primary);
  border: 2px solid var(--border);
  border-radius: 12px;
  padding: 3rem;
  max-width: 400px;
  text-align: center;
  box-shadow: var(--shadow-xl);
}

.password-header {
  margin-bottom: 2rem;
}

.password-header h3 {
  font-size: 1.5rem;
  color: var(--accent);
  margin-bottom: 0.5rem;
  font-weight: 700;
}

.password-header p {
  color: var(--text-secondary);
  font-size: 1rem;
}

.password-input {
  width: 100%;
  padding: 0.75rem 1rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-size: 1rem;
  color: var(--text-primary);
  background: var(--bg-secondary);
  margin-bottom: 1rem;
  transition: var(--transition);
}

.password-input:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1);
}

.password-input::placeholder {
  color: var(--text-tertiary);
}

.password-btn {
  width: 100%;
  padding: 0.85rem 1.5rem;
  background: linear-gradient(135deg, var(--accent) 0%, var(--accent-dark) 100%);
  color: white;
  border: none;
  border-radius: 8px;
  font-size: 1rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
}

.password-btn:hover {
  transform: translateY(-2px);
  box-shadow: 0 8px 20px rgba(37, 99, 235, 0.4);
}

.password-btn:active {
  transform: translateY(0);
  box-shadow: 0 2px 8px rgba(37, 99, 235, 0.3);
}

.password-btn:focus {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

.insights-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: 1.15rem;
}

.insight-card {
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: 12px;
  padding: 1.3rem 1.4rem;
  transition: var(--transition);
  box-shadow: var(--shadow-md);
  position: relative;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.insight-card::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--accent), var(--accent-light));
  opacity: 0;
  transition: opacity 0.3s ease;
}

.insight-card:hover::before {
  opacity: 1;
}

.insight-card:hover {
  border-color: var(--accent);
  box-shadow: 0 0 30px rgba(59, 130, 246, 0.25);
  transform: translateY(-8px);
}

.insight-card h3 {
  color: var(--accent-light);
  font-size: 1.3rem;
  margin-bottom: 1rem;
  font-weight: 700;
}

.insight-card p {
  color: var(--text-secondary);
  line-height: 1.7;
  margin-bottom: 1.5rem;
  flex: 1;
}

.insight-link {
  color: var(--accent);
  text-decoration: none;
  font-weight: 600;
  transition: var(--transition);
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  align-self: flex-start;
}

.insight-link--locked {
  color: var(--text-secondary);
}

.insight-link--locked:hover {
  color: var(--accent);
}

.insight-link:hover {
  color: var(--accent-light);
  text-decoration: underline;
  transform: translateX(4px);
}

/* ============================================================================
 *  EDUCATION SECTION
 * =========================================================================== */

.education-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
  gap: 1.15rem;
  margin-bottom: 1.5rem;
}

.education-item {
  padding: 1.3rem 1.4rem;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-left: 4px solid var(--accent-green);
  border-radius: 8px;
  transition: var(--transition);
}

.education-item:hover {
  box-shadow: var(--shadow-lg);
  transform: translateY(-4px);
  border-left-color: var(--accent-light);
}

/* The degree is the headline; the awarding body sits under it. */
.degree {
  font-size: 1.12rem;
  font-weight: 700;
  line-height: 1.3;
  color: var(--text-primary);
  margin-bottom: 0.2rem;
}

.institution {
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--accent);
  margin-bottom: 0.4rem;
}

/* Field and year share a row rather than stacking. */
.edu-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.84rem;
  color: var(--text-tertiary);
}

.edu-meta .field::after {
  content: "\00b7";
  margin-left: 0.5rem;
  opacity: 0.6;
}

.edu-meta .field:last-child::after {
  content: none;
}

.field,
.edu-year {
  color: var(--text-tertiary);
  font-weight: 500;
}

.edu-details {
  margin-top: 0.5rem;
  font-size: 0.86rem;
  line-height: 1.5;
  color: var(--text-secondary);
}

.certifications-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1.15rem;
}

.cert-item {
  padding: 1.3rem 1.4rem;
  background: linear-gradient(135deg, var(--bg-tertiary) 0%, var(--bg-secondary) 100%);
  border: 1px solid var(--border);
  border-top: 4px solid var(--accent-orange);
  border-radius: 8px;
  transition: var(--transition);
}

.cert-item:hover {
  box-shadow: var(--shadow-lg);
  transform: translateY(-4px);
  border-top-color: var(--accent-light);
}

.cert-name {
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 0.5rem;
}

.cert-issuer {
  color: var(--text-secondary);
  font-size: 0.95rem;
  margin-bottom: 0.25rem;
}

.cert-year {
  color: var(--accent-light);
  font-weight: 600;
  font-size: 0.9rem;
}

.cert-dates {
  color: var(--text-tertiary);
  font-weight: 500;
  font-size: 0.84rem;
  margin-bottom: 0.35rem;
}

/* The bare fact, without the date. Quiet enough not to dominate the card. */
.cert-lapsed {
  font-style: italic;
  opacity: 0.75;
}

/* Training delivered, not a credential held. The green rule separates it from
   the certifications beside it at a glance. */
.cert-item--training {
  border-top-color: var(--accent-green);
}

.cert-item--training:hover {
  border-top-color: var(--accent-green);
}

.training-topics {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  margin-top: 0.55rem;
}

.training-topic {
  padding: 0.24rem 0.6rem;
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 600;
  color: var(--accent-green);
  background: rgba(5, 150, 105, 0.1);
  border: 1px solid rgba(5, 150, 105, 0.32);
}

.section--dark .training-topic {
  color: #5dd6a8;
  background: rgba(93, 214, 168, 0.12);
  border-color: rgba(93, 214, 168, 0.34);
}

/* A lapsed credential gets a muted top rule, so it reads as history rather
   than as something currently held. */
.cert-item--lapsed {
  border-top-color: var(--text-tertiary);
}

.cert-item--lapsed:hover {
  border-top-color: var(--text-secondary);
}

.cert-credential {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.35rem;
  font-size: 0.78rem;
  color: var(--text-tertiary);
}

.cert-credential code {
  font-family: ui-monospace, "Cascadia Mono", "SF Mono", Menlo, Consolas, monospace;
  font-size: 0.95em;
  letter-spacing: 0.02em;
  color: var(--text-secondary);
  word-break: break-all;
}

.cert-note {
  margin-top: 0.5rem;
  padding-top: 0.5rem;
  border-top: 1px dashed var(--border);
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--text-tertiary);
}

.section--dark .cert-dates,
.section--dark .cert-credential { color: #94a3b8; }
.section--dark .cert-credential code { color: #cbd5e1; }
.section--dark .cert-note {
  color: #94a3b8;
  border-top-color: rgba(148, 163, 184, 0.25);
}

/* ============================================================================
 *  CONTACT SECTION
 * =========================================================================== */

/* Form on the left, direct channels on the right. Stacking these was what
   made the section so tall while leaving the width unused. */
.contact-layout {
  display: grid;
  grid-template-columns: 1.55fr 1fr;
  gap: 1.75rem;
  align-items: start;
  max-width: 940px;
  margin: 0 auto;
}

.contact-form {
  max-width: none;
  margin: 0;
}

/* The right column is narrow, so the two channels stack inside it. */
.contact-layout .quick-actions {
  max-width: none;
  margin: 0;
  height: 100%;
}

.contact-layout .quick-action-grid {
  grid-template-columns: 1fr;
  gap: 0.7rem;
}

@media (max-width: 820px) {
  .contact-layout {
    grid-template-columns: 1fr;
    gap: 1.25rem;
  }

  .contact-layout .quick-action-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.form-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 0.85rem;
}

.form-group {
  margin-bottom: 0.85rem;
}

.form-group input,
.form-group textarea {
  width: 100%;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  font-family: inherit;
  font-size: 1rem;
  color: var(--text-primary);
  transition: var(--transition);
  background: var(--bg-tertiary);
}

.form-group input::placeholder,
.form-group textarea::placeholder {
  color: var(--text-tertiary);
}

.form-group input:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: var(--bg-secondary);
  box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.2);
}

/* Send Message leads; Clear sits beside it as a quiet text action so it never
   competes with the primary button. */
.form-actions {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 0.9rem;
}

.form-clear {
  background: none;
  border: 0;
  padding: 0.35rem 0.1rem;
  font-family: inherit;
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--text-tertiary);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-color: color-mix(in srgb, currentColor 40%, transparent);
  transition: color 0.2s ease;
}

.form-clear:hover {
  color: var(--accent);
}

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

.section--dark .form-clear {
  color: #94a3b8;
}

.section--dark .form-clear:hover {
  color: #7dd3fc;
}

.form-status {
  margin-top: 1rem;
  padding: 1rem;
  border-radius: 8px;
  display: none;
  font-weight: 600;
  border: 1px solid;
}

.form-status.success {
  display: block;
  background: rgba(63, 185, 80, 0.15);
  color: var(--accent-green);
  border-color: var(--accent-green);
}

.form-status.error {
  display: block;
  background: rgba(248, 81, 73, 0.15);
  color: #f85149;
  border-color: #f85149;
}

/* --- icon alignment across the page --- */

.section-title {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 0.7rem;
}

/* Tinted badge behind each heading glyph, echoing the logo's two hues. */
.section-icon {
  display: inline-grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: 13px;
  flex-shrink: 0;
  color: var(--accent);
  background:
    linear-gradient(135deg, rgba(37, 99, 235, 0.12) 0%, rgba(34, 211, 238, 0.12) 100%);
  box-shadow: inset 0 0 0 1px rgba(37, 99, 235, 0.14);
}

.section-title svg {
  flex-shrink: 0;
}

/* Holds the pin icon beside the location text. */
.hero-subtitle {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
}

.hero-subtitle svg {
  flex-shrink: 0;
  opacity: 0.8;
}


.skill-icon {
  display: inline-grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 10px;
  color: var(--accent);
  background: rgba(37, 99, 235, 0.09);
  flex-shrink: 0;
}


.insight-link svg {
  flex-shrink: 0;
}

.cta-btn svg {
  vertical-align: -0.2em;
  margin-right: 0.5rem;
}

.social-link svg {
  display: block;
}

/* Styled tooltip carrying the real address / number / profile. */
.social-link {
  position: relative;
}

.social-link::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 10px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  padding: 0.4rem 0.7rem;
  border-radius: 7px;
  background: var(--text-primary);
  color: var(--bg-primary);
  font-size: 0.76rem;
  font-weight: 600;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
  z-index: 20;
}

.social-link::before {
  content: '';
  position: absolute;
  bottom: calc(100% + 5px);
  left: 50%;
  transform: translateX(-50%) translateY(4px);
  border: 5px solid transparent;
  border-top-color: var(--text-primary);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
  z-index: 20;
}

.social-link[data-tip]:hover::after,
.social-link[data-tip]:focus-visible::after,
.social-link[data-tip]:hover::before,
.social-link[data-tip]:focus-visible::before {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* --- call chooser --- */

.hero-socials {
  position: relative;
}

.phone-menu {
  display: flex;
  flex-direction: column;
  gap: 0.4rem;
  width: max-content;
  margin: 0.9rem auto 0;
  padding: 0.5rem;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: var(--bg-primary);
  box-shadow: var(--shadow-lg);
}

/* Sits inline under the quick actions rather than floating as a popover, so
   it pushes the section open instead of covering what is beneath it. */
.phone-menu--inline {
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  gap: 0.5rem;
  width: 100%;
  max-width: 30rem;
  margin: 0.75rem auto 0;
}

.phone-menu--inline .phone-option-row {
  flex: 1 1 13rem;
}

.section--dark .phone-menu--inline {
  background: rgba(12, 20, 36, 0.85);
  border-color: rgba(148, 163, 184, 0.28);
}

/* Marks the Call action while its numbers are on screen. */
.send-channel.is-open {
  border-color: var(--channel-accent, var(--accent));
  background: color-mix(in srgb, var(--channel-accent, var(--accent)) 14%, transparent);
}

/* The number and its copy button. The button is a sibling of the link, never
   a child: a button inside an anchor is invalid, and tapping it would dial. */
.phone-option-row {
  display: flex;
  align-items: center;
  gap: 0.15rem;
}

.phone-option-row .copy-btn {
  flex-shrink: 0;
  margin-right: 0.3rem;
}

.phone-option {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.6rem 0.9rem;
  border-radius: 8px;
  text-decoration: none;
  color: var(--text-primary);
  transition: var(--transition);
  flex: 1 1 auto;
}

.phone-option:hover {
  background: var(--bg-secondary);
  color: var(--accent);
}

.phone-option svg {
  flex-shrink: 0;
  color: var(--accent);
}

.phone-option-text {
  display: flex;
  flex-direction: column;
  text-align: left;
  line-height: 1.25;
}

.phone-option-label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-tertiary);
}

.phone-option-number {
  font-size: 0.95rem;
  font-weight: 600;
}

/* Brand marks fill their button rather than sitting as a small stroked glyph. */
.social-link[data-icon="linkedin"] svg,
.social-link[data-icon="github"] svg {
  width: 26px;
  height: 26px;
}

.social-link[data-icon="linkedin"]:hover,
.social-link[data-icon="github"]:hover {
  background: var(--bg-secondary);
}

/* --- form labels & inline validation --- */

[hidden] {
  display: none !important;
}

.form-group label {
  display: block;
  margin-bottom: 0.28rem;
  font-size: 0.82rem;
  font-weight: 600;
  color: var(--text-primary);
}

.form-group label .req {
  color: #dc2626;
  font-weight: 700;
}

.form-group label .optional {
  color: var(--text-tertiary);
  font-weight: 500;
  font-size: 0.8rem;
  text-transform: lowercase;
}

.form-group input.invalid,
.form-group textarea.invalid {
  border-color: #dc2626;
  background: rgba(220, 38, 38, 0.04);
}

.form-group input.invalid:focus,
.form-group textarea.invalid:focus {
  box-shadow: 0 0 0 3px rgba(220, 38, 38, 0.12);
}

/* Collapses to nothing when empty rather than reserving a blank line under
   every field, which was costing four dead rows on a clean form. */
.field-error {
  font-size: 0.8rem;
  color: #dc2626;
}

.field-error:not(:empty) {
  margin-top: 0.28rem;
}

/* --- always-visible quick actions, closing the contact section --- */

.quick-actions {
  max-width: 620px;
  margin: 1.75rem auto 0;
  padding: 1.25rem 1.4rem 1.4rem;
  border-radius: 14px;
  border: 1px solid var(--border);
  background: var(--bg-secondary);
  text-align: center;
}

.quick-actions-head {
  margin-bottom: 1.1rem;
}

.quick-actions-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 0.2rem;
}

.quick-actions-sub {
  color: var(--text-tertiary);
  font-size: 0.85rem;
}

/* Always two across - these are a matched pair, not a wrapping list. */
.quick-action-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.9rem;
}

.quick-action-grid .send-channel {
  flex-direction: row;
  align-items: center;
  text-align: left;
  padding: 0.85rem 1rem;
  gap: 0.75rem;
}

.quick-action-grid .send-channel-icon {
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 11px;
  flex-shrink: 0;
  background: color-mix(in srgb, var(--channel-accent, var(--accent)) 12%, transparent);
  transition: var(--transition);
}

.quick-action-grid .send-channel:hover {
  border-color: var(--channel-accent, var(--accent));
}

.quick-action-grid .send-channel:hover .send-channel-icon {
  background: color-mix(in srgb, var(--channel-accent, var(--accent)) 20%, transparent);
}

.quick-action-grid .send-channel-label {
  font-size: 0.95rem;
  line-height: 1.2;
}

.quick-action-grid .send-channel-hint {
  font-size: 0.76rem;
}

@media (max-width: 520px) {
  .quick-action-grid {
    grid-template-columns: 1fr;
  }
}

/* --- send channel chooser --- */

.send-channels {
  max-width: 940px;
  margin: 1.25rem auto 0;
  padding: 1.35rem 1.5rem;
  background: var(--bg-secondary);
  border: 1px solid var(--border);
  border-radius: 12px;
}

.send-channels-title {
  font-size: 1.05rem;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 0.2rem;
}

.send-channels-hint {
  color: var(--text-tertiary);
  font-size: 0.85rem;
  margin-bottom: 1rem;
}

.send-channel-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 1rem;
}

.send-channel-text {
  display: flex;
  flex-direction: column;
  gap: 0.15rem;
}

.send-channel-icon {
  color: var(--channel-accent, var(--accent));
  display: inline-flex;
}

.send-channel {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 0.55rem;
  padding: 1rem 1.15rem;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: 10px;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  transition: var(--transition);
}

.send-channel:hover {
  border-color: var(--accent);
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}

.send-channel:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}


.send-channel-label {
  font-weight: 600;
  color: var(--text-primary);
}

.send-channel-hint {
  font-size: 0.8rem;
  color: var(--text-tertiary);
}

/* ============================================================================
 *  FOOTER
 * =========================================================================== */

.footer {
  background: var(--bg-primary);
  color: var(--text-secondary);
  padding: 1.5rem 2rem;
  border-top: 1px solid var(--border);
}

/* One row: brand lockup left, credits right. No internal divider. */
.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem 2rem;
  flex-wrap: wrap;
}

.footer-brand {
  display: flex;
  align-items: center;
  gap: 0.7rem;
}

.footer-brand .brand-text {
  font-size: 1.1rem;
}

.footer-meta {
  text-align: right;
  line-height: 1.5;
}

.footer-subtitle {
  font-size: 0.82rem;
  color: var(--accent);
}

.footer-copy {
  font-size: 0.78rem;
  color: var(--text-tertiary);
}

@media (max-width: 640px) {
  .footer-inner {
    flex-direction: column;
    justify-content: center;
    text-align: center;
  }

  .footer-meta {
    text-align: center;
  }
}

/* ============================================================================
 *  EDIT MODE
 * =========================================================================== */

.edit-link {
  margin-left: 0.75rem;
  padding: 0;
  border: 0;
  background: none;
  color: var(--text-tertiary);
  font: inherit;
  font-size: 0.72rem;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
  opacity: 0.65;
  transition: var(--transition);
}

.edit-link:hover {
  color: var(--accent);
  opacity: 1;
}

.edit-panel {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 3rem 1.25rem;
  overflow-y: auto;
  background: rgba(8, 14, 26, 0.55);
  backdrop-filter: blur(3px);
}

.edit-panel-inner {
  width: 100%;
  max-width: 640px;
  background: var(--bg-primary);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: var(--shadow-xl);
  padding: 1.75rem;
}

.edit-panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-bottom: 1rem;
}

.edit-panel-head h3 {
  font-size: 1.25rem;
  font-weight: 700;
  color: var(--text-primary);
}

.edit-close {
  padding: 0.45rem 0.9rem;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--bg-secondary);
  color: var(--text-secondary);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: var(--transition);
}

.edit-close:hover {
  border-color: var(--accent);
  color: var(--accent);
}

/* Whether a save reaches visitors or stays local has to be unmissable. */
.edit-notice {
  padding: 0.75rem 0.9rem;
  margin-bottom: 0.6rem;
  border-radius: 8px;
  border-left: 3px solid var(--accent-orange);
  background: rgba(217, 119, 6, 0.08);
  color: var(--text-secondary);
  font-size: 0.82rem;
  line-height: 1.55;
}

.edit-notice.live {
  border-left-color: var(--accent-green);
  background: rgba(5, 150, 105, 0.08);
}

.edit-sync {
  min-height: 1rem;
  margin-bottom: 1.25rem;
  font-size: 0.78rem;
  font-weight: 600;
}

.edit-sync.ok {
  color: var(--accent-green);
}

.edit-sync.warn {
  color: var(--accent-orange);
}

.edit-block {
  padding-top: 1.25rem;
  margin-top: 1.25rem;
  border-top: 1px solid var(--border);
}

.edit-block:first-of-type {
  padding-top: 0;
  margin-top: 0;
  border-top: 0;
}

.edit-block h4 {
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--text-primary);
  margin-bottom: 0.3rem;
}

.edit-help {
  font-size: 0.8rem;
  color: var(--text-tertiary);
  line-height: 1.5;
  margin-bottom: 0.9rem;
}

.edit-file {
  display: block;
  width: 100%;
  font-size: 0.85rem;
  color: var(--text-secondary);
  margin-bottom: 0.6rem;
}

.edit-current {
  font-size: 0.82rem;
  color: var(--text-secondary);
  margin-bottom: 0.6rem;
}

.edit-fields {
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  margin-bottom: 0.6rem;
}

.edit-fields-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
}

/* The in-place text editors. Grouped so a long list of paths reads as a few
   labelled areas rather than one undifferentiated wall of inputs. */
.edit-text-group {
  padding: 0.9rem 0 0.2rem;
  border-top: 1px solid var(--border);
}

.edit-text-group:first-child {
  border-top: 0;
  padding-top: 0;
}

.edit-text-group-title {
  margin: 0 0 0.15rem;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--text-primary);
}

.edit-text-group .edit-inline-label {
  margin-top: 0.6rem;
}

.edit-fields input,
.edit-fields textarea,
.edit-fields select,
.edit-text-group input,
.edit-text-group textarea {
  width: 100%;
  padding: 0.6rem 0.75rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  background: var(--bg-secondary);
  color: var(--text-primary);
  font: inherit;
  font-size: 0.88rem;
}

.edit-text-group textarea {
  min-height: 4.5rem;
  line-height: 1.5;
  resize: vertical;
}

.edit-fields input:focus,
.edit-fields textarea:focus,
.edit-fields select:focus,
.edit-text-group input:focus,
.edit-text-group textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);
}

.edit-inline-label {
  font-size: 0.78rem;
  font-weight: 600;
  color: var(--text-secondary);
}

.edit-error {
  min-height: 1rem;
  font-size: 0.8rem;
  color: #dc2626;
  margin-bottom: 0.5rem;
}

.edit-btn {
  padding: 0.55rem 1.1rem;
  border-radius: 8px;
  border: 1px solid var(--border);
  background: var(--bg-secondary);
  color: var(--text-primary);
  font: inherit;
  font-size: 0.85rem;
  font-weight: 600;
  cursor: pointer;
  transition: var(--transition);
}

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

.edit-btn.primary:hover {
  background: var(--accent-dark);
}

.edit-btn.subtle {
  padding: 0.3rem 0.65rem;
  font-size: 0.76rem;
  color: var(--text-tertiary);
}

.edit-btn.subtle:hover {
  color: #dc2626;
  border-color: #dc2626;
}

.edit-btn.danger {
  color: #dc2626;
  border-color: rgba(220, 38, 38, 0.4);
}

.edit-btn.danger:hover {
  background: #dc2626;
  color: #fff;
}

/* --- reorder list --- */

.edit-order-row {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding: 0.55rem 0.7rem;
  border: 1px solid var(--border);
  border-radius: 8px;
  margin-bottom: 0.45rem;
  background: var(--bg-secondary);
}

.edit-order-index {
  flex-shrink: 0;
  width: 22px;
  height: 22px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 700;
}

.edit-order-name {
  flex: 1;
  min-width: 0;
  font-size: 0.85rem;
  color: var(--text-primary);
}

.edit-order-tag {
  font-size: 0.68rem;
  font-style: normal;
  color: var(--accent);
  margin-left: 0.4rem;
  opacity: 0.8;
}

.edit-order-actions {
  display: flex;
  align-items: center;
  gap: 0.35rem;
  flex-shrink: 0;
}

.edit-icon-btn {
  width: 28px;
  height: 28px;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--bg-primary);
  color: var(--accent);
  font-size: 0.9rem;
  line-height: 1;
  cursor: pointer;
  transition: var(--transition);
}

.edit-icon-btn:hover:not(:disabled) {
  background: var(--accent);
  color: #fff;
  border-color: var(--accent);
}

.edit-icon-btn:disabled {
  opacity: 0.3;
  cursor: default;
}

/* Destructive and site-wide, so it gets its own clearly marked block
   rather than sitting as an unlabelled button. */
.edit-panel-foot {
  padding: 1.1rem 1.2rem;
  margin-top: 1.5rem;
  border: 1px solid rgba(220, 38, 38, 0.3);
  border-radius: 10px;
  background: rgba(220, 38, 38, 0.04);
}

.edit-panel-foot h4 {
  font-size: 0.95rem;
  font-weight: 700;
  color: #b91c1c;
  margin-bottom: 0.3rem;
}

@media (max-width: 520px) {
  .edit-fields-row {
    grid-template-columns: 1fr;
  }
}

/* ============================================================================
 *  RESPONSIVE DESIGN
 * =========================================================================== */

@media (max-width: 768px) {
  .nav-toggle {
    display: flex;
  }

  .nav-menu {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.5rem;
    background: var(--bg-secondary);
    padding: 1rem 2rem;
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-lg);
    max-height: 0;
    overflow: hidden;
    transition: max-height 0.3s ease;
  }

  /* Stacked, so the links get their own readable size back. */
  .nav-link {
    font-size: var(--nav-font-size-mobile);
    padding: 0.4rem 0;
    width: 100%;
  }

  .nav-menu.active {
    /* Nine rows need more headroom than the old 400px, and the list scrolls
       on short screens rather than being clipped. */
    max-height: 70vh;
    overflow-y: auto;
  }

  /* .hero-title is fluid via clamp(), so no override is needed here. */

  .section-title {
    font-size: 2rem;
  }

  .hero-cta {
    flex-direction: column;
    max-width: 300px;
    margin-left: auto;
    margin-right: auto;
  }

  .cta-btn {
    width: 100%;
  }

  .about-grid {
    grid-template-columns: 1fr;
    gap: 2rem;
  }

  .about-stats {
    grid-template-columns: 1fr;
  }

  .skills-grid,
  .projects-grid,
  .education-list,
  .certifications-list {
    grid-template-columns: 1fr;
  }

  .section {
    padding: 3rem 1.5rem;
  }

  .hero {
    padding: 3rem 1.5rem;
  }
}

@media (max-width: 480px) {
  .main-content {
    margin-top: 70px;
  }

  .navbar {
    padding: 0.75rem 0;
  }

  .nav-container {
    padding: 0 1rem;
  }

  .nav-brand {
    font-size: 1.3rem;
  }

  .nav-menu {
    padding: 0.75rem 1rem;
  }

  .hero-avatar {
    width: 120px;
    height: 120px;
  }

  /* .hero-title is fluid via clamp(); the lower bound already covers phones. */

  .hero-subtitle {
    font-size: 1.1rem;
  }

  .section-title {
    font-size: 1.5rem;
  }

  .container {
    padding: 0 1rem;
  }

  .hero-socials {
    gap: 0.75rem;
  }

  .social-link {
    width: 40px;
    height: 40px;
    font-size: 1.1rem;
  }
}