/* 3dnegar — shared component classes
   Values transcribed verbatim from the literal .dc.html source (not the README's
   prose summary, where the two ever disagree -- e.g. the homepage's own services/
   why-us/process numbering uses var(--accent-soft), while sub-pages' index numbers
   (order types, case-study steps, about timeline, b2b cards) use var(--accent3),
   confirmed by reading each file's actual markup). */

/* ---- Section header pattern ---- */
.section-kicker {
  display: block;
  font-size: 13px;
  letter-spacing: .06em;
  color: var(--accent-tint);
  font-weight: 600;
  margin-bottom: 14px;
}
.section-heading {
  font-family: 'Archivo', sans-serif;
  font-weight: 800;
  font-size: clamp(28px, 3.4vw, 40px);
  letter-spacing: -0.01em;
  margin: 0 0 32px;
}
.section-heading.hero-heading { font-size: clamp(36px, 5vw, 60px); line-height: 1.1; }

/* ---- Section divider ---- */
.section-divider-wrap { display: flex; justify-content: center; }
.section-divider {
  width: 36px; height: 3px; border-radius: 2px;
  background: linear-gradient(90deg, var(--accent1), var(--accent2));
}

/* ---- Glass surfaces ---- */
.glass-panel {
  background: rgba(var(--ink), 0.04);
  border: 1px solid rgba(var(--ink), 0.1);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}
/* Structural / data cards: sharper corners + brighter top edge highlight */
.glass-card {
  background: rgba(var(--ink), 0.04);
  border: 1px solid rgba(var(--ink), 0.1);
  border-top: 1px solid rgba(var(--ink), 0.2);
  box-shadow: inset 0 1px 0 rgba(var(--ink), 0.12);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-radius: 10px;
}

/* ---- CTA buttons ---- */
.btn-cta {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-weight: 700; font-size: 15px; color: #fff;
  background: linear-gradient(135deg, var(--accent1), var(--accent2));
  padding: 15px 30px; border-radius: 999px;
  box-shadow: 0 10px 30px rgba(var(--accent1-rgb), 0.4);
  transition: transform .3s, box-shadow .3s;
  border: none; cursor: pointer; font-family: inherit;
}
.btn-cta:hover { transform: translateY(-3px) scale(1.03); box-shadow: 0 16px 40px rgba(var(--accent1-rgb), 0.55); color: #fff; }
.btn-secondary {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-weight: 600; font-size: 15px; color: var(--fg);
  background: rgba(var(--ink), 0.07);
  border: 1px solid rgba(var(--ink), 0.18);
  padding: 15px 30px; border-radius: 999px;
  backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
  transition: transform .3s, background .3s;
  cursor: pointer; font-family: inherit;
}
.btn-secondary:hover { transform: translateY(-3px); background: rgba(var(--ink), 0.14); color: var(--fg); }
.btn-cta-sm {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; font-weight: 700; color: #fff;
  background: linear-gradient(135deg, var(--accent1), var(--accent2));
  padding: 9px 18px; border-radius: 999px;
  box-shadow: 0 4px 16px rgba(var(--accent1-rgb), 0.4);
  transition: transform .25s, box-shadow .25s;
  white-space: nowrap;
}
.btn-cta-sm:hover { transform: translateY(-1px) scale(1.03); box-shadow: 0 8px 22px rgba(var(--accent1-rgb), 0.55); color: #fff; }

/* ---- Red "Modernist" index numbering (sub-pages) ---- */
.idx-num-red {
  display: block;
  font-family: 'Archivo', sans-serif;
  font-weight: 800;
  font-size: 12px;
  color: var(--accent3);
  margin-bottom: 8px;
}

/* ---- Pills / tags ---- */
.pill-tag {
  font-size: 13px; color: rgba(var(--ink), 0.8);
  background: rgba(var(--ink), 0.06);
  border: 1px solid rgba(var(--ink), 0.12);
  padding: 8px 16px; border-radius: 999px;
}

/* ---- Forms ---- */
.field-label { display: block; font-size: 13px; color: rgba(var(--ink), 0.6); margin-bottom: 8px; }
.field-input, .field-select, .field-textarea {
  width: 100%; padding: 12px 14px;
  background: rgba(var(--ink), 0.06);
  border: 1.5px solid rgba(var(--ink), 0.14);
  border-radius: 12px; color: var(--fg);
  font-family: inherit; font-size: 14px;
  transition: border-color .25s, box-shadow .25s;
}
.field-input:hover, .field-select:hover, .field-textarea:hover { border-color: rgba(var(--accent1-rgb), 0.4); }
.field-input:focus, .field-select:focus, .field-textarea:focus { border-color: var(--accent1); box-shadow: 0 0 0 3px rgba(var(--accent1-rgb), 0.15); outline: none; }
.field-textarea { min-height: 70px; resize: vertical; }
.field-select option { background: #1c1c22; color: #fff; }

/* ---- Header / rail shared surface ---- */
.site-header {
  position: fixed; top: 0; z-index: 46;
  backdrop-filter: blur(22px) saturate(180%); -webkit-backdrop-filter: blur(22px) saturate(180%);
  border-bottom: 1px solid rgba(var(--ink), 0.14);
  transition: inset-inline-start .45s cubic-bezier(.16,1,.3,1);
}
.site-rail {
  position: fixed; top: 0; bottom: 0; right: 0; z-index: 50;
  transition: width .45s cubic-bezier(.16,1,.3,1);
}
.site-rail-inner {
  position: relative; height: 100%;
  backdrop-filter: blur(22px) saturate(180%); -webkit-backdrop-filter: blur(22px) saturate(180%);
  display: flex; flex-direction: column; gap: 2px;
  padding: 76px 8px 20px; overflow-y: auto; overflow-x: hidden;
}

/* Services mega-menu (js/home-nav.js): slides in/out from the rail's own
   physical edge (translateX is always physical, so positive = toward the
   right-docked rail regardless of RTL) instead of a generic center pop --
   and the "out" keyframes give the close an actual exit instead of an
   instant removal. */
@keyframes s3dServicesMenuIn { from { opacity: 0; transform: translateX(22px) scale(.96); } to { opacity: 1; transform: translateX(0) scale(1); } }
@keyframes s3dServicesMenuOut { from { opacity: 1; transform: translateX(0) scale(1); } to { opacity: 0; transform: translateX(16px) scale(.97); } }
@keyframes s3dServicesBackdropIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes s3dServicesBackdropOut { from { opacity: 1; } to { opacity: 0; } }

/* Hero video scene captions (js/page-home.js): one caption per video scene,
   typed in, held, then swapped for the next -- crossfade+blur+lift matches
   the fadeUp motion language used sitewide (tokens.css), not a generic pop.
   The exit keyframe duration here (.38s) and the JS swap timer that follows
   it (390ms, in page-home.js) are deliberately kept in sync -- a mismatch
   previously cut the exit animation off ~40ms before it finished, which is
   why it read as "no disappear animation" rather than a real fade-out. */
.s3d-hero-caret {
  display: inline-block; width: 3px; height: 0.8em; background: #fff;
  vertical-align: -0.05em; margin-inline-start: 3px; border-radius: 2px;
  animation: blinkCaret .85s step-end infinite;
}
#s3d-hero-caption { transition: opacity .3s ease; }
#s3d-hero-caption.s3d-caption-in { animation: s3dCaptionIn .6s cubic-bezier(.16,1,.3,1) both; }
#s3d-hero-caption.s3d-caption-out { animation: s3dCaptionOut .38s ease both; }
@keyframes s3dCaptionIn { from { opacity: 0; transform: translateY(18px); filter: blur(8px); } to { opacity: 1; transform: translateY(0); filter: blur(0); } }
@keyframes s3dCaptionOut { from { opacity: 1; transform: translateY(0); filter: blur(0); } to { opacity: 0; transform: translateY(-14px); filter: blur(8px); } }
@media (prefers-reduced-motion: reduce) {
  .s3d-hero-caret { animation: none; }
  #s3d-hero-caption.s3d-caption-in, #s3d-hero-caption.s3d-caption-out { animation: none; }
}
.rail-link {
  position: relative; display: flex; align-items: center; gap: 12px;
  padding: 9px 8px; border-radius: 14px; transition: background .3s;
  white-space: nowrap;
}
.rail-link-bar {
  position: absolute; inset-inline-start: 0; top: 8px; bottom: 8px; width: 3px;
  border-radius: 0 3px 3px 0;
  background: linear-gradient(180deg, var(--accent1), var(--accent2));
  transition: opacity .25s;
}
.rail-link-icon { width: 32px; height: 32px; border-radius: 10px; display: flex; align-items: center; justify-content: center; flex-shrink: 0; }
.rail-link-label { font-size: 13px; transition: opacity .25s; }

.icon-btn {
  display: flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: 50%;
  background: rgba(var(--ink), 0.06); border: 1px solid rgba(var(--ink), 0.1);
  color: var(--fg); cursor: pointer; flex-shrink: 0;
  transition: transform .3s, background .3s;
}
.icon-btn:hover { background: rgba(var(--ink), 0.14); transform: rotate(20deg); }

/* ---- Interactive logo (header + footer) ----
   Real logo image (assets/logo-icon.png -- the emblem cropped out of the
   owner's actual logo file via corner-seeded flood-fill background removal,
   NOT a naive near-white color threshold: a plain threshold also caught the
   character's own silver specular highlights as "background" and punched
   transparent holes through her face/hair, which read as solid black on the
   dark theme -- flood fill only removes the background pixels actually
   CONNECTED to the image edges, so highlights enclosed by her dark outline
   strokes are never touched). Text uses the logo's own two-tone coloring
   (violet "3D" + ink "Negar") instead of an invented gradient -- "Negar"
   uses var(--fg) rather than the photo's literal dark navy, since that
   literal color is unreadable on the dark theme's near-black background;
   this is the same ink token every other heading on the site already uses,
   so it stays legible in both themes instead of matching the photo exactly
   in one and vanishing in the other.

   Hover is a real mouse-tracked 3D tilt (perspective rotateX/rotateY driven
   by cursor position, wired in dc-shim.js's initLogoFx) plus a holographic
   sheen overlay that shifts with the same tilt values -- a genuinely
   different mechanism from a canned CSS-only hover, and literal to the "3D"
   in the brand name. Idle state stays a calm ambient glow pulse. */
.logo-link {
  display: flex;
  align-items: center;
  gap: 6px; /* footer (10px, larger mark) reads correctly; header was pushed
    all the way to 0 chasing a pixel-perfect "touching" look the circular
    mark's own tapered edge fights against. Matching the footer's proportion
    at the smaller header size instead of insisting on literal zero. */
  flex-shrink: 0;
}
.logo-mark-wrap {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  width: auto; /* was a fixed 48px square -- the image's own portrait aspect
    ratio (~0.89) renders narrower than that at any given height, so a fixed
    square box centered a narrower image inside it, adding a few more
    avoidable pixels of dead space on top of the gap already removed above */
  height: 48px;
  perspective: 500px;
  --logo-rx: 0deg;
  --logo-ry: 0deg;
}
.logo-mark-wrap.logo-mark-wrap--lg { width: auto; height: 60px; }
.logo-glow {
  /* This was the ACTUAL source of "the gap" everyone kept reporting: inset:-10px
     plus a 6px blur made the glow's visible halo extend well beyond the icon's
     own edge on every side, INCLUDING the side facing the text -- so even with
     the real flex gap at 0 (boxes genuinely touching), the soft purple aura
     visually read as empty space before the "real" character began. Confirmed
     by zooming into an actual pixel-level render, not guessed. Pulled the inset
     and blur way in so the glow hugs the artwork instead of surrounding it with
     a moat. */
  position: absolute;
  inset: -2px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(var(--accent2-rgb), 0.55), rgba(var(--accent1-rgb), 0.25) 55%, transparent 75%);
  opacity: 0.28;
  filter: blur(2px);
  transform: scale(0.94);
  transition: opacity .35s ease, transform .35s ease;
  animation: logoGlowPulse 3.2s ease-in-out infinite;
  pointer-events: none;
}
@keyframes logoGlowPulse {
  0%, 100% { opacity: 0.22; transform: scale(0.94); }
  50% { opacity: 0.34; transform: scale(1); }
}
.logo-mark {
  position: relative;
  z-index: 1;
  height: 100%;
  width: auto;
  display: block;
  filter: drop-shadow(0 2px 8px rgba(0,0,0,0.35));
  transform: perspective(500px) rotateX(var(--logo-rx)) rotateY(var(--logo-ry)) scale(1);
  transition: transform .12s ease-out, filter .3s ease;
  transform-style: preserve-3d;
}
.logo-link:hover .logo-mark {
  filter: drop-shadow(0 6px 18px rgba(var(--accent2-rgb),0.55));
}
.logo-link.logo-tilting .logo-mark { transform: perspective(500px) rotateX(var(--logo-rx)) rotateY(var(--logo-ry)) scale(1.1); }
.logo-link:hover .logo-glow { opacity: 0.75; transform: scale(1.2); animation-play-state: paused; }

/* Holographic sheen: a low-opacity iridescent gradient masked to the mark's
   own alpha, whose angle/position tracks the same tilt values so it visibly
   shifts as the cursor moves across it -- a foil-card effect. */
.logo-holo {
  position: absolute;
  inset: 0;
  z-index: 2;
  pointer-events: none;
  opacity: 0;
  mix-blend-mode: color-dodge;
  -webkit-mask-size: contain;
  -webkit-mask-repeat: no-repeat;
  -webkit-mask-position: center;
  mask-size: contain;
  mask-repeat: no-repeat;
  mask-position: center;
  background: linear-gradient(
    calc(135deg + var(--logo-ry) * 2),
    transparent 15%,
    rgba(255, 100, 220, 0.55) 30%,
    rgba(120, 140, 255, 0.55) 45%,
    rgba(120, 255, 220, 0.5) 60%,
    transparent 80%
  );
  background-size: 220% 220%;
  background-position: calc(50% + var(--logo-ry) * 4%) calc(50% + var(--logo-rx) * -4%);
  transition: opacity .25s ease;
}
.logo-link:hover .logo-holo { opacity: 0.85; }

.logo-text-wrap {
  display: flex;
  flex-direction: column;
  /* THE actual root cause of the whole "gap next to 3D Negar" saga, found by
     measuring exact pixel boxes: for a flex-direction:column container,
     align-items:flex-start/flex-end resolve against the CROSS axis, which
     for column direction is the INLINE axis -- so on this RTL page,
     flex-start = right and flex-end = LEFT (the opposite of block-level
     "start/end" intuition). flex-end was therefore aligning every line to
     the LEFT, not the right: the widest line (the tagline) happened to
     stretch far enough right to look "close" to the icon by coincidence of
     its own width, while the short "3D Negar" line sat flush-left with a
     large, real, measured gap (56px in a test render) between its own right
     edge and the icon. flex-start is the correct value for right-alignment
     here. */
  align-items: flex-start;
  gap: 2px;
  line-height: 1;
  white-space: nowrap;
}
.logo-text-main {
  font-family: 'Archivo', sans-serif;
  font-weight: 800;
  letter-spacing: -0.01em;
}
/* Fixed brand purple sampled directly from the logo file's own "3D" glyph and
   ring (RGB ~118,63,225 / ~108,64,209 -- effectively the same ink), used
   literally instead of the site's --accent2 token so it reads identical to
   the source photo in both themes, not a theme-shifted approximation. The
   "Negar"/"نگار" half stays var(--fg) -- the literal photo ink (#252d37) is
   close to var(--fg) on the light theme already, and only var(--fg) stays
   legible when the theme flips dark. Same purple/ink split is applied to
   the Persian name (سه‌بعدی = purple, نگار = ink) so the two scripts read as
   one consistent brand mark rather than two different treatments. */
.logo-3d, .logo-3d-fa { color: #7c3fe0; transition: text-shadow .3s ease; }
.logo-negar, .logo-negar-fa { color: var(--fg); transition: color .3s ease; }
.logo-link:hover .logo-3d, .logo-link:hover .logo-3d-fa { text-shadow: 0 0 14px rgba(124,63,224,0.65); }
.logo-link:hover .logo-negar, .logo-link:hover .logo-negar-fa { color: var(--accent-tint); }
.logo-fa-line {
  font-family: 'Vazirmatn', sans-serif;
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0;
}
.logo-tagline {
  font-size: 10px;
  font-weight: 600;
  letter-spacing: .04em;
  color: rgba(var(--ink), 0.4);
  margin-top: 1px;
}
.logo-text-lg .logo-text-main { font-size: 24px; }
.logo-text-lg .logo-fa-line { font-size: 18px; margin-top: 2px; }
.logo-link.logo-text-lg { gap: 10px; } /* the compact header lockup wants the
  mark and text touching (gap:0, above); this standalone footer lockup is
  bigger and reads better with real breathing room between them */

/* Narrow phones: the 3-line header lockup (wordmark + Persian name + tagline)
   plus the hamburger/theme-toggle buttons on the other side of the header
   didn't leave enough width for the two text lines that survive the
   <520px tagline hide (home-nav.js), overflowing past the viewport edge
   and getting clipped by body's overflow-x:hidden. Shrink the mark and
   text at this width instead of relying on the tagline hide alone. */
@media (max-width: 480px) {
  .site-header .logo-mark-wrap:not(.logo-mark-wrap--lg) { width: auto; height: 34px; }
  .site-header .logo-text-main { font-size: 14px !important; }
  .site-header .logo-fa-line { font-size: 11px; }
}

@media (prefers-reduced-motion: reduce) {
  .logo-glow { animation: none; opacity: 0.3; }
  .logo-mark, .logo-holo, .logo-3d, .logo-negar, .logo-3d-fa, .logo-negar-fa { transition-duration: .01ms; }
}

/* Utility */
.hidden { display: none !important; }
[dir] .flip-x { transform: scaleX(-1); }

/* ---- Before/after compare slider ----
   #design-before is a full-size image-slot clipped via clip-path to
   whatever fraction the pointer is currently hovering (page-home.js's
   setPos() updates the clip on every mousemove -- this isn't a fixed 50/50
   split), so its empty-state icon/caption can't be centered with a fixed
   50% offset: that only looked right exactly at the midpoint, and drifted
   away from the actually-visible sliver everywhere else the pointer moved.
   setPos() also writes the same live fraction to --s3d-before-pct, so the
   caption's flex box tracks the real clip boundary instead of a constant. */
#s3d-compare-before image-slot::part(empty),
#s3d-compare-before image-slot::part(attribution-error) {
  padding-inline-end: calc(100% - var(--s3d-before-pct, 50%));
}
