/*
==================================================================================
* Site overrides — loaded after the template's stylesheets.
*
* Keep this file tiny. Everything here is a deliberate departure from the base
* stylesheet, each one written down with the reason it exists.
==================================================================================
*/

/* ------------------------------------------------------------------
   Latin technical names inside RTL text
   ------------------------------------------------------------------
   font-ir.css puts IRANYekanX on effectively every element, and that face is a
   FaNum variant: it renders Latin digits as Persian glyphs. Combined with the
   page's RTL direction, ".NET 10" comes out as "NET ۱۰." — the leading dot
   reordered to the end and the version number transliterated.

   A version number is an identifier, not a quantity expressed in Persian, so it
   keeps Latin digits. Applied only to strings with no Persian letters; see
   src/components/Tech.tsx. */
.tech-ltr {
  direction: ltr !important;
  unicode-bidi: isolate;
  font-family: 'Segoe UI', Roboto, Arial, sans-serif !important;
}

/* ------------------------------------------------------------------
   Sub-page heading
   ------------------------------------------------------------------
   The sub-page banner is an <h1> rather than the template's <h2>, so each page
   actually marks up its own subject as its heading. font-ir.css pins h1 to
   Gofteh and h2-h6 to Morabba, both with !important, so without this the
   correction would also change the typeface. This keeps the banner looking
   exactly as it did. */
.page-header h1 {
  font-family: Morabba, Sans-serif !important;
}

/* ------------------------------------------------------------------
   Skip link
   ------------------------------------------------------------------
   The template has none, so a keyboard user tabs through the whole nav on every
   page before reaching the content. Off-screen until focused, so nothing about
   the design changes. */
.skip-link {
  position: absolute;
  top: -100px;
  right: 1rem;
  z-index: 100000;
  padding: 0.75rem 1.25rem;
  border-radius: 0 0 0.5rem 0.5rem;
  background: var(--bs-themecolor);
  color: #000;
  font-weight: 600;
  text-decoration: none;
  transition: top 0.15s ease-in-out;
}

.skip-link:focus {
  top: 0;
  color: #000;
}

/* ------------------------------------------------------------------
   Reduced motion
   ------------------------------------------------------------------
   The template animates constantly: WOW on nearly every block, a typing effect,
   two auto-scrolling logo marquees, a parallax portrait that tracks the cursor,
   and an infinite bouncing scroll arrow. For a visitor who has asked their
   system for less motion, that is not decoration.

   CSS handles what CSS starts. The script-driven effects — Typed, Parallax and
   Owl autoplay — are switched off in main.js, which checks the same query. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }

  /* WOW hides these until it animates them in; with animation effectively
     disabled they must not be left invisible. */
  .wow {
    visibility: visible !important;
  }

  .scroll-down-arrow .animated {
    animation: none !important;
  }
}

/* ------------------------------------------------------------------
   Hero name sizing
   ------------------------------------------------------------------
   The template sizes the hero h1 with `.text-36`, whose breakpoints are tuned
   for the short surname it shipped with ("واتسون", 6 letters). "امیراحمدی" is 9,
   and at the template's sizes it runs past the container at every width below
   1200px — invisibly, because font-ir.css sets `body{overflow-x:hidden}`, so the
   glyphs are simply sliced off at both edges rather than producing a scrollbar.

   Measured in the browser: rendered width is ~4.18x the font size for this
   string, so the largest size that fits a Bootstrap container is
   containerWidth / 4.3. The values below are that, per breakpoint. At 1200px and
   up the template's own 16.25rem already fits, so it is left untouched and the
   design is unchanged on desktop.

   If the name in the hero ever changes length, re-measure rather than assuming
   these still hold. */
@media (max-width: 575.98px) {
  #home h1.text-36 {
    font-size: calc((100vw - 1.5rem) / 4.3) !important;
  }
}

@media (min-width: 576px) and (max-width: 767.98px) {
  #home h1.text-36 {
    font-size: 7.5rem !important; /* container 540 − 24 padding = 516 */
  }
}

@media (min-width: 768px) and (max-width: 991.98px) {
  #home h1.text-36 {
    font-size: 10rem !important; /* container 720 − 24 = 696 */
  }
}

@media (min-width: 992px) and (max-width: 1199.98px) {
  #home h1.text-36 {
    font-size: 13.5rem !important; /* container 960 − 24 = 936 */
  }
}

/* -------------------------------------------------------------------------
   Technology marquee
   -------------------------------------------------------------------------
   The template's cells held full-colour client logos on a raster background.
   These are Simple Icons: a single path with no `fill`, so they render solid
   black by default — invisible on this theme. `invert` turns them white and the
   opacity holds them at the same muted weight the original logos had, so the row
   still reads as a background band rather than competing with the quote above it.

   filter, not `fill: currentColor`: the marks are <img> elements inside an Owl
   stage, which measures its own children — inlining nineteen SVGs to gain a
   colour property would cost more than it buys. */
.tech-cell {
  height: 84px;
}

/* The `.owl-carousel .owl-item img` selector in owl.carousel.css sets
   `width: 100%` on every image inside a slide — written for the photo galleries
   the plugin ships for. It outweighs a single class, so a bare `.tech-mark`
   lost and each 28px icon stretched to the full width of its cell, shoving the
   name against the edge. Matching Owl's own selector is what takes the rule
   back; !important would work too but would also break the next person who
   legitimately needs to resize one of these. */
.owl-carousel .owl-item img.tech-mark,
.tech-mark {
  width: 28px;
  height: 28px;
  flex: 0 0 auto;
  filter: invert(1);
  opacity: 0.7;
  transition: opacity 0.25s ease;
}

/* The item counts above are chosen so the longest name ("Chrome Extension",
   about 200px with its mark) fits on one line at every breakpoint. This is the
   safety net for the next name that does not: wrapping inside the 84px cell
   costs nothing, whereas `nowrap` pushed the text straight through the border
   with no clipping to hide it. */
.tech-name {
  color: rgba(255, 255, 255, 0.7);
  text-align: center;
  line-height: 1.25;
  transition: color 0.25s ease;
}

.tech-cell:hover .tech-mark {
  opacity: 1;
}

.tech-cell:hover .tech-name {
  color: rgba(255, 255, 255, 0.9);
}

/* The light theme needs the marks left as they are — they are already dark ink
   on a light ground. */
[data-bs-theme='light'] .tech-mark {
  filter: none;
  opacity: 0.6;
}

[data-bs-theme='light'] .tech-name {
  color: rgba(0, 0, 0, 0.6);
}

[data-bs-theme='light'] .tech-cell:hover .tech-name {
  color: rgba(0, 0, 0, 0.9);
}

@media (prefers-reduced-motion: reduce) {
  .tech-mark,
  .tech-name {
    transition: none;
  }
}

/* -------------------------------------------------------------------------
   Testimonial monogram
   -------------------------------------------------------------------------
   Same 90px circle the template's portrait occupied, so the slide keeps its
   rhythm when a slide has no photograph. */
.testimonial-monogram {
  width: 90px;
  height: 90px;
  font-size: 2.25rem;
  line-height: 1;
  color: var(--bs-primary);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.12);
}

[data-bs-theme='light'] .testimonial-monogram {
  background: rgba(0, 0, 0, 0.04);
  border-color: rgba(0, 0, 0, 0.1);
}

/* -------------------------------------------------------------------------
   Underline form fields
   -------------------------------------------------------------------------
   The template ships `.form-border .form-control { padding: 0 }`, which leaves
   every field 32px tall with its text sitting directly on the underline. Two
   problems: the control is below the 44px touch target, and between a 31px
   label and the rule there is a band of empty space that reads as a gap in the
   layout rather than as a field.

   Padding is vertical only. The label has none, so adding horizontal padding
   would indent the typed text away from the label's edge — visible immediately
   in a right-to-left column where both share that edge. */
.form-border .form-control {
  padding: 0.5rem 0 0.625rem;
}

/* Bootstrap's own min-height is expressed against its padding, which is gone
   here; without this a one-row textarea collapses shorter than an input. */
.form-border textarea.form-control {
  min-height: calc(1.5em + 1.125rem + 1px);
}

/* The label sits 0.5rem above its field everywhere; the captcha group has one
   extra row and used a different value, so the group drifted out of the
   form's rhythm. */
#contact-form .form-label {
  margin-bottom: 0.5rem;
}

/* The answer field is text-5 so the typed digits are large and easy to check
   against the image. Its placeholder is a sentence, though, and at that size it
   arrived as a second label competing with the real one. */
#contact-form ::placeholder {
  font-size: 0.7em;
  opacity: 0.7;
}

/* -------------------------------------------------------------------------
   Project gallery
   -------------------------------------------------------------------------
   The slides mix two shapes: 1440x900 captures of the web projects and
   563x1000 phone screenshots of the apps. `img-fluid` alone stretches whatever
   it is given to the width of the slide, which upscaled the phone shots by a
   quarter — visibly soft — and produced a 1243px-tall slide for a picture of a
   phone.

   Height is the constraint that suits both: a landscape capture still fills the
   slide because it is wider than it is tall, and a portrait one settles at its
   own width instead of being blown up. The carousel runs with autoWidth, so
   each slide is exactly as wide as its image and no slide carries empty space. */
.project-gallery .item img {
  /* owl.carousel sets `width: 100%` on stage images; the slide's width comes
     from the image here (data-autowidth), so the image must keep its own. */
  width: auto !important;
  height: auto;
  max-height: 560px;
  max-width: 85vw;
}

@media (max-width: 767.98px) {
  .project-gallery .item img {
    max-height: 460px;
  }
}

/* ------------------------------------------------------------------
   Touch targets on a phone
   ------------------------------------------------------------------
   Measured in a real browser at 360px, not guessed. The template sizes several
   controls below the 44px minimum a finger needs:

     .navbar-toggler        31x30   the ONLY way to open navigation on a phone
     .owl-dot               32x13   carousel pagination
     .btn                   42 tall
     .tags a                41 tall
     .social-links a        70x32   footer social row, every page
     .scroll-down-arrow     35x46   too narrow, not too short
     .meta-blog a           23 tall  author / category on every post card
     .list-item li a        41 tall  category list in the blog sidebar
     .sample-site-link      86x32   the site links in the /about samples list

   The hamburger is the one that matters: a 30px target for the primary
   navigation control means missed taps on every visit.

   All of it is corrected HERE rather than in the template's own stylesheets,
   which stay untouched — this file is loaded last and is the project's
   override seam.

   The visual size is preserved wherever it is part of the design: the carousel
   dots keep their 13px appearance and gain the hit area from an overlay, so
   nothing looks different and the target is real.

   Two things the audit flags that are NOT corrected, each for a reason:

     .side-post .img-thumb a   65x23 -- a false positive. The anchor is
       `display: inline`, so its own box is one line tall, but the 65x65 image
       inside it is what the finger lands on. Measured, not assumed.

     inline links inside prose -- see the note at the bottom of this file. */
@media (max-width: 991.98px) {
  /* The breakpoint is the template's own `navbar-expand-lg`, i.e. exactly when
     the toggler appears. */
  .navbar-toggler {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    /* The template draws the three bars as child spans with fixed margins;
       centring them in the larger box keeps the icon identical. */
    gap: 4px;
  }

  /* 42 -> 44. Two pixels, but they are the two that decide whether the rule is
     met, and `min-height` cannot shrink a button that is already taller. */
  .btn:not(.btn-link) {
    min-height: 44px;
  }

  /* Tag and category pills in the blog sidebar and post footer. */
  .tags a,
  .blog-sidebar .tags a {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* The social row, which is in the footer of every page. */
  .social-links a {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* The site links in the "نمونه وب‌سایت‌ها" list on /about. The class is on the
     anchor itself; deriving a selector from the grid columns around it would
     break the moment the layout changes. */
  .sample-site-link {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }

  /* Tall enough already; it is 35px WIDE. */
  .scroll-down-arrow {
    min-width: 44px;
    justify-content: center;
  }

  /* The category list in the blog sidebar: 41 tall, three pixels short. */
  .list-item li a {
    padding-block: 9px;
  }

  /*
   * The date / author / category line under every post title.
   *
   * The links in it are `display: inline`, and that rules out the obvious fix:
   * vertical padding on an inline element grows the hit area WITHOUT moving
   * the layout, so the padded box would sit on top of the post title directly
   * above it and swallow taps meant for the title. Trading the primary target
   * for a secondary one is not an improvement.
   *
   * Growing the line box instead gives the same 44px with no overlap at all,
   * and it applies to the whole `li`, so the unlinked date keeps its baseline
   * aligned with the two links beside it.
   *
   * The line box alone is not enough, and this was measured rather than
   * assumed: with `line-height: 44px` the `li` really is 44px tall, but the
   * anchor inside it still reported 137x23 and a point 14px below its centre
   * missed it. An inline box takes its hit area from the font's own metrics,
   * not from the line-height around it. So the `li` opens up the room and the
   * anchor is switched to `inline-flex` to fill it -- the hit area becomes the
   * full 44px while staying inside the line box that was already there, which
   * is why nothing below the post title moves and nothing overlaps it.
   */
  .meta-blog li {
    line-height: 44px;
  }

  .meta-blog li a {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
    /* Without this the 44px flex box sits on the text baseline and hangs below
       the line it belongs to. */
    vertical-align: middle;
  }
}

/* ------------------------------------------------------------------
   Post thumbnails reserve their box
   ------------------------------------------------------------------
   The template pins the thumbnail's WIDTH (`width: 65px !important` in the
   sidebar, 75px for the previous/next pair) and leaves the height to the
   image. The height is therefore unknown until the file decodes, and the list
   reflows underneath it.

   Hardcoding `width`/`height` on the tag would be wrong: `thumb` is a database
   column the panel can edit, so the next thumbnail an editor uploads may be
   16:9, and a square attribute pair would reserve a box the image never fills.

   A square slot plus `object-fit: cover` reserves the space without assuming
   anything about the file. Every thumbnail in the project today is already
   square, so nothing looks different -- and a non-square upload is cropped to
   the slot instead of pushing the rest of the sidebar down. */
.side-post .item-post .img-thumb img,
.item-post .img-thumb img {
  aspect-ratio: 1;
  object-fit: cover;
  width: 100%;
}

/* Carousel pagination dots: a 32x13 button, far under the 44px target.

   Padding does not work here, and that is not a guess -- owl ships
   `.owl-carousel button.owl-dot { padding: 0 !important }`, which beats any
   padding we declare whatever the order of the stylesheets. Rather than
   escalate into an `!important` fight with the vendor, the hit area is grown
   with a transparent overlay, which also leaves the painted dot untouched:
   this is a 1:1 template port and the dots must still LOOK the same.

   The overlay is full-width and 44px tall but NOT 44px wide, deliberately.
   The dots sit side by side, so a 44px-wide box on each would overlap its
   neighbours and a tap near an edge would hit the wrong slide -- worse than
   the problem being fixed. Horizontally the strip of dots is continuous, so
   there is no dead gap to miss, and each dot still clears the 24px minimum. */
.owl-dots .owl-dot {
  position: relative;
}

.owl-dots .owl-dot::after {
  content: '';
  position: absolute;
  inset-inline: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 44px;
}

/* ------------------------------------------------------------------
   Inline links are deliberately NOT padded
   ------------------------------------------------------------------
   The audit also flags every inline link inside prose — "جزئیات را بررسی کنید"
   at 151x23, the footer's profile links at 70x32 — for being under 44px tall.
   They are left alone on purpose.

   A link inside a sentence cannot be given a 44px box without breaking the line
   height of the paragraph around it, and WCAG's target-size criterion exempts
   exactly that case: a target "in a sentence or block of text". The rule is for
   standalone controls, which are the ones corrected above. */

/* ------------------------------------------------------------------
   Header logo on a phone
   ------------------------------------------------------------------
   The wordmark is 159px wide at its desktop size. With the CTA button and the
   menu toggle on the same row, that pushed the toggle onto a second line below
   ~430px, so the logo and the CTA both narrow with the viewport instead. */
@media (max-width: 575.98px) {
  #header .logo img {
    width: 112px;
    height: auto;
  }

  #header .header-cta {
    font-size: 0.8125rem !important;
    padding-inline: 0.625rem !important;
  }

  #header .navbar-toggler {
    margin-inline-start: 0.5rem !important;
  }
}

@media (max-width: 389.98px) {
  #header .logo img {
    width: 96px;
  }
}

@media (max-width: 359.98px) {
  #header .logo img {
    width: 80px;
  }

  #header .header-cta {
    font-size: 0.75rem !important;
    padding-inline: 0.5rem !important;
  }
}

/* ------------------------------------------------------------------
   Breadcrumb separator
   ------------------------------------------------------------------
   The template's separator is Font Awesome's angle-right (\f105), copied from
   the LTR build. In a right-to-left trail the path reads right to left, so the
   arrow has to point left, towards the deeper page. */
.page-header .breadcrumb > li + li::before {
  content: "\f104";
}

/* ------------------------------------------------------------------
   Page-load bar
   ------------------------------------------------------------------
   Under the header menu; see NavProgress.tsx. It grows from the right, since the
   site reads right to left. `overflow: hidden` clips only the two highlights
   below: an element's own box-shadow, the glow, is not clipped by it. */
.nav-progress {
  position: absolute;
  right: 0;
  bottom: 0;
  z-index: 2;
  width: 0;
  height: 3px;
  overflow: hidden;
  border-radius: 3px 0 0 3px;
  background: linear-gradient(to left, #c80f00, #ff2400 55%, #ff5a1f);
  box-shadow:
    0 0 6px #ff2400,
    0 0 14px rgba(255, 36, 0, 0.75),
    0 0 28px rgba(255, 69, 0, 0.35);
  opacity: 0;
  pointer-events: none;
}

.nav-progress.is-loading {
  width: 85%;
  opacity: 1;
  /* Quick at first, then crawling: the real duration is unknown. */
  transition: width 8s cubic-bezier(0.08, 0.8, 0.2, 1);
}

.nav-progress.is-done {
  width: 100%;
  opacity: 0;
  transition:
    width 0.2s ease-out,
    opacity 0.25s ease 0.2s;
}

/* The shine: a band of light sweeping along the bar. */
.nav-progress.is-loading::before {
  content: "";
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  width: 25%;
  background: linear-gradient(to left, transparent, rgba(255, 255, 255, 0.9), transparent);
  animation: nav-progress-shine 1.2s linear infinite;
}

/* The white-hot leading edge. */
.nav-progress.is-loading::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 48px;
  background: linear-gradient(to right, rgba(255, 240, 220, 0.95), transparent);
}

@keyframes nav-progress-shine {
  from {
    transform: translateX(100%);
  }
  to {
    transform: translateX(-400%);
  }
}
