/* ==========================================================================
   NUUK LINK — brand override  (nuuk.css)
   ---------------------------------------------------------------------------
   Load LAST, AFTER Sandbox style.css. UNLAYERED on purpose (Sandbox style.css
   is unlayered; @layer would drop these below it in the cascade).

   Brand palette (4 colors): White #FFFFFF · Blue #0054D1 · Deep Blue #0139B0
   · Cloud gray #F3F5F7. Combination rules + full spec: DESIGN.md.
   Do NOT load any Sandbox css/colors/*.css or css/fonts/*.css.

   NOTE: drop PretendardVariable.woff2 into assets/fonts/pretendard/ (SIL OFL,
   https://github.com/orioncactus/pretendard). Until then the fallback renders.
   ========================================================================== */

/* ---- Font: Pretendard Variable (self-hosted, replaces Sandbox fonts) ------ */
@font-face {
  font-family: "Pretendard Variable";
  font-weight: 45 920;
  font-style: normal;
  font-display: swap;
  src: url("../fonts/pretendard/PretendardVariable.woff2") format("woff2-variations");
}

:root {
  /* -- Brand primary (Blue) ---------------------------------------------- */
  --bs-primary:     #0054D1;
  --bs-primary-rgb: 0, 84, 209;

  /* -- Links + hover/emphasis = Deep Blue -------------------------------- */
  --bs-link-color-rgb:       0, 84, 209;
  --bs-link-hover-color-rgb: 1, 57, 176;

  /* -- BS 5.3 subtle/emphasis tokens (independent literals in style.css) - */
  --bs-primary-text-emphasis: #0139B0;
  --bs-primary-bg-subtle:     #EAF1FB;
  --bs-primary-border-subtle: #CFE0F7;

  /* -- Sandbox soft/pale hooks ------------------------------------------- */
  --bs-soft-primary: #EAF1FB;

  /* -- Neutrals ---------------------------------------------------------- */
  --bs-light:         #F3F5F7;   /* alternating section / card gray */
  --bs-light-rgb:     243, 245, 247;
  --bs-body-bg:       #FFFFFF;
  --bs-body-color:    #475467;
  --bs-heading-color: #0B1B33;
  --bs-border-color:  #E4E8EE;
  --bs-dark:          #0B1B33;   /* footer / dark surfaces (brand navy) */
  --bs-dark-rgb:      11, 27, 51;

  /* -- Font -------------------------------------------------------------- */
  --bs-body-font-family: "Pretendard Variable", "Pretendard", -apple-system,
    BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial,
    "Apple SD Gothic Neo", "Noto Sans KR", "Noto Sans", sans-serif;
}

/* ---- Focus-shadow fix — Sandbox hardcodes the old-blue rgb inside the
   .btn-primary / .btn-outline-primary rule bodies; re-point it to the brand blue. */
.btn-primary,
.btn-outline-primary { --bs-btn-focus-shadow-rgb: 0, 84, 209; }

/* ---- Primary button hover/active = Deep Blue ------------------------------ */
.btn-primary:hover,
.btn-primary:focus-visible,
.btn-primary:active,
.btn-primary.active {
  background-color: #0139B0;
  border-color: #0139B0;
}

/* ---- The ONLY gradient allowed: same-hue blue depth (white text) ---------- */
.gradient-brand { background-image: linear-gradient(135deg, #0054D1, #0139B0); color: #fff; }

/* ---- Footer / dark surfaces: link hover to white (blue-on-navy is low
   contrast); Sandbox defaults the hover to --bs-primary. --------------------- */
.bg-dark.text-inverse a:not(.btn):not([class*="link-"]):hover { color: #fff; }

/* ---- flag-icons: align flags with the text in the language switcher -------- */
.language-select .fi { vertical-align: -0.15em; border-radius: 2px; }

/* ---- Language dropdown alignment (THE fix) ---------------------------------
   Sandbox's `.language-select .dropdown-menu` hard-codes `left:50% !important` +
   `transform:translateX(-50%) !important` - a CENTERED, narrow menu meant for
   2-letter codes (En/De/Es). Our menu carries full names + flags, so centering it
   under the small "EN" trigger left it unanchored and jutting toward the page edge /
   the Get-a-Quote button. Anchor it to the trigger's right edge instead (matches the
   `dropdown-menu-end` already in the markup). ------------------------------------ */
.language-select .dropdown-menu {
  left: auto !important;
  right: 0 !important;
  transform: none !important;
}

/* ---- Navbar focus ring fix -------------------------------------------------
   Two problems with the Sandbox default `.nav-link:focus-visible` ring:
   1) it uses the OLD Sandbox blue (rgba(63,120,224)) instead of the brand blue;
   2) Bootstrap programmatically `.focus()`es a dropdown toggle when its menu opens,
      so the browser paints the focus-visible ring even on a MOUSE click - it shows
      up as a stray box around the toggle (e.g. the "EN" language switcher).
   Fix: re-point the ring to the brand blue for real keyboard focus on plain links,
   and drop the ring on dropdown TOGGLES (the open menu + active color already signal
   state, so the toggle does not need a ring and must not flash a box on click). --- */
.navbar .nav-link:focus-visible {
  box-shadow: 0 0 0 0.2rem rgba(0, 84, 209, 0.3);
}
.navbar .dropdown-toggle:focus,
.navbar .dropdown-toggle:focus-visible {
  box-shadow: none;
  outline: 0;
}

/* ==========================================================================
   HERO GLASSMORPHISM  (HERO ONLY — do not spread .glass across the site)
   Surface is kept semi-opaque so text stays WCAG-legible over any photo, and
   degrades gracefully where backdrop-filter / transparency isn't wanted.
   ========================================================================== */

/* Full-bleed image hero shell */
.hero-glass { position: relative; overflow: hidden; }
.hero-glass > .hero-bg {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;              /* svg uses preserveAspectRatio="…slice" too */
  z-index: 0;
}
/* Dark scrim so white hero text passes contrast regardless of the photo */
.hero-glass > .hero-scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  /* Text sits top-left, so darken the left (and a little of the top) for white-text contrast
     while keeping the right clear for the callout image + the port in the photo. */
  background:
    linear-gradient(90deg,
      rgba(11, 27, 51, .68) 0%, rgba(11, 27, 51, .40) 48%, rgba(11, 27, 51, 0) 82%),
    linear-gradient(180deg,
      rgba(11, 27, 51, .40) 0%, rgba(11, 27, 51, .12) 45%, rgba(11, 27, 51, 0) 100%);
}
/* On mobile the columns stack (text spans full width at the top): use a top-down scrim instead. */
@media (max-width: 991.98px) {
  .hero-glass > .hero-scrim {
    background: linear-gradient(180deg,
      rgba(11, 27, 51, .58) 0%, rgba(11, 27, 51, .28) 40%, rgba(11, 27, 51, 0) 80%);
  }
}

/* Hero text reveal — a gentle staggered fade-up of the hero content on load.
   Above the fold, so it plays on page load (no scroll trigger needed). Each direct
   child of .hero-reveal (eyebrow, h1, lead, CTAs) eases in one after another.
   Guarded by prefers-reduced-motion: no-preference, so if motion is reduced the
   content simply renders in place (no opacity:0, nothing to reset). */
@media (prefers-reduced-motion: no-preference) {
  .hero-reveal > * {
    opacity: 0;
    animation: heroReveal .7s cubic-bezier(.2, .6, .2, 1) both;
  }
  .hero-reveal > *:nth-child(1) { animation-delay: .10s; }
  .hero-reveal > *:nth-child(2) { animation-delay: .24s; }
  .hero-reveal > *:nth-child(3) { animation-delay: .38s; }
  .hero-reveal > *:nth-child(4) { animation-delay: .52s; }
  /* Scroll cue arrives last. Its own keyframe keeps the translateX(-50%) centering,
     and `backwards` (not forwards) so after it plays the base styles resume and the
     scroll-to-hide `.is-hidden` toggle keeps working. */
  .hero-scroll { animation: heroScrollIn .7s cubic-bezier(.2, .6, .2, 1) .8s backwards; }
}
@keyframes heroReveal {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: translateY(0); }
}
@keyframes heroScrollIn {
  from { opacity: 0; transform: translateX(-50%) translateY(18px); }
  to   { opacity: 1; transform: translateX(-50%) translateY(0); }
}

/* Scroll cue — a mouse indicator at the hero's foot: a brand-blue pill outline with
   a small dot that glides down inside. The universal "scroll" affordance, kept airy
   so it whispers. The <a> is a 44px hit area; the pill itself is drawn on the inner
   span. Sits on the white fade, so the blue outline + dot read cleanly. */
.hero-scroll {
  position: absolute; left: 50%; bottom: 24px; transform: translateX(-50%);
  z-index: 2; width: 44px; height: 52px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: opacity .35s ease, transform .35s ease, visibility .35s ease;
}
/* JS adds .is-hidden once the user scrolls — fade + drift out, no longer clickable. */
.hero-scroll.is-hidden {
  opacity: 0; visibility: hidden; pointer-events: none;
  transform: translateX(-50%) translateY(12px);
}
.hero-scroll .hero-mouse {
  width: 26px; height: 42px; border-radius: 13px;
  border: 2px solid rgba(255, 255, 255, .8);
  background: rgba(11, 27, 51, .18);
  display: flex; justify-content: center; padding-top: 8px;
  transition: border-color .2s ease, background-color .2s ease;
}
.hero-scroll:hover .hero-mouse {
  border-color: #fff;
  background: rgba(255, 255, 255, .18);
}
.hero-scroll .hero-mouse-dot {
  width: 4px; height: 8px; border-radius: 2px;
  background: #fff;
}
.hero-scroll:focus-visible {
  outline: 2px solid #fff; outline-offset: 3px; border-radius: 14px;
}
/* Dot glides down and fades — GPU-friendly (transform + opacity only). */
@media (prefers-reduced-motion: no-preference) {
  .hero-scroll .hero-mouse-dot { animation: heroMouseDot 1.9s ease-in-out infinite; }
}
@keyframes heroMouseDot {
  0%        { transform: translateY(0); opacity: 0; }
  25%       { opacity: 1; }
  60%, 100% { transform: translateY(12px); opacity: 0; }
}

/* ==========================================================================
   PROCESS BLOCK  (How it works — Sandbox .process-wrapper.line)
   Sandbox draws the connector line at EVERY width. Below lg the steps stack
   (or go 2-up), where a horizontal/half connector just floats beside each
   circle as noise. Hide it there so mobile + tablet stay clean; keep it on
   lg+ where all four steps sit in one row and the line reads as the journey.
   ========================================================================== */
@media (max-width: 991.98px) {
  .process-wrapper.line [class*="col-"]::before,
  .process-wrapper.line [class*="col-"]::after { display: none; }
}

/* ==========================================================================
   CLIENT LOGO TICKER  (Trusted section — Sandbox .clients.ticker)
   Sandbox assumes uniform, small logos. Make it robust for our fixed-size SVG
   placeholders and for real logos of varying size: center each logo in its slide
   and cap it so it never overflows the narrow 2-up mobile slide. A soft edge mask
   lets logos emerge/vanish instead of hard-clipping at the container edges.
   ========================================================================== */
.clients .swiper-slide {
  display: flex;
  align-items: center;
  justify-content: center;
}
/* Size logos by HEIGHT so every logo reads the same size regardless of aspect ratio.
   max-height + max-width (both dims auto) always preserve the ratio: height binds where
   there is room (uniform ~32px logo-bar height), width binds only on a cramped mobile slide
   (logo shrinks a touch, never distorts). Tune --clients-logo-h to taste.
   Kept at 2rem (not 3rem) on purpose: at 3rem the widest wordmarks (ratio ~4-5, e.g. Slack,
   Asana) exceed the desktop slide width, so max-width binds and THEY alone render shorter,
   which reads as "some logos bigger, some smaller". 2rem keeps every wordmark within slide
   width so height is the single binding dimension and all logos read the same height. */
.clients { --clients-logo-h: 2rem; }
.clients .swiper-slide svg,
.clients .swiper-slide img {
  width: auto;
  height: auto;
  max-width: 100%;
  max-height: var(--clients-logo-h);
}
/* Unify real client logos to monochrome (brand requirement). The SVG placeholders
   are already gray, so this only affects the real logos swapped in later. */
.clients .swiper-slide img { filter: grayscale(1); opacity: .7; }
/* Soft fade at both edges so the marquee does not hard-cut at the container edge. */
.clients {
  -webkit-mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
          mask-image: linear-gradient(90deg, transparent 0, #000 6%, #000 94%, transparent 100%);
}

/* ==========================================================================
   BLOG CAROUSEL  (Blog — Sandbox .swiper-container.blog, demo25 caption-overlay)
   Titles sit over the image on theme.js's dark bottom scrim (span.bg). Clamp long
   headlines to 2 lines so they can't grow past the scrim onto the light part of the
   image (the full title stays in the DOM for SEO/AT). Real photos read the same.
   ========================================================================== */
.blog .caption figcaption .post-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
/* Our placeholders (and light photos) are pale, so the bottom scrim alone may not hit
   AA on the upper line of the title. A subtle shadow guarantees the white caption text
   stays legible over any image. Scoped to title + meta so the white category badge is
   untouched. */
.blog .caption figcaption .post-title,
.blog .caption figcaption .post-meta {
  text-shadow: 0 1px 4px rgba(11, 27, 51, .6);
}

/* ==========================================================================
   FAQ ACCORDION  (Home §7 — Sandbox .accordion-wrapper .card.plain)
   Sandbox's `plain` accordion is border-less (fine for its short demo labels).
   Our questions are full sentences that wrap to two lines, so four collapsed
   items blur into one another. Add a hairline divider + breathing room between
   items (not on the last) so the list stays scannable. Scoped to #faqAccordion
   only, so other accordions keep the stock Sandbox look. */
#faqAccordion .accordion-item:not(:last-child) {
  border-bottom: 1px solid rgba(164, 174, 198, .22);
  margin-bottom: .85rem;
  padding-bottom: .85rem;
}

/* The glass surface */
.glass {
  background-color: rgba(255, 255, 255, .62);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  backdrop-filter: blur(16px) saturate(140%);
  border: 1px solid rgba(255, 255, 255, .55);
  box-shadow: 0 8px 32px rgba(11, 27, 51, .14);
}
/* No backdrop-filter support → raise opacity so contrast holds */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .glass { background-color: rgba(255, 255, 255, .90); }
}
/* Respect reduced-transparency: drop the blur, make it near-solid */
@media (prefers-reduced-transparency: reduce) {
  .glass {
    background-color: rgba(255, 255, 255, .94);
    -webkit-backdrop-filter: none; backdrop-filter: none;
  }
}
/* Mobile: blur is costly and small screens need more legibility */
@media (max-width: 767.98px) {
  .glass {
    background-color: rgba(255, 255, 255, .85);
    -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
  }
}
