/* ==========================================================================
   PT. Assyaffa Digital Media : brand layer
   --------------------------------------------------------------------------
   Loaded after style.css. Only index.html links this file, so the ~70 Webteck
   demo pages keep their original template palette for design comparison.

   Palette: #012971 navy, #FD6A00 orange, #FCB319 yellow, #F8FAFC surface.

   Contrast rules that are NOT negotiable (measured, not estimated):
     - #FD6A00 on white  = 2.90:1  -> orange is a FILL colour only. Never text,
                                      never a border, never an icon on light.
     - #012971 on #FD6A00 = 4.65:1 -> orange fills always carry navy text.
     - #FCB319 on white  = 1.81:1  -> yellow is a FILL colour only, navy text.
     - #C24A00 on #F8FAFC = 4.70:1 -> the only legal orange for text on light.
   ========================================================================== */

/* --------------------------------------------------------------------------
   10. Custom Breadcrumb Gradient & Text Utilities
   -------------------------------------------------------------------------- */
.breadcumb-wrapper.page-hero-gradient {
  background: linear-gradient(135deg, #012971 0%, #0B1B33 100%) !important;
  padding: 80px 0;
  position: relative;
}
.breadcumb-wrapper.page-hero-gradient .breadcumb-title {
  color: #ffffff;
}
.breadcumb-wrapper.page-hero-gradient .breadcumb-menu li,
.breadcumb-wrapper.page-hero-gradient .breadcumb-menu li a {
  color: rgba(255, 255, 255, 0.8);
}
.breadcumb-wrapper.page-hero-gradient .breadcumb-menu li a:hover {
  color: #FCB319;
}

/* Legal text accent for orange text on light bg (passes WCAG AA 4.7:1) */
.text-orange-accent {
  color: #C24A00 !important;
  font-weight: 700;
}
body.theme-blue2,
body.theme-assyaffa {
  --theme-color: #012971;
  --theme-color2: #012971;
  --theme-color3: #FD6A00;
  --theme-color3-ink: #C24A00;
  --yellow-color: #FCB319;
  /* Must stay distinct from --theme-color: .th-btn:before/:after (style.css:2518)
     use --title-color as the hover fill, so navy-on-navy would make every button
     hover state invisible. */
  --title-color: #0B1B33;
  --body-color: #5A6472;
  --smoke-color: #F8FAFC;
  --smoke-color2: #EEF2F8;
  --smoke-color3: #F8FAFC;
  --th-border-color: #DCE3ED;
  background-color: #F8FAFC;
}

/* --------------------------------------------------------------------------
   2. Header : light surface, navy topbar
   style.css hardcodes #080E1C on .menu-area and white on the nav links, so both
   have to be overridden explicitly; neither reads from a variable.
   -------------------------------------------------------------------------- */
.header-layout1 .menu-area,
.header-layout1 .sticky-wrapper.sticky .menu-area {
  background-color: #F8FAFC;
  border-bottom: 1px solid var(--th-border-color);
}

.header-layout1 .main-menu > ul > li > a:not(:hover) {
  color: var(--theme-color);
}

.header-layout1 .main-menu > ul > li > a:hover,
.header-layout1 .main-menu > ul > li.active > a {
  color: var(--theme-color3-ink);
}

/* Topbar sits on navy, so its hover colour cannot be --title-color (near-black
   on navy is unreadable). Yellow on navy is 7.45:1. */
.header-layout1 .header-top a:hover {
  color: var(--yellow-color);
}

.th-menu-toggle,
.header-layout1 .th-menu-toggle {
  background-color: var(--theme-color);
  color: #ffffff;
}

/* --------------------------------------------------------------------------
   3. Footer : brand navy
   -------------------------------------------------------------------------- */
.footer-layout1 {
  background-color: var(--theme-color);
}

.footer-layout1 .footer-top {
  background-color: #06327F;
  border-bottom: 1px solid rgba(255, 255, 255, 0.12);
}

.footer-layout1 .copyright-wrap {
  background-color: #011B4D;
}

.footer-wrapper .widget_title,
.footer-wrapper .footer-social .social-title {
  color: #ffffff;
}

.footer-wrapper a:hover,
.footer-wrapper .info-link:hover {
  color: var(--yellow-color);
}

/* --------------------------------------------------------------------------
   4. Buttons
   .th-btn base is background:var(--theme-color) + white text = navy/white, fine.
   The accent variants exist because orange and yellow cannot carry white text.
   There is deliberately no orange outline variant: an orange border on a light
   surface is 2.90:1 and fails the 3:1 non-text minimum.
   -------------------------------------------------------------------------- */
.th-btn.btn-accent {
  background-color: var(--theme-color3);
  color: var(--theme-color);
  font-weight: 700;
}

.th-btn.btn-accent:before,
.th-btn.btn-accent:after {
  background-color: var(--theme-color);
}

.th-btn.btn-accent:hover,
.th-btn.btn-accent:focus-visible {
  color: #ffffff;
}

.th-btn.btn-accent2 {
  background-color: var(--yellow-color);
  color: var(--theme-color);
  font-weight: 700;
}

.th-btn.btn-accent2:before,
.th-btn.btn-accent2:after {
  background-color: var(--theme-color);
}

.th-btn.btn-accent2:hover,
.th-btn.btn-accent2:focus-visible {
  color: #ffffff;
}

.th-btn.btn-outline-navy {
  background-color: transparent;
  color: var(--theme-color);
  border: 2px solid var(--theme-color);
  box-shadow: none;
}

.th-btn.btn-outline-navy:before,
.th-btn.btn-outline-navy:after {
  background-color: var(--theme-color);
}

.th-btn.btn-outline-navy:hover,
.th-btn.btn-outline-navy:focus-visible {
  color: #ffffff;
}

/* --------------------------------------------------------------------------
   5. Indonesian typography
   The template Title-Cases every section heading and UPPERCASES every button.
   In Indonesian that produces "Dan", "Yang", "Di" and inflates CTA width by
   15-20%, which is what pushes buttons out of their row.
   -------------------------------------------------------------------------- */
.sec-title,
.th-btn,
.th-btn.style8,
.brand-title2,
.box-title {
  text-transform: none;
}

/* style.css has no word-breaking rule at all for these, so a long Indonesian
   compound simply pushes out of its container instead of wrapping. */
.sec-title,
.box-title,
.hero-title,
.brand-title2,
.th-btn,
.counter-text {
  overflow-wrap: break-word;
}

/* A hard 233px cap on service card copy makes Indonesian blurbs run 5 lines and
   leaves the grid row ragged. */
.service-box2_text {
  max-width: none;
}

/* --------------------------------------------------------------------------
   6. Partner logos
   The original cap lived at .brand-sec6 .brand-box img, so any .brand-box used
   outside that section rendered its logo at natural size (up to 983px tall on
   this page). Scoping removed so it cannot recur.
   -------------------------------------------------------------------------- */
.brand-box {
  display: flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  border: 1px solid var(--th-border-color);
  border-radius: 12px;
  padding: 12px 18px;
  height: 80px;
  width: 100%;
  transition: all 0.3s ease;
}

.brand-box:hover {
  border-color: var(--theme-color);
  transform: translateY(-4px);
  box-shadow: 0 10px 25px rgba(1, 41, 113, 0.1);
}

.brand-box img {
  max-height: 52px;
  max-width: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
}

.brand-sec6 {
  background: #ffffff;
  border-top: 1px solid var(--th-border-color);
  border-bottom: 1px solid var(--th-border-color);
  margin: 40px auto;
  padding: 48px 0;
}

.brand-sec6 .brand-title2 {
  color: var(--theme-color);
  font-weight: 700;
  letter-spacing: -0.5px;
}

/* --------------------------------------------------------------------------
   7. Logo sizing
   style.css:7287 sets max-height:80px inside @media (max-width:991px) at higher
   specificity than a bare .header-logo img, so the logo GREW on small screens.
   The override is repeated inside a matching media query for that reason.
   -------------------------------------------------------------------------- */
.header-layout1 .header-logo img,
.header-logo img,
.footer-logo img,
.mobile-logo img {
  max-height: 44px;
  width: auto;
  height: auto;
  object-fit: contain;
}

@media (max-width: 991px) {
  .header-layout1 .header-logo img,
  .header-logo img,
  .footer-logo img,
  .mobile-logo img {
    max-height: 40px;
    width: auto;
  }
}

.footer-layout1 .footer-logo {
  padding: 28px 45px 28px 0;
}

/* --------------------------------------------------------------------------
   8. Accessibility
   -------------------------------------------------------------------------- */
a:focus-visible,
button:focus-visible,
input:focus-visible,
.th-btn:focus-visible {
  outline: 3px solid var(--theme-color3);
  outline-offset: 2px;
}

/* Tap targets: template nav/footer links are ~20px tall on mobile. */
@media (max-width: 991px) {
  .th-mobile-menu a,
  .footer-widget .menu li a,
  .footer-links a {
    min-height: 44px;
    display: flex;
    align-items: center;
  }
}

/* --------------------------------------------------------------------------
   9. Residual Webteck literals
   These six #F3F2EA beige fills survived compilation as literals, so no token
   change reaches them. Enumerated from a computed-style audit of this page,
   not from a blind grep, so the list is exactly what actually renders.
   style.css lines: 4265, 14133, 31821, 38857, 38952, 47924.
   -------------------------------------------------------------------------- */
.smoke-body,
.counter-area-7,
.service-box2:before {
  background-color: var(--smoke-color2);
}

.service-box2 .icon-btn {
  background-color: #ffffff;
  color: var(--theme-color);
}

.hero-10 .th-hero-img .hero-line2,
.choose-feature2-wrap .divider,
.counter-card7 .divider {
  background: var(--th-border-color);
}

/* --------------------------------------------------------------------------
   10. Footer text on navy
   style.css leaves .info-link inheriting the global `a { color: var(--theme-color) }`.
   With --theme-color now navy and the footer now navy, those links rendered at
   1.00:1 : literally invisible. Measured replacements: #DCE6F5 = 10.71:1,
   #C3D0E6 = 8.66:1 on #012971.
   -------------------------------------------------------------------------- */
.footer-layout1 .info-link,
.footer-layout1 .copyright-text a,
.footer-layout1 .footer-widget a,
.footer-layout1 .footer-links a,
.footer-layout1 .th-widget-about a {
  color: #DCE6F5;
}

.footer-layout1 .info-link:hover,
.footer-layout1 .copyright-text a:hover,
.footer-layout1 .footer-widget a:hover,
.footer-layout1 .footer-links a:hover {
  color: var(--yellow-color);
}

.footer-layout1 .info-title,
.footer-layout1 .about-text,
.footer-layout1 .copyright-text,
.footer-layout1 .newsletter-text,
.footer-layout1 p {
  color: #C3D0E6;
}

.footer-layout1 .footer-social a {
  color: #ffffff;
  border-color: rgba(255, 255, 255, 0.25);
}

.footer-layout1 .footer-social a:hover {
  background-color: var(--theme-color3);
  border-color: var(--theme-color3);
  color: var(--theme-color);
}

/* --------------------------------------------------------------------------
   11. Hero facts panel
   Replaces the empty hero image column. Marked up as a description list: the
   label is the term and the figure is its value, so it reads correctly to a
   screen reader. column-reverse puts the big figure on top visually without
   inverting the semantics.
   -------------------------------------------------------------------------- */
.hero-facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 14px;
  /* The hero row is centre-aligned; this keeps the panel clear of the hero's
     lower edge, which it previously sat flush against. */
  margin: 24px 0 40px;
  padding: 0;
}

.hero-facts_item {
  display: flex;
  flex-direction: column-reverse;
  gap: 6px;
  padding: 22px 20px;
  background: #ffffff;
  border: 1px solid var(--th-border-color);
  border-left: 4px solid var(--theme-color3);
  border-radius: 14px;
}

.hero-facts_item dd {
  margin: 0;
  font-family: var(--title-font);
  font-size: 34px;
  line-height: 1.1;
  font-weight: 700;
  color: var(--theme-color);
}

.hero-facts_item dt {
  margin: 0;
  font-size: 14px;
  line-height: 1.45;
  color: var(--body-color);
}

@media (max-width: 1199px) {
  .hero-facts { margin: 48px 0 60px; }
}

@media (max-width: 400px) {
  .hero-facts { grid-template-columns: minmax(0, 1fr); }
}

/* --------------------------------------------------------------------------
   12. Coverage area
   -------------------------------------------------------------------------- */
.coverage-list {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.coverage-list li {
  padding: 9px 16px;
  min-height: 44px;
  display: flex;
  align-items: center;
  font-size: 15px;
  font-weight: 500;
  color: var(--theme-color);
  background: #ffffff;
  border: 1px solid var(--th-border-color);
  border-radius: 999px;
}

.coverage-map {
  margin: 0;
  padding: 20px;
  background: #ffffff;
  border: 1px solid var(--th-border-color);
  border-radius: 20px;
}

.coverage-map img {
  width: 100%;
  height: auto;
  border-radius: 12px;
}

.coverage-map figcaption {
   margin-top: 14px;
   font-size: 14px;
   line-height: 1.5;
   color: var(--body-color);
}

/* Google Maps iframe styling */
.map-frame {
   width: 100%;
   height: 450px;
   margin-top: 20px;
   padding: 20px;
   background: #ffffff;
   border: 1px solid var(--th-border-color);
   border-radius: 20px;
   border: none; /* Override any default border */
}

/* --------------------------------------------------------------------------
   13. Quote CTA (replaces the template's USD pricing table)
   -------------------------------------------------------------------------- */
.quote-area {
  background-color: var(--theme-color);
}

.quote-area .sub-title,
.quote-area .sub-title3 {
  color: var(--yellow-color);
}

.quote-lead {
  max-width: 720px;
  margin: 0 auto;
  color: #C3D0E6;
}

.quote-card {
  height: 100%;
  padding: 28px 26px;
  background: #06327F;
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 16px;
  transition: border-color 0.3s ease, transform 0.3s ease;
}

.quote-card:hover {
  border-color: var(--theme-color3);
  transform: translateY(-4px);
}

.quote-card_title {
  margin: 0 0 12px;
  font-size: 20px;
  line-height: 1.35;
  color: #ffffff;
}

.quote-card_text {
  margin: 0;
  font-size: 15px;
  line-height: 1.6;
  color: #C3D0E6;
}

/* --------------------------------------------------------------------------
   14. Copyright bar
   .bg-theme carries !important (style.css:4184), so beating it needs !important
   too. The class stays in the markup because footer.js is shared with the demo
   pages, which do not load this stylesheet.
   -------------------------------------------------------------------------- */
.footer-layout1 .copyright-wrap.bg-theme {
  background-color: #011B4D !important;
}

/* --------------------------------------------------------------------------
   15. Icons
   The template's service/feature icons were cyber-security artwork (an analytics
   dashboard, a hoodie hacker, an Android robot) with fills hardcoded inside the
   SVG files. Replaced with Font Awesome glyphs already loaded on this page, so
   they inherit the brand colour and carry the right meaning.
   -------------------------------------------------------------------------- */
.service-box2_icon i,
.choose-feature2 .box-icon i {
  font-size: 40px;
  line-height: 1;
  color: var(--theme-color);
}

.choose-feature2 .box-icon {
  width: auto;
  height: auto;
}

.checklist.style4 li i,
.checklist li .fa-circle-check {
  /* Navy, not orange: orange on white is 2.90:1 and misses the 3:1 floor for
     meaningful non-text graphics. */
  color: var(--theme-color);
  font-size: 17px;
  margin-right: 4px;
}

/* --------------------------------------------------------------------------
   16. Service cards
   .service-box2:before/:after paint the card background through a clip-path with
   hardcoded 327x250 coordinates (style.css:38851). Indonesian copy runs taller
   than 250px, so the background stopped short and the last line of every card sat
   on bare page. A rounded rectangle tracks the real content height instead.
   -------------------------------------------------------------------------- */
.service-box2 {
  height: 100%;
  padding: 30px 30px 70px 30px;
}

.service-box2:before,
.service-box2:after {
  -webkit-clip-path: none;
  clip-path: none;
  border-radius: 20px;
}

/* Only the resting layer is full width. :after stays 0 and expands to 100% on
   hover, which is what carries the white text. */
.service-box2:before {
  width: 100%;
}

.service-box2:hover .service-box2_icon i,
.service-box2:hover .icon-btn {
  color: #ffffff;
}

.service-box2:hover .icon-btn {
  background-color: var(--theme-color3);
  color: var(--theme-color);
}

.service-box2_shape {
  display: none;
}

.service-box2 .icon-btn {
  position: absolute;
  left: 30px;
  bottom: 24px;
  right: auto;
}

/* Equal-height cards: without this the row staggered because the template used
   align-items-center on cards of differing content length. */
.service-grid-row > [class*="col-"] {
  display: flex;
}

/* --------------------------------------------------------------------------
   17. Touch targets
   Icon-only links (social, logo) rendered as 19px-tall inline boxes. Text links
   inside a sentence are exempt from the 44px minimum; icon-only controls are not.
   -------------------------------------------------------------------------- */
.social-links a,
.footer-social a,
.header-social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
}

.header-logo > a,
.footer-logo > a,
.mobile-logo > a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

/* --------------------------------------------------------------------------
   18. Footer detail
   The widget underline is var(--theme-color), which is now the same navy as the
   footer itself, so only the white end-dot was visible. And the contact list
   still carried default list bullets.
   -------------------------------------------------------------------------- */
.footer-layout1 .footer-widget .widget_title:before {
  background-color: var(--theme-color3);
}

.footer-layout1 .footer-info ul,
.footer-layout1 .th-widget-about ul {
  list-style: none;
  padding-left: 0;
  margin-left: 0;
}

.footer-layout1 .footer-info li {
  display: flex;
  align-items: center;
  gap: 10px;
}

.footer-layout1 .footer-info .icon {
  color: var(--theme-color3);
}

/* --------------------------------------------------------------------------
   19. Hero rhythm
   The template's 206px bottom padding assumed a decorative image column filling
   the right side. With the facts panel there instead, that much trailing space
   reads as a mistake.
   -------------------------------------------------------------------------- */
.hero-style10 {
  padding: 110px 0 120px 0;
}

@media (max-width: 1199px) {
  .hero-style10 {
    padding: 90px 0 0 0;
  }
}

/* --------------------------------------------------------------------------
   20. Page hero (inner pages)
   Replaces the template's photo breadcrumb strip, which showed a stock image and
   a bare page name. Structure follows the pattern used by MyRepublic and
   Telkomsel: a welcome line, a short memorable tagline, then the mission in one
   paragraph, on a solid brand-colour ground.
   -------------------------------------------------------------------------- */
.page-hero {
  position: relative;
  overflow: hidden;
  background-color: var(--theme-color);
  background-image:
    radial-gradient(120% 140% at 88% 8%, rgba(253, 106, 0, 0.30) 0%, rgba(253, 106, 0, 0) 55%),
    radial-gradient(90% 120% at 4% 100%, rgba(252, 179, 25, 0.16) 0%, rgba(252, 179, 25, 0) 60%),
    linear-gradient(160deg, #012971 0%, #011B4D 100%);
  padding: 70px 0 96px;
}

/* A soft ruled grid, drawn in CSS so it costs no request. */
.page-hero:before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.05) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(80% 80% at 50% 0%, #000 0%, transparent 75%);
          mask-image: radial-gradient(80% 80% at 50% 0%, #000 0%, transparent 75%);
  pointer-events: none;
}

.page-hero > .container {
  position: relative;
  z-index: 1;
}

.page-hero_crumbs ol {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin: 0 0 34px;
  padding: 0;
  list-style: none;
  font-size: 14px;
}

.page-hero_crumbs li {
  color: #A9BDDE;
}

.page-hero_crumbs li + li:before {
  content: '/';
  margin-right: 10px;
  color: #6E86AE;
}

.page-hero_crumbs a {
  color: #DCE6F5;
  min-height: 44px;
  display: inline-flex;
  align-items: center;
}

.page-hero_crumbs a:hover {
  color: var(--yellow-color);
}

.page-hero_content {
  max-width: 860px;
}

.page-hero_title {
  margin: 0 0 14px;
  color: #ffffff;
  font-size: 54px;
  line-height: 1.12;
  letter-spacing: -0.5px;
  overflow-wrap: break-word;
}

/* The tagline is the emotional line, so it carries the brand accent. Yellow on
   this navy ground measures 7.45:1. */
.page-hero_tagline {
  margin: 0 0 22px;
  color: var(--yellow-color);
  font-family: var(--title-font);
  font-size: 26px;
  line-height: 1.3;
  font-weight: 600;
}

.page-hero_lead {
  margin: 0;
  max-width: 720px;
  color: #C3D0E6;
  font-size: 17px;
  line-height: 1.75;
}

.page-hero_actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-top: 34px;
}

/* Light outline button, for use on the dark hero only. */
.th-btn.btn-outline-light {
  background-color: transparent;
  color: #ffffff;
  border: 2px solid rgba(255, 255, 255, 0.55);
  box-shadow: none;
}

.th-btn.btn-outline-light:before,
.th-btn.btn-outline-light:after {
  background-color: #ffffff;
}

.th-btn.btn-outline-light:hover,
.th-btn.btn-outline-light:focus-visible {
  color: var(--theme-color);
  border-color: #ffffff;
}

@media (max-width: 991px) {
  .page-hero { padding: 54px 0 66px; }
  .page-hero_title { font-size: 40px; }
  .page-hero_tagline { font-size: 22px; }
}

@media (max-width: 575px) {
  .page-hero { padding: 42px 0 52px; }
  .page-hero_title { font-size: 31px; }
  .page-hero_tagline { font-size: 19px; }
  .page-hero_lead { font-size: 16px; }
  .page-hero_actions .th-btn { width: 100%; }
}

/* --------------------------------------------------------------------------
   21. About portrait
   Replaces the template's two grey placeholder slabs (about_1_1.png 537x537 and
   about_shape_1.png 826x1169) with the director portrait from the company profile.
   -------------------------------------------------------------------------- */
.about-portrait {
  position: relative;
  margin: 0;
  max-width: 460px;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 24px 60px rgba(1, 41, 113, 0.16);
}

.about-portrait img {
  display: block;
  width: 100%;
  height: auto;
}

.about-portrait figcaption {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 46px 22px 18px;
  /* Opaque fallback first: a gradient is a background-image, so without this the
     caption would have no background-color to sit on if the image ever fails. */
  background-color: #011B4D;
  background-image: linear-gradient(to top, rgba(1, 27, 77, 0.94) 30%, rgba(1, 27, 77, 0.55) 100%);
  color: #ffffff;
}

.about-portrait figcaption strong {
  display: block;
  font-family: var(--title-font);
  font-size: 20px;
  line-height: 1.3;
}

.about-portrait figcaption span {
  display: block;
  margin-top: 2px;
  font-size: 14px;
  color: #C3D0E6;
}

/* --------------------------------------------------------------------------
   22. Counter cards on inner pages
   The template's counter icons were 50px SVGs sitting inside a decorative blob.
   Font Awesome glyphs need explicit sizing or they render tiny inside it.
   -------------------------------------------------------------------------- */
.counter-card_icon i {
  font-size: 34px;
  line-height: 1;
  color: var(--theme-color);
}

.counter-card_icon {
  display: flex;
  align-items: center;
  justify-content: center;
}

/* --------------------------------------------------------------------------
   23. Promo banner carousel (index.html)
   Rendered at runtime by components/content.js from data/konten.json, so the
   owner can swap the artwork without touching HTML. Two consequences shape
   the CSS: the image is arbitrary (whatever they generate later), and the
   markup arrives after first paint.

   Arbitrary image means the caption cannot rely on the photo being dark. On
   desktop a navy scrim covers the caption zone; measured against a pure white
   photo underneath, white text still reads 9.6:1. On mobile the caption moves
   out from over the image onto solid navy, so there is no exposure at all.

   Arriving after first paint means the skeleton must occupy the exact final
   height, otherwise the page jumps when the data lands.
   -------------------------------------------------------------------------- */
.banner-sec {
  padding: 0 0 40px;
}

.banner-slider {
  position: relative;
  border-radius: 20px;
  overflow: hidden;
  background-color: var(--theme-color);
}

.banner-slide {
  position: relative;
  margin: 0;
}

.banner-slide_img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 2.5 / 1;
  object-fit: cover;
}

.banner-slide_body {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  gap: 12px;
  padding: 0 clamp(28px, 5vw, 66px);
  background-image: linear-gradient(90deg,
    rgba(1, 27, 77, 0.95) 0%,
    rgba(1, 27, 77, 0.92) 46%,
    rgba(1, 27, 77, 0.55) 72%,
    rgba(1, 27, 77, 0.18) 100%);
}

.banner-slide_label {
  margin: 0;
  color: var(--yellow-color);
  font-family: var(--title-font);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.banner-slide_title {
  margin: 0;
  max-width: 20ch;
  color: #ffffff;
  font-family: var(--title-font);
  font-size: clamp(24px, 2.7vw, 40px);
  line-height: 1.15;
  font-weight: 700;
  overflow-wrap: break-word;
}

.banner-slide_text {
  margin: 0;
  max-width: 46ch;
  color: #C3D0E6;
  font-size: 16px;
  line-height: 1.6;
}

.banner-slide_btn {
  margin-top: 8px;
}

/* The control pill carries its own white ground, so the arrows and dots keep
   a fixed contrast regardless of what the photo behind them looks like. */
.banner-nav {
  position: absolute;
  right: 24px;
  bottom: 24px;
  z-index: 2;
  display: inline-flex;
  align-items: center;
  gap: 2px;
  height: 50px;
  padding: 0 8px;
  border-radius: 999px;
  background-color: rgba(255, 255, 255, 0.95);
  box-shadow: 0 6px 18px rgba(1, 27, 77, 0.18);
}

.banner-arrow {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background-color: transparent;
  color: var(--theme-color);
  font-size: 15px;
  transition: 0.3s;
}

.banner-arrow:hover,
.banner-arrow:focus-visible {
  background-color: var(--theme-color);
  color: #ffffff;
}

/* Swiper stamps .swiper-pagination on this element, which carries
   position:absolute + width:100% from swiper-bundle.min.css. Here the dots sit
   inside a static control pill instead, so that positioning has to be undone. */
.banner-nav .banner-dots,
.banner-nav .banner-dots.swiper-pagination {
  position: static;
  display: inline-flex;
  align-items: center;
  width: auto;
  height: 44px;
  margin: 0;
  line-height: 1;
  -webkit-transform: none;
          transform: none;
}

/* The template already has a bullet idiom (style.css:1710-1747): the bullet is a
   small neutral dot, and its ::before is an absolutely positioned overlay that
   scales from 0 to 0.9 when the slide becomes active. That rule is what made an
   earlier attempt here invisible, because any ::before written for these dots
   inherits transform:scale(0) from it. Reusing the idiom and only recolouring it
   also keeps these dots consistent with every other slider on the site. */
.banner-nav .banner-dots .swiper-pagination-bullet {
  --swiper-pagination-bullet-size: 10px;
  margin: 0 12px;
  background-color: rgba(1, 41, 113, 0.4);
}

.banner-nav .banner-dots .swiper-pagination-bullet:before {
  border-color: var(--theme-color3);
  background: var(--theme-color3);
}

/* A 10px dot is not a usable touch target. ::after is unused by the template's
   bullet styling, so it can carry an invisible 40x44 hit area. */
.banner-nav .banner-dots .swiper-pagination-bullet:after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 40px;
  height: 44px;
  -webkit-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
}

.banner-skeleton {
  aspect-ratio: 2.5 / 1;
  border-radius: 20px;
  background-color: #E7ECF5;
  background-image: linear-gradient(100deg, #E7ECF5 34%, #F3F6FB 50%, #E7ECF5 66%);
  background-size: 220% 100%;
  animation: adm-shimmer 1.5s linear infinite;
}

@keyframes adm-shimmer {
  from { background-position: 140% 0; }
  to { background-position: -40% 0; }
}

/* Below the medium breakpoint the caption leaves the image entirely. Overlaying
   text on a 360px-wide photo leaves no room for either. */
@media (max-width: 767px) {
  .banner-slide_img,
  .banner-skeleton {
    aspect-ratio: 16 / 9;
  }

  .banner-slide_body {
    position: static;
    padding: 26px 22px 30px;
    background-image: none;
    background-color: var(--theme-color);
  }

  .banner-slide_title {
    max-width: none;
    font-size: 22px;
  }

  .banner-nav {
    position: static;
    display: flex;
    justify-content: center;
    margin: 18px auto 0;
    width: -webkit-fit-content;
    width: fit-content;
    box-shadow: none;
    background-color: var(--smoke-color2);
  }

  .banner-slide_btn {
    width: 100%;
    text-align: center;
  }
}

/* --------------------------------------------------------------------------
   24. Paket layanan (index.html + pricing.html)
   Built on the template's .price-box.style2, which is the only pricing variant
   that already has a badge slot, an eyebrow line for the speed, and separate
   check/cross icons for included and excluded features.
   -------------------------------------------------------------------------- */
.paket-lead {
  max-width: 760px;
  margin: 16px auto 0;
  color: var(--body-color);
}

.paket-tabs {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 12px;
  margin: 40px 0 30px;
}

.paket-tab {
  min-height: 48px;
  padding: 12px 26px;
  border: 1px solid var(--th-border-color);
  border-radius: 999px;
  background-color: #ffffff;
  color: var(--theme-color);
  font-family: var(--title-font);
  font-size: 16px;
  font-weight: 600;
  transition: 0.3s;
}

.paket-tab:hover {
  border-color: var(--theme-color);
}

.paket-tab.is-active {
  background-color: var(--theme-color);
  border-color: var(--theme-color);
  color: #ffffff;
}

.paket-panel_desc {
  max-width: 760px;
  margin: 0 auto 34px;
  text-align: center;
  color: var(--body-color);
}

.paket-wrap .price-box.style2 {
  height: 100%;
  margin-top: 0;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background-color: #ffffff;
  border: 1px solid var(--th-border-color);
  /* Extra top padding on EVERY card, badged or not, reserves the strip below so
     the package names still line up across the row. */
  padding-top: 74px;
}

@media (max-width: 991px) {
  .paket-wrap .price-box.style2 { padding-top: 64px; }
}

@media (max-width: 575px) {
  .paket-wrap .price-box.style2 { padding-top: 58px; }
}

/* style.css:41503 lifts the featured card by translateY(-30px). That is a common
   pricing-table flourish, but it pushes every row of the featured card out of
   line with its neighbours, and comparing rows is the entire job of this table.
   The card is already unmistakable from the orange strip, the navy border and
   the shadow, so the lift goes. */
.paket-wrap .price-box.style2.active {
  border-color: var(--theme-color);
  box-shadow: 0 18px 42px rgba(1, 41, 113, 0.12);
  -webkit-transform: none;
      -ms-transform: none;
          transform: none;
}

.paket-wrap .price-box.style2.active:hover {
  -webkit-transform: translateY(-5px);
      -ms-transform: translateY(-5px);
          transform: translateY(-5px);
}

/* The template's badge is a 120x120 diagonal corner ribbon, and it has two
   problems here. style.css:42540 gives it z-index:-1 while the card is z-index:1
   with an opaque background, so a negative child paints behind its own parent and
   the ribbon never appears at all. Once that is fixed the rotated 210px bar is
   far too big for these cards and its text lands off-centre.
   Replaced with a flat strip across the card top: same information, readable at
   any width, and no rotation geometry to keep in tune. */
.paket-wrap .price-box.style2 .offer-tag {
  position: absolute;
  top: 0;
  right: 0;
  left: 0;
  width: auto;
  height: auto;
  z-index: 2;
  overflow: visible;
  text-align: center;
}

.paket-wrap .price-box.style2 .offer-tag .tag {
  position: static;
  display: block;
  width: 100%;
  left: auto;
  top: auto;
  padding: 11px 12px;
  -webkit-transform: none;
      -ms-transform: none;
          transform: none;
  /* Orange fill always carries navy text: white on this orange is 2.9:1. */
  background-color: var(--theme-color3);
  color: var(--theme-color);
  font-family: var(--title-font);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.paket-wrap .price-box.style2 .price-title-wrap .subtitle {
  color: var(--theme-color);
}

.paket-wrap .price-box_price {
  color: var(--theme-color);
}

/* Reserved on every card, filled only where there is a promo price, so the
   headline figure sits on the same line whether or not one is struck through. */
.paket-wrap .price-box_was {
  display: block;
  min-height: 1.5em;
  margin-bottom: 2px;
  font-family: var(--body-font);
  font-size: 16px;
  line-height: 1.5;
  font-weight: 400;
  color: var(--body-color);
}

.paket-wrap .price-box_price--ask {
  font-size: 30px;
}

/* The price sits above the summary so it lands at the same height on every card.
   The summary then gets a floor so the feature lists line up too; a longer
   summary still grows, it just stops being ragged at ordinary lengths. */
.paket-wrap .price-box.style2 .price-box_price {
  border-top: 0;
  padding-top: 22px;
  padding-bottom: 4px;
}

.paket-wrap .price-box.style2 .price-box_text {
  min-height: 4.9em;
  padding-bottom: 24px;
  border-bottom: 1px solid var(--th-border-color);
  margin-bottom: 24px;
}

/* Cards in a row are only as tall as the tallest, so the call to action has to
   be pinned to the bottom or the buttons sit at six different heights. */
.paket-wrap .price-box_content {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
}

.paket-wrap .price-box_content .available-list {
  flex: 1 1 auto;
}

.paket-wrap .price-box_content .th-btn {
  margin-top: 22px;
}

.paket-catatan {
  max-width: 860px;
  margin: 40px auto 0;
  padding: 16px 22px;
  border-radius: 12px;
  border-left: 4px solid var(--theme-color3);
  background-color: var(--smoke-color2);
  color: var(--title-color);
  font-size: 15px;
  line-height: 1.6;
}

.paket-more {
  margin-top: 44px;
}

.paket-skeleton {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 24px;
  margin-top: 40px;
}

.paket-skeleton span {
  display: block;
  height: 430px;
  border-radius: 15px;
  background-color: #E7ECF5;
  background-image: linear-gradient(100deg, #E7ECF5 34%, #F3F6FB 50%, #E7ECF5 66%);
  background-size: 220% 100%;
  animation: adm-shimmer 1.5s linear infinite;
}

@media (max-width: 991px) {
  .paket-skeleton { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .paket-skeleton span:nth-child(3) { display: none; }
}

@media (max-width: 575px) {
  .paket-skeleton { grid-template-columns: minmax(0, 1fr); }
  .paket-skeleton span:nth-child(2) { display: none; }
  .paket-tab { width: 100%; }
}

/* --------------------------------------------------------------------------
   25. Loading, empty and failure states
   data/konten.json can be missing, unreadable over file://, or malformed after
   an edit. None of those may leave a blank hole where content was promised.
   -------------------------------------------------------------------------- */
.konten-gagal {
  max-width: 660px;
  margin: 40px auto 0;
  padding: 36px 26px;
  text-align: center;
  border: 1px dashed var(--th-border-color);
  border-radius: 16px;
  background-color: #ffffff;
}

.konten-gagal_title {
  margin: 0 0 10px;
  font-family: var(--title-font);
  font-size: 20px;
  font-weight: 600;
  color: var(--title-color);
}

.konten-gagal_text {
  margin: 0 0 22px;
  color: var(--body-color);
}

/* The template sets display on list items and social links, which would beat
   the user-agent rule for the hidden attribute. Contact rows are hidden that
   way whenever konten.json has no value for them yet. */
[hidden] {
  display: none !important;
}

@media (prefers-reduced-motion: reduce) {
  .banner-skeleton,
  .paket-skeleton span {
    animation: none;
  }
}

/* --------------------------------------------------------------------------
   26. Paket detail panels (pricing.html)
   The fixed terms that apply to every package. Static HTML rather than JSON,
   because this is policy text, not data the owner changes with prices.
   -------------------------------------------------------------------------- */
.paket-info_card {
  height: 100%;
  padding: 40px;
  border: 1px solid var(--th-border-color);
  border-radius: 20px;
  background-color: #ffffff;
}

.paket-info_title {
  margin: 0 0 24px;
  font-size: 26px;
  line-height: 1.25;
}

.paket-info_list {
  margin: 0;
  padding: 0;
  list-style: none;
}

.paket-info_list li {
  position: relative;
  margin-bottom: 16px;
  padding-left: 32px;
  color: var(--body-color);
  line-height: 1.6;
}

.paket-info_list li:last-child {
  margin-bottom: 0;
}

.paket-info_list li i {
  position: absolute;
  top: 4px;
  left: 0;
  color: var(--theme-color);
  font-size: 17px;
}

.paket-info_dl {
  margin: 0;
}

.paket-info_dl dt {
  margin-bottom: 6px;
  font-family: var(--title-font);
  font-size: 17px;
  font-weight: 600;
  color: var(--title-color);
}

.paket-info_dl dd {
  margin: 0 0 22px;
  color: var(--body-color);
  line-height: 1.6;
}

.paket-info_dl dd:last-child {
  margin-bottom: 0;
}

@media (max-width: 575px) {
  .paket-info_card { padding: 28px 24px; }
  .paket-info_title { font-size: 22px; }
}

/* --------------------------------------------------------------------------
   27. Links inside cards that sit on navy
   .quote-card has a #06327F ground, but an <a> inside it inherits the global
   link colour, which is --theme-color navy. Measured 1.14:1 against the card,
   i.e. the link was there but nobody could see it. Yellow is the established
   on-navy accent elsewhere on the site, and the underline keeps the link
   distinguishable without relying on colour alone.
   -------------------------------------------------------------------------- */
.quote-card a {
  color: var(--yellow-color);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.quote-card a:hover,
.quote-card a:focus-visible {
  color: #ffffff;
}

/* --------------------------------------------------------------------------
   28. Tim (team/)
   Built on .paket-info_card so the card shell stays one component, not two.
   Only the icon, the heading scale and the contact rows are new here.
   -------------------------------------------------------------------------- */
.team-role {
  padding: 32px 28px;
  text-align: center;
}

.team-role_icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 62px;
  height: 62px;
  margin-bottom: 20px;
  border-radius: 50%;
  /* Navy fill with a white glyph: 13.49:1. An orange fill here would need navy
     ink, which reads as a warning rather than a category marker. */
  background-color: var(--theme-color);
  color: #ffffff;
  font-size: 24px;
}

.team-role_title {
  margin: 0 0 12px;
  font-size: 19px;
  line-height: 1.35;
}

.team-role_text {
  margin: 0;
  color: var(--body-color);
  font-size: 15px;
  line-height: 1.65;
}

.team-role_desig {
  margin: 6px 0 0;
  color: var(--theme-color3-ink);
  font-family: var(--title-font);
  font-size: 17px;
  font-weight: 600;
}

.team-contact-list {
  margin: 26px 0 30px;
}

.team-contact-list_item {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0 0 12px;
  color: var(--body-color);
  line-height: 1.6;
}

.team-contact-list_item:last-child {
  margin-bottom: 0;
}

.team-contact-list_item i {
  flex: none;
  margin-top: 5px;
  color: var(--theme-color);
  font-size: 16px;
}

@media (max-width: 575px) {
  .team-role { padding: 28px 22px; }
}

/* --------------------------------------------------------------------------
   29. Mobile drawer close button
   The button that opens the drawer was already sized in section 8, but the one
   that CLOSES it, inside .th-menu-area, was left at 33x33. It is a touch-only
   control, so it gets the same 44px floor. Affects every page that ships the
   mobile menu, which is all of them.
   -------------------------------------------------------------------------- */
.th-menu-area .th-menu-toggle,
.th-menu-wrapper .th-menu-area .th-menu-toggle {
  width: 44px;
  height: 44px;
  line-height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
}

/* --------------------------------------------------------------------------
   30. Kartu anggota tim (team/)
   Two states share one component. A filled card carries a photo and a name; a
   placeholder card carries the same role information with a dashed edge and an
   avatar mark, so it reads as "not filled in yet" rather than as a broken image.
   The grey-square placeholders this template shipped with were indistinguishable
   from failed loads, which is what made them damaging.
   -------------------------------------------------------------------------- */
.team-member {
  height: 100%;
  padding: 34px 24px;
  text-align: center;
  border: 1px solid var(--th-border-color);
  border-radius: 20px;
  background-color: #ffffff;
  transition: border-color 0.3s ease, transform 0.3s ease;
}

.team-member:hover {
  border-color: var(--theme-color);
  transform: translateY(-4px);
}

.team-member.is-placeholder {
  border-style: dashed;
  background-color: var(--smoke-color);
}

.team-member_avatar {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 96px;
  height: 96px;
  margin: 0 auto 20px;
  overflow: hidden;
  border-radius: 50%;
  background-color: var(--smoke-color2);
  color: var(--theme-color);
  font-size: 34px;
}

.team-member_avatar img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.team-member_role {
  margin: 0 0 6px;
  font-size: 18px;
  line-height: 1.35;
}

.team-member_name {
  margin: 0 0 14px;
  color: var(--theme-color3-ink);
  font-family: var(--title-font);
  font-size: 15px;
  font-weight: 600;
}

/* Placeholder names are stated, not styled to look like real ones. */
.team-member.is-placeholder .team-member_name {
  color: var(--body-color);
  font-style: italic;
  font-weight: 400;
}

.team-member_note {
  margin: 0;
  color: var(--body-color);
  font-size: 14px;
  line-height: 1.6;
}
