/* =================================================================
   site.css — Intixa, layered on Bootstrap 5.

   Replaces the SemiColonWeb "Canvas" theme (style.css 237 KB +
   combined.js 759 KB + jQuery + animate.css + font-icons). Nothing
   here derives from that theme; the class names are Bootstrap's or
   ours.

   Load order (include/html_head.php):
     bootstrap.min.css -> swiper-bundle.min.css -> site.css (last)
   ================================================================= */

/* -----------------------------------------------------------------
   1. Brand tokens
----------------------------------------------------------------- */
:root {
    --brand: #0162b4;         /* 6.2:1 on white — AA for body text   */
    --brand-dark: #014b8a;    /* link hover                          */
    --brand-light: #3e8fd8;   /* accents on dark backgrounds         */
    --ink: #333;              /* body text                           */
    --heading-ink: #1a1a1a;
    --muted: #6c757d;
    --dark-bg: #1b1f24;       /* header, footer, dark bands          */
    --dark-ink: #cfd6dd;
    --line: #e5e7eb;
    --header-h: 84px;
}

/* -----------------------------------------------------------------
   2. Base
----------------------------------------------------------------- */
html { scroll-behavior: smooth; scroll-padding-top: var(--header-h); }
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: .001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: .001ms !important;
    }
}

body {
    color: var(--ink);
    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    font-size: 1rem;
    line-height: 1.7;
    -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4, h5, h6 {
    color: var(--heading-ink);
    font-weight: 600;
    letter-spacing: -.01em;
}
h2 { font-size: clamp(1.75rem, 1.2rem + 1.8vw, 2.5rem); }
h3 { font-size: 1.25rem; }

a { color: var(--brand); text-decoration-thickness: 1px; text-underline-offset: .15em; }
a:hover, a:focus { color: var(--brand-dark); }

:focus-visible { outline: 3px solid var(--brand-light); outline-offset: 2px; }

.skip-link {
    position: absolute; top: .5rem; left: .5rem; z-index: 2000;
    background: #fff; color: var(--brand-dark);
    padding: .5rem .9rem; border-radius: .25rem; font-weight: 600;
}

.text-brand { color: var(--brand) !important; }

/* Bootstrap ships #0d6efd and it does NOT pick up --brand on its own: the
   compiled .btn-primary carries its colours as literals. Without this the main
   "Send Message" button renders in stock Bootstrap blue while the rest of the
   page is Intixa blue — two blues, with the wrong one on the conversion button. */
:root {
    --bs-primary: #0162b4;
    --bs-primary-rgb: 1, 98, 180;
    --bs-link-color: #0162b4;
    --bs-link-color-rgb: 1, 98, 180;
    --bs-link-hover-color: #014b8a;
    --bs-link-hover-color-rgb: 1, 75, 138;
}
.btn-primary {
    --bs-btn-bg: var(--brand);
    --bs-btn-border-color: var(--brand);
    --bs-btn-hover-bg: var(--brand-dark);
    --bs-btn-hover-border-color: var(--brand-dark);
    --bs-btn-active-bg: var(--brand-dark);
    --bs-btn-active-border-color: var(--brand-dark);
    --bs-btn-disabled-bg: var(--brand);
    --bs-btn-disabled-border-color: var(--brand);
    --bs-btn-focus-shadow-rgb: 1, 98, 180;
}
.text-primary { color: var(--brand) !important; }
.form-control:focus,
.form-select:focus {
    border-color: var(--brand-light);
    box-shadow: 0 0 0 .25rem rgba(1, 98, 180, .25);
}

/* -----------------------------------------------------------------
   3. Header
   Transparent over the hero, solid once scrolled (js/site.js toggles
   .is-stuck). No sticky-header plugin, no data-attributes.
----------------------------------------------------------------- */
.site-header {
    position: fixed; inset: 0 0 auto 0; z-index: 1030;
    background: transparent;
    transition: background-color .25s ease, box-shadow .25s ease;
}
.site-header .navbar { padding: 1rem 0; transition: padding .25s ease; }
.site-header .navbar-brand img { height: 40px; width: auto; }

.site-header .nav-link {
    color: #fff;
    font-weight: 600;
    font-size: .95rem;
    text-transform: uppercase;
    letter-spacing: .04em;
    padding: .5rem .9rem;
}
.site-header .nav-link:hover,
.site-header .nav-link:focus { color: var(--brand-light); }

.site-header.is-stuck {
    background: var(--dark-bg);
    box-shadow: 0 2px 14px rgba(0,0,0,.28);
}
.site-header.is-stuck .navbar { padding: .5rem 0; }

.navbar-toggler {
    color: #fff; border-color: rgba(255,255,255,.4);
}
.navbar-toggler-icon {
    background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255,255,255,0.85%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e");
}
/* Collapsed menu needs a background of its own — it opens over the hero. */
@media (max-width: 991.98px) {
    .navbar-collapse.show, .navbar-collapse.collapsing {
        background: var(--dark-bg);
        margin-top: .75rem;
        padding: .5rem 1rem;
        border-radius: .375rem;
    }
}

/* -----------------------------------------------------------------
   4. Hero slider
----------------------------------------------------------------- */
.hero { position: relative; height: 100vh; min-height: 560px; background: var(--dark-bg); }
.hero .swiper, .hero .swiper-slide { height: 100%; }

.hero-slide {
    position: relative;
    display: flex; align-items: center;
    height: 100%;
    background-size: cover; background-position: center;
    color: #fff;
}
/* Media sits behind the caption; the scrim keeps text legible over
   whatever frame the video happens to be on. */
.hero-media {
    position: absolute; inset: 0; overflow: hidden;
}
.hero-media video {
    width: 100%; height: 100%; object-fit: cover;
    display: block;
}
/* The scrim is a contrast control, not decoration. The caption is white text
   over video, so the worst case is a near-white frame — and the compositing
   maths is unforgiving: at the old .45 midpoint a white-on-scrim paragraph came
   out at 3.08:1. That clears AA for the large heading (3:1) and FAILS it for
   the body text beneath (4.5:1). At .60 the worst case is ~5:1, so both pass
   whatever the video is showing. */
.hero-slide::after {
    content: ""; position: absolute; inset: 0;
    background: linear-gradient(180deg, rgba(12,15,18,.62) 0%, rgba(12,15,18,.60) 50%, rgba(12,15,18,.72) 100%);
}
.hero-caption { position: relative; z-index: 2; max-width: 46rem; }
.hero-caption h1, .hero-caption h2 {
    color: #fff;
    font-size: clamp(2.25rem, 1.4rem + 3.6vw, 4rem);
    font-weight: 700; margin-bottom: .5rem;
}
.hero-caption p {
    font-size: clamp(1rem, .93rem + .4vw, 1.25rem);
    color: rgba(255,255,255,.92);
    margin-bottom: 0;
}
.hero-caption .btn { margin: 1.5rem .5rem 0 0; }

.btn-hero {
    --bs-btn-color: #fff;
    --bs-btn-border-color: rgba(255,255,255,.7);
    --bs-btn-hover-color: var(--dark-bg);
    --bs-btn-hover-bg: #fff;
    --bs-btn-hover-border-color: #fff;
    --bs-btn-focus-shadow-rgb: 255,255,255;
    border-radius: 2rem; padding: .6rem 1.6rem; font-weight: 600;
}

/* Swiper chrome */
.hero .swiper-button-next, .hero .swiper-button-prev { color: #fff; }
/* Below md the arrows land on top of the caption text. Pagination and swipe
   already cover navigation at that size, so hide them rather than reflow. */
@media (max-width: 767.98px) {
    .hero .swiper-button-next, .hero .swiper-button-prev { display: none; }
}
.hero .swiper-button-next::after, .hero .swiper-button-prev::after { font-size: 1.75rem; }
/* Swiper's default bullet is 8px, which fails WCAG 2.5.8. The dot stays small
   — four large circles over the hero would be ugly — and the ::after expands
   the hit area invisibly to 30x30 with a gap between neighbours, so adjacent
   targets never overlap. */
.hero .swiper-pagination-bullet {
    background: #fff;
    opacity: .45;
    width: 14px;
    height: 14px;
    position: relative;
    margin: 0 9px !important;
}
.hero .swiper-pagination-bullet::after {
    content: "";
    position: absolute;
    inset: -8px;
}
.hero .swiper-pagination-bullet-active { opacity: 1; background: var(--brand-light); }
/* Lift the bullets clear of the scroll cue. Both default to bottom-centre, so
   once the bullets got a real hit area the two interactive controls overlapped
   — you could aim for the arrow and change slide instead. */
.hero .swiper-pagination { bottom: 76px !important; }

/* Pause control for the autoplaying background video — WCAG 2.2.2:
   any moving content over 5s needs a way to stop it. The theme had none. */
.hero-motion-toggle {
    position: absolute; right: 1rem; bottom: 1rem; z-index: 5;
    display: inline-flex; align-items: center; gap: .4rem;
    background: rgba(0,0,0,.5); color: #fff;
    border: 1px solid rgba(255,255,255,.35); border-radius: 2rem;
    padding: .35rem .8rem; font-size: .8rem; cursor: pointer;
}
.hero-motion-toggle:hover { background: rgba(0,0,0,.72); }

.scroll-cue {
    position: absolute; left: 50%; bottom: 1.25rem; z-index: 4;
    transform: translateX(-50%);
    /* 44px box so it meets the comfortable touch target, not just WCAG 2.5.8's
       24px floor. The glyph inside stays 30px. */
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px;
    color: #fff; opacity: .8;
    animation: cue-bob 2.2s ease-in-out infinite;
}
.scroll-cue:hover { color: #fff; opacity: 1; }
@keyframes cue-bob { 0%,100% { transform: translate(-50%, 0); } 50% { transform: translate(-50%, 7px); } }

/* -----------------------------------------------------------------
   5. Sections
----------------------------------------------------------------- */
.section { padding: 5rem 0; }
.section-sm { padding: 3rem 0; }

.heading-block { max-width: 52rem; margin: 0 auto 3rem; text-align: center; }
.heading-block p, .heading-block .lead { color: var(--muted); margin-bottom: 0; }

/* The rotating phrase in the services heading. One element is visible at a
   time; js/site.js cycles them. Without JS the first stays put, which is a
   complete sentence on its own. */
.rotator { color: var(--brand); white-space: nowrap; }

/* Service cards */
.service-card {
    height: 100%;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: .5rem;
    overflow: hidden;
    transition: transform .2s ease, box-shadow .2s ease;
}
.service-card:hover { transform: translateY(-4px); box-shadow: 0 .75rem 1.5rem rgba(0,0,0,.08); }
.service-card img { width: 100%; height: 190px; object-fit: cover; display: block; }
.service-card .card-body { padding: 1.25rem; }
.service-card h3 { margin-bottom: .25rem; }
.service-card .subtitle {
    display: block; color: var(--brand);
    font-size: .875rem; font-weight: 500;
    margin-top: -.1rem;
}
.service-card p { margin: .6rem 0 0; color: var(--muted); font-size: .95rem; }

/* Portfolio items */
.portfolio-item { display: flex; gap: 1rem; }
.portfolio-item .icon-badge {
    flex: 0 0 auto;
    width: 3rem; height: 3rem; border-radius: 50%;
    display: inline-flex; align-items: center; justify-content: center;
    background: rgba(1,98,180,.09); color: var(--brand);
}
.portfolio-item h3 { font-size: 1.05rem; margin-bottom: .35rem; }
.portfolio-item p { margin: 0; color: var(--muted); font-size: .95rem; }

/* Dark quote / testimonial bands. The theme used a parallax plugin here;
   background-attachment does the same job in CSS, and is switched off on
   touch devices where it janks. */
.band {
    position: relative;
    padding: 6rem 0;
    background: var(--dark-bg) center/cover no-repeat;
    color: #fff;
}
.band::before { content: ""; position: absolute; inset: 0; background: rgba(14,18,22,.72); }
.band > * { position: relative; z-index: 1; }
.band h2, .band h3 { color: #fff; }
/* No background-attachment: fixed. With background-size: cover the image is
   sized to the VIEWPORT rather than the element, so a short band shows a thin
   out-of-focus sliver of a much larger image — no discernible subject, and it
   slides under the text as you scroll. Scrolling with the page keeps the
   artwork legible, which is the whole point of having it. */

.pull-quote { font-size: clamp(1.4rem, 1.1rem + 1.2vw, 2.1rem); font-weight: 600; margin: 0; }

.testimonial blockquote { font-size: 1.15rem; margin: 0 auto; max-width: 46rem; }
.testimonial figcaption { margin-top: 1rem; color: var(--brand-light); font-weight: 600; }
.testimonial figcaption span { display: block; color: var(--dark-ink); font-weight: 400; font-size: .9rem; }

/* -----------------------------------------------------------------
   6. Contact form
----------------------------------------------------------------- */
.contact-form label { font-weight: 600; font-size: .9rem; margin-bottom: .25rem; }
.contact-form .form-control, .contact-form .form-select { border-radius: .375rem; }
.contact-form .required-marker { color: #b3261e; }

.form-result { display: none; }
.form-result.show { display: block; }

/* Honeypot — hidden from people, visible to naive bots. Not display:none,
   which some bots skip; off-screen instead. */
.hp-field {
    position: absolute !important;
    left: -9999px !important;
    width: 1px; height: 1px; overflow: hidden;
}

/* Not height:100% — matching the form column's height left ~290px of empty
   grey below the last address. */
.contact-aside { background: #f6f8fa; border-radius: .5rem; padding: 1.5rem; }

/* -----------------------------------------------------------------
   7. Footer
----------------------------------------------------------------- */
.site-footer { background: var(--dark-bg); color: var(--dark-ink); padding-top: 4rem; }
.site-footer h2, .site-footer h3, .site-footer strong { color: #fff; }
.site-footer a { color: var(--brand-light); }
.site-footer a:hover { color: #fff; }
.site-footer address { font-style: normal; margin-bottom: .5rem; }
/* Capped at the file's own 126x35 so it is pixel-exact at 1x. There is no valid
   2x of this wordmark — images/intixa-footer-logo@2x.png is byte-identical to
   intixa-logo-dark@2x.png, a different logo — so upscaling it only adds blur. */
.footer-logo { width: 126px; height: 35px; }

.footer-social li + li { margin-top: .9rem; }
.footer-social a { display: inline-flex; align-items: center; gap: .6rem; text-decoration: none; }
.footer-social a span { color: var(--dark-ink); font-size: .9rem; }
.footer-social a:hover span { color: #fff; }

#copyrights {
    margin-top: 3rem; padding: 1.25rem 0;
    border-top: 1px solid rgba(255,255,255,.1);
    font-size: .85rem; color: #98a2ac;
}

/* -----------------------------------------------------------------
   8. Back to top
----------------------------------------------------------------- */
#gotoTop {
    /* Sits above the reCAPTCHA badge, which Google pins to the bottom-right
       and which we cannot move. 5.5rem clears its 60px height plus a gap. */
    position: fixed; right: 1.25rem; bottom: 5.5rem; z-index: 1040;
    width: 2.75rem; height: 2.75rem; border-radius: 50%;
    border: 0; background: var(--brand); color: #fff;
    display: inline-flex; align-items: center; justify-content: center;
    box-shadow: 0 .35rem .9rem rgba(0,0,0,.25);
    opacity: 0; transform: translateY(.5rem);
    transition: opacity .2s ease, transform .2s ease;
}
#gotoTop.show { opacity: 1; transform: translateY(0); }
#gotoTop:hover { background: var(--brand-dark); }

/* -----------------------------------------------------------------
   9. Reveal on scroll (replaces animate.css + the theme's animator)
----------------------------------------------------------------- */
.reveal { opacity: 0; transform: translateY(14px); transition: opacity .5s ease, transform .5s ease; }
.reveal.is-visible { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
    .reveal { opacity: 1; transform: none; }
}

/* -----------------------------------------------------------------
   10. Simple content pages (accessibility statement, etc.)
   The header is fixed and transparent over the hero on the home page;
   on a page with no hero it needs a solid background and the content
   needs to clear it.
----------------------------------------------------------------- */
.page-simple .site-header { background: var(--dark-bg); }
.page-simple #content { padding-top: var(--header-h); }

.page-head { padding-bottom: 1rem; }
.page-head h1 { font-size: clamp(2rem, 1.5rem + 2vw, 3rem); margin: 0; }
.eyebrow {
    color: var(--brand);
    font-size: .8rem; font-weight: 700;
    letter-spacing: .12em; text-transform: uppercase;
    margin-bottom: .35rem;
}

.prose { max-width: 46rem; }
.prose h2 { font-size: 1.35rem; margin: 2.25rem 0 .6rem; }
.prose ul { padding-left: 1.2rem; }
.prose li { margin-bottom: .4rem; }
.prose .lead { font-size: 1.15rem; color: var(--ink); }
