/* ==========================================================================
   D Abhishek Yadav — Portfolio custom layer
   Loads AFTER main.css (index.html:53 → :55), so equal-specificity rules here
   win. Mobile-first: every base rule targets the narrowest screen, and each
   `min-width` query adds complexity as space appears.

   BREAKPOINTS
   main.css is written max-width-first with this ladder:
       424 / 575 / 767 / 991 / 1199 / 1399 / 1499 / 1699 / 1799
   The min-width queries below are the exact inversion of it:
       425 / 576 / 768 / 992 / 1200 / 1400 / 1500 / 1700 / 1800
   so the two files tile with no gaps and no double-matching bands. Values are
   in px on purpose — main.css's queries are px, and using em here would drift
   apart from them whenever the user changes their default font size.

   SIZING RULES OF THUMB USED THROUGHOUT
   - one length axis per image, never width *and* max-height (see §5)
   - fluid type/space via the clamp() tokens in §0, no bare px for anything
     that has to survive a resize
   - flex/grid children get `min-width: 0` so a long word can't push the row
     wider than the viewport
   ========================================================================== */

/* --------------------------------------------------------------------------
   0. Tokens
   -------------------------------------------------------------------------- */
:root {
  --ay-lime: hsl(72, 99%, 50%);
  --ay-orange: hsl(19, 100%, 50%);
  --ay-ink: hsl(208, 76%, 3%);
  --ay-line: rgba(6, 13, 20, 0.12);
  --ay-line-light: rgba(255, 255, 255, 0.12);

  /* Fluid type scale. Each token reads clamp(min, A + B·vw, max) and
     interpolates linearly between a 360px phone and a 1440px laptop, then
     holds flat outside that range. The px pairs in the comments are the
     endpoints, so the intent stays checkable. */
  --ay-fs-3xs: clamp(0.53125rem, 0.5104rem + 0.093vw, 0.59375rem); /*  8.5 → 9.5 */
  --ay-fs-2xs: clamp(0.6875rem, 0.65625rem + 0.139vw, 0.78125rem); /*   11 → 12.5 */
  --ay-fs-xs: clamp(0.75rem, 0.71875rem + 0.139vw, 0.84375rem); /*      12 → 13.5 */
  --ay-fs-sm: clamp(0.875rem, 0.84375rem + 0.139vw, 0.96875rem); /*     14 → 15.5 */
  --ay-fs-base: clamp(0.9375rem, 0.8958rem + 0.185vw, 1.0625rem); /*    15 → 17 */
  --ay-fs-md: clamp(1.0625rem, 1rem + 0.278vw, 1.25rem); /*             17 → 20 */
  --ay-fs-lg: clamp(1.25rem, 1.1458rem + 0.463vw, 1.5625rem); /*        20 → 25 */
  --ay-fs-xl: clamp(1.375rem, 1.2917rem + 0.37vw, 1.625rem); /*         22 → 26 */
  --ay-fs-2xl: clamp(1.5rem, 1.375rem + 0.556vw, 1.875rem); /*          24 → 30 */
  --ay-fs-3xl: clamp(1.625rem, 1.5rem + 0.556vw, 2rem); /*              26 → 32 */

  /* Fluid space scale, same construction. */
  --ay-space-2xs: clamp(0.375rem, 0.3333rem + 0.185vw, 0.5rem); /*       6 → 8 */
  --ay-space-xs: clamp(0.5rem, 0.4583rem + 0.185vw, 0.625rem); /*        8 → 10 */
  --ay-space-sm: clamp(0.75rem, 0.7083rem + 0.185vw, 0.875rem); /*      12 → 14 */
  --ay-space-md: clamp(1rem, 0.875rem + 0.556vw, 1.375rem); /*          16 → 22 */
  --ay-space-lg: clamp(1.375rem, 1.125rem + 1.111vw, 2.125rem); /*      22 → 34 */
  --ay-space-xl: clamp(2rem, 1.2083rem + 3.519vw, 4.375rem); /*         32 → 70 */

  /* Component sizes */
  --ay-mark-size: clamp(2.5rem, 2.375rem + 0.556vw, 2.875rem); /*       40 → 46 */
  --ay-icon-size: clamp(2.875rem, 2.7083rem + 0.741vw, 3.375rem); /*    46 → 54 */
  --ay-dp-size: clamp(7.5rem, 6rem + 6.5vw, 10rem); /*                 120 → 160 */
  --ay-circle-size: clamp(13.75rem, 10rem + 16vw, 21.25rem); /*        220 → 340 */

  /* Hero portrait width. One axis only — see §5 for why. Overridden upward at
     each breakpoint; the 40rem ceiling reproduces the size already signed off
     on desktop. */
  --ay-hero-photo-w: min(66vw, 16rem);
}

/* --------------------------------------------------------------------------
   0b. Overflow guards
       These three rules remove the structural causes of horizontal scrollbars,
       rather than hiding the symptom with overflow:hidden (which would also
       break GSAP ScrollSmoother's transform on #smooth-content).
   -------------------------------------------------------------------------- */

/* main.css sets `img { max-width: 100% }` but leaves these out, so an SVG or a
   <picture> can still overflow its column. */
picture,
svg,
video,
canvas {
  max-width: 100%;
}

/* Flex and grid children default to `min-width: auto`, which means their
   min-content size acts as a floor — one long word (a URL, an email address,
   a 9-letter wordmark) then pushes the whole row wider than the viewport.
   Zeroing it lets them shrink and wrap instead. This is the single most
   common source of horizontal overflow in the template's flex rows. */
.banner-three-wrap > *,
.service-three-item > *,
.service-three-content > *,
.footer-three-top-info > *,
.footer-three-bottom-wrap > *,
.ay-about-stats > * {
  min-width: 0;
}

/* Oversized display type is the other source: these are single long words that
   cannot wrap at a space, so without this they just run off the edge. */
.banner-three-title,
.banner-three-center-title,
.footer-three-bottom-title,
.ay-edu-title,
.ay-skill-title,
.ay-cert-reveal b {
  overflow-wrap: break-word;
}

/* --------------------------------------------------------------------------
   1. Text logo (replaces the bitmap logo, both light + dark placements)
   -------------------------------------------------------------------------- */
.ay-logo {
  display: inline-flex;
  align-items: center;
  gap: var(--ay-space-xs);
  line-height: 1;
  text-decoration: none;
}

.ay-logo-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ay-mark-size);
  height: var(--ay-mark-size);
  border-radius: 50%;
  overflow: hidden;
  /* the portrait is exported on an opaque white matte, so the disc must be
     white too — a dark disc bled through the semi-transparent edge pixels and
     made the avatar "mix" with whatever surface it sat on */
  background: #ffffff;
  box-shadow:
    0 0 0 2px var(--ay-lime),
    0 6px 16px -6px rgba(6, 13, 20, 0.55);
  flex-shrink: 0;
}

.ay-logo-mark picture,
.ay-logo-mark img {
  display: block;
  width: 100%;
  height: 100%;
}

.ay-logo-mark img {
  object-fit: cover;
  object-position: 50% 22%;
  border-radius: 50%;
}

/* on dark surfaces the white disc needs a brighter halo so it does not vanish */
.ay-logo--light .ay-logo-mark {
  box-shadow:
    0 0 0 2px var(--ay-lime),
    0 0 0 5px rgba(255, 255, 255, 0.08);
}

.ay-logo-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  min-width: 0;
}

.ay-logo-name {
  font-family: var(--heading-font);
  font-weight: 700;
  font-size: var(--ay-fs-md);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: var(--ay-ink);
  transition: color 0.3s;
}

.ay-logo-role {
  font-family: var(--body-font);
  font-size: var(--ay-fs-3xs);
  font-weight: 500;
  /* tracking has to relax on narrow screens or the role line outgrows the
     name above it */
  letter-spacing: clamp(0.18em, 0.15em + 0.13vw, 0.24em);
  text-transform: uppercase;
  color: rgba(6, 13, 20, 0.55);
  transition: color 0.3s;
}

.ay-logo-dot {
  color: var(--ay-orange);
}

/* dark surfaces: offcanvas panel + footer */
.ay-logo--light .ay-logo-name {
  color: #fff;
}

.ay-logo--light .ay-logo-role {
  color: rgba(255, 255, 255, 0.6);
}

/* --------------------------------------------------------------------------
   1b. Offcanvas navigation — main.css colours these links with the heading
       colour, which is the same near-black as the panel behind them. This is
       the site's only nav, so it gets proper oversized treatment here.
   -------------------------------------------------------------------------- */
.tw-offcanvas-2-left .tw-main-menu-mobile {
  margin-block-start: var(--ay-space-xl);
  counter-reset: ay-nav;
}

.tw-offcanvas-2-left .tw-main-menu-mobile nav > ul > li > a {
  display: flex;
  align-items: baseline;
  gap: var(--ay-space-md);
  font-family: var(--heading-font);
  font-weight: 600;
  font-size: clamp(1.625rem, 1.018rem + 3.04vw, 3.75rem); /* 26 → 60 */
  line-height: 1.1;
  letter-spacing: -0.01em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.72);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  padding-block: var(--ay-space-md);
  /* nav labels are long single words ("CERTIFICATIONS"); let them shrink and
     break rather than widen the offcanvas panel */
  min-width: 0;
  overflow-wrap: break-word;
  transition:
    color 0.35s,
    padding-inline-start 0.35s;
}

.tw-offcanvas-2-left .tw-main-menu-mobile nav > ul > li > a::before {
  counter-increment: ay-nav;
  content: "0" counter(ay-nav);
  font-family: var(--body-font);
  font-size: var(--ay-fs-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--ay-orange);
  flex-shrink: 0;
}

.tw-offcanvas-2-left .tw-main-menu-mobile nav > ul > li > a:hover,
.tw-offcanvas-2-left .tw-main-menu-mobile nav > ul > li > a.color-active {
  color: var(--ay-lime);
  padding-inline-start: 12px;
}

.tw-offcanvas-2-left .tw-main-menu-mobile nav > ul > li:last-child > a {
  border-bottom: 1px solid rgba(255, 255, 255, 0.1);
}

.twoffcanvas__contact-title h5 {
  font-family: var(--heading-font);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin-block-end: var(--ay-space-md);
}

.twoffcanvas__contact-info ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.twoffcanvas__contact-info ul li {
  display: flex;
  align-items: flex-start;
  gap: var(--ay-space-sm);
  margin-block-end: var(--ay-space-md);
  font-size: var(--ay-fs-sm);
  line-height: 1.6;
  /* phone numbers and long addresses must break rather than widen the panel */
  min-width: 0;
  overflow-wrap: anywhere;
}

.twoffcanvas__contact-info ul li a {
  color: rgba(255, 255, 255, 0.78) !important;
  transition: color 0.3s;
}

.twoffcanvas__contact-info ul li a:hover {
  color: var(--ay-lime) !important;
}

/* --------------------------------------------------------------------------
   2. Hero wordmark
       main.css steps .banner-three-title through nine fixed px sizes. Those
       are fine at the wide end of each band but overflow at the narrow end —
       "developer" is one unbreakable 9-character word, so at 78px on a 360px
       phone it is wider than the container.

       Wrapping each step in min(19vw, <step>) fixes that without touching the
       look anywhere it was already safe: the vw term only wins at the START of
       a band (where the template overflowed) and the px ceiling takes over by
       the END of the band, matching main.css exactly. Worked example:
           360px → min(68.4, 78)    = 68.4px  (template 78, would overflow)
           424px → min(80.6, 78)    = 78px    (matches template)
           576px → min(109.4, 123)  = 109.4px (template 123, would overflow)
           767px → min(145.7, 123)  = 123px   (matches template)
       From 1200px up the ladder is restated at the template's exact px values,
       because the desktop rendering is already signed off.
   -------------------------------------------------------------------------- */
.banner-three-title {
  letter-spacing: -0.02em;
}

/* the extra class raises specificity to 0,2,0 so this beats the .tw-mb-30
   utility (0,1,0) on the same element without needing !important */
.banner-three-wrapper .banner-three-title {
  font-size: min(19vw, 4.875rem); /* ceiling 78px — main.css ≤424 step */
  line-height: 0.83;
  /* collapse the 7.5rem utility gap on phones; the portrait sits in the flow
     directly beneath and supplies its own rhythm */
  margin-block-end: var(--ay-space-sm);
}

@media screen and (min-width: 425px) {
  .banner-three-wrapper .banner-three-title {
    font-size: min(19vw, 5.5rem); /* 88px */
  }
}

@media screen and (min-width: 576px) {
  .banner-three-wrapper .banner-three-title {
    font-size: min(19vw, 7.6875rem); /* 123px */
  }
}

@media screen and (min-width: 768px) {
  .banner-three-wrapper .banner-three-title {
    font-size: min(19vw, 10.375rem); /* 166px */
  }
}

@media screen and (min-width: 992px) {
  .banner-three-wrapper .banner-three-title {
    font-size: min(19vw, 13.5rem); /* 216px */
  }
}

@media screen and (min-width: 1200px) {
  .banner-three-wrapper .banner-three-title {
    font-size: 16.25rem; /* 260px — matches main.css 1200–1399 */
    /* restore the template's gap: the portrait goes absolute from here up, so
       this margin is what positions the three-column row below */
    margin-block-end: var(--size-30);
  }
}

@media screen and (min-width: 1400px) {
  .banner-three-wrapper .banner-three-title {
    font-size: 19.1875rem; /* 307px — matches main.css 1400–1499 */
  }
}

@media screen and (min-width: 1500px) {
  .banner-three-wrapper .banner-three-title {
    font-size: 21.875rem; /* 350px — matches main.css 1500–1699 */
  }
}

@media screen and (min-width: 1700px) {
  .banner-three-wrapper .banner-three-title {
    font-size: 23.125rem; /* 370px — matches main.css 1700–1799 */
  }
}

@media screen and (min-width: 1800px) {
  .banner-three-wrapper .banner-three-title {
    font-size: 24.8125rem; /* 397px — matches main.css 1800+ */
  }
}

.ay-hero-badge {
  display: inline-flex;
  align-items: center;
  gap: var(--ay-space-xs);
  /* logical padding so the pill reflows correctly if the page ever goes RTL */
  padding-block: 0.5625rem;
  padding-inline: var(--ay-space-md);
  border: 1px solid var(--ay-line);
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.7);
  backdrop-filter: blur(6px);
  font-family: var(--body-font);
  font-size: var(--ay-fs-xs);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ay-ink);
  margin-block-end: var(--ay-space-lg);
  /* allow the pill to wrap its own text instead of stretching the column */
  max-width: 100%;
  flex-wrap: wrap;
}

.ay-pulse {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--ay-lime);
  box-shadow: 0 0 0 0 rgba(190, 253, 2, 0.8);
  animation: ay-pulse 2s infinite;
  flex-shrink: 0;
}

@keyframes ay-pulse {
  0% {
    box-shadow: 0 0 0 0 rgba(190, 253, 2, 0.9);
  }
  70% {
    box-shadow: 0 0 0 12px rgba(190, 253, 2, 0);
  }
  100% {
    box-shadow: 0 0 0 0 rgba(190, 253, 2, 0);
  }
}

/* --------------------------------------------------------------------------
   3. Hero three-column row
       main.css hides .banner-three-left/-right below 1200px and centres the
       middle column, so the markup's `d-flex justify-content-between` really
       only does work on desktop. Restating it as a grid makes the stacking
       explicit and removes the `justify-content-between` gap artefacts that
       appear when only one of the three children is visible.
       `display: grid !important` is needed because Bootstrap's .d-flex
       utility carries !important (bootstrap.min.css:7425).
   -------------------------------------------------------------------------- */
.banner-three-wrap {
  display: grid !important;
  grid-template-columns: 1fr;
  gap: var(--ay-space-lg);
  align-items: end;
}

@media screen and (min-width: 1200px) {
  .banner-three-wrap {
    /* side cards take their natural max-width (410/350/260 per main.css), the
       centre column absorbs the slack */
    grid-template-columns: auto minmax(0, 1fr) auto;
    gap: var(--ay-space-xl);
  }
}

/* keep the centre column from growing wider than the stroke headline */
.banner-three-center {
  max-width: 575px;
  width: 100%;
  margin-inline: auto;
}

/* --------------------------------------------------------------------------
   4. Hero section rhythm
       main.css: padding-block 200/100 base, 300/100 ≤1199, 200/100 ≤991,
       120/70 ≤767. Inverted to min-width and made fluid so the top pad grows
       with the viewport instead of jumping 180px between two breakpoints.
   -------------------------------------------------------------------------- */
.banner-three-area {
  padding-block: clamp(6.25rem, 4rem + 10vw, 12.5rem) /* 100 → 200 */
    clamp(3.75rem, 2.9rem + 3.7vw, 6.25rem); /*             60 → 100 */
}

/* --------------------------------------------------------------------------
   5. Hero portrait
       The background-removed full seated figure. Two layouts:

       • phone → laptop (base): the figure sits in the normal document flow,
         centred, pulled up slightly so it still reads as rising out of the
         wordmark. Staying in flow is what guarantees it can never land on top
         of the hero copy or get clipped on a narrow screen.

       • ≥1200px: the side cards reappear and the wordmark is ≥260px tall, so
         the figure switches to absolute and overlaps the "O" of "developer"
         from below — the same anchor main.css gives its own figure
         (.banner-three-man { inset-block-end: 27% }). .banner-three-wrap
         carries `position-relative z-1`, so the copy row always paints above
         the figure and stays readable.

       portfolio.js dissolves it on scroll via GSAP ScrollTrigger.
   -------------------------------------------------------------------------- */
.ay-hero-photo {
  position: relative;
  z-index: 0;
  display: flex;
  justify-content: center;
  /* negative top margin lifts the figure into the wordmark's descender band,
       expressed as a fraction of its own width so the overlap scales with it */
  margin-block: calc(var(--ay-hero-photo-w) * -0.1) var(--ay-space-lg);
  pointer-events: none;
  will-change: opacity, transform;
}

.ay-hero-photo picture {
  display: block;
}

/* ONE length axis, never two.
   The previous rule set `width: 48vw` AND `max-height: 880px`. Browsers
   resolve that pair through the CSS 2.1 §10.7 min/max algorithm, which
   back-computes the width to preserve the aspect ratio — so the declared 48vw
   was never the width actually rendered. Driving width alone makes the result
   explicit and predictable.
   No `aspect-ratio` is declared here on purpose: abhishek-hero.webp (864×1184,
   0.730) and abhishek-hero.png (560×900, 0.622) are different crops, so any
   single hard-coded ratio would distort one of them. `height: auto` lets each
   file use its own intrinsic ratio. */
.ay-hero-photo img {
  display: block;
  width: var(--ay-hero-photo-w);
  max-width: 100%;
  height: auto;
  /* the cut edge fades so the figure blends into the hero background */
  -webkit-mask-image: linear-gradient(to bottom, #000 97%, transparent 100%);
  mask-image: linear-gradient(to bottom, #000 97%, transparent 100%);
  filter: drop-shadow(0 0.875rem 1.25rem rgba(6, 13, 20, 0.2));
}

@media screen and (min-width: 576px) {
  :root {
    --ay-hero-photo-w: min(52vw, 20rem);
  }
}

@media screen and (min-width: 768px) {
  :root {
    --ay-hero-photo-w: min(46vw, 24rem);
  }
  .ay-hero-photo img {
    filter: drop-shadow(0 1.125rem 1.625rem rgba(6, 13, 20, 0.24));
  }
}

@media screen and (min-width: 992px) {
  :root {
    --ay-hero-photo-w: min(42vw, 30rem);
  }
}

@media screen and (min-width: 1200px) {
  :root {
    /* 40rem = 640px wide → 877px tall for the 0.730 webp, which reproduces the
       previously approved desktop rendering (48vw capped by the old
       max-height: 880px worked out to ≈642×880 on a 1440px screen) */
    --ay-hero-photo-w: min(48vw, 40rem);
  }
  .ay-hero-photo {
    position: absolute;
    inset-inline: 0;
    inset-block-end: 27%;
    margin-block: 0;
  }
  .ay-hero-photo img {
    filter: drop-shadow(0 1.625rem 2.125rem rgba(6, 13, 20, 0.3));
  }
}

/* --------------------------------------------------------------------------
   6. Shared helpers
   -------------------------------------------------------------------------- */
/* the template markup uses this on the offcanvas shell but never defines it */
.p-relative {
  position: relative;
}

.ay-eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--ay-space-xs);
  font-family: var(--body-font);
  font-size: var(--ay-fs-2xs);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ay-ink);
  margin-block-end: var(--ay-space-md);
}

.ay-eyebrow::before {
  content: "";
  /* the rule shrinks before the label does on very narrow screens */
  width: clamp(1.25rem, 0.9rem + 1.5vw, 2.125rem);
  height: 2px;
  background: var(--ay-orange);
  flex-shrink: 0;
}

.ay-eyebrow--light {
  color: rgba(255, 255, 255, 0.75);
}

/* --------------------------------------------------------------------------
   6b. Section headings — keep the marquee/hero rhythm on the two sections
       that didn't have a heading in the original template
   -------------------------------------------------------------------------- */
.feature-three-area .tw-char-animation,
.footer-three-top-left .tw-char-animation {
  letter-spacing: -0.01em;
}

/* --------------------------------------------------------------------------
   7. Education timeline (fills the slot the about photo used to occupy)
   -------------------------------------------------------------------------- */
.ay-edu {
  max-width: 100%;
  width: 100%;
  margin-block-end: var(--ay-space-xl);
}

.ay-edu-item {
  position: relative;
  /* the rail indent scales with the viewport so the copy keeps its measure on
     a 360px screen instead of losing 34px to the gutter */
  padding-inline-start: clamp(1.25rem, 0.9rem + 1.7vw, 2.125rem);
  padding-block-end: var(--ay-space-lg);
  border-inline-start: 1px solid var(--ay-line);
}

.ay-edu-item:last-child {
  padding-block-end: 0;
  border-inline-start-color: transparent;
}

.ay-edu-item::before {
  content: "";
  position: absolute;
  inset-block-start: 6px;
  inset-inline-start: -7px;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: #f5f5f5;
  border: 3px solid var(--ay-orange);
}

.ay-edu-item:first-child::before {
  background: var(--ay-orange);
}

.ay-edu-date {
  font-family: var(--body-font);
  font-size: var(--ay-fs-2xs);
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(6, 13, 20, 0.55);
  display: block;
  margin-block-end: var(--ay-space-xs);
}

.ay-edu-title {
  font-family: var(--heading-font);
  font-size: var(--ay-fs-xl);
  font-weight: 600;
  line-height: 1.25;
  color: var(--ay-ink);
  margin-block-end: var(--ay-space-2xs);
}

.ay-edu-meta {
  font-family: var(--body-font);
  font-size: var(--ay-fs-base);
  color: hsl(var(--body-color));
  margin: 0;
}

.ay-edu-score {
  display: inline-block;
  margin-block-start: var(--ay-space-xs);
  padding-block: 0.3125rem;
  padding-inline: var(--ay-space-sm);
  border-radius: 999px;
  background: var(--ay-lime);
  font-family: var(--heading-font);
  font-size: var(--ay-fs-xs);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ay-ink);
}

@media screen and (min-width: 1200px) {
  .ay-edu {
    max-width: 725px;
    margin-block-end: 0;
  }
}

/* --------------------------------------------------------------------------
   7b. About: CGPA circle + stat cards
       main.css gives the circle no size of its own — the markup sizes it with
       `tw-w-160-px tw-h-160-px` and clips it with `overflow-hidden`. A 132px
       numeral inside a 160px disc was being cut off at every screen width, so
       both the disc and the numeral are driven from one token here and the
       numeral is held at 38% of the disc (≈0.63 × diameter for "8.3", which
       clears the circle's inner chord comfortably).
       Specificity 0,2,0 beats the 0,1,0 tw-w- and tw-h- utilities.
   -------------------------------------------------------------------------- */
.about-three-counter .tw-btn-circle {
  width: var(--ay-circle-size);
  height: var(--ay-circle-size);
  max-width: 100%;
  background: #f5f5f5;
}

.about-three-counter .tw-btn-circle-icon,
.ay-circle-value {
  font-size: calc(var(--ay-circle-size) * 0.38);
  line-height: 1;
}

.ay-circle-label {
  font-family: var(--body-font);
  font-size: var(--ay-fs-sm);
  letter-spacing: clamp(0.06em, 0.04em + 0.1vw, 0.1em);
  text-transform: uppercase;
  margin-block-start: var(--ay-space-xs);
}

/* the two stat cards below the about copy — kept in normal flow rather than
   the template's -172px absolute overlap, which had nothing left to overlap.
   Grid rather than flex so they share width evenly and drop to one column on
   phones without a wrap gap. */
.ay-about-stats {
  display: grid !important; /* beats Bootstrap's .d-flex */
  grid-template-columns: 1fr;
  gap: var(--ay-space-lg);
  margin-block-start: var(--ay-space-xl);
}

@media screen and (min-width: 576px) {
  .ay-about-stats {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* main.css caps these at 284px / 245px; let them fill their grid cell instead
   so the pair stays symmetrical at every width */
.ay-about-stats .banner-three-counter-item {
  max-width: 100%;
}

/* --------------------------------------------------------------------------
   8. Experience rows — date replaces the old thumbnail on the right
   -------------------------------------------------------------------------- */
.service-three-item {
  display: grid !important; /* beats Bootstrap's .d-flex */
  grid-template-columns: 1fr;
  gap: var(--ay-space-sm);
  align-items: start;
}

.ay-exp-period {
  font-family: var(--heading-font);
  font-size: var(--ay-fs-md);
  font-weight: 500;
  letter-spacing: 0.04em;
  color: rgba(255, 255, 255, 0.55);
  /* nowrap only once there is a column of its own to sit in — see ≥992px */
  transition: color 0.3s;
}

.service-three-single:hover .ay-exp-period {
  color: var(--ay-lime);
}

.ay-exp-org {
  font-family: var(--body-font);
  font-size: var(--ay-fs-base);
  font-weight: 500;
  color: rgba(255, 255, 255, 0.65);
  margin-block-end: var(--ay-space-sm);
}

.ay-exp-note {
  font-family: var(--body-font);
  font-size: var(--ay-fs-base);
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.6);
  max-width: 62ch; /* a measure, not a pixel width — scales with the type */
  margin-block: var(--ay-space-md) 0;
}

@media screen and (min-width: 992px) {
  .service-three-item {
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: var(--ay-space-lg);
  }
  .ay-exp-period {
    white-space: nowrap;
    padding-inline-start: var(--ay-space-lg);
  }
}

/* --------------------------------------------------------------------------
   9. Skills grid
       The cards live in a Bootstrap `.row g-4` with `.col-xl-4 .col-md-6`,
       which is already flexbox and already stacks 1 → 2 → 3 columns. Nothing
       to restate here; the card just has to fill whatever cell it lands in.
   -------------------------------------------------------------------------- */
.ay-skill-card {
  position: relative;
  height: 100%;
  padding: var(--ay-space-lg) var(--ay-space-md);
  border-radius: 12px;
  background: #f5f5f5;
  box-shadow:
    0 4px 4px 0 rgba(0, 0, 0, 0.25),
    -4px -4px 0 0 rgba(255, 255, 255, 0.25);
  transition: transform 0.35s ease;
}

@media screen and (min-width: 576px) {
  .ay-skill-card {
    padding: 2.125rem 1.875rem; /* 34px 30px — the original desktop padding */
  }
}

.ay-skill-card:hover {
  transform: translateY(-6px);
}

.ay-skill-num {
  position: absolute;
  inset-block-start: var(--ay-space-lg);
  inset-inline-end: var(--ay-space-md);
  font-family: var(--heading-font);
  font-size: var(--ay-fs-xs);
  font-weight: 600;
  letter-spacing: 0.1em;
  color: rgba(6, 13, 20, 0.25);
}

.ay-skill-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ay-icon-size);
  height: var(--ay-icon-size);
  border-radius: 12px;
  background: var(--ay-ink);
  color: var(--ay-lime);
  font-size: calc(var(--ay-icon-size) * 0.48);
  margin-block-end: var(--ay-space-md);
  flex-shrink: 0;
  transition:
    background 0.35s,
    color 0.35s;
}

.ay-skill-card:hover .ay-skill-icon {
  background: var(--ay-orange);
  color: #fff;
}

.ay-skill-title {
  font-family: var(--heading-font);
  font-size: var(--ay-fs-lg);
  font-weight: 600;
  color: var(--ay-ink);
  /* leave room for the absolutely positioned number in the top-right corner */
  padding-inline-end: 2.5rem;
  margin-block-end: var(--ay-space-md);
}

.ay-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--ay-space-xs);
  list-style: none;
  padding: 0;
  margin: 0;
}

.ay-tags li {
  font-family: var(--body-font);
  font-size: var(--ay-fs-xs);
  font-weight: 500;
  letter-spacing: 0.04em;
  padding-block: 0.4375rem;
  padding-inline: var(--ay-space-sm);
  border: 1px solid var(--ay-line);
  border-radius: 999px;
  color: hsl(var(--body-color));
  background: #fff;
  transition:
    background 0.3s,
    color 0.3s,
    border-color 0.3s;
}

.ay-tags li:hover {
  background: var(--ay-ink);
  border-color: var(--ay-ink);
  color: #fff;
}

/* --------------------------------------------------------------------------
   10. Projects — text panel instead of a screenshot
   -------------------------------------------------------------------------- */
/* the staggered second column only makes sense once the projects sit side by
   side, so the offset is added at ≥1200px rather than removed below it */
.portfolio-three-item:nth-child(even) {
  margin-block-start: 0;
}

@media screen and (min-width: 1200px) {
  .portfolio-three-item:nth-child(even) {
    margin-block-start: 8.75rem; /* 140px */
  }
}

@media screen and (min-width: 1400px) {
  .portfolio-three-item:nth-child(even) {
    margin-block-start: 11.25rem; /* 180px */
  }
}

.ay-project-panel {
  position: relative;
  border-radius: 12px;
  overflow: hidden;
  padding: var(--ay-space-lg) var(--ay-space-md);
  background:
    radial-gradient(
      120% 120% at 100% 0%,
      rgba(190, 253, 2, 0.16) 0%,
      transparent 55%
    ),
    linear-gradient(150deg, #101a22 0%, #060d14 100%);
  /* min-height rather than height so the panel grows with its own content
     instead of clipping it on a narrow column */
  min-height: clamp(17.5rem, 15rem + 11vw, 21.25rem); /* 280 → 340 */
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  gap: var(--ay-space-md);
}

@media screen and (min-width: 576px) {
  .ay-project-panel {
    padding: 2.125rem; /* 34px — the original desktop padding */
  }
}

.ay-project-panel::after {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.045) 1px, transparent 1px);
  background-size: 42px 42px;
  pointer-events: none;
}

.ay-project-panel > * {
  position: relative;
  z-index: 1;
}

.ay-project-kicker {
  font-family: var(--body-font);
  font-size: var(--ay-fs-2xs);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--ay-lime);
  margin-block-end: var(--ay-space-sm);
}

.ay-project-summary {
  font-family: var(--body-font);
  font-size: var(--ay-fs-base);
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.72);
  margin-block-end: var(--ay-space-lg);
}

/* auto-fit means the metrics sit side by side whenever two will fit in the
   available column and drop to one per row when they won't — no breakpoint
   needed, and it reacts to the column width rather than the viewport */
.ay-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
  gap: var(--ay-space-sm);
}

.ay-metric {
  padding: var(--ay-space-md);
  border-radius: 10px;
  border: 1px solid var(--ay-line-light);
  background: rgba(255, 255, 255, 0.03);
  min-width: 0;
}

.ay-metric strong {
  display: block;
  font-family: var(--heading-font);
  font-size: var(--ay-fs-3xl);
  font-weight: 600;
  line-height: 1;
  color: #fff;
  margin-block-end: var(--ay-space-2xs);
}

.ay-metric span {
  font-family: var(--body-font);
  font-size: var(--ay-fs-2xs);
  line-height: 1.5;
  color: rgba(255, 255, 255, 0.5);
}

.ay-project-stack {
  font-family: "SFMono-Regular", "JetBrains Mono", Menlo, Consolas, monospace;
  font-size: var(--ay-fs-2xs);
  letter-spacing: 0.02em;
  color: rgba(255, 255, 255, 0.4);
  margin-block: var(--ay-space-lg) 0;
  /* a stack string is one long slash-separated token — it has to be allowed to
     break anywhere or it widens the panel */
  overflow-wrap: anywhere;
}

/* --------------------------------------------------------------------------
   11. Certifications — gradient reveal panel carries text, not an image
        NOTE: custom-gsap.js reads hoverItem.children[1] for the reveal, so
        .ay-cert-reveal must stay the 2nd child of each .hover__reveal-item.
   -------------------------------------------------------------------------- */
.ay-cert-reveal {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: var(--ay-space-lg);
  background:
    radial-gradient(
      120% 100% at 0% 0%,
      rgba(255, 81, 0, 0.35) 0%,
      transparent 60%
    ),
    linear-gradient(160deg, #16222c 0%, #060d14 100%);
  border: 1px solid var(--ay-line-light);
}

.ay-cert-reveal b {
  font-family: var(--heading-font);
  font-size: var(--ay-fs-2xl);
  font-weight: 600;
  line-height: 1.15;
  color: #fff;
  display: block;
  margin-block-end: var(--ay-space-xs);
}

.ay-cert-reveal i {
  font-style: normal;
  font-family: var(--body-font);
  font-size: var(--ay-fs-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ay-lime);
}

.ay-cert-type {
  font-family: var(--body-font);
  font-size: var(--ay-fs-2xs);
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ay-orange);
}

/* The certification titles carry a tw-text-605 utility (1.625rem / 26px) that
   is too large on a phone. The clamp tops out at exactly that value, so from
   ~1022px up this is identical to the template and no reset is needed. */
.feature-three-text {
  font-size: clamp(1.25rem, 1.05rem + 0.9vw, 1.625rem) !important; /* 20 → 26 */
}

/* --------------------------------------------------------------------------
   12. Contact card + form feedback
   -------------------------------------------------------------------------- */
.footer-three-top-info {
  display: grid !important; /* beats Bootstrap's .d-flex */
  grid-template-columns: 1fr;
  gap: var(--ay-space-lg);
  align-items: start;
}

@media screen and (min-width: 576px) {
  .footer-three-top-info {
    /* avatar takes its intrinsic square, the name/social block takes the rest */
    grid-template-columns: auto minmax(0, 1fr);
  }
}

/* a square avatar at every width. The old rule stretched it to 100% width and
   120px tall below 576px, which cropped the face into a letterbox. */
.ay-contact-mono {
  display: block;
  width: var(--ay-dp-size);
  height: var(--ay-dp-size);
  max-width: 100%;
  border-radius: 14px;
  background: var(--ay-lime);
  overflow: hidden;
  flex-shrink: 0;
}

.ay-contact-mono picture,
.ay-contact-mono img {
  display: block;
  width: 100%;
  height: 100%;
}

.ay-contact-mono img {
  object-fit: cover;
  object-position: 50% 22%;
}

.ay-field-error {
  border-color: var(--ay-orange) !important;
}

#toast-container {
  position: fixed;
  /* full-bleed with a gutter on phones, corner-anchored once there is room */
  inset-block-end: var(--ay-space-md);
  inset-inline: var(--ay-space-md);
  z-index: 9999;
  display: flex;
  flex-direction: column;
  gap: var(--ay-space-xs);
  pointer-events: none;
}

.ay-toast {
  display: flex;
  align-items: center;
  gap: var(--ay-space-sm);
  padding: var(--ay-space-md);
  border-radius: 10px;
  background: var(--ay-ink);
  color: #fff;
  font-family: var(--body-font);
  font-size: var(--ay-fs-sm);
  line-height: 1.5;
  box-shadow: 0 18px 40px -12px rgba(6, 13, 20, 0.6);
  border-inline-start: 3px solid var(--ay-lime);
  opacity: 0;
  transform: translateY(14px);
  transition:
    opacity 0.3s,
    transform 0.3s;
}

@media screen and (min-width: 576px) {
  #toast-container {
    inset-inline: auto 1.75rem;
    inset-block-end: 1.75rem;
  }
  .ay-toast {
    min-width: 17.5rem; /* 280px */
    max-width: 22.5rem; /* 360px */
  }
}

.ay-toast.is-visible {
  opacity: 1;
  transform: translateY(0);
}

.ay-toast--error {
  border-inline-start-color: var(--ay-orange);
}

.ay-toast i {
  font-size: var(--ay-fs-md);
  color: var(--ay-lime);
  flex-shrink: 0;
}

.ay-toast--error i {
  color: var(--ay-orange);
}

/* --------------------------------------------------------------------------
   13. Misc
   -------------------------------------------------------------------------- */
.ay-footer-links a {
  transition: color 0.3s;
}

.ay-footer-links a:hover {
  color: var(--ay-lime) !important;
}

/* honour reduced-motion preferences */
@media (prefers-reduced-motion: reduce) {
  .ay-pulse {
    animation: none;
  }
  .ay-skill-card,
  .ay-skill-icon,
  .ay-tags li,
  .ay-exp-period,
  .ay-toast {
    transition: none;
  }
  .ay-skill-card:hover {
    transform: none;
  }
}
