/* CV — components */

/* --- nav ---
   Below the desktop breakpoint this is the only nav (top bar + hamburger
   drawer). At 860px+ the persistent identity sidebar (see below) takes
   over navigation entirely, so the top bar is hidden there. */
.site-nav {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 100;
  padding-block: var(--sp-3);
  transition: background var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
}

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

.site-nav.is-scrolled {
  padding-block: var(--sp-1);
  background: rgba(245, 245, 243, 0.85);
  backdrop-filter: blur(10px);
  box-shadow: 0 1px 0 var(--line);
}

.site-nav .container {
  display: grid;
  /* Symmetric flexible outer columns so the logo lands dead-center
     regardless of the phone icon and hamburger's (different) widths —
     grid column 1 is the physically-right cell here (dir:rtl), so the
     toggle (grid-column:1) ends up on the right and the phone icon
     (grid-column:3) on the left, logo in between. */
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
}

.brand {
  grid-column: 2;
  grid-row: 1;
  justify-self: center;
  /* Height-matched to the phone icon/hamburger either side (both ~42px)
     rather than the full multi-line desktop logo, which — even shrunk —
     was either too tall to align with them or too small to read. Uses
     just the "AK" mark (logo-mark.png, cropped from the full logo) at
     its natural aspect ratio. */
  display: inline-flex;
  align-items: center;
  height: 42px;
  transition: transform var(--dur-fast) var(--ease-premium);
}

.brand img {
  height: 100%;
  width: auto;
  display: block;
}

.site-nav.is-scrolled .brand {
  transform: scale(0.86);
}

.site-nav.is-scrolled .nav-phone {
  transform: scale(0.92);
}

.nav-phone {
  grid-column: 3;
  grid-row: 1;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 42px;
  height: 42px;
  background: var(--ink);
  color: var(--bg);
  border-radius: 50%;
  transition: transform var(--dur-fast) var(--ease-premium);
}

.nav-phone svg {
  width: 19px;
  height: 19px;
}

.nav-phone:hover {
  transform: translateY(-2px);
}

/* --- identity sidebar (desktop-only persistent nav) ---
   Rendered from the start in its final "resting" compact shape (fixed,
   narrow column, right side — the inline-start edge in RTL). During the
   hero, JS applies a transform (translate + scale) that makes it appear
   large and centered, matching the hero's dramatic first impression; that
   transform is scrubbed back to identity as the user scrolls past the
   hero, so it visually "shrinks into" this resting position. Hidden below
   the desktop breakpoint in favor of the ordinary top nav. */
.identity {
  display: none;
}

@media (min-width: 860px) {
  .identity {
    display: flex;
    position: fixed;
    inset-inline-start: 0;
    top: 0;
    height: 100vh;
    width: var(--identity-width);
    z-index: 90;
    align-items: center;
    justify-content: center;
    padding: var(--sp-4);
    will-change: transform;
  }

  main {
    padding-inline-start: var(--identity-width);
  }

  /* The hero alone breaks back out to full viewport width — its photo
     should run edge-to-edge behind the sidebar's logo, not stop short of
     it like every other (properly offset) section does. */
  #hero {
    margin-inline-start: calc(-1 * var(--identity-width));
    width: calc(100% + var(--identity-width));
  }
}

.identity-inner {
  width: 100%;
  max-width: 15rem;
  background: var(--paper);
  border: var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-3);
  box-shadow: 0 20px 50px -20px rgba(0, 0, 0, 0.15);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.identity-logo {
  align-self: flex-start;
  width: 132px;
}

.identity-logo img {
  display: block;
  width: 100%;
  height: auto;
}

.identity-blurb {
  font-size: var(--step-xs);
  color: var(--ink-soft);
  line-height: 1.6;
}

.identity-stats {
  display: flex;
  gap: var(--sp-3);
}

.identity-stats strong {
  display: block;
  font-size: var(--step-md);
  font-weight: 800;
  color: var(--accent);
}

.identity-stats span {
  font-size: var(--step-xs);
  color: var(--ink-soft);
}

.identity-nav {
  display: flex;
  flex-direction: column;
  gap: 2px;
  border-top: var(--border);
  border-bottom: var(--border);
  padding-block: var(--sp-1);
}

.identity-nav a {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  padding: 0.55rem 0.6rem;
  border-radius: var(--radius-sm);
  /* Was step-sm (14px, fixed) — too small to read comfortably at
     laptop/desktop sizes, where this sidebar is the site's only nav. */
  font-size: var(--step-md);
  font-weight: 600;
  color: var(--ink-soft);
  white-space: nowrap;
  transition: background var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out);
}

.identity-nav a:hover,
.identity-nav a.is-active {
  /* A translucent tint rather than an opaque light fill — during the
     hero flight (hero-identity.js) these links are temporarily forced
     white via an inline style to stay legible over the photo, which an
     opaque near-white hover background would sit behind invisibly. This
     reads fine either way: a soft gray highlight on the resting white
     card, a subtle darkening over the photo. */
  background: rgba(0, 0, 0, 0.06);
  color: var(--ink);
}

.identity-nav svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

.identity-cta {
  justify-content: center;
  width: 100%;
}

/* --- back-to-top --- */
.back-to-top {
  position: fixed;
  bottom: var(--sp-3);
  inset-inline-start: var(--sp-3);
  z-index: 90;
  width: 46px;
  height: 46px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--bg);
  display: flex;
  align-items: center;
  justify-content: center;
  box-shadow: 0 10px 24px -8px rgba(0, 0, 0, 0.35);
  opacity: 0;
  transform: translateY(12px);
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-out), background var(--dur-fast) var(--ease-out);
}

.back-to-top.is-visible {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}

.back-to-top:hover {
  background: var(--accent);
}

.back-to-top svg {
  width: 20px;
  height: 20px;
}

.nav-toggle {
  grid-column: 1;
  grid-row: 1;
  justify-self: start;
  display: inline-flex;
  flex-direction: column;
  padding: 0.5rem;
}

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

.nav-toggle span {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--ink);
  margin-block: 4px;
  transform-origin: center;
  transition: transform var(--dur-fast) var(--ease-premium),
    opacity var(--dur-fast) var(--ease-premium);
}

/* Hamburger → X, tracking the drawer's own open state. */
.nav-toggle[aria-expanded="true"] span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}

.nav-toggle[aria-expanded="true"] span:nth-child(2) {
  opacity: 0;
  transform: scaleX(0);
}

.nav-toggle[aria-expanded="true"] span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}

.mobile-menu {
  position: fixed;
  inset-block: 0;
  /* Physical right, not inset-inline-end — spec-correct RTL resolves
     inline-end to the physical left, which (per the shadow direction
     below, clearly authored for a right-anchored panel) wasn't the
     intent; it also now needs to match the hamburger's own position. */
  right: 0;
  width: min(80vw, 320px);
  background: var(--paper);
  box-shadow: -8px 0 40px rgba(0, 0, 0, 0.12);
  padding: var(--sp-5) var(--sp-4);
  transform: translateX(100%);
  transition: transform var(--dur-med) var(--ease-premium);
  z-index: 150;
}

.mobile-menu.is-open {
  transform: translateX(0);
}

.mobile-menu-close {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  color: var(--ink);
  transition: background var(--dur-fast) var(--ease-out);
}

.mobile-menu-close:hover {
  background: var(--bg-raised);
}

.mobile-menu-close svg {
  width: 20px;
  height: 20px;
}

.mobile-menu nav {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
}

.mobile-menu a {
  font-size: var(--step-lg);
  font-weight: 700;
}

.menu-overlay {
  position: fixed;
  inset: 0;
  background: rgba(16, 16, 20, 0.4);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--dur-fast) var(--ease-out);
  z-index: 140;
}

.menu-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
}

/* --- buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-1);
  padding: 0.85rem 1.6rem;
  border-radius: 999px;
  font-weight: 700;
  font-size: var(--step-sm);
  transition: transform var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
}

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

.btn-primary:hover {
  transform: translateY(-2px);
  box-shadow: 0 12px 30px -10px var(--accent);
}

.btn-ghost {
  border: var(--border);
  color: var(--ink);
}

.btn-ghost:hover {
  border-color: var(--ink);
}

.dark-section .btn-ghost {
  border-color: var(--dark-line);
  color: var(--dark-ink);
}

/* --- hero ---
   A full-bleed portrait with the sidebar's own logo/nav flying across it
   (see hero-identity.js), plus a heading+description revealed near the
   end of that sequence. */
.hero {
  position: relative;
  min-height: 100vh;
  overflow: hidden;
  background: var(--bg-raised);
}

/* Cutout portrait, bottom-anchored on the physical left (not a logical
   inset — this needs to stay put regardless of RTL). Blurs/desaturates/
   fades as the identity sidebar forms, scrubbed with the pinned scroll
   range in hero-identity.js. */
.hero-photo {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}

.hero-photo img {
  position: absolute;
  bottom: 0;
  left: 3%;
  height: 92%;
  width: auto;
  max-width: 60%;
  object-fit: contain;
  will-change: transform, filter;
}

@media (max-width: 859px) {
  /* Flipped to the physical right on mobile (no sidebar there to justify
     keeping it on the left) — reads better against the RTL header/menu
     side and the text below it. Slightly taller too, now that the header
     is short enough (see .brand) not to need as much clearance above
     the portrait. */
  .hero-photo img {
    left: auto;
    right: 3%;
    height: 95%;
  }
}

/* Hero-only decorations layered near the portrait — glass-tinted so they
   read over any part of the photo or the plain background alike. Fade out
   together with the photo (hero-identity.js) well before the hero-intro
   heading takes over the same general area. Desktop only: on the mobile
   hero (no pin/flight sequence there) this would just be clutter next to
   the always-visible heading/description. */
.hero-badge,
.hero-traits,
.hero-tagline,
.hero-actions-float {
  display: none;
}

@media (min-width: 860px) {
  .hero-badge,
  .hero-traits,
  .hero-tagline,
  .hero-actions-float {
    display: block;
    position: absolute;
    z-index: 1;
  }

  .hero-badge {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    gap: 0.2rem;
    padding: var(--sp-3) var(--sp-4);
    border-radius: var(--radius-lg);
    background: rgba(255, 255, 255, 0.7);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid rgba(255, 255, 255, 0.8);
    box-shadow: 0 12px 32px -10px rgba(0, 0, 0, 0.22);
    box-sizing: border-box;
  }

  .hero-badge strong {
    font-size: 1.6rem;
    font-weight: 800;
    color: var(--accent);
    line-height: 1;
  }

  .hero-badge span {
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--ink-soft);
  }

  /* Same row as the floating CTAs, not tucked under the trait pills.
     Sized to exactly match the primary CTA in JS (syncHeroSizes) — the
     font sizes above are chosen to comfortably fit inside that box
     rather than the box growing to fit them. */
  .hero-badge-experience {
    bottom: 8%;
    /* Same column as the trait pills below it (not the sidebar-clearance
       line) — visually reads as "the pills' column, continued down to
       the CTA row" rather than a third unrelated position. */
    right: calc(var(--identity-width) + var(--gutter) + var(--sp-3) - 200px);
    padding: var(--sp-2);
  }

  .hero-traits {
    top: 14%;
    /* ~200px further right than the plain sidebar-clearance offset —
       roughly under where the flying nav's first ("בית") link sits. */
    right: calc(var(--identity-width) + var(--gutter) + var(--sp-3) - 200px);
    display: flex;
    flex-direction: column;
    gap: var(--sp-1);
    /* Empirically flex-end resolves to the visual LEFT here, not the
       right — align-items apparently isn't following `dir` the way the
       spec says it should in this rendering context, so this is the
       physically-correct keyword rather than the logically-correct one. */
    align-items: flex-start;
  }

  .hero-traits span {
    padding: 0.5rem 1.3rem;
    border-radius: 999px;
    background: var(--ink);
    font-size: var(--step-md);
    font-weight: 700;
    color: #fff;
  }

  .hero-tagline {
    /* Same row as the CTA buttons/badge, not above them. */
    bottom: 8%;
    left: var(--gutter);
    padding: var(--sp-2) var(--sp-3);
    border-radius: var(--radius-lg);
    background: rgba(255, 255, 255, 0.7);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border: 1px solid rgba(255, 255, 255, 0.8);
    box-shadow: 0 12px 32px -10px rgba(0, 0, 0, 0.22);
    font-size: calc(var(--step-md) * 1.3);
    font-weight: 800;
    color: var(--ink);
    line-height: 1.3;
    /* Wide enough for exactly two lines at this font size — narrower
       wrapped it into four, wider let it sit on one. */
    max-width: 17rem;
  }

  .hero-actions-float {
    bottom: 8%;
    /* Centered within the space actually free of the sidebar (#hero's own
       box is exactly the viewport width, so 50% here is 50vw) — plain
       left:50% centered on the full viewport and ran the buttons under
       the sidebar on narrower desktop widths, where the sidebar eats a
       proportionally bigger share of the screen. */
    left: calc(50% - var(--identity-width) / 2);
    transform: translateX(-50%);
    display: flex;
    gap: var(--sp-3);
  }

  .hero-actions-float .btn {
    /* Modest by default — full drama only once there's genuinely tall
       room for it (see the 1400px tier below). */
    padding: 1.1rem 2.2rem;
    font-size: calc(var(--step-sm) * 1.3);
  }

  .hero-actions-float .btn-ghost {
    background: var(--paper);
    box-shadow: 0 8px 20px -8px rgba(0, 0, 0, 0.2);
  }
}

@media (min-width: 1600px) {
  /* Full size only once there's enough width for the now-larger CTA
     buttons to still clear the badge sitting next to them (their shared
     row: badge on the sidebar side, buttons centered in the remaining
     space) — below this the wider buttons crept under the badge. */
  .hero-tagline {
    font-size: calc(var(--step-md) * 2);
    max-width: 26rem;
  }

  .hero-actions-float .btn {
    padding: 1.7rem 3.2rem;
    font-size: calc(var(--step-sm) * 1.8);
  }
}

.hero-intro {
  position: absolute;
  z-index: 1;
  bottom: var(--sp-6);
  /* Physical left/right, not inset-inline-start/end — logical properties
     have repeatedly resolved opposite of spec in this rendering context
     (see hero-traits/hero-photo above). Using them here silently dropped
     the desktop override below at real widths: instead of stopping clear
     of the sidebar, the box only kept the base gutter offset from the
     viewport edge — overlapping the sidebar by ~250px+ once its card
     faded in on scroll. */
  right: var(--gutter);
  left: var(--gutter);
  max-width: 44rem;
  margin-left: auto;
  text-align: right;
}

@media (max-width: 859px) {
  /* On mobile there's no fade/blur pass over the photo (no pin/scrub
     there) — the heading sits over a still fully-visible portrait, so it
     needs its own contrast rather than relying on the photo dimming. */
  .hero-intro {
    /* Pinned to the very bottom of the hero, right before the next
       section starts, rather than floating with a gap below it. */
    bottom: var(--sp-3);
    background: rgba(255, 255, 255, 0.82);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border-radius: var(--radius-lg);
    padding: var(--sp-3);
  }
}

@media (min-width: 860px) {
  .hero-intro {
    /* Stop short of the sidebar's own column, not the full-bleed photo
       edge (#hero itself breaks out to full width on desktop). Pushed
       further right from there — see hero-identity.js, which computes a
       safe shift (up to 550px, clamped so it can never overlap the
       sidebar or run off-screen at narrower desktop widths) and sits
       above the sidebar in z-index so it's never covered. Widened past
       what the heading itself needs, so the (wider) description below it
       has room to cap at three lines instead of wrapping further. */
    right: calc(var(--identity-width) + var(--gutter));
    left: auto;
    max-width: 62rem;
    z-index: 95;
  }
}

/* Mobile-only booking CTA — desktop already has its own floating pair
   (.hero-actions-float), so this only shows below the breakpoint where
   that's hidden. Sits inside the glass card, right above the heading —
   effectively "below the photo" on mobile, since this card is the first
   thing after it. */
.hero-mobile-cta {
  display: inline-flex;
  margin-bottom: var(--sp-3);
}

@media (min-width: 860px) {
  .hero-mobile-cta {
    display: none;
  }
}

.hero-intro-heading {
  /* Full size only on desktop, where the box is wide enough for the two
     authored lines to stay two lines — at mobile widths this would wrap
     into four. */
  font-size: var(--step-lg);
  overflow: hidden;
  text-align: right;
  color: var(--accent);
}

@media (min-width: 860px) {
  .hero-intro-heading {
    /* Scales up in two steps rather than jumping straight to 2x at the
       860px breakpoint — at the narrow end of the desktop range the box
       is much narrower (sidebar + shift eat proportionally more of the
       viewport there), so the full 2x size wrapped into extra lines and
       could push the box's top above the viewport (it's bottom-anchored). */
    font-size: calc(var(--step-lg) * 1.3);
  }
}

@media (min-width: 1200px) {
  .hero-intro-heading {
    /* The hero's one big statement, at full size once there's room —
       landing right as everything else finishes settling. */
    font-size: calc(var(--step-lg) * 2);
  }
}

.hero-intro-heading .line {
  display: block;
  overflow: hidden;
  padding-block: 0.08em;
}

.hero-intro-heading .line span {
  display: inline-block;
  will-change: transform;
}

.hero-intro-desc {
  margin-top: var(--sp-2);
  color: var(--ink-soft);
  font-size: var(--step-body);
}

@media (min-width: 860px) {
  .hero-intro-desc {
    /* Same two-step scaling as the heading above, for the same reason. */
    font-size: calc(var(--step-body) * 1.5);
    max-width: 38rem;
  }
}

@media (min-width: 1200px) {
  .hero-intro-desc {
    font-size: calc(var(--step-body) * 2.2);
    /* Wider than the heading needs — this is what actually caps it at
       three lines instead of wrapping further; there's open space to the
       left (the box is right-anchored) to grow into. */
    max-width: 52rem;
  }
}

/* --- experience section: decorative color behind the glass cards --- */
#experience {
  position: relative;
  overflow: hidden;
}

#experience .container {
  position: relative;
  z-index: 1;
}

.experience-blob {
  position: absolute;
  border-radius: 50%;
  filter: blur(70px);
  opacity: 0.55;
  pointer-events: none;
  z-index: 0;
}

.experience-blob-a {
  width: 26rem;
  height: 26rem;
  top: -8rem;
  inset-inline-start: -8rem;
  background: radial-gradient(circle, var(--accent-soft), transparent 70%);
}

.experience-blob-b {
  width: 22rem;
  height: 22rem;
  bottom: -6rem;
  inset-inline-end: 6%;
  background: radial-gradient(circle, #ffb020, transparent 70%);
}

/* --- timeline (experience) — zigzag of glass cards --- */
.timeline {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-5);
}

/* Zigzag curve threaded through each card's dot marker — built in JS from
   the cards' actual measured positions, then "drawn" via stroke-dashoffset
   scrubbed to scroll progress. Spans the full timeline (not just a center
   gutter): the dots it connects sit at the outer edge of alternating
   left/right cards. */
.timeline-curve {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
  pointer-events: none;
  z-index: 0;
}

.timeline-curve path {
  fill: none;
  stroke: var(--accent);
  stroke-width: 2;
  stroke-linecap: round;
}

.timeline-card {
  position: relative;
  z-index: 1;
  width: min(46%, 27rem);
  padding: var(--sp-4);
  background: rgba(255, 255, 255, 0.5);
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  border: 1px solid rgba(255, 255, 255, 0.65);
  border-radius: var(--radius-lg);
  box-shadow: 0 8px 32px -10px rgba(30, 41, 90, 0.2);
}

/* Zigzag: right, left, right, ... (nth-child(odd) = flex-start, which on
   a column flex container is the inline-start edge — the right in RTL). */
.timeline-card:nth-child(odd) {
  align-self: flex-start;
}

.timeline-card:nth-child(even) {
  align-self: flex-end;
}

.timeline-card::before {
  content: "";
  position: absolute;
  top: var(--sp-4);
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--accent);
  z-index: 2;
}

.timeline-card:nth-child(odd)::before {
  inset-inline-end: -26px;
}

.timeline-card:nth-child(even)::before {
  inset-inline-start: -26px;
}

@media (max-width: 700px) {
  .timeline-curve {
    display: none;
  }

  .timeline-card {
    width: 100%;
    align-self: stretch !important;
  }

  .timeline-card::before {
    display: none;
  }
}

.timeline-dates {
  font-size: var(--step-xs);
  font-weight: 700;
  color: var(--accent);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}

.timeline-role {
  font-size: var(--step-lg);
  margin-top: var(--sp-1);
}

.timeline-org {
  color: var(--ink-soft);
  font-weight: 600;
  margin-top: 2px;
}

.timeline-desc {
  margin-top: var(--sp-2);
  color: var(--ink-soft);
  max-width: 40rem;
}

/* --- projects: pinned horizontal showcase (desktop) --- */
.work-pin {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--sp-5);
  overflow: hidden;
}

.work-track {
  display: flex;
  gap: var(--sp-4);
  padding-inline: var(--gutter);
  will-change: transform;
}

@media (max-width: 859px) {
  .work-pin {
    min-height: 0;
  }

  .work-track {
    flex-direction: column;
    padding-inline: 0;
  }

  .work-track .container {
    padding-inline: 0;
  }
}

/* --- project cards ---
   Bordered box, but no colored edge accent — a strip of accent color
   framing a card (top, side, doesn't matter which edge) is the single
   most recognizable "AI-generated UI" tell there is. The accent lives
   on the tag label instead (a short underline, like a print kicker),
   not on the container. */
.project-card {
  flex: 0 0 min(78vw, 420px);
  background: var(--dark-bg-raised);
  border: 1px solid var(--dark-line);
  border-radius: var(--radius);
  padding: var(--sp-4);
  height: 100%;
}

@media (max-width: 859px) {
  .project-card {
    flex-basis: auto;
  }
}

.project-card-tag {
  display: inline-block;
  font-size: var(--step-xs);
  color: var(--accent-soft);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding-bottom: 0.4rem;
  border-bottom: 2px solid var(--accent-soft);
}

.project-card-heading {
  font-size: var(--step-lg);
  margin-top: var(--sp-2);
}

.project-card-desc {
  color: var(--dark-ink-soft);
  margin-top: var(--sp-2);
}

.project-card-tags {
  display: flex;
  gap: var(--sp-1);
  flex-wrap: wrap;
  margin-top: var(--sp-3);
}

.project-card-tags span {
  font-size: var(--step-xs);
  border: 1px solid var(--dark-line);
  border-radius: 999px;
  padding: 0.25rem 0.7rem;
  color: var(--dark-ink-soft);
}

/* --- skill / expertise cards ---
   A flat filled tile — no border at all, no accent line — reads as a
   different object entirely from the bordered .project-card and the
   borderless .value-card below. The small square bullet before each
   name echoes .section-label's dot rather than repeating either of the
   other two families' box treatment. */
.card {
  background: var(--bg-raised);
  border-radius: var(--radius);
  padding: var(--sp-4);
  height: 100%;
}

.card-heading {
  font-size: var(--step-md);
  display: flex;
  align-items: center;
  gap: 0.55rem;
}

.card-heading::before {
  content: "";
  width: 9px;
  height: 9px;
  flex-shrink: 0;
  background: var(--accent);
  transform: rotate(45deg);
}

.card-desc {
  color: var(--ink-soft);
  margin-top: var(--sp-2);
}

/* --- value cards (מי אני) ---
   No box at all — an oversized outlined numeral, heading, description,
   separated from the next value by a hairline rule rather than by a
   card boundary. The point is that this section shouldn't look like a
   "feature grid" in the first place. */
.value-card {
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--line);
}

.value-card-icon {
  font-family: var(--font-display);
  font-size: 3.25rem;
  font-weight: 800;
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1.5px var(--line);
  margin-bottom: var(--sp-2);
}

.value-card-heading {
  font-size: var(--step-md);
}

.value-card-desc {
  color: var(--ink-soft);
  margin-top: var(--sp-1);
}

@media (min-width: 860px) {
  /* On the 4-column grid, only the hairline between rows makes sense —
     side-by-side columns get a vertical divider instead so the rule
     doesn't read as "closing off" each cell into a box. */
  .value-grid .value-card {
    padding-bottom: 0;
    border-bottom: none;
    padding-inline-end: var(--sp-4);
    border-inline-end: 1px solid var(--line);
  }

  .value-grid .value-card:last-child {
    padding-inline-end: 0;
    border-inline-end: none;
  }
}

/* --- CTA --- */
.cta_section {
  text-align: center;
}

.cta-heading {
  font-size: var(--step-xl);
  max-width: 42rem;
  margin-inline: auto;
  overflow: hidden;
}

.cta-heading .line {
  display: block;
  overflow: hidden;
}

.cta-actions {
  margin-top: var(--sp-4);
  display: flex;
  justify-content: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
}

/* --- testimonials --- */
.testimonial-slider {
  overflow: hidden;
}

.testimonial-card {
  position: relative;
  background: var(--paper);
  border: var(--border);
  border-radius: var(--radius-lg);
  padding: var(--sp-4);
  padding-top: var(--sp-5);
  height: 100%;
  /* No overflow:hidden — it was clipping almost all of the ::before
     quote mark below, since that's deliberately positioned bleeding
     above the card's own top edge. */
}

/* A real decorative quote mark, not a stock "quote card" icon — large
   and faint, sitting inside the card's own top padding (kept inside the
   card's box, not bleeding above it — the slider that holds these cards
   clips overflow for its horizontal paging, which was cutting the mark
   off almost entirely when it extended past the card's own top edge). */
.testimonial-card::before {
  content: "\201C";
  position: absolute;
  top: 0.4rem;
  right: var(--sp-3);
  font-family: Georgia, "Times New Roman", serif;
  font-size: 4.5rem;
  font-weight: 700;
  color: var(--accent);
  opacity: 0.18;
  line-height: 1;
  pointer-events: none;
}

.testimonial-quote {
  position: relative;
  font-size: var(--step-md);
  line-height: 1.5;
}

.testimonial-person {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-top: var(--sp-3);
}

.testimonial-avatar {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--bg-raised);
  color: var(--accent);
  display: flex;
  align-items: center;
  justify-content: center;
}

.testimonial-avatar svg {
  width: 18px;
  height: 18px;
}

.testimonial-name {
  font-weight: 700;
}

.testimonial-role {
  font-size: var(--step-xs);
  color: var(--ink-soft);
}

.swiper-nav-row {
  display: flex;
  gap: var(--sp-2);
  margin-top: var(--sp-4);
  justify-content: center;
}

.swiper-nav-btn {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink-soft);
  transition: background var(--dur-fast) var(--ease-out),
    border-color var(--dur-fast) var(--ease-out), color var(--dur-fast) var(--ease-out),
    transform var(--dur-fast) var(--ease-premium);
}

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

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

/* --- contact --- */
.contact-grid {
  display: grid;
  gap: var(--sp-5);
}

@media (min-width: 860px) {
  .contact-grid {
    grid-template-columns: 1fr 1fr;
  }
}

.field {
  display: flex;
  flex-direction: column;
  gap: 0.2rem;
  margin-bottom: 0.6rem;
}

.field-row {
  display: flex;
  gap: var(--sp-2);
  margin-bottom: 0.6rem;
}

.field-row .field {
  flex: 1 1 0;
  min-width: 0;
  margin-bottom: 0;
}

.field label {
  font-size: var(--step-sm);
  font-weight: 700;
}

.field-required {
  color: #d3312f;
}

.field-hint {
  color: var(--ink-soft);
  font-weight: 400;
}

.field input,
.field textarea {
  padding: 0.55rem 0.85rem;
  border-radius: var(--radius);
  border: var(--border);
  background: var(--paper);
}

/* Optional fields (email/message) stay visually quieter and take up
   less room than the required name/phone pair above them. */
.field-optional label {
  font-size: var(--step-xs);
  font-weight: 600;
  color: var(--ink-soft);
}

.field-optional textarea {
  min-height: unset;
}

.field-error {
  font-size: var(--step-xs);
  color: #d3312f;
  min-height: 1.2em;
}

.field-consent {
  margin-bottom: var(--sp-3);
}

.consent-label {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-1);
  cursor: pointer;
}

.consent-label input[type="checkbox"] {
  flex-shrink: 0;
  width: 20px;
  height: 20px;
  margin-top: 2px;
  accent-color: var(--accent);
}

.consent-label span {
  font-size: var(--step-xs);
  color: var(--ink-soft);
  line-height: 1.5;
}

.consent-label a {
  color: var(--accent);
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 2px;
}

/* --- footer --- */
.site-footer {
  border-top: var(--border);
  padding-block: var(--sp-4);
}

.site-footer .container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-2);
}

.footer-links {
  display: flex;
  gap: var(--sp-3);
}
