/*
  PDA Group CI override.
  Repio's compiled main.css derives every shade of "main", "main-two",
  "main-four", "main-six" and "main-eight" from five HSL custom properties
  set once in :root. Re-pointing those five hues at the brand's CI colors
  recolors the whole template without touching the ~17k lines of compiled
  component CSS.

  Brand source: docs brief page 4 (แบรนด์ ci) + logo.png
    teal  #1792A8 -> hsl(189, 76%, 37%)  primary
    navy  #1F3441 -> hsl(203, 35%, 19%)  accent / heading text
    amber #E0A526                       single accent (ratings only, not var-driven)
*/
:root {
  --main-h: 189;      --main-s: 76%;  --main-l: 37%;   /* primary teal */
  --main-two-h: 189;  --main-two-s: 76%;  --main-two-l: 37%;
  --main-four-h: 203; --main-four-s: 35%; --main-four-l: 19%;  /* navy accent */
  --main-six-h: 189;  --main-six-s: 76%;  --main-six-l: 37%;
  --main-eight-h: 189; --main-eight-s: 76%; --main-eight-l: 37%;

  --black: 203 35% 19%; /* heading color -> CI navy instead of template's near-black */
}

/* header-top utility bar used the template's own literal navy hex; align it to CI navy */
.header-top-bg { background-color: #1F3441 !important; }

/* rating stars keep the single warm accent instead of the template's orange literal */
.banner-gaping [style*="color: #FF5B02"] { color: #E0A526 !important; }
/* .banner-gaping is a plain block (no d-flex) - the flex-wrap/justify-content
   rule added for it further down was a no-op since flex properties only
   apply to the actual flex child inside it. text-align:center is what
   actually centers its content. */
.banner-gaping { text-align: center; }

/*
  Font split: body{} in main.css defaults everything to Sarabun and only
  h1-h6 opt into Kanit. That leaves nav/buttons/badges/stat-labels on
  Sarabun by inheritance even though they're UI chrome, not reading
  content. Opt those into Kanit explicitly; paragraphs/descriptions stay
  on the body default.
*/
.nav-menu, .nav-submenu, .mega-menu,
.tw-primary-btn, .service-three-btn,
button, .btn,
.section-subtitle, .section-eight-subtitle, .section-three-subtitle, .section-six-subtitle,
.banner-counter-wrapper p, .counter-paragraph, .about-eight-thumb-count p,
.header-top-paragraph, .header-call-number h2, .header-call-number h3,
.footer-two-col-3 a, .footer-two-col-4 a, .blog-meta {
  font-family: var(--heading-font);
}

/*
  Hero bento grid. Repio's original .banner-wrapper was a plain flex row
  with .banner-left sized off a chain of fixed max-width breakpoints —
  the two columns never lined up to a real ratio or matched height.
  Rebuilt as a real 2-col grid: 60/40 desktop, 50/40->50/50 once the
  right column gets too narrow (992-1199px), single column on phones.
  grid's default align-items:stretch is what makes both columns match
  height — .banner-right just needs to be a grid itself to make its
  photo row fill that stretched height.
*/
.pda-hero-grid {
  display: grid !important;
  /* fr units, not %: % columns ignore `gap` and sum to 100% + gap,
     which pushed .banner-right past the container edge. fr correctly
     subtracts the gap from the available track space first. */
  grid-template-columns: 3fr 2fr;
  gap: 28px;
  align-items: stretch;
  /* no min-height: the row is exactly as tall as .banner-left's own
     content (left is the taller side in practice) - grid's default
     stretch then pulls .banner-right up to match, and the photo slider
     crops via object-fit:cover to fill whatever that height ends up
     being, instead of forcing a fixed viewport height. */
}
.pda-hero-grid .banner-left,
.pda-hero-grid .banner-right {
  max-width: 100% !important;
  width: 100%;
  min-width: 0;
}
@media screen and (max-width: 1199px) and (min-width: 768px) {
  .pda-hero-grid {
    grid-template-columns: 1fr 1fr;
  }
}
@media screen and (max-width: 767px) {
  .pda-hero-grid {
    grid-template-columns: 1fr;
  }
}

.pda-hero-grid .banner-right {
  display: grid;
  grid-template-rows: 1fr auto;
  gap: 16px;
  height: 100%;
  min-height: 0;
}
.pda-hero-grid .banner-thumb {
  min-height: 220px;
  border-radius: 16px;
  overflow: hidden;
}
/* Below 768px, .pda-hero-grid drops to a single column and .banner-left/
   .banner-right are no longer height-matched via align-items:stretch (that
   only did anything with two columns side by side) - so .banner-thumb's
   height here was just the bare 220px min-height above, with no upper
   control. Give it a real aspect-ratio at these widths instead. This is
   safe against the min-height floor: .banner-thumb spans the single-column
   container's full width (~510px in the 576-767 Bootstrap "sm" container,
   ~290px+ even on the narrowest real phones), so 2/1 and 1/1 both compute
   well above 220px and the floor never actually engages.
   aspect-ratio goes on .banner-thumb (the overflow:hidden box) rather than
   .banner-thumb-slider or the img: with height:auto here, aspect-ratio
   gives .banner-thumb a definite height, .banner-thumb-slider's
   height:100% then resolves against that definite height, and
   .swiper-wrapper's position:absolute; inset:0 (see the fallback-bug
   comment above) fills it the same way it does at wider widths - no
   competing min-height/height rule sits between them. */
@media screen and (max-width: 767px) and (min-width: 576px) {
  .pda-hero-grid .banner-thumb {
    aspect-ratio: 2 / 1;
  }
}
@media screen and (max-width: 575px) {
  .pda-hero-grid .banner-thumb {
    aspect-ratio: 1 / 1;
  }
  .pda-hero-grid .banner-counter-wrap {
    grid-template-columns: 1fr !important;
  }
}
.pda-hero-grid .banner-thumb .banner-thumb-slider {
  width: 100%;
  height: 100%;
}
/* height:100% on .swiper-wrapper/.swiper-slide/img was chaining back up
   to .pda-hero-grid's own auto row - an indefinite height. Percentages
   that can't resolve against an indefinite ancestor fall back to the
   element's own intrinsic size, and for an <img> that means its native
   aspect ratio: at the column's rendered width, hero.jpeg's 502x900
   source computed to ~1.8x the width tall, and THAT height then counted
   as real content the outer grid had to accommodate - making the photo
   card (and everything stretched to match it) balloon independent of
   .banner-left's actual content. Taking .swiper-wrapper out of flow
   breaks the chain: an absolutely positioned box never contributes to
   its ancestor's auto-height, so .banner-thumb's only real contribution
   back up to the grid is its own min-height below, and .banner-left's
   text content is reliably what the row sizes against. inset:0 fills
   whatever height the row resolves to on the second, definite pass. */
.pda-hero-grid .banner-thumb .swiper-wrapper {
  position: absolute;
  inset: 0;
}
.pda-hero-grid .banner-thumb .swiper-slide {
  width: 100%;
  height: 100%;
}
.pda-hero-grid .banner-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}
/* the swiper-bundle.css shipped here uses the old "swiper-container"
   naming (confirmed against the working brand-strip carousel), not the
   newer "swiper" class — that's what was giving this slider its
   position:relative + overflow:hidden. Without it, loop-mode's
   duplicated slides weren't clipped (blowing out the section's height)
   and the pagination dots had no positioned ancestor to anchor to, so
   they escaped to the bottom of the section instead of sitting over
   the photo. .swiper-container class on the element fixes both; this
   just makes the active dot readable against a photo. */
.banner-thumb-slider .swiper-pagination-bullet {
  background: rgba(255, 255, 255, 0.6);
  opacity: 1;
}
.banner-thumb-slider .swiper-pagination-bullet-active {
  background: #fff;
}
/* Veloce/SPT are two independent cards now, not one shared bar split
   in two — this wrapper is just the layout grid around them. */
.pda-hero-grid .banner-counter-wrap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
}

/* main.css's .banner-title font-size steps are non-monotonic across
   breakpoints: 4.3rem at <=1499px, 3rem at <=1399px, then it JUMPS UP to
   4.8rem at <=1199px (bigger than the 4.5rem desktop base), before
   dropping back to 3.2rem at <=991px. That's a leftover from another
   Repio demo page reusing this shared class with different sizing needs.
   In our hero grid, align-items:stretch means an oversized heading at
   this one tier inflates .banner-left's content height, which then
   inflates .banner-right (photo + Veloce/SPT cards) to match - the
   "right column height depends on whichever side is tallest" behavior
   the user correctly identified, just triggered by this heading bug
   rather than anything in the grid rules themselves. Flatten it back
   into the surrounding progression instead of the anomalous spike. */
@media screen and (max-width: 1199px) {
  .banner-title {
    font-size: 3rem;
  }
}

/* removed .header-cart (shopping bag, unused since the site has no cart) —
   compensate so nav-menu-to-search spacing stays the same as before */
.header-search {
  padding-left: 20px;
}

/* pull the phone number in against the call icon — tighter than the
   plain flex gap, the "ml-20" class it had was a dead utility with no
   matching CSS rule anywhere in the theme */
.header-call-item .header-call-number {
  margin-inline-start: -8px;
}

/* .nav-menu__link had no font-size rule anywhere, inheriting the 16px
   body default — set the requested 18px baseline and step it down at
   the same breakpoints main.css already uses for .banner-title */
.nav-menu__link {
  font-size: 18px;
}
@media screen and (max-width: 1399px) {
  .nav-menu__link {
    font-size: 16px;
  }
}
@media screen and (max-width: 1199px) {
  .nav-menu__link {
    font-size: 15px;
  }
}

/* the hover-underline on .nav-submenu__link::before is positioned with
   bottom:18px (relative to the link's own box) — when a label wraps to
   2 lines the box grows and the underline no longer sits under the
   first line. Simplest fix: never let it wrap. .nav-submenu has
   min-width:230px and no max-width (tw-w-max), so it just grows to
   fit the longest label. */
.nav-submenu__link {
  white-space: nowrap;
}

/* banner-left is now taller than its content (min-height:100vh on the
   grid), so "no bottom margin" alone left a gap below the photo before
   the card's actual bottom edge. Make banner-left a flex column and
   push the photo block to the bottom with margin-top:auto so it's
   flush against the edge regardless of how much extra height there is. */
.banner-left {
  display: flex;
  flex-direction: column;
  /* tw-pt-32 (140px) was sized for the original fixed-width gradient
     card, not for a grid item whose height .banner-right stretches to
     match - it was inflating the whole row height, stretching the photo
     card into an unnaturally tall crop. Shrink to real breathing room.
     Bumped 32px -> 48px per follow-up request for a bit more top space. */
  padding-top: 48px !important;
}
.banner-personal-thumb {
  margin-top: auto;
}
/* breathing room between the paragraph and the CTA button — the
   paragraph's tw-mb-9 was removed earlier and nothing replaced it */
.banner-button {
  margin-top: 32px;
  margin-bottom: 24px;
}
.banner-personal-thumb img {
  max-width: 360px;
  width: 100%;
  height: auto;
  margin: 0 auto;
  display: block;
}

/* replaces bg-black on the Veloce/SPT cards; solid color first as a
   fallback, the gradient is what actually renders */
.banner-counter-wrapper {
  background: #1F3441;
  background: linear-gradient(180deg, rgba(31, 52, 65, 1) 0%, rgba(23, 145, 166, 1) 150%);
}

.banner-graph-shape {
  pointer-events: none;
}
.banner-graph-shape {
  width: 100%;
  height: 60%;
}

/* ==================== Top bar (.header-top) ====================
   Was d-none d-xxl-block (desktop-only); now shown at every breakpoint
   per spec, so it needs to shed content gracefully as it narrows
   instead of wrapping/overflowing. Priority: social icons go first,
   then the address line, then the descriptive paragraph itself (but a
   standalone "ทัก LINE" link takes its place so LINE contact stays
   reachable). Email + "ทัก LINE" remain visible at every width. */
@media (max-width: 1199px) {
  .header-social {
    /* the element also carries Bootstrap's .d-flex utility, which sets
       display:flex !important - a plain display:none here loses to it,
       so this override needs !important too */
    display: none !important;
  }
}

@media (max-width: 991px) {
  .header-top-address-wrap {
    display: none;
  }
}

@media (max-width: 575px) {
  .header-top-paragraph {
    display: none;
  }
  .header-top-line-standalone {
    display: inline-block !important;
  }
}

/* ==================== Mobile menu link color ====================
   .nav-menu__link inherits --heading-color (CI navy), and .mobile-menu
   has bg-black which resolves to that same navy, so non-active links
   were invisible against the drawer. Scoped to .mobile-menu only so
   the desktop nav is untouched; the active item's teal color (set via
   .nav-menu__item.activePage > a in main.css, !important + higher
   specificity) still wins over this. */
.mobile-menu .nav-menu__link {
  color: #fff;
}

/* ==================== Mobile menu footer ====================
   New block added below .mobile-menu__menu inside the drawer: call
   button, email/address, social icons. The drawer's tw-pb-68 bottom
   padding already reserves room for it and .mobile-menu is
   overflow-y-auto, so it scrolls into view on short screens.
   Separator to read as a distinct footer section, not a continuation
   of the nav list. */
.mobile-menu__footer {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
}
/* The call item is copied from the desktop header (.header-call-item),
   which assumes a light page background: the label used a literal
   #5c6672 gray and the phone number relied on .text-heading (CI navy,
   set via --heading-color) - both unreadable on the drawer's dark navy
   bg-black. Swap in light-on-dark equivalents; everything else about
   the block (icon circle, spacing) is theme-driven and already fine
   against dark backgrounds. */
.mobile-menu__footer-label {
  color: rgba(255, 255, 255, 0.65);
}
.mobile-menu__footer-phone {
  color: #fff;
}
/* main.css hides .header-call-item at <=767px with !important (correct
   for the desktop header, which swaps to the hamburger there) - but this
   footer's call item is a different, reused instance of that same class
   sitting *inside* the mobile menu, which only ever shows in that exact
   width range. Force it back on, scoped to this footer only. */
.mobile-menu__footer .header-call-item {
  display: flex !important;
}

/* ==================== Search popup logo ====================
   main.css forces `filter: brightness(0) invert(1)` on the search
   popup logo, turning the teal wordmark into a plain white silhouette.
   The popup background is navy, so the real teal logo has fine
   contrast without the filter. */
.search_wrapper .search_top .search_logo a img {
  filter: none;
}

/* expert-area (ทีมงานมืออาชีพ section): full-width decorative graph line
   behind the content, and mobile column reordering so the center photo
   shows first on narrow screens */
.expert-graph-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0.55;
  z-index: 0;
  pointer-events: none;
}
@media only screen and (min-width: 992px) {
  .expert-thumb.tw-mb-25 {
    margin-bottom: 0;
  }
}
@media only screen and (max-width: 767px) {
  .expert-area {
    overflow: hidden;
  }
}
/* Image Center Sticky for laptop down */
.laptop-sticky,
.expert-thumb {
  height: 100%;
}
.laptop-sticky > div > img {
  position: sticky;
  top: 100px;
}
/* "24/7" used to be SVG <text> inside .expert-graph-bg, but that wrapper
   is pointer-events: none so it could never receive the section's hover-
   wobble. It's now a plain HTML element, a sibling of the SVG, styled to
   sit in roughly the same spot (upper-right, large + faint) and wired
   into the existing .animation-item / .animate__wobble hover pattern
   (see .expert-item icons below) so it wobbles on hover like they do. */
.expert-graph-247-wrap {
  position: absolute;
  top: 14%;
  inset-inline-end: 6%;
  z-index: 0;
}
.expert-graph-247-text {
  display: inline-block;
  font-family: Arial, sans-serif;
  font-weight: 700;
  font-size: 7.5rem;
  line-height: 1;
  color: #1792A8;
  opacity: 0.14;
}
.expert-area .container {
  position: relative;
  z-index: 1;
}
@media screen and (max-width: 991px) {
  .expert-thumb-col {
    order: -1;
  }
}
@media screen and (max-width: 767px) {
  .expert-graph-247-wrap {
    display: none;
  }
  /* Non-uniform stretch (preserveAspectRatio="none") over a narrow
     viewport squishes the 1440x400 graph into a tall, distorted shape.
     Render it at its natural size instead and let it bleed off both
     edges (.expert-area has overflow: hidden, so the bleed is clipped)
     so it keeps its 3.6:1 proportions and just gets cropped, not
     stretched. This rule comes after the base .expert-graph-bg rule
     above, so at equal specificity it wins by source order. */
  .expert-graph-bg {
    width: 767px;
    height: 400px;
    left: 50%;
    right: auto;
    transform: translateX(-50%);
  }
}

/* expert-thumb: at >=992px main.css bleeds the photo -40px past its
   column with no max-width, so it overflows into the right column's
   gutter. Push it back into its column and cap its width; the <992px
   reset in main.css (margin 0 / width 100%) is already correct as-is. */
@media screen and (min-width: 992px) {
  .expert-thumb {
    margin-inline-start: 32px;
  }
  .expert-thumb img {
    max-width: 100%;
  }
}

/* At the col-lg-6 tier (992-1199px, 2-per-row) the 3-column flex row
   wraps to: row 1 = left icon-list + photo (50/50), row 2 = right
   icon-list alone, visually "falling" below on its own. At >=1200px the
   3 columns already sit side by side (untouched) and below 992px it
   already stacks cleanly photo-first (untouched, see .expert-thumb-col
   order: -1 above). Fix scoped to exactly this one tier: turn the row
   into a 2-column grid so the left and right icon-lists share the same
   column (reading as one continuous 6-item list) while the photo spans
   both rows beside them and stays in view via position: sticky as the
   user scrolls past the now-taller combined list. */
@media screen and (min-width: 992px) and (max-width: 1199px) {
  .expert-area .row.align-items-center {
    display: grid;
    grid-template-columns: 1fr 1fr;
    grid-template-rows: auto auto;
    /* align-items: start (rather than the grid default "stretch") keeps
       each item at its own content height instead of stretching it to
       fill its cell. Without this, .expert-thumb-col — which spans both
       rows — would stretch to exactly fill that spanned height, leaving
       it no room within its own containing block to move: position:
       sticky needs the sticky element's box to be shorter than its
       containing block so there's scroll distance left for it to
       travel before it runs out of room and unsticks. */
    align-items: start;
  }
  .expert-area .row.align-items-center > .col-xl-3.col-lg-6:first-child {
    grid-column: 1;
    grid-row: 1;
    width: 100%;
    max-width: 100%;
    flex: none;
  }
  .expert-area .row.align-items-center > .col-xl-3.col-lg-6:first-child > .tw-mt-25 {
    margin-block-start: 0;
  }
  .expert-area .row.align-items-center > .expert-thumb-col {
    grid-column: 2;
    grid-row: 1 / -1;
    align-self: start;
    /* position: sticky doesn't actually stick on this page at any width -
       traced to a Chromium quirk tied to <body>'s display:flex +
       min-height:100vh (documented in STATUS.md). No JS fallback is
       used here anymore (removed - felt janky); this column just stays
       in normal flow with no sticky positioning at this tier. */
    width: 100%;
    max-width: 100%;
    flex: none;
  }
  .expert-area .row.align-items-center > .col-xl-3.col-lg-6:last-child {
    grid-column: 1;
    grid-row: 2;
    width: 100%;
    max-width: 100%;
    flex: none;
  }
  .expert-area .row.align-items-center > .col-xl-3.col-lg-6:last-child .expert-right {
    margin-block-start: 0;
  }
}

/* Veloce/SPT cards: real icon images instead of Phosphor glyphs, sized
   much bigger per request ("ใหญ่เลย"). Source PNGs are square (512x512),
   so object-fit: contain at a fixed box is safe. */
.banner-counter-icon img {
  width: 96px;
  height: 96px;
  object-fit: contain;
}
/* tw-py-12/tw-px-10 (3rem/2.5rem) utility classes on the element left the
   bigger icon still boxed in - override the padding here instead of
   touching the shared utility classes (used elsewhere too). Same
   specificity as the bare utility classes, but this rule loads later in
   the cascade (pda-theme.css after main.css), so it wins without
   !important. */
.banner-counter-wrapper {
  padding-block: 18px;
  padding-inline: 18px;
}
.banner-counter-wrapper h2 {
  font-size: 1.6rem;
}
@media screen and (max-width: 767px) {
  .banner-counter-icon img {
    width: 64px;
    height: 64px;
  }
}

/* mobile: let the avatar row + rating wrap instead of overflowing, and
   collapse the Veloce/SPT cards to one column - same 767px breakpoint
   .pda-hero-grid itself already switches to a single column at.
   Selector matches ".pda-hero-grid .banner-counter-wrap"'s specificity
   above so this override actually wins instead of losing to source
   order. */
@media screen and (max-width: 767px) {
  .banner-gaping {
    flex-wrap: wrap;
    justify-content: center;
  }
}

/* About-us section (#about-us .about-eight-area) polish pass */

/* 1. Tab nav-link idle state still uses the template's original literal
   blue (#0164e1 / #0165df) for the bottom border and the ::before
   triangle pointer, while :hover/.active already correctly use the CI
   teal var(--main-eight-600). Re-theme the two leftover blue spots. */
.about-eight-tab .nav-link {
  border-bottom-color: var(--main-eight-600);
}
.about-eight-tab .nav-link::before {
  border-color: var(--main-eight-600) transparent transparent transparent;
}

/* 3. Force the big about-us photo into a square crop regardless of the
   source image's native aspect ratio. Scoped to the direct-child photo
   only (`>`) — .about-eight-thumb also contains .about-eight-thumb-review,
   which nests 4 more <img>s (3 client avatars + the Google badge) two
   levels deep. Without the `>` this rule was also squashing those into a
   1:1 crop, which is what mangled the Google logo. */
.about-eight-thumb > img {
  aspect-ratio: 1 / 1;
  object-fit: cover;
}

/* 3b. Below the xl breakpoint (1200px) the photo/content columns
   (col-xl-6 col-lg-10 + col-xl-6 col-lg-11 = 21 > 12) are already forced
   to stack, so this is the single trigger for "narrow, stacked" layout.
   Switch the crop to full-width 4:3 instead of the desktop 1:1 square. */
@media screen and (max-width: 1199px) {
  .about-eight-thumb > img {
    width: 100%;
    aspect-ratio: 4 / 3;
  }
}

/* 4. Nudge the "8+ ปีที่ดูแลลูกค้า" badge in from the photo's edge. */
.about-eight-thumb-count {
  margin-right: 3%;
}

/* 5. Mobile: the floating review card (avatars + Google rating) is
   position: absolute; bottom: 0; left: 0 relative to the photo's own
   box. At mobile sizes its default padding/avatar sizing made it taller
   than comfortably fits within the (now 4:3, shorter) photo, tempting a
   negative bottom margin to "make room" — but a negative margin bleeds
   the card past the photo's bottom edge and over the heading that
   follows in DOM flow. Fix: shrink the card's contents so it fits
   *inside* the photo's box, and use a small positive inset instead of a
   negative one. */
@media screen and (max-width: 767px) {
  .about-eight-thumb-review {
    bottom: 10px !important;
    left: 10px !important;
    margin: 0 !important;
    padding: 12px 14px;
  }
  .about-eight-thumb-review .tw-w-166 {
    width: 36px;
  }
  .about-eight-thumb-review .tw-h-166 {
    height: 36px;
  }
  .about-eight-thumb-review .tw-mb-4 {
    margin-block-end: 8px;
  }
  .about-eight-thumb-review h3.tw-text-lg {
    font-size: 14px;
  }
  .about-eight-thumb-review p {
    font-size: 11px;
  }

  /* 5b. The "8+ ปีที่ดูแลลูกค้า" count badge (a different element from
     .about-eight-thumb-review above) had no mobile sizing at all - just
     main.css's flat padding: 30px plus this file's own margin-right: 3%
     override. At ~375-414px wide that padding plus the tw-text-14
     (56px) number made the badge cover a large chunk of the (now 4:3,
     shorter) photo. Shrink it using the same scale-down ratio as the
     .about-eight-thumb-review block above. */
  .about-eight-thumb-count {
    padding: 14px 16px;
  }
  .about-eight-thumb-count .tw-gap-4 {
    gap: 8px;
  }
  .about-eight-thumb-count h2.tw-text-14 {
    font-size: 22px;
  }
  .about-eight-thumb-count p.tw-text-base {
    font-size: 11px;
  }
}

/* Services section restructure: the counter-area stats block was moved
   from its own separate <section> into a second container inside
   #services (.service-two-area), so it inherits the section's light-blue
   background instead of sitting on unstyled white. Spacing between the
   tab-nav container above it and this block now comes from swapping
   counter-area's own pb-120 to pt-120 in the markup (index.html) - the
   section's outer py-120 already covers the bottom, so pt-120 gives the
   counter-area its own top breathing room without a bespoke margin. */

/* The counter labels used bg-white (a Bootstrap utility with its own
   !important, confirmed in bootstrap.min.css: .bg-white{...!important}),
   which now floats as a white card on the section's light-blue
   background. Match it to the section tint instead. Compound selector
   (.counter-paragraph.bg-white) gives this higher specificity than the
   bare .bg-white utility, so it wins regardless of stylesheet order. */
.counter-paragraph.bg-white {
  background: rgb(242 247 254) !important;
}

/* Service tab panes (.service-two-content, overlaid on
   .service-two-thumbs): nudge the text stack down a bit on desktop -
   it sat too close to the photo's top edge / overlapped more than
   intended. inset-block-end is measured from the bottom, so increasing
   it pushes the block up less / keeps it lower relative to the photo
   top. Applies at all widths; the mobile block below replaces this
   with static, in-flow positioning instead of overlaying the photo. */
.service-two-content {
  inset-block-end: 30px;
}

@media screen and (max-width: 767px) {
  /* Stop overlaying the photo - stack the text below it instead, so
     the title/paragraph/link are legible instead of competing with the
     photo for contrast at narrow widths. */
  .service-two-content {
    position: static !important;
    inset-block-end: auto;
    inset-inline-start: auto;
    max-width: 100%;
    padding-block-start: 16px;
  }
  /* The markup carries text-white (readable over the photo's dark
     gradient) - now that the text sits on the section's light
     background instead, swap it for the theme's normal heading/body
     colors. !important matches bootstrap.min.css's .text-white
     !important so this actually wins. */
  .service-two-content h3,
  .service-two-content h3 a {
    font-size: 1.375rem;
    color: hsl(var(--heading-color)) !important;
  }
  .service-two-content p {
    font-size: 1rem;
    color: hsl(var(--body-color)) !important;
  }
  .service-two-content > div > a {
    color: hsl(var(--heading-color)) !important;
  }
  /* This dark gradient existed only to keep the white text readable
     over the photo; with the text no longer overlaid, it's just extra
     paint over the image - hide it for a cleaner mobile look. */
  .service-two-thumbs::before {
    display: none;
  }
}

@media screen and (max-width: 1199px) {
    .service-two-nav-item {
        margin-bottom: 0;
    }
}

/* ==================== Concepts section (#concepts) brand filter ====================
   10 product cards, client-side filtered by data-brand via custom-gsap.js
   section 05. Real per-concept brand logos don't exist in this project, so
   the filter buttons and each card's badge reuse the 6 generic client-logo
   images already staged at demo/demobrand/brand-thumb1-6.png (copied in as
   assets/images/icons/filter-brand-1..6.png), cycled across the 10 slots. */
.concepts-filter-bar {
  gap: 12px;
  row-gap: 14px;
}
.concepts-filter-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 60px;
  height: 46px;
  padding: 0 16px;
  border: 1px solid rgb(32 52 66 / 14%);
  border-radius: 999px;
  background: #fff;
  font-family: var(--heading-font);
  font-weight: 500;
  font-size: 14px;
  cursor: pointer;
  transition: all 0.3s ease;
}
.concepts-filter-btn img {
  height: 18px;
  width: auto;
  object-fit: contain;
  filter: grayscale(1);
  opacity: 0.55;
  transition: all 0.3s ease;
}
.concepts-filter-btn:hover {
  border-color: var(--main-eight-600);
}
.concepts-filter-btn:hover img {
  opacity: 0.85;
}
.concepts-filter-btn.active {
  border-color: transparent;
  background: var(--main-eight-600);
  color: #fff;
}
.concepts-filter-btn.active img {
  filter: grayscale(0);
  opacity: 1;
}

/* Card badge replacing the old 5-star rating row (no real rating data
   behind those stars) - reuses that card's own cycled brand-logo image,
   shown as a small round badge instead of a filter pill. */
.product-three-brand-badge img {
  object-fit: contain;
  width: 100%;
  height: 30px;
  margin-bottom: 5px;
}
.product-three-thumb {
    border: 1px solid #ececec;
    border-radius: 15px;
    height: auto;
    padding-block: 0;
    margin-block-end: 20px;
}
.product-three-wrapper{
    border-radius: 15px;
}

/* 09. CTA section (#contact, .cta-two-area) - swap the big raster
   background (cta-two-shape7.png) for a single thick, faint SVG wave,
   and keep the 6 floating decorative shapes visible below 1499px
   instead of main.css hiding them outright (they may bleed past the
   section edge on narrow screens - .cta-two-area is overflow-hidden,
   so that's an intentional/acceptable clip, not a layout bug). */
@media screen and (max-width: 1499px) {
  .cta-two-shape-1,
  .cta-two-shape-2,
  .cta-two-shape-3,
  .cta-two-shape-4,
  .cta-two-shape-5,
  .cta-two-shape-6 {
    display: block;
  }
}

/* main.css centers shapes 2 and 5 at inset-inline-start: 46%, putting them
   directly under the centered .col-xl-8 text column (heading/paragraph/
   button) and overlapping it. Move them out toward the true edges instead,
   alongside shapes 1/4 (left-ish) and 3/6 (right-ish) - just visible near
   the edges, not overlapping the centered text. */
.cta-two-shape-2 {
  inset-inline-start: 3%;
  inset-inline-end: auto;
}
.cta-two-shape-5 {
  inset-inline-start: auto;
  inset-inline-end: 3%;
}

/* 10. Footer (.footer-two-area) - plain white background (no template
   tint, no decorative blob). */
.footer-two-area {
  background: #ffffff;
}
/* Same faint grid as #contact (.cta-two-area::after): fades out toward the top. */
.footer-two-area::before {
  content: "";
  display: block;
  position: absolute;
  inset: 0;
  width: auto;
  height: auto;
  z-index: -1;
  pointer-events: none;
  border-radius: 0;
  filter: none; /* main.css blurs this pseudo by 801px (old tint blob) */
  background: none;
  background-image:
    linear-gradient(rgb(32 52 66 / 10%) 1px, transparent 1px),
    linear-gradient(90deg, rgb(32 52 66 / 10%) 1px, transparent 1px);
  background-size: 48px 48px;
  -webkit-mask-image: linear-gradient(to top, #000 0%, transparent 85%);
  mask-image: linear-gradient(to top, #000 0%, transparent 85%);
}
/* copyright bar (.container-fluid at the bottom of the footer): dark
   #1F3441 with light text/icons. */
.footer-bottom-bar {
  background: #1F3441;
  padding-block: 10px;
  border-top-left-radius: 25px;
  border-top-right-radius: 25px;
}
.footer-bottom-bar .text-heading,
.footer-bottom-bar p {
  color: rgb(255 255 255 / 85%) !important;
}
.footer-bottom-bar p a {
  color: #fff !important;
}
.footer-bottom-bar p a:hover {
  color: #8fd6e2 !important;
}
.footer-bottom-bar .footer-two-social li a {
  color: #fff !important;
  background: rgb(255 255 255 / 10%);
}
.footer-bottom-bar .footer-two-social li a:hover {
  background: var(--main-eight-600);
}
.footer-two-social li a {
  border: 0;
}
@media (max-width: 575px) {
  .footer-bottom-bar {
      width: 97%;
  }
}

/* 12. cta-area (the plain "เริ่มต้นวันนี้" CTA right before </main>, not
   .cta-two-area) - stretch the navy panel to fill the full section
   instead of a fixed-size rounded blob, drop the rounded corners, add
   a faint SVG wave line like .cta-two-area for visual consistency,
   rebalance the two remaining columns after removing the review-stat
   column, and undo the large 1199px-down padding except a top gap
   kept for the sm tier where the layout stacks. */
.cta-area::before {
  background: #1792a8 !important;
  width: 100%;
  height: 100%;
  z-index: -1;
  border-radius: 0;
}
.cta-line {
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
@media (max-width: 1199px) {
  .cta-area {
    padding-block: 0;
  }
}
@media (max-width: 575px) {
  .cta-area {
    padding-block-start: 0;
  }
  .cta-button {
    text-align: center;
    width: 100%;
  }
}

/* Mobile submenu flicker fix: main.css's .has-submenu:hover rule isn't
   scoped to desktop, so a "stuck" mobile :hover fights the JS-driven
   display toggle. Key visibility off .active (set by toggleSubMenu())
   instead, so exactly one mechanism drives it below 1200px. */
@media screen and (max-width: 1199px) {
  .has-submenu:hover .nav-submenu { opacity: 0; visibility: hidden; transform: scaleY(0); }
  .has-submenu.active .nav-submenu { opacity: 1; visibility: visible; transform: scaleY(1); }
}

/* Mobile menu drawer: pin the footer (call/email/address/social icons)
   to the very bottom of the drawer regardless of how many submenus are
   open. .mobile-menu__body wraps .mobile-menu__menu + .mobile-menu__footer
   as the only two children of .mobile-menu__inner. */
.mobile-menu__inner {
  display: flex;
  flex-direction: column;
  min-height: 100%;
}
.mobile-menu__body {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}
.mobile-menu__footer {
  margin-top: auto;
}

/* Team section (.expert-area) "24/7" graph label: replays its wobble
   every time it scrolls into view (custom-gsap.js toggles this class via
   ScrollTrigger onEnter/onEnterBack/onLeave/onLeaveBack), instead of the
   shared .animation-item:hover pattern used by the ~10 other icons on
   this page. Reuses the existing global @keyframes wobble from main.css. */
.expert-graph-247-text.is-inview {
  animation: wobble 1.5s ease-in-out;
}

/* Preloader failsafe. #loading-screen is normally removed by main.js; if
   the served index.html is ever truncated (Docker bind-mount stale file
   size - see STATUS.md) main.js never loads and the overlay would stay
   forever. This lives in <head> CSS so it always arrives: after 6s the
   overlay hides itself regardless of JS. */
.loading-screen {
  animation: pda-preloader-failsafe 0.4s ease 6s forwards;
}
@keyframes pda-preloader-failsafe {
  to {
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
  }
}


/* Aspect Ratio */
.aspect-1 {
  aspect-ratio: 1 / 1;
  object-fit: cover;
}
.aspect-2 {
  aspect-ratio: 2 / 2.5;
  object-fit: cover;
}

/* CTA: subtitle + playful "wiggle" on the quote button, with a pulsing
   ring, paused on hover so the primary-button slide effect takes over. */
.cta-subtitle {
  opacity: 0.9;
}
.cta-button .tw-primary-btn {
  animation: pda-cta-wiggle 3.2s ease-in-out 1.5s infinite;
}
.cta-button .tw-primary-btn::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  animation: pda-cta-ring 3.2s ease-out 1.5s infinite;
}
.cta-button .tw-primary-btn:hover,
.cta-button .tw-primary-btn:hover::after {
  animation-play-state: paused;
}
@keyframes pda-cta-wiggle {
  0%, 62%, 100% { transform: translateY(0) rotate(0); }
  68% { transform: translateY(-6px) rotate(-3deg); }
  74% { transform: translateY(0) rotate(3deg); }
  80% { transform: translateY(-3px) rotate(-2deg); }
  86% { transform: translateY(0) rotate(1.5deg); }
  92% { transform: translateY(0) rotate(0); }
}
@keyframes pda-cta-ring {
  0%, 62% { box-shadow: 0 0 0 0 rgb(255 255 255 / 55%); }
  95%, 100% { box-shadow: 0 0 0 18px rgb(255 255 255 / 0%); }
}
@media (prefers-reduced-motion: reduce) {
  .cta-button .tw-primary-btn,
  .cta-button .tw-primary-btn::after { animation: none; }
}

/* CTA graph: dots at each vertex (HTML, so they stay round under the
   svg's non-uniform stretch) + faint percentage labels. Positions are
   viewBox-percentages of the svg, which fills the section. */
.cta-graph-points {
  inset: 0;
  pointer-events: none;
}
.cta-graph-dot {
  position: absolute;
  width: 10px;
  height: 10px;
  margin: -5px 0 0 -5px;
  border-radius: 50%;
  background: #fff;
  opacity: 0.7;
  box-shadow: 0 0 0 5px rgb(255 255 255 / 15%);
}
.cta-graph-dot em {
  position: absolute;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  font-style: normal;
  font-family: var(--heading-font);
  font-weight: 500;
  font-size: 14px;
  color: #fff;
  opacity: 0.45;
  white-space: nowrap;
}
@media (max-width: 767px) {
  .cta-graph-dot em { display: none; }
  .cta-con-over {
    background: hsl(189.1deg 75.92% 37.45% / 50%);
  }

}

/* Team section graph dots/labels: same look as .cta-graph-dot (reused),
   teal instead of white for the light background, overlaid on the graph
   svg with identical geometry (incl. the fixed 767px mobile sizing). */
.expert-graph-points {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  opacity: 0.85;
}
.expert-graph-dot {
  background: #1792A8;
  box-shadow: 0 0 0 5px rgb(23 146 168 / 15%);
}
.expert-graph-dot em {
  color: #1792A8;
  opacity: 0.8;
}
@media (max-width: 767px) {
  .expert-graph-points {
    inset: auto;
    top: 0;
    width: 767px;
    height: 400px;
    left: 50%;
    transform: translateX(-50%);
  }
}

/* Avatar photos are portrait headshots; keep the face inside the circle crop. */
.avatar-face {
  object-position: 50% 20%;
}

/* cta-two floating shapes are now photo crops (demo/blog-six-crops): round the corners. */
.cta-two-shape-1,
.cta-two-shape-2,
.cta-two-shape-3,
.cta-two-shape-4,
.cta-two-shape-5,
.cta-two-shape-6 {
  border-radius: 16px;
}

/* ปรึกษา (#contact.cta-two-area): faint grid background that fades out
   toward the top, a translucent white panel behind the text, and the six
   photo shapes kept on every device. Below 1500px they're pushed past the
   section edges (negative insets; .cta-two-area is overflow-hidden) so
   they get cropped by the viewport and only peek out around the sides,
   sitting behind the panel. */
.cta-two-area::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    linear-gradient(rgb(32 52 66 / 10%) 1px, transparent 1px),
    linear-gradient(90deg, rgb(32 52 66 / 10%) 1px, transparent 1px);
  background-size: 48px 48px;
  -webkit-mask-image: linear-gradient(to top, #000 0%, transparent 85%);
  mask-image: linear-gradient(to top, #000 0%, transparent 85%);
}
.cta-two-panel {
  position: relative;
  padding-top: 5%;
  padding-bottom: 5%;
  padding-inline: 16px;
  border-radius: 20px;
}
.cta-two-panel {
  /* solid white outline on every glyph (stroke painted under the fill so
     letters keep their full weight); the button keeps its own look */
  -webkit-text-stroke: 5px #fff;
  paint-order: stroke fill;
}
.cta-two-panel .tw-primary-btn {
  -webkit-text-stroke: 0;
}
.cta-two-panel p {
  max-width: 100%; /* tw-w-680-px overflowed the panel on narrow screens */
}

.cta-two-shape-4 {
    inset-block-end: 125px;
    inset-inline-start: 130px;
}
.cta-two-shape-3 {
    inset-block-start: 0px;
    inset-inline-end: 100px;
}

@media screen and (max-width: 1499px) {
  .cta-two-shape-1 { inset-block: -30px auto; inset-inline: -90px auto; }
  .cta-two-shape-6 { inset-block: -20px auto; inset-inline: auto -85px; }
  .cta-two-shape-3 { inset-block: 38% auto;   inset-inline: auto -260px; }
  .cta-two-shape-4 { inset-block: auto -80px; inset-inline: -240px auto; }
  .cta-two-shape-2 { inset-block: 10% auto;   inset-inline: -60px auto; }
  .cta-two-shape-5 { inset-block: auto -30px; inset-inline: auto -60px; }
}
@media screen and (max-width: 575px) {
  .cta-two-shape-1,
  .cta-two-shape-2,
  .cta-two-shape-3,
  .cta-two-shape-4,
  .cta-two-shape-5,
  .cta-two-shape-6 {
    scale: 0.7;
  }
  .blc-overlay {
    background: hsl(0deg 0% 100% / 50%);
  }
}

/* ผลงาน (.service-eight-area): cards are h-100 + tw-mb-705 inside a stretched
   flex column, so their margin-bottom overflows the column instead of
   pushing the next wrapped row down and stacked cards touch. Bootstrap's
   row gutter (margin-top on each col) doesn't depend on h-100. */
.service-eight-area .row.d-flex {
  --bs-gutter-y: 2rem;
}

/* CTA graph on narrow screens: same idea as the team section - don't
   squash the graph into the viewport. Keep its natural 1920:400 aspect
   (fixed 320px tall, top-anchored, width follows the aspect ratio - the section itself is ~900px tall when stacked, which would make the graph far too wide), centre it
   and let the sides bleed/crop; the dots/labels overlay gets identical
   geometry so their percentage positions still land on the vertices. */
@media (max-width: 767px) {
  .cta-area {
    overflow: hidden;
  }
  .cta-area .cta-line,
  .cta-area .cta-graph-points {
    inset: 0 auto auto 50%;
    width: auto;
    height: 550px;
    aspect-ratio: 1920 / 400;
    transform: translateX(-50%);
  }
}

/* Preloader: "PDA" lettering + a small rising-bars loader (replaces the
   template's cartoon gif spinner). The letter-flip animation itself is
   main.css's .letters-loading; only font/spacing are overridden here. */
.loading-screen .animation-preloader .txt-loading {
  font-family: var(--heading-font);
  font-weight: 600;
  letter-spacing: 0.12em;
}
.loading-screen .animation-preloader .txt-loading .letters-loading:before {
  font-family: var(--heading-font);
}
.pda-loader {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  gap: 8px;
  height: 56px;
  margin-bottom: 20px;
}
.pda-loader span {
  width: 10px;
  height: 100%;
  border-radius: 4px;
  background: var(--main-eight-600);
  transform-origin: bottom;
  transform: scaleY(0.25);
  animation: pda-loader-bars 1.2s ease-in-out infinite;
}
.pda-loader span:nth-child(2) { animation-delay: 0.15s; }
.pda-loader span:nth-child(3) { animation-delay: 0.3s; }
.pda-loader span:nth-child(4) { animation-delay: 0.45s; }
@keyframes pda-loader-bars {
  0%, 100% { transform: scaleY(0.25); opacity: 0.5; }
  50% { transform: scaleY(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .pda-loader span { animation: none; transform: scaleY(0.6); }
}

/* "GROUP.CO" line under the PDA lettering in the preloader (plain black). */
.pda-loader-group {
  margin-top: 4px;
  text-align: center;
  font-family: var(--heading-font);
  font-weight: 500;
  font-size: 1.1rem;
  letter-spacing: 0.5em;
  padding-inline-start: 0.5em; /* offsets the trailing letter-spacing so it stays centred */
  color: #000;
  user-select: none;
}
