/* =============================================================
   EdgeConn Design System
   Fonts are loaded via <link> in each page's <head> (Google Fonts,
   font-display=swap) — see components/header.html or any page head.
   Heading font: Sora · Body/UI font: Inter
   ============================================================= */

/* ---------- Design tokens ---------- */
:root {
  /* Color — brand */
  --color-primary: #3652f6;
  --color-primary-dark: #2540d6;
  --color-primary-light: #e8ecfe;
  --color-accent: #ff6b4a;
  /* a11y: darkened from #e0532f — the original failed WCAG AA (3.28:1) as text
     on --color-accent-light (badge-accent, value-icon); this pairing is now 4.89:1. */
  --color-accent-dark: #b83a1a;
  --color-accent-light: #ffe8e1;

  /* Color — neutrals (near-white to near-black) */
  --color-gray-50: #fafafb;
  --color-gray-100: #f1f2f5;
  --color-gray-300: #d7d9df;
  --color-gray-500: #8b8f9c;
  /* a11y: gray-500 (#8b8f9c) is 3.23:1 on white — fails 4.5:1 for text, though it
     passes fine as light copy on the dark footer. Adding gray-600 as a distinct,
     darker rung specifically for muted/disabled text on light backgrounds
     (.link-arrow--disabled) so we don't have to darken gray-500 globally and
     break the footer usage that already relies on its lighter value. */
  --color-gray-600: #6b7280;
  --color-gray-700: #4a4e5a;
  --color-gray-900: #14161c;

  /* Color — semantic aliases */
  --color-bg: #ffffff;
  --color-surface: var(--color-gray-50);
  --color-border: var(--color-gray-300);
  /* a11y: gray-300 (1.41:1 on white) is well below the 3:1 UI-component-boundary
     minimum. It's fine for the many decorative dividers/card borders that use
     --color-border (not subject to 1.4.11), but form fields need their own,
     more visible border so users can actually perceive the field boundary. */
  --color-input-border: #828a99;
  --color-text: var(--color-gray-900);
  --color-text-muted: var(--color-gray-700);

  /* Color — form / status states */
  /* a11y: darkened from #1a9e5c — the original was 3.45:1 on white / 3.06:1 on
     --color-success-light, both below the 4.5:1 text minimum. New value is
     5.77:1 / 5.11:1. */
  --color-success: #12753e;
  --color-success-light: #e2f6ea;
  /* a11y: darkened from #e5384d — the original was 4.20:1 on white / 3.60:1 on
     --color-error-light, both below the 4.5:1 text minimum. New value is
     5.67:1 / 4.86:1. */
  --color-error: #c81e3a;
  --color-error-light: #fce9eb;

  /* Typography — families */
  --font-heading: 'Sora', 'Segoe UI', sans-serif;
  --font-body: 'Inter', 'Segoe UI', sans-serif;

  /* Typography — modular scale */
  --text-xs: 0.75rem;    /* 12px */
  --text-sm: 0.875rem;   /* 14px */
  --text-base: 1rem;     /* 16px */
  --text-lg: 1.125rem;   /* 18px */
  --text-xl: 1.25rem;    /* 20px */
  --text-2xl: 1.5rem;    /* 24px */
  --text-3xl: 1.875rem;  /* 30px */
  --text-4xl: 2.25rem;   /* 36px */
  --text-5xl: 3rem;      /* 48px */
  --text-6xl: 3.75rem;   /* 60px */

  /* Typography — line heights & weights */
  --leading-tight: 1.15;
  --leading-snug: 1.35;
  --leading-normal: 1.6;
  --leading-relaxed: 1.75;
  --font-normal: 400;
  --font-medium: 500;
  --font-semibold: 600;
  --font-bold: 700;

  /* Spacing — 4px base unit */
  --space-1: 0.25rem;  /* 4px */
  --space-2: 0.5rem;   /* 8px */
  --space-3: 0.75rem;  /* 12px */
  --space-4: 1rem;     /* 16px */
  --space-5: 1.5rem;   /* 24px */
  --space-6: 2rem;     /* 32px */
  --space-7: 3rem;     /* 48px */
  --space-8: 4rem;     /* 64px */

  /* Radius */
  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 16px;
  --radius-full: 999px;

  /* Shadow */
  --shadow-sm: 0 1px 2px rgba(20, 22, 28, 0.06);
  --shadow-md: 0 4px 16px rgba(20, 22, 28, 0.08);
  --shadow-lg: 0 16px 40px rgba(20, 22, 28, 0.12);

  /* Transitions */
  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --transition-fast: 150ms var(--ease);
  --transition-base: 220ms var(--ease);
  --transition-slow: 400ms var(--ease);

  /* Layout */
  --container-max: 1200px;
  --container-padding: var(--space-5);

  /* Breakpoints — documented for reference only; custom properties
     cannot be substituted into @media feature values, so the same
     768px / 1200px figures are hardcoded in the media queries below. */
  --breakpoint-tablet: 768px;
  --breakpoint-desktop: 1200px;
}

@media (min-width: 768px) {
  :root { --container-padding: var(--space-6); }
}

@media (min-width: 1200px) {
  :root { --container-padding: var(--space-7); }
}

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

* {
  margin: 0;
  padding: 0;
}

html {
  -webkit-text-size-adjust: 100%;
}

body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-text);
  background-color: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

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

ul,
ol {
  list-style: none;
}

button,
input,
textarea,
select {
  font: inherit;
  color: inherit;
}

/* ---------- Accessibility: visible focus ----------
   Only .input fields (and its select/textarea variants) define their own
   :focus styling (border-color change + ring, see the Forms section) — every
   other interactive element on the site (buttons, links, nav toggle, carousel
   controls, accordion triggers, filter buttons, card links) was relying on
   whatever the browser's default outline happens to be, which varies across
   browsers and can be hard to see. This site also has three very different
   focusable surfaces — plain white/light backgrounds, the near-black footer,
   and the primary-blue gradient CTA band — and no single flat outline color
   has strong contrast against all three simultaneously. A white inner ring +
   dark outer ring (in either order, at least one of the two is always
   high-contrast against any of those three surfaces) is the standard fix for
   that. :focus-visible (not :focus) so it only appears for keyboard/
   programmatic focus, not mouse clicks. .input's own :focus rule (higher
   specificity, see Forms section) overrides this for form fields, so their
   existing border-color + ring treatment is unaffected. */
:focus-visible {
  outline: 2px solid #ffffff;
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--color-gray-900);
}

/* Skip link: off-screen until focused, so the first Tab press on any page
   lets a keyboard user jump straight past the nav to <main>, rather than
   having to tab through every header/nav link first. Plain :focus (not
   :focus-visible) is fine here — nothing but keyboard/AT focus can ever
   reach an off-screen link, so there's no mouse-click case to exclude. */
.skip-link {
  position: absolute;
  top: -100px;
  left: var(--space-4);
  z-index: 9999;
  padding: var(--space-3) var(--space-5);
  background-color: var(--color-gray-900);
  color: #ffffff;
  border-radius: var(--radius-md);
  font-weight: var(--font-semibold);
  transition: top var(--transition-base);
}

.skip-link:focus {
  top: var(--space-4);
  outline: 2px solid #ffffff;
  outline-offset: 2px;
  box-shadow: 0 0 0 4px var(--color-gray-900);
}

/* ---------- Typography ---------- */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-heading);
  font-weight: var(--font-semibold);
  line-height: var(--leading-tight);
  letter-spacing: -0.01em;
  color: var(--color-gray-900);
}

h1 { font-size: var(--text-4xl); }
h2 { font-size: var(--text-3xl); }
h3 { font-size: var(--text-2xl); }
h4 { font-size: var(--text-xl); }
h5 { font-size: var(--text-lg); }
h6 { font-size: var(--text-base); }

@media (min-width: 768px) {
  h1 { font-size: var(--text-5xl); }
  h2 { font-size: var(--text-4xl); }
  h3 { font-size: var(--text-3xl); }
}

@media (min-width: 1200px) {
  h1 { font-size: var(--text-6xl); }
}

p {
  line-height: var(--leading-normal);
}

p + p {
  margin-top: var(--space-4);
}

.lead {
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
  color: var(--color-text-muted);
}

small,
.text-small {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* ---------- Layout: container & grid ---------- */
.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--container-padding);
}

.grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .grid-cols-2,
  .grid-cols-3,
  .grid-cols-4 {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1200px) {
  .grid-cols-3 { grid-template-columns: repeat(3, 1fr); }
  .grid-cols-4 { grid-template-columns: repeat(4, 1fr); }
}

/* Responsive: reflow — .grid-cols-3's generic 2-column tablet step (above)
   works fine for variable-length collections (e.g. a filterable project grid,
   where a partial last row reads as normal), but these sections always hold
   exactly 3 fixed cards (pricing tiers, featured work, professional-
   experience projects). At 2 columns the 3rd card ends up alone in its own
   row with empty space beside it, which reads like a mistake rather than a
   deliberate layout. Keeping them at 1 column through tablet and jumping
   straight to 3 at desktop avoids that. */
@media (min-width: 768px) and (max-width: 1199px) {
  #packages .grid-cols-3,
  #work .grid-cols-3,
  #professional .grid-cols-3 {
    grid-template-columns: 1fr;
  }
}

.flex {
  display: flex;
}

.flex-wrap {
  flex-wrap: wrap;
}

.items-center {
  align-items: center;
}

.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }

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

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

/* ---------- Section wrapper ---------- */
.section {
  padding-block: var(--space-7);
}

@media (min-width: 768px) {
  .section { padding-block: var(--space-8); }
}

.section-sm {
  padding-block: var(--space-6);
}

.section--muted {
  background-color: var(--color-surface);
}

.section-header {
  max-width: 640px;
  margin-bottom: var(--space-6);
}

.eyebrow {
  display: inline-block;
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--color-primary);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-bottom: var(--space-2);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  font-family: var(--font-body);
  font-size: var(--text-base);
  font-weight: var(--font-medium);
  line-height: 1;
  padding: var(--space-3) var(--space-5);
  /* touch target: padding + line-height alone computes to 40px (base) or 30px
     (.btn-sm) — both under the 44px minimum. min-height guarantees the floor
     at every size without changing the padding/font that gives each size its
     visual character; .btn-lg already clears 44px so this is a no-op there. */
  min-height: 44px;
  border-radius: var(--radius-md);
  border: 1px solid transparent;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color var(--transition-base),
    border-color var(--transition-base), color var(--transition-base),
    transform var(--transition-fast);
}

.btn:active {
  transform: translateY(1px);
}

.btn-primary {
  background-color: var(--color-primary);
  color: #ffffff;
}

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

.btn-secondary {
  background-color: var(--color-gray-900);
  color: #ffffff;
}

.btn-secondary:hover {
  background-color: var(--color-gray-700);
}

.btn-outline {
  background-color: transparent;
  border-color: var(--color-border);
  color: var(--color-text);
}

.btn-outline:hover {
  border-color: var(--color-gray-900);
  background-color: var(--color-gray-50);
}

.btn-outline-light {
  background-color: transparent;
  /* a11y: 0.35 opacity measured ~1.9-2.2:1 against the primary/primary-dark
     backgrounds this button sits on (cta-section) — below the 3:1 UI-boundary
     minimum. 0.7 measures ~3.6-4.5:1 depending on where on the gradient it sits. */
  border-color: rgba(255, 255, 255, 0.7);
  color: #ffffff;
}

.btn-outline-light:hover {
  background-color: rgba(255, 255, 255, 0.1);
  border-color: rgba(255, 255, 255, 0.85);
}

.btn-sm {
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
}

.btn-lg {
  padding: var(--space-4) var(--space-6);
  font-size: var(--text-lg);
}

/* ---------- Cards ---------- */
.card {
  background-color: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base), transform var(--transition-base);
}

.card:hover {
  box-shadow: var(--shadow-md);
}

.card-title {
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  font-weight: var(--font-semibold);
  margin-bottom: var(--space-2);
}

.card-body {
  color: var(--color-text-muted);
}

.card-footer {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

/* ---------- Badge / tag ---------- */
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  font-size: var(--text-xs);
  font-weight: var(--font-semibold);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-full);
  background-color: var(--color-gray-100);
  color: var(--color-gray-700);
}

.badge-primary {
  background-color: var(--color-primary-light);
  color: var(--color-primary-dark);
}

.badge-accent {
  background-color: var(--color-accent-light);
  color: var(--color-accent-dark);
}

.badge-success {
  background-color: var(--color-success-light);
  color: var(--color-success);
}

.badge-error {
  background-color: var(--color-error-light);
  color: var(--color-error);
}

/* Outlined, not filled — deliberately distinct from the solid badges above,
   so a "Concept Project" label never reads as one of our real, filled
   category badges (Mobile & AI, Backend & Integration, etc.). */
.badge-outline {
  background-color: transparent;
  border: 1.5px solid var(--color-primary);
  color: var(--color-primary-dark);
}

/* ---------- Forms (uses success / error tokens) ---------- */
.field {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-bottom: var(--space-5);
}

.label {
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--color-text);
}

.input {
  font-family: var(--font-body);
  font-size: var(--text-base);
  padding: var(--space-3) var(--space-4);
  /* a11y: --color-border is only 1.41:1 on white — fine for decorative dividers,
     but a form field's boundary needs to actually be perceivable (WCAG 1.4.11,
     3:1 minimum), so inputs get their own darker --color-input-border (3.47:1). */
  border: 1px solid var(--color-input-border);
  border-radius: var(--radius-md);
  background-color: var(--color-bg);
  transition: border-color var(--transition-base), box-shadow var(--transition-base);
}

.input:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-light);
}

.input-success {
  border-color: var(--color-success);
}

.input-error {
  border-color: var(--color-error);
}

.help-text {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.help-text.is-success { color: var(--color-success); }
.help-text.is-error { color: var(--color-error); }

/* ---------- Header & navigation ---------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background-color: var(--color-bg);
  border-bottom: 1px solid transparent;
  transition: box-shadow var(--transition-base), border-color var(--transition-base);
}

.site-header.is-scrolled {
  border-bottom-color: var(--color-border);
  box-shadow: var(--shadow-sm);
}

.site-header-inner {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-4);
}

.logo {
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  font-weight: var(--font-bold);
  color: var(--color-gray-900);
  letter-spacing: -0.01em;
}

.nav-toggle {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  /* touch target: was 40x40, under the 44px minimum */
  width: 44px;
  height: 44px;
  background-color: transparent;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  cursor: pointer;
}

.nav-toggle-bar {
  width: 18px;
  height: 2px;
  background-color: var(--color-gray-900);
  border-radius: var(--radius-full);
  transition: transform var(--transition-base), opacity var(--transition-base);
}

.nav-toggle.is-active .nav-toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle.is-active .nav-toggle-bar:nth-child(2) { opacity: 0; }
.nav-toggle.is-active .nav-toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.site-nav {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
  padding: var(--space-5);
  background-color: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
  box-shadow: var(--shadow-md);
  transform: translateY(-8px);
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transition: transform var(--transition-base), opacity var(--transition-base), visibility var(--transition-base);
  /* responsive: giving every link a proper 44px touch target (below) makes
     this dropdown ~550px tall with all 7 links + CTA open — taller than the
     visible viewport on shorter phones (iPhone SE-class, ~607px). Capping the
     height and scrolling internally keeps every item reachable instead of
     silently pushing the CTA below the fold with no way to reach it. */
  max-height: calc(100vh - 80px);
  overflow-y: auto;
}

.site-nav.is-open {
  transform: translateY(0);
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
}

.site-nav-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.site-nav-list a {
  display: inline-block;
  /* touch target: font-size + inherited line-height alone is ~26px tall with
     no padding — under the 44px minimum. This matters most in the mobile
     dropdown, where these links are the primary way to navigate. */
  padding-block: var(--space-3);
  font-size: var(--text-base);
  font-weight: var(--font-medium);
  color: var(--color-text-muted);
  transition: color var(--transition-base);
}

.site-nav-list a:hover {
  color: var(--color-primary);
}

.site-nav-list a.is-active {
  color: var(--color-primary);
  font-weight: var(--font-semibold);
}

.site-nav-cta {
  align-self: flex-start;
}

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

  .site-nav {
    position: static;
    flex-direction: row;
    align-items: center;
    gap: var(--space-6);
    padding: 0;
    background-color: transparent;
    border-bottom: none;
    box-shadow: none;
    transform: none;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
  }

  .site-nav-list {
    flex-direction: row;
    align-items: center;
    gap: var(--space-5);
  }
}

/* ---------- Footer ---------- */
.site-footer {
  margin-top: var(--space-8);
  background-color: var(--color-gray-900);
  color: var(--color-gray-300);
}

.site-footer .logo {
  color: #ffffff;
}

.site-footer-inner {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
  padding-block: var(--space-8);
}

@media (min-width: 768px) {
  .site-footer-inner {
    grid-template-columns: 2fr 1fr 1fr;
    gap: var(--space-6);
  }
}

.site-footer-tagline {
  margin-top: var(--space-3);
  max-width: 32ch;
  color: var(--color-gray-300);
}

.site-footer-social {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.site-footer-social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* touch target: was 36x36, under the 44px minimum */
  width: 44px;
  height: 44px;
  border-radius: var(--radius-full);
  background-color: rgba(255, 255, 255, 0.08);
  color: var(--color-gray-100);
  transition: background-color var(--transition-base), color var(--transition-base);
}

.site-footer-social a:hover {
  background-color: var(--color-primary);
  color: #ffffff;
}

.site-footer h6 {
  color: var(--color-gray-100);
  font-size: var(--text-sm);
  text-transform: uppercase;
  letter-spacing: 0.06em;
  margin-bottom: var(--space-4);
}

.site-footer-links ul,
.site-footer-contact ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

.site-footer-links a,
.site-footer-contact a {
  color: var(--color-gray-300);
  transition: color var(--transition-base);
}

.site-footer-links a:hover,
.site-footer-contact a:hover,
.site-footer-links a.is-active {
  color: #ffffff;
}

.site-footer-links a.is-active {
  font-weight: var(--font-semibold);
}

.site-footer-bottom {
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.site-footer-bottom-inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  padding-block: var(--space-5);
  font-size: var(--text-sm);
  /* gray-500 (not gray-600) deliberately — on this dark footer background it's
     5.60:1, comfortably above 4.5:1; gray-600 was tuned for light backgrounds
     and only manages 3.74:1 here. */
  color: var(--color-gray-500);
}

@media (min-width: 768px) {
  .site-footer-bottom-inner {
    flex-direction: row;
    justify-content: space-between;
  }
}

/* ---------- Home: hero ---------- */
.hero {
  position: relative;
  overflow: hidden;
}

.hero-inner {
  display: grid;
  gap: var(--space-7);
  align-items: center;
}

@media (min-width: 1200px) {
  .hero-inner {
    grid-template-columns: 1.1fr 0.9fr;
    gap: var(--space-8);
  }
}

.hero-subheadline {
  margin-top: var(--space-4);
  max-width: 52ch;
}

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

.hero-visual {
  position: relative;
}

.hero-glow {
  position: absolute;
  inset: -15% -10%;
  z-index: 0;
  background:
    radial-gradient(circle at 30% 25%, var(--color-primary-light), transparent 60%),
    radial-gradient(circle at 75% 75%, var(--color-accent-light), transparent 60%);
  filter: blur(40px);
}

.code-card {
  position: relative;
  z-index: 1;
  background-color: var(--color-gray-900);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}

.code-card-header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-3) var(--space-4);
  background-color: rgba(255, 255, 255, 0.04);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.code-dot {
  width: 10px;
  height: 10px;
  border-radius: var(--radius-full);
  background-color: rgba(255, 255, 255, 0.2);
}

.code-card-title {
  margin-left: var(--space-2);
  font-family: monospace;
  font-size: var(--text-xs);
  color: var(--color-gray-300);
}

.code-card-body {
  padding: var(--space-5);
  font-family: Consolas, Monaco, monospace;
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
  color: var(--color-gray-100);
  overflow-x: auto;
}

.code-keyword {
  color: var(--color-accent);
}

.code-fn {
  color: #ffffff;
  font-weight: var(--font-semibold);
}

/* ---------- Home: trust bar ---------- */
.trust-bar {
  border-top: 1px solid var(--color-border);
  border-bottom: 1px solid var(--color-border);
}

.trust-bar-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-4);
  text-align: center;
  padding-block: var(--space-6);
}

@media (min-width: 768px) {
  .trust-bar-inner {
    flex-direction: row;
    justify-content: space-between;
    text-align: left;
  }
}

.trust-bar-text {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.trust-bar-stack {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-5);
}

.trust-bar-stack li {
  font-family: var(--font-heading);
  font-weight: var(--font-semibold);
  font-size: var(--text-sm);
  color: var(--color-gray-700);
  letter-spacing: 0.02em;
}

/* ---------- Home: icon chips (services & value props) ---------- */
.card-icon,
.value-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-md);
  margin-bottom: var(--space-4);
}

.card-icon {
  width: 48px;
  height: 48px;
  background-color: var(--color-primary-light);
  color: var(--color-primary);
}

.card-icon svg {
  width: 24px;
  height: 24px;
}

.value-icon {
  width: 40px;
  height: 40px;
  border-radius: var(--radius-full);
  background-color: var(--color-accent-light);
  color: var(--color-accent-dark);
  margin-bottom: var(--space-3);
}

.value-icon svg {
  width: 20px;
  height: 20px;
}

.value-item h3 {
  /* a11y: this is semantically an h3 (h2 "Why EdgeConn"/"Principles" section
     title -> h3 value items, no skipped level) but keeps the smaller size the
     old h4 rendered at by default, so fixing the heading hierarchy doesn't
     change the visual design. */
  font-size: var(--text-xl);
  margin-bottom: var(--space-2);
}

/* ---------- Home: "learn more" link ---------- */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  /* touch target: a plain text-sized hit area here would be ~22px tall.
     Padding adds a bit more breathing room around these links than before —
     an acceptable tradeoff, and simpler/more robust than trying to cancel it
     out with a negative margin, which would fight with .back-link's own
     margin-bottom on the two pages that combine both classes. */
  padding-block: var(--space-3);
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--color-primary);
  transition: gap var(--transition-base), color var(--transition-base);
}

.link-arrow:hover {
  gap: var(--space-2);
  color: var(--color-primary-dark);
}

/* ---------- Home: featured work cards ---------- */
.work-card {
  display: block;
  background-color: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base), transform var(--transition-base);
}

.work-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

.work-card-thumb {
  height: 160px;
  display: flex;
  align-items: flex-end;
  padding: var(--space-4);
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
}

.work-card-thumb--2 {
  background: linear-gradient(135deg, var(--color-accent), var(--color-accent-dark));
}

.work-card-thumb--3 {
  background: linear-gradient(135deg, var(--color-gray-700), var(--color-gray-900));
}

.badge-on-image {
  background-color: rgba(255, 255, 255, 0.2);
  color: #ffffff;
}

.work-card-body {
  padding: var(--space-5);
}

.work-card-body .card-title {
  margin-top: var(--space-1);
}

/* ---------- Home: testimonials ---------- */
.testimonial-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}

.testimonial-quote {
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  font-weight: var(--font-medium);
  line-height: var(--leading-snug);
  color: var(--color-text);
}

.testimonial-attribution {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.testimonials-more {
  margin-top: var(--space-6);
  text-align: center;
}

/* ---------- Home: final CTA ---------- */
.cta-section {
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
  color: #ffffff;
}

.cta-inner {
  max-width: 640px;
  margin-inline: auto;
  text-align: center;
}

.cta-inner h2 {
  color: #ffffff;
  margin-bottom: var(--space-4);
}

.cta-lead {
  color: var(--color-primary-light);
  margin-bottom: var(--space-6);
}

/* ---------- Interior pages: page header ---------- */
.page-header {
  padding-block: var(--space-8) var(--space-7);
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
}

.page-header .lead {
  margin-top: var(--space-4);
  max-width: 60ch;
}

/* ---------- Services: alternating service blocks ---------- */
.service-block {
  display: grid;
  gap: var(--space-6);
  align-items: center;
}

@media (min-width: 1200px) {
  .service-block {
    grid-template-columns: 1fr 1fr;
    gap: var(--space-8);
  }

  .service-block--reverse .service-block-content {
    order: 2;
  }

  .service-block--reverse .service-block-visual {
    order: 1;
  }
}

.service-block-content .eyebrow {
  margin-bottom: var(--space-3);
}

.service-block-content p {
  color: var(--color-text-muted);
}

.service-visual-card {
  aspect-ratio: 4 / 3;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--color-primary-light), var(--color-bg));
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.service-visual-card--accent {
  background: linear-gradient(135deg, var(--color-accent-light), var(--color-bg));
}

.service-visual-icon {
  width: 96px;
  height: 96px;
  color: var(--color-primary);
}

.service-visual-card--accent .service-visual-icon {
  color: var(--color-accent-dark);
}

/* ---------- Services: checklist & tech tags ---------- */
.check-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.check-list li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
  color: var(--color-text-muted);
}

.check-list li::before {
  content: "";
  flex-shrink: 0;
  width: 6px;
  height: 6px;
  margin-top: 9px;
  border-radius: var(--radius-full);
  background-color: var(--color-primary);
}

.tech-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-top: var(--space-5);
}

/* ---------- Services: process timeline ---------- */
.process-timeline {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: 1fr;
}

@media (min-width: 768px) {
  .process-timeline {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (min-width: 1200px) {
  .process-timeline {
    position: relative;
    grid-template-columns: repeat(4, 1fr);
    gap: var(--space-5);
  }

  .process-timeline::before {
    content: "";
    position: absolute;
    top: 24px;
    left: 0;
    right: 0;
    height: 2px;
    background-color: var(--color-border);
  }
}

.process-step {
  position: relative;
  z-index: 1;
}

.process-step-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  border-radius: var(--radius-full);
  background-color: var(--color-primary);
  color: #ffffff;
  font-family: var(--font-heading);
  font-weight: var(--font-bold);
  font-size: var(--text-lg);
  margin-bottom: var(--space-4);
}

.process-step h3 {
  margin-bottom: var(--space-2);
}

/* ---------- Portfolio: filter bar ---------- */
.filter-bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-bottom: var(--space-6);
}

.filter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  padding: var(--space-2) var(--space-4);
  /* touch target: padding + line-height alone computes to ~38px, under 44px */
  min-height: 44px;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background-color: var(--color-bg);
  color: var(--color-text-muted);
  cursor: pointer;
  transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}

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

.filter-btn[aria-pressed="true"] {
  background-color: var(--color-gray-900);
  border-color: var(--color-gray-900);
  color: #ffffff;
}

.portfolio-filter-bar {
  margin-bottom: var(--space-6);
}

.filter-bar--secondary {
  margin-bottom: 0;
}

.filter-empty-state {
  text-align: center;
  padding: var(--space-8) var(--space-5);
  color: var(--color-text-muted);
}

.filter-empty-state-title {
  color: var(--color-text);
  margin-bottom: var(--space-2);
}

.filter-empty-state .btn {
  margin-top: var(--space-4);
}

/* ---------- Portfolio: project cards ---------- */
.project-card {
  display: flex;
  flex-direction: column;
  background-color: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base), transform var(--transition-base);
}

.project-card:hover {
  box-shadow: var(--shadow-md);
  transform: translateY(-2px);
}

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

.project-card-body {
  padding: var(--space-5);
}

.project-card-body > .badge-primary {
  margin-bottom: var(--space-3);
}

.project-card-body .card-title {
  margin-top: 0;
}

/* ---------- Portfolio: thumbnail placeholders ([REPLACE WITH SCREENSHOT]) ---------- */
.project-thumb {
  height: 180px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  text-align: center;
  padding: var(--space-4);
  background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark));
}

.project-thumb--2 {
  background: linear-gradient(135deg, var(--color-accent), var(--color-accent-dark));
}

.project-thumb--3 {
  background: linear-gradient(135deg, var(--color-gray-700), var(--color-gray-900));
}

.project-thumb-icon {
  width: 32px;
  height: 32px;
  color: rgba(255, 255, 255, 0.7);
}

.project-thumb-name {
  font-family: var(--font-heading);
  font-weight: var(--font-semibold);
  font-size: var(--text-sm);
  color: #ffffff;
}

.project-thumb--hero {
  height: 260px;
  border-radius: var(--radius-lg);
}

@media (min-width: 768px) {
  .project-thumb--hero {
    height: 340px;
  }
}

.project-thumb--hero .project-thumb-icon {
  width: 48px;
  height: 48px;
}

.project-thumb--hero .project-thumb-name {
  font-size: var(--text-lg);
}

/* ---------- Portfolio: "coming soon" disabled link ---------- */
.link-arrow--disabled {
  color: var(--color-gray-600);
  cursor: default;
}

.link-arrow--disabled:hover {
  gap: var(--space-1);
  color: var(--color-gray-600);
}

/* ---------- Case study template ---------- */
.back-link {
  margin-bottom: var(--space-5);
}

.case-study-block {
  max-width: 720px;
}

.case-study-block .eyebrow {
  margin-bottom: var(--space-2);
}

.case-study-block h2 {
  margin-bottom: var(--space-4);
}

.case-study-block p {
  color: var(--color-text-muted);
}

.case-study-block .check-list {
  margin-top: var(--space-5);
}

/* ---------- About: headshot placeholder ([REPLACE WITH HEADSHOT PHOTO]) ---------- */
.headshot-placeholder {
  aspect-ratio: 3 / 4;
  display: flex;
  align-items: center;
  justify-content: center;
  background: linear-gradient(135deg, var(--color-primary-light), var(--color-bg));
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

.headshot-placeholder-icon {
  width: 88px;
  height: 88px;
  color: var(--color-primary);
}

/* ---------- About: skills by category ---------- */
.skill-group h3 {
  margin-bottom: var(--space-3);
}

/* ---------- Pricing: cards ---------- */
.pricing-card {
  display: flex;
  flex-direction: column;
  background-color: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--transition-base);
}

.pricing-card:hover {
  box-shadow: var(--shadow-md);
}

.pricing-card--featured {
  border-color: var(--color-primary);
  box-shadow: var(--shadow-lg);
}

@media (min-width: 1200px) {
  .pricing-card--featured {
    margin-top: calc(-1 * var(--space-5));
    padding-bottom: calc(var(--space-6) + var(--space-5));
  }
}

.pricing-badge {
  align-self: flex-start;
  margin-bottom: var(--space-4);
}

.pricing-name {
  margin-bottom: var(--space-2);
}

.pricing-tagline {
  color: var(--color-text-muted);
  margin-bottom: var(--space-5);
}

.pricing-price {
  margin-bottom: var(--space-5);
}

.price-amount {
  display: block;
  font-family: var(--font-heading);
  font-size: var(--text-2xl);
  font-weight: var(--font-bold);
  color: var(--color-gray-900);
}

.price-period {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.pricing-features {
  flex-grow: 1;
  margin-bottom: var(--space-6);
}

/* ---------- Pricing: FAQ accordion ---------- */
.accordion {
  max-width: 760px;
  margin-inline: auto;
}

.accordion-item {
  border-bottom: 1px solid var(--color-border);
}

.accordion-item:first-child {
  border-top: 1px solid var(--color-border);
}

.accordion-header {
  margin: 0;
}

.accordion-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: 100%;
  padding-block: var(--space-5);
  background: none;
  border: none;
  text-align: left;
  font-family: var(--font-heading);
  font-size: var(--text-lg);
  font-weight: var(--font-semibold);
  color: var(--color-text);
  cursor: pointer;
  transition: color var(--transition-base);
}

.accordion-trigger:hover {
  color: var(--color-primary);
}

.accordion-icon {
  position: relative;
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  color: var(--color-primary);
}

.accordion-icon::before,
.accordion-icon::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  background-color: currentColor;
  transform: translate(-50%, -50%);
}

.accordion-icon::before {
  width: 16px;
  height: 2px;
}

.accordion-icon::after {
  width: 2px;
  height: 16px;
  transition: transform var(--transition-base);
}

.accordion-trigger[aria-expanded="true"] .accordion-icon::after {
  transform: translate(-50%, -50%) rotate(90deg);
}

.accordion-panel {
  max-width: 65ch;
  padding-bottom: var(--space-5);
}

.accordion-panel p {
  color: var(--color-text-muted);
}

/* ---------- Utility: visually hidden but screen-reader accessible ---------- */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* ---------- Testimonials: stats strip ---------- */
.stats-strip {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-6);
  margin-top: var(--space-6);
}

@media (min-width: 768px) {
  .stats-strip {
    grid-template-columns: repeat(4, 1fr);
  }
}

.stat-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
}

.stat-number {
  font-family: var(--font-heading);
  font-size: var(--text-4xl);
  font-weight: var(--font-bold);
  color: var(--color-primary);
}

.stat-label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* ---------- Testimonials: avatar placeholder ---------- */
.avatar-placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  background-color: var(--color-primary-light);
  color: var(--color-primary);
}

.avatar-placeholder-icon {
  width: 24px;
  height: 24px;
}

.testimonial-author {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: var(--space-5);
}

.testimonial-role {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* ---------- Testimonials: carousel ---------- */
.carousel {
  position: relative;
  max-width: 760px;
  margin-inline: auto;
}

.carousel-viewport {
  overflow: hidden;
}

.carousel-slide[hidden] {
  display: none;
}

.carousel-testimonial {
  /* responsive: --space-7 (48px) on each side left only ~231px of readable
     width at a 375px viewport — noticeably narrower than every other card on
     the site (which use --space-5/6) and cramped for --text-xl quote text.
     Smaller on mobile, full-size once there's width to spare. */
  padding: var(--space-5);
}

@media (min-width: 768px) {
  .carousel-testimonial {
    padding: var(--space-7);
  }
}

.carousel-testimonial .testimonial-quote {
  font-size: var(--text-xl);
}

.carousel-testimonial .testimonial-attribution {
  color: var(--color-text);
  font-weight: var(--font-semibold);
  font-size: var(--text-base);
}

.carousel-controls {
  display: flex;
  /* responsive: prev/dots/next/pause at their 44px touch-target sizes need
     ~356px in a single row (4 items x 44px + 3x16px gaps) — more than the
     ~327px available at a 375px viewport once container padding is
     subtracted. flex-wrap lets whichever item doesn't fit (the pause button,
     in practice) drop to its own centered row instead of overflowing. */
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-4);
  margin-top: var(--space-6);
}

.carousel-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* touch target: was 40x40, under the 44px minimum */
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  border: 1px solid var(--color-border);
  background-color: var(--color-bg);
  color: var(--color-text);
  cursor: pointer;
  transition: background-color var(--transition-base), border-color var(--transition-base);
}

.carousel-btn:hover {
  border-color: var(--color-gray-900);
  background-color: var(--color-gray-50);
}

.carousel-btn svg {
  width: 18px;
  height: 18px;
}

.carousel-pause .icon-play {
  display: none;
}

.carousel-pause[aria-pressed="true"] .icon-pause {
  display: none;
}

.carousel-pause[aria-pressed="true"] .icon-play {
  display: block;
}

.carousel-dots {
  display: flex;
  align-items: center;
}

/* touch target: the visible indicator is deliberately a small 8px dot (below),
   but a 44x44 dot would look wrong here — so the *button* itself is enlarged
   to the 44px minimum (invisible hit area, no gap needed since the buttons'
   own width already spaces them out) and the small dot is drawn as a ::before
   centered inside it. */
.carousel-dot {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: none;
  background-color: transparent;
  cursor: pointer;
}

.carousel-dot::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: var(--radius-full);
  background-color: var(--color-gray-300);
  transition: background-color var(--transition-base), transform var(--transition-base);
}

.carousel-dot[aria-selected="true"]::before {
  background-color: var(--color-primary);
  transform: scale(1.3);
}

/* ---------- Blog: post list ---------- */
.post-list {
  display: flex;
  flex-direction: column;
}

.post-card {
  padding-block: var(--space-6);
  border-bottom: 1px solid var(--color-border);
}

.post-list .post-card:first-child {
  padding-top: 0;
}

.post-list .post-card:last-child {
  border-bottom: none;
}

.post-card-body > time,
.post-card-body > .badge {
  margin-bottom: var(--space-2);
}

.post-date {
  display: inline-block;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.post-card .card-title {
  margin-bottom: var(--space-3);
}

.post-card .card-body {
  margin-bottom: var(--space-4);
}

/* ---------- Blog post: article layout ---------- */
.post-meta {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-4);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

.article-body {
  max-width: 70ch;
  margin-inline: auto;
  font-size: var(--text-lg);
  line-height: var(--leading-relaxed);
  color: var(--color-text);
}

.article-body p {
  margin-bottom: var(--space-5);
}

.article-body h2 {
  margin-top: var(--space-7);
  margin-bottom: var(--space-4);
}

.article-body h3 {
  margin-top: var(--space-6);
  margin-bottom: var(--space-3);
}

.article-body ul,
.article-body ol {
  margin-bottom: var(--space-5);
  padding-left: 1.25em;
}

.article-body ul {
  list-style: disc;
}

.article-body ol {
  list-style: decimal;
}

.article-body li {
  margin-bottom: var(--space-2);
  color: var(--color-text);
}

.article-body pre {
  background-color: var(--color-gray-900);
  color: var(--color-gray-100);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  margin-bottom: var(--space-5);
  overflow-x: auto;
  font-family: Consolas, Monaco, monospace;
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
}

.article-body p code {
  background-color: var(--color-gray-100);
  color: var(--color-gray-900);
  padding: 0.15em 0.4em;
  border-radius: var(--radius-sm);
  font-size: 0.9em;
  font-family: Consolas, Monaco, monospace;
}

/* ---------- Contact: layout ---------- */
.contact-layout {
  display: grid;
  gap: var(--space-7);
}

@media (min-width: 1200px) {
  .contact-layout {
    grid-template-columns: 1.6fr 1fr;
    gap: var(--space-8);
  }
}

.contact-sidebar {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.social-links {
  display: flex;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

.social-links a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* touch target: was 36x36, under the 44px minimum */
  width: 44px;
  height: 44px;
  border-radius: var(--radius-full);
  background-color: var(--color-gray-100);
  color: var(--color-gray-700);
  transition: background-color var(--transition-base), color var(--transition-base);
}

.social-links a:hover {
  background-color: var(--color-primary-light);
  color: var(--color-primary);
}

/* ---------- Contact: form field refinements ---------- */
select.input {
  appearance: none;
  -webkit-appearance: none;
  -moz-appearance: none;
  /* Chevron color is hardcoded to match --color-gray-700 (#4a4e5a) — a data-URI
     background can't reference a CSS custom property. */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%234a4e5a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--space-4) center;
  background-size: 16px;
  padding-right: var(--space-8);
}

textarea.input {
  min-height: 140px;
  resize: vertical;
  line-height: var(--leading-normal);
}

/* Honeypot: hidden off-screen (not display:none) rather than removed from the
   DOM, so it still catches simple bots that fill every field indiscriminately. */
.honeypot-field {
  position: absolute;
  left: -9999px;
  top: -9999px;
}

.form-status {
  min-height: 1.5em;
  margin-bottom: var(--space-4);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  color: var(--color-text-muted);
}

.form-status.is-error {
  color: var(--color-error);
}

.form-success {
  padding: var(--space-6);
  border: 1px solid var(--color-success);
  border-radius: var(--radius-lg);
  background-color: var(--color-success-light);
}

.form-success-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  margin-bottom: var(--space-4);
  border-radius: var(--radius-full);
  background-color: var(--color-success);
  color: #ffffff;
}

.form-success h2 {
  margin-bottom: var(--space-2);
}

.confirmation-actions {
  margin-top: var(--space-6);
}

/* ---------- Header: language toggle ---------- */
.lang-toggle {
  display: inline-flex;
  flex-shrink: 0;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  overflow: hidden;
}

.lang-toggle-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: var(--font-semibold);
  color: var(--color-text-muted);
  background-color: transparent;
  border: none;
  cursor: pointer;
  transition: background-color var(--transition-base), color var(--transition-base);
}

.lang-toggle-btn + .lang-toggle-btn {
  border-left: 1px solid var(--color-border);
}

.lang-toggle-btn:hover {
  color: var(--color-text);
}

.lang-toggle-btn[aria-pressed="true"] {
  background-color: var(--color-gray-900);
  color: #ffffff;
}

.lang-toggle-btn[aria-pressed="true"]:hover {
  color: #ffffff;
}

/* ---------- Portfolio: real project images ----------
   Distinct from .project-thumb (the SVG-placeholder box used by
   project-template.html, which intentionally stays illustrative since it's
   not a real project). These wrap actual screenshots, which mix portrait
   (mobile) and landscape (web) orientations across projects — sized by a
   fixed box with the image scaled via max-width/max-height rather than a
   forced aspect-ratio + object-fit:cover, so nothing gets cropped. */
.project-card-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 200px;
  padding: var(--space-4);
  background-color: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  overflow: hidden;
}

.project-card-thumb img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  border-radius: var(--radius-sm);
}

.project-hero-image-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 280px;
  padding: var(--space-6);
  background: linear-gradient(135deg, var(--color-primary-light), var(--color-bg));
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

@media (min-width: 768px) {
  .project-hero-image-wrap {
    min-height: 380px;
  }
}

.project-hero-image-wrap img {
  max-width: 100%;
  max-height: 420px;
  width: auto;
  height: auto;
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
}

/* ---------- Portfolio: image gallery grid + lightbox thumbnails ----------
   Every project's full image folder is shown here (not a curated subset) —
   .gallery-thumb is a <button>, not a <div>, since js/lightbox.js wires each
   one to open a full-screen, keyboard- and swipe-navigable viewer (see the
   Lightbox section below). */
.image-gallery-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: var(--space-4);
  margin-top: var(--space-5);
}

.gallery-thumb {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 200px;
  padding: var(--space-3);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  cursor: pointer;
  position: relative;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast),
    border-color var(--transition-fast);
}

.gallery-thumb::after {
  content: '';
  position: absolute;
  inset: 0;
  background-color: rgba(20, 22, 28, 0);
  transition: background-color var(--transition-fast);
  pointer-events: none;
}

.gallery-thumb:hover,
.gallery-thumb:focus-visible {
  transform: scale(1.03);
  box-shadow: var(--shadow-md);
  border-color: var(--color-gray-500);
}

.gallery-thumb:hover::after,
.gallery-thumb:focus-visible::after {
  background-color: rgba(20, 22, 28, 0.08);
}

.gallery-thumb img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  border-radius: var(--radius-sm);
}

/* Extra thumbnails beyond the compact cap (Areaionx, TQC) — collapsed by
   default, revealed by the "View all" button below the grid. Every image is
   still in the DOM (and still fully navigable from the lightbox once any
   visible thumbnail is opened) — this only affects what's visible up front. */
.image-gallery-grid:not(.is-expanded) .gallery-thumb--extra {
  display: none;
}

.gallery-view-all-btn {
  margin-top: var(--space-4);
}

/* ---------- Case study: labeled gallery sub-groups (e.g. Areaionx's
   Edge/Mobile/Web split, TQC's Android/Web split) — each sub-group's grid
   carries its own [data-lightbox-gallery] value, so the lightbox scopes
   prev/next navigation to that sub-group only. ---------- */
.gallery-subgroup {
  margin-top: var(--space-6);
}

.gallery-subgroup:first-of-type {
  margin-top: var(--space-5);
}

.gallery-subgroup-title {
  font-size: var(--text-lg);
  margin-bottom: var(--space-2);
}

.gallery-subgroup-description {
  color: var(--color-text-muted);
  max-width: 640px;
  margin-bottom: var(--space-4);
}

/* ---------- Case study: dark/light screenshot toggle (TQC) ----------
   Visually mirrors .lang-toggle in the header — a pill-shaped button group
   with a filled "active" state — for a consistent toggle pattern site-wide. */
.theme-toggle {
  display: inline-flex;
  gap: var(--space-1);
  padding: var(--space-1);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  margin-bottom: var(--space-4);
}

.theme-toggle-btn {
  min-width: 44px;
  min-height: 44px;
  padding: var(--space-2) var(--space-4);
  border: none;
  border-radius: var(--radius-full);
  background-color: transparent;
  color: var(--color-text-muted);
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  cursor: pointer;
  transition: background-color var(--transition-fast), color var(--transition-fast);
}

.theme-toggle-btn:hover {
  color: var(--color-text);
}

.theme-toggle-btn[aria-pressed="true"] {
  background-color: var(--color-gray-900);
  color: #ffffff;
}

.theme-toggle-btn[aria-pressed="true"]:hover {
  color: #ffffff;
}

.project-note {
  padding: var(--space-4) var(--space-5);
  background-color: var(--color-surface);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}

/* ---------- Portfolio: category sections ---------- */
.portfolio-category {
  margin-bottom: var(--space-8);
}

.portfolio-category:last-child {
  margin-bottom: 0;
}

.portfolio-category-header {
  max-width: 720px;
  margin-bottom: var(--space-6);
}

.qr-menu-block {
  margin-top: var(--space-7);
}

/* ---------- Lightbox: full-screen image viewer ----------
   Built and injected by js/lightbox.js; one shared modal instance is reused
   across every gallery on the page — see js/lightbox.js for the open/close
   and focus-trap logic. z-index clears the skip-link (previously the
   highest at 9999), since this can open from any scroll position. */
.lightbox-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-5);
  background-color: rgba(10, 11, 15, 0.94);
  z-index: 10000;
}

.lightbox-overlay[hidden] {
  display: none;
}

body.lightbox-open {
  overflow: hidden;
}

.lightbox-dialog {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  max-width: 1400px;
}

.lightbox-image-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

.lightbox-image {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
}

.lightbox-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--radius-full);
  border: 1px solid rgba(255, 255, 255, 0.3);
  background-color: rgba(255, 255, 255, 0.08);
  color: #ffffff;
  cursor: pointer;
  transition: background-color var(--transition-fast), border-color var(--transition-fast);
}

.lightbox-btn svg {
  width: 22px;
  height: 22px;
}

.lightbox-btn:hover {
  background-color: rgba(255, 255, 255, 0.18);
  border-color: rgba(255, 255, 255, 0.5);
}

.lightbox-close {
  position: absolute;
  top: var(--space-2);
  right: var(--space-2);
}

.lightbox-prev {
  position: absolute;
  left: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
}

.lightbox-next {
  position: absolute;
  right: var(--space-2);
  top: 50%;
  transform: translateY(-50%);
}

.lightbox-counter {
  position: absolute;
  bottom: var(--space-2);
  left: 50%;
  transform: translateX(-50%);
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  background-color: rgba(255, 255, 255, 0.12);
  color: #ffffff;
  font-size: var(--text-sm);
  font-weight: var(--font-medium);
  white-space: nowrap;
}

@media (min-width: 768px) {
  .lightbox-overlay {
    padding: var(--space-7);
  }

  .lightbox-close {
    top: var(--space-4);
    right: var(--space-4);
  }

  .lightbox-prev {
    left: var(--space-4);
  }

  .lightbox-next {
    right: var(--space-4);
  }

  .lightbox-counter {
    bottom: var(--space-4);
  }
}
