/* ====== v2 COMPONENTS ======
   Anything used on more than one page. Loaded on every page.
   Single-page styles belong in assets/css/pages/<page>.css instead.
*/

/* ── Buttons ─────────────────────────────────────────────────────── */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    padding: var(--space-3) var(--space-5);
    border-radius: var(--radius-pill);
    font-family: var(--font-secondary);
    font-size: var(--t-cta);
    font-weight: var(--fw-regular);
    letter-spacing: var(--ls-cta);
    text-transform: uppercase;
    white-space: nowrap;
    transition: background-color .2s ease, color .2s ease, border-color .2s ease;
}

.btn--primary {
    /* Body: lighter teal at the top, the token teal below; edge light; a
       glow that grows on hover. The most repeated element on the site, so
       its finish sets the page's.                                         */
    background: var(--gloss-sheen), linear-gradient(180deg, #14A898 0%, var(--c-accent-teal) 100%);
    color: var(--c-neutral-cream);
    box-shadow: var(--gloss-edge), 0 4px 14px rgba(0, 150, 136, .28);
    transition: background-color .2s ease, color .2s ease, box-shadow .25s ease;
}
.btn--primary:hover {
    /* Hover is a change of colour, not of height: no lift, and the resting
       shadow stays exactly as it was, so the button does not appear to
       rise off the page.                                                  */
    background: var(--gloss-sheen), linear-gradient(180deg, #C9F5F8 0%, var(--c-accent-cyan) 100%);
    color: var(--c-primary-dark);
    box-shadow: var(--gloss-edge), 0 4px 14px rgba(0, 150, 136, .28);
}

.btn--secondary {
    /* Full-strength cyan outline (as before gloss) and enough fill to sit
       on the lighter grounds — at 3% it vanished into section 5's purple. */
    background: var(--gloss-sheen), rgba(255, 255, 255, .07);
    color: var(--c-neutral-cream);
    border: 1px solid var(--c-accent-cyan);
    box-shadow: var(--gloss-edge), 0 4px 14px rgba(0, 0, 0, .25);
    transition: background-color .2s ease, color .2s ease, box-shadow .25s ease, border-color .2s ease;
}
.btn--secondary:hover {
    background: var(--gloss-sheen), linear-gradient(180deg, #C9F5F8 0%, var(--c-accent-cyan) 100%);
    color: var(--c-primary-dark);
    border-color: var(--c-accent-cyan);
    box-shadow: var(--gloss-edge), var(--gloss-glow);
}

/* ── Navbar ──────────────────────────────────────────────────────── */

.nav {
    position: sticky;
    top: 0;
    z-index: var(--z-nav);
    border-bottom: 1px solid var(--c-border);
}

/* Solid, per the Figma frame (#15001B). An earlier build used a translucent
   backdrop-filter blur here; over the animated hero canvas that blur had to
   re-sample the canvas every frame and dragged the whole page down. Do not
   reintroduce backdrop-filter on anything that overlaps the hero. */
.nav::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: -1;
    background-color: var(--c-nav-bg-solid);
}

.nav__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-8);
    width: 100%;
    max-width: var(--page-max);
    /* Fixed, not min-height: the mobile panel is positioned at exactly
       --nav-height, so the bar must actually be that tall or the panel
       overlaps it. Desktop 80 = 48px logo + 2×16 padding.
       Mobile 76 = 44px hamburger + 2×16. */
    height: var(--nav-height);
    margin-inline: auto;
    padding: var(--space-4) var(--page-gutter);
}

.nav__logo { flex: 0 0 auto; }
.nav__logo img { width: 119px; height: auto; }   /* mobile; 143px at >=1024 */

.nav__desktop { display: none; }        /* mobile base; flex at >=1024 */

/* .nav__cta inherits display:inline-flex from .btn, so it needs an explicit
   mobile rule — the mobile menu has its own CTA at the bottom of the panel. */
.nav__cta     { display: none; }        /* mobile base; inline-flex at >=1024 */

.nav__list {
    display: flex;
    align-items: center;
    gap: var(--space-8);
}

.nav__item { position: relative; }

.nav__link {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding-block: var(--space-3);
    font-family: var(--font-secondary);
    font-size: var(--t-cta);
    letter-spacing: var(--ls-cta);
    text-transform: uppercase;
    color: var(--c-neutral-cream);
    transition: color .2s ease;
    white-space: nowrap;
}
.nav__link:hover { color: var(--c-accent-cyan); }

/* Active page: colour AND an underline, so it does not depend on colour alone. */
.nav__item.is-active > .nav__link {
    color: var(--c-accent-cyan);
}
.nav__item.is-active > .nav__link::after {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: calc(var(--space-3) - 6px);
    height: 2px;
    background-color: var(--c-accent-cyan);
    border-radius: 2px;
}

.nav__chevron { transition: transform .2s ease; flex: 0 0 auto; }
.nav__item.is-open .nav__chevron { transform: rotate(180deg); }

/* ── Desktop dropdown ─────────────────────────────────────────────
   Kept in the DOM and revealed with opacity/visibility rather than display,
   so it can transition and so the hover bridge below works.               */

.nav__menu {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translate(-50%, 6px);
    min-width: 220px;
    padding: var(--space-2);
    background-color: var(--c-nav-dropdown-bg);
    border: 1px solid var(--c-border);
    border-radius: 12px;
    box-shadow: 0 16px 40px rgba(0, 0, 0, .45);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity .18s ease, transform .18s ease, visibility .18s;
}

/* Invisible bridge across the gap, so the menu does not close while the
   pointer travels from the label down to it. */
.nav__item--has-menu::after {
    content: '';
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    height: 10px;
}

.nav__item.is-open > .nav__menu,
.nav__item--has-menu:hover > .nav__menu,
.nav__item--has-menu:focus-within > .nav__menu {
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    transform: translate(-50%, 0);
}

.nav__menu-link {
    display: block;
    padding: var(--space-3) var(--space-4);
    border-radius: 8px;
    font-family: var(--font-secondary);
    font-size: var(--t-p3);
    letter-spacing: var(--ls-cta);
    text-transform: uppercase;
    color: var(--c-neutral-cream);
    white-space: nowrap;
    transition: background-color .15s ease, color .15s ease;
}
.nav__menu-link:hover { background-color: rgba(171, 235, 240, .1); color: var(--c-accent-cyan); }
.nav__menu-link.is-active { color: var(--c-accent-cyan); background-color: rgba(171, 235, 240, .07); }

/* ── Hamburger ───────────────────────────────────────────────────── */

.nav__burger {
    display: flex;          /* mobile base; hidden at >=1024 */
    flex-direction: column;
    justify-content: center;
    gap: 5px;
    width: 44px;
    height: 44px;
    padding: 10px;
}
.nav__burger span {
    display: block;
    height: 2px;
    background-color: var(--c-neutral-cream);
    border-radius: 2px;
    transition: transform .25s ease, opacity .2s ease;
}
.nav__burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav__burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.nav__burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* ── Mobile menu ─────────────────────────────────────────────────── */

.nav__mobile {
    /* Shown by default — this IS the mobile design. [hidden] still wins via the
       !important guard in base.css, so the panel starts closed. */
    display: block;
    position: fixed;
    /* Fills everything below the bar. Deliberately not height:100vh — on mobile
       browsers 100vh includes the address bar and the last items fall off the
       end. inset with a bottom of 0 tracks the real viewport. */
    inset: calc(var(--nav-height) + 1px) 0 0;  /* +1 clears the nav border */
    z-index: var(--z-mobile-menu);
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
    /* Long menus (Products has six children) must scroll, and the last item
       needs clearance above the on-screen keyboard / home indicator. */
    overscroll-behavior: contain;
    padding: var(--space-6) var(--page-gutter) var(--space-16);
    background-color: var(--c-nav-bg-solid);
    border-top: 1px solid var(--c-border);
}

.nav__mobile-list { display: flex; flex-direction: column; }

.nav__mobile-link {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    padding: var(--space-4) 0;
    border-bottom: 1px solid var(--c-border);
    font-family: var(--font-secondary);
    font-size: var(--t-p1);
    letter-spacing: var(--ls-cta);
    text-transform: uppercase;
    color: var(--c-neutral-cream);
    text-align: left;
}
.nav__mobile-link.is-active { color: var(--c-accent-cyan); }
.nav__mobile-link--toggle[aria-expanded="true"] .nav__chevron { transform: rotate(180deg); }

.nav__mobile-sub { padding: var(--space-2) 0 var(--space-3) var(--space-4); }
.nav__mobile-sublink {
    display: block;
    padding: var(--space-3) 0;
    font-family: var(--font-secondary);
    font-size: var(--t-p2);
    letter-spacing: var(--ls-cta);
    text-transform: uppercase;
    color: var(--c-neutral-gray);
}
.nav__mobile-sublink:hover,
.nav__mobile-sublink.is-active { color: var(--c-accent-cyan); }

.nav__mobile-cta { width: 100%; margin-top: var(--space-8); }

/* Menu open: stop the page behind it scrolling. Mobile only in practice,
   but harmless above the breakpoint since the menu cannot open there. */
/* Lock the page while the menu is open. On html, not body: html carries
   overflow-x:clip (base.css), so body's overflow no longer propagates to the
   viewport — a body lock did nothing and, worse, made body a scroll container
   that the sticky nav then stuck to and scrolled away with (phone, 2026-09-17). */
html.nav-open { overflow: hidden; }
/* The panel must itself be scrollable even when its list is short, or iOS
   hands the touch to the page behind. 1px past full height does it; with
   overscroll-behavior:contain (above) the touch never chains out.          */
.nav__mobile > nav { min-height: calc(100% + 1px); }

/* ═══ DESKTOP — 1024 and up ════════════════════════════════════════════
   Everything above is the mobile design. This block only ADDS.
   See tokens.css for the breakpoint rationale.                          */

@media (min-width: 1024px) {
    .nav__logo img { width: 143px; }

    .nav__desktop  { flex: 1 1 auto; display: flex; justify-content: flex-end; }
    .nav__cta      { display: inline-flex; }

    .nav__burger   { display: none; }

    /* Both selectors are needed: .nav__mobile:not([hidden]) above has higher
       specificity than .nav__mobile alone, so matching it is what lets this
       rule win. */
    .nav__mobile,
    .nav__mobile:not([hidden]) { display: none; }
}

/* ── Forms ───────────────────────────────────────────────────────────
   Shared by the contact, demo and careers forms. Labels are visible, not
   placeholders — v1 used placeholder-only fields, which vanish on focus
   and fail WCAG 3.3.2. Mobile-first: one column, two at >=768.         */

.form { display: flex; flex-direction: column; gap: var(--space-5); max-width: 880px; }

.form__row { display: flex; flex-direction: column; gap: var(--space-5); }

.form__field { display: flex; flex-direction: column; gap: var(--space-2); flex: 1 1 0; }

.form__label {
    font-family: var(--font-secondary);
    font-size: var(--t-p3);
    letter-spacing: var(--ls-cta);
    text-transform: uppercase;
    color: var(--c-text-muted);
}
.form__label em    { color: var(--c-accent-cyan); font-style: normal; }
.form__label small { text-transform: none; letter-spacing: 0; opacity: .7; margin-left: var(--space-2); }

/* the required asterisk had no legend anywhere on the form (2026-10-03) */
.form__note    { margin: 0; font-size: var(--t-p3); color: var(--c-text-muted); }
.form__note em { font-style: normal; color: var(--c-accent-cyan); }

.form__input {
    width: 100%;
    padding: var(--space-3) var(--space-4);
    /* Gloss: inputs are recessed — shade along the top edge, light along
       the bottom — the inverse of a raised surface.                       */
    background-color: rgba(0, 0, 0, .18);
    border: 1px solid rgba(171, 235, 240, .16);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, .35), inset 0 -1px 0 rgba(255, 255, 255, .06);
    border-radius: 8px;
    color: var(--c-text);
    font-family: var(--font-primary);
    font-size: var(--t-p2);
    line-height: var(--lh-body);
    transition: border-color .15s ease, background-color .15s ease;
}
.form__input:hover  { border-color: var(--c-accent-band); }
.form__input:focus  { outline: none; border-color: var(--c-accent-cyan); background-color: rgba(0, 0, 0, .22); box-shadow: inset 0 1px 2px rgba(0, 0, 0, .35), var(--gloss-glow); }
.form__input:user-invalid { border-color: var(--accent-neon-red); }

select.form__input {
    appearance: none;
    padding-right: calc(var(--space-4) * 2 + 12px);
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 4.5L6 8l3.5-3.5' fill='none' stroke='%23ABEBF0' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right var(--space-4) center;
}
select.form__input option { background-color: var(--c-primary-dark); }

textarea.form__input { resize: vertical; min-height: 120px; }

.form__input--file { padding: var(--space-2) var(--space-3); cursor: pointer; }
.form__input--file::file-selector-button {
    margin-right: var(--space-3);
    padding: var(--space-2) var(--space-4);
    border: 1px solid var(--c-accent-cyan);
    border-radius: var(--radius-pill);
    background: none;
    color: var(--c-accent-cyan);
    font: inherit;
    font-family: var(--font-secondary);
    font-size: var(--t-p3);
    text-transform: uppercase;
    letter-spacing: var(--ls-cta);
    cursor: pointer;
}

.form__check { display: flex; align-items: flex-start; gap: var(--space-3); font-size: var(--t-p3); color: var(--c-text-muted); cursor: pointer; }
.form__check input { margin-top: 3px; accent-color: var(--c-accent-teal); }

.form__actions { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); margin-top: var(--space-2); }
.form__actions .btn[disabled] { opacity: .6; cursor: wait; }

.form__status { font-size: var(--t-p3); }
/* The success state replaces the form rather than sitting beside it
   (2026-09-25). A reset form under a 14px line read as though nothing had
   happened — and as though it were asking again. The panel keeps its box; what
   was the form becomes the receipt, so there is no ambiguity about whether it
   sent, the reply promise lands where it matters, and the emptied fields are
   gone rather than left staring back. forms.js does the swap. */
.form__done {
    display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-4);
    padding-block: var(--space-6);
}
.form__done__mark {
    position: relative; display: grid; place-items: center;
    width: 56px; height: 56px; border-radius: 50%;
    background: rgba(171, 235, 240, .12);
    box-shadow: inset 0 0 0 1px rgba(171, 235, 240, .45), 0 0 32px rgba(171, 235, 240, .18);
}
.form__done__mark svg { width: 26px; height: 26px; fill: none; stroke: var(--c-accent-cyan); stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.js .form__done__mark svg path { stroke-dasharray: 1; stroke-dashoffset: 1; }
.js .form__done.is-in .form__done__mark svg path { animation: fd-tick .5s ease-out .1s forwards; }
.js .form__done.is-in .form__done__mark { animation: fd-pop .45s cubic-bezier(.2, .7, .2, 1) both; }
@keyframes fd-tick { to { stroke-dashoffset: 0; } }
@keyframes fd-pop  { from { transform: scale(.7); opacity: 0; } to { transform: none; opacity: 1; } }
.form__done h3 { font-size: var(--t-h3); line-height: var(--lh-heading); font-weight: var(--fw-medium); color: var(--c-accent-cyan); }
.form__done p  { font-size: var(--t-p1); line-height: 1.55; color: var(--c-text); max-width: 46ch; }
.form__done a  { color: var(--c-accent-highlight); }
.form__done .btn { margin-top: var(--space-2); }
.form__done:focus { outline: none; }   /* focus is moved here for screen readers, not to draw a ring */
@media (prefers-reduced-motion: reduce) { .js .form__done__mark svg path { stroke-dashoffset: 0; } }
.form__status.is-ok      { color: var(--c-accent-cyan); }
.form__status.is-error   { color: var(--accent-neon-red); }
.form__status.is-pending { color: var(--c-text-muted); }

@media (min-width: 768px) {
    .form__row { flex-direction: row; gap: var(--space-8); }
}

/* ── Footer ──────────────────────────────────────────────────────────
   From the Figma Home frame. Mobile: everything stacks. Desktop (1024+):
   tagline | four columns | LinkedIn on one row, then the legal row.      */

.footer {
    padding-block: var(--space-10) var(--space-5);
    background-color: var(--c-neutral-darkbg);
    border-top: 1px solid var(--c-border);
}

.footer__top {
    display: flex;
    flex-direction: column;
    gap: var(--space-8);
    padding-bottom: var(--space-8);
    border-bottom: 1px solid rgba(171, 235, 240, .25);   /* Figma: cyan at 25% */
}

.footer__tagline {
    max-width: 354px;                  /* Figma text box width */
    font-size: var(--t-p1);
    line-height: var(--lh-body);
    color: var(--c-accent-pink);
}

.footer__nav {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: var(--space-8) var(--space-6);
}
.footer__col ul { display: flex; flex-direction: column; gap: var(--space-3); }
.footer__heading {
    margin-bottom: var(--space-3);
    font-size: var(--t-h5);
    line-height: var(--lh-heading);
    font-weight: var(--fw-regular);
    color: var(--c-accent-band);
}
.footer__col a { font-size: var(--t-p2); color: var(--c-text); }
.footer__col a:hover { color: var(--c-accent-cyan); }

.footer__social { display: inline-flex; color: var(--c-text); }
.footer__social:hover { color: var(--c-accent-cyan); }

.footer__bottom {
    display: flex;
    flex-direction: column;
    gap: var(--space-3);
    padding-top: var(--space-5);
    font-size: var(--t-p3);
    color: var(--c-text-on-dark);
}
/* the legal name and the office address travel together as one block, so the
   bottom row stays two things wide however many lines the address runs to */
.footer__who { display: flex; flex-direction: column; gap: var(--space-2); }
.footer__address { font-style: normal; line-height: 1.55; color: rgba(255, 249, 245, .6); }   /* <address> is italic by default */
.footer__legal { display: flex; gap: var(--space-10); }
.footer__legal a { color: inherit; }
.footer__legal a:hover { color: var(--c-accent-cyan); }

@media (min-width: 768px) {
    .footer__nav { grid-template-columns: repeat(4, auto); gap: var(--space-8) var(--space-15); }
    .footer__bottom { flex-direction: row; justify-content: space-between; align-items: flex-start; gap: var(--space-8); min-height: 64px; padding-top: var(--space-6); }
}

@media (min-width: 1024px) {
    .footer { padding-block: var(--space-15) var(--space-5); }
    .footer__top { flex-direction: row; justify-content: space-between; align-items: flex-start; gap: var(--space-16); }
    .footer__nav { justify-content: flex-end; }
}

/* ── Scroll reveal ───────────────────────────────────────────────────
   Initial hidden state applies ONLY under html.js (set inline in head.php
   before any CSS loads). If JS never runs, nothing is ever hidden — the
   opposite failure mode to the July 2026 outage.                          */

/* Below 768 the sideways reveals travel 16px, not 50: an element waiting to
   reveal from the left would otherwise sit 30px past the 20px gutter, and
   Android Chrome lets a finger pan into that even with the root clipped.  */
@media (max-width: 767px) { :root { --reveal-x: 16px; } }
.js [data-reveal] {
    opacity: 0;
    transition: opacity .6s cubic-bezier(.25, .46, .45, .94), transform .6s cubic-bezier(.25, .46, .45, .94);
    /* No will-change here. Pre-promoting 24 layers and then demoting them the
       instant the transition starts made every reveal begin with a hitch. */
}
.js [data-reveal="up"]    { transform: translateY(50px); }
.js [data-reveal="left"]  { transform: translateX(var(--reveal-x, 50px)); }
.js [data-reveal="right"] { transform: translateX(calc(var(--reveal-x, 50px) * -1)); }
.js [data-reveal].is-visible { opacity: 1; transform: none; }

/* ── CTA band ────────────────────────────────────────────────────────
   From the Home frame; includes/cta-band.php. Black, gradient-bar art on
   the right, centred heading + primary button.                          */

.cta {
    position: relative; min-height: 414px; display: flex; align-items: center;
    background:
        linear-gradient(180deg, rgba(255, 255, 255, .04) 0%, rgba(255, 255, 255, 0) 30%),   /* gloss: light from above */
        url('../images/home/cta-art.svg') right center / auto 100% no-repeat,
        var(--c-neutral-darkbg);
}
.cta__inner { display: flex; flex-direction: column; align-items: center; gap: var(--space-5); text-align: center; }
.cta h2 { max-width: 1110px; }
@media (min-width: 1024px) { .cta__inner { padding-block: var(--space-16); } }

/* ── Panel ───────────────────────────────────────────────────────────
   A raised card for forms and grouped content. Same surface as the AVI-OS
   text panel on Home.                                                    */
.panel {
    padding: var(--space-6);
    border: 1px solid rgba(171, 235, 240, .16);
    border-radius: var(--radius-card);
    background: var(--gloss-sheen), var(--c-bg-raised);
    box-shadow: var(--gloss-edge), 0 20px 60px rgba(0, 0, 0, .35);
}
@media (min-width: 768px) { .panel { padding: var(--space-10); } }
