
    /* ================== brand palette (P2) ================================
     * ONE place to change the brand blue for every page that loads this file.
     *
     *   --brand       #137FEC   use as `color: var(--brand)`
     *   --brand-rgb   19,127,236  only for alpha mixes:
     *                            `rgba(var(--brand-rgb), .95)`
     *
     * Why this exists: the brand blue used to be hard-coded ~40 times across
     * page-level <style> blocks, so a brand change meant grepping the whole
     * template tree and hoping nothing was missed (a miss fails SILENTLY).
     * Consume the token, never re-type the hex.
     *
     * Scope note: two STANDALONE landing pages (`gas.html`, `hdp.html`) ship
     * their own full <html> document and define their own --brand (#3b82f6,
     * a Tailwind blue) — they do NOT include this file, so there is no
     * override today. If one of them ever starts including head_base, its
     * local --brand must be renamed first, or these pages will silently
     * repaint.
     * ==================================================================== */
    :root {
        --brand: #137FEC;
        --brand-rgb: 19, 127, 236;
        --brand-dark: #0e62b8;   /* hover / pressed shade of the brand blue */
    }

    body {
        scroll-behavior: smooth;
    }

    .max-w-\[1440px\] {
        max-width: 1700px !important;
    }

    @media (min-width: 1024px) {
        .lg\:grid-cols-4-expanded {
            grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
        }
    }

    .header-sticky {
        position: sticky;
        top: 0;
        z-index: 1000;
        background-color: #ffffff;
    }

    .dropdown:hover .dropdown-menu {
        display: block;
    }

    .whatsapp-pulse {
        display: none !important;
    }

    .scrollbar-hide::-webkit-scrollbar {
        display: none;
    }

    .scrollbar-hide {
        -ms-overflow-style: none;
        scrollbar-width: none;
    }

    /* ================== hover-fill tokens =================================
     * Two hover-fill effects live here, sharing ONE token vocabulary:
     *   .ball-fill   the round badge at the right edge expands to fill
     *   .disc-rise   a disc rises from the bottom and fills
     * Both are pure MECHANICS: colour belongs to the button.
     *
     *   --fill-bg          rest background            (ball #18181b / disc #ffffff)
     *   --fill-text        rest label colour          (ball #ffffff / disc #1c1e21)
     *   --fill-border      rest border colour         (ball = --fill-bg / disc #1c1e21)
     *   --fill-shape       ball+disc colour = hover fill      <<< THE knob
     *   --fill-text-hover  label colour once filled   (both #ffffff)
     *   --fill-ball-bg     the ball's resting disc    (.ball-fill only)
     *   --fill-icon        arrow colour at rest       (.ball-fill only)
     *   --fill-icon-hover  arrow colour once filled   (.ball-fill only)
     *
     * Colour belongs to the BUTTON. Prefer a SKIN class over inline tokens
     * (skins are defined at the end of this section, after the effects they
     * drive — source order matters, see the note there):
     *   <a class="ball-fill skin-ink-blue">                   <- the whole recipe
     *   <a class="ball-fill skin-ink-blue"
     *      style="--fill-shape:#ff0000">                     <- one-off tweak wins
     * ====================================================================== */
    .ball-fill {
        --icon-circle: 2rem;
        --icon-right: 0.5rem;
        --icon-size: 1rem;
        --pad-right: calc(var(--icon-circle) + var(--icon-right) + 0.75rem);
        --circle-inset-y: calc((100% - var(--icon-circle)) / 2);
        --circle-inset: var(--circle-inset-y) var(--icon-right) var(--circle-inset-y) calc(100% - var(--icon-right) - var(--icon-circle));
        --fill-ball-bg: #ffffff;   /* the ball's resting disc */
        --fill-icon: #ffffff;      /* arrow colour at rest */
        --fill-icon-hover: #ffffff;/* arrow colour once filled */

        position: relative;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        height: 2.75rem;
        padding-left: 1.75rem;
        padding-right: var(--pad-right);
        border-radius: 9999px;
        background-color: var(--fill-bg, #18181b);
        border: 1px solid var(--fill-bg, #18181b);
        color: var(--fill-text, #ffffff);
        font-weight: 700;
        font-size: 14px;
        line-height: 1;
        overflow: hidden;
        white-space: nowrap;
        cursor: pointer;
        transition: background-color 450ms cubic-bezier(0.785, 0.135, 0.15, 0.86),
                    border-color 450ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
    }
    .ball-fill__label {
        position: relative;
        z-index: 1;
        margin-right: 0.5rem;
    }
    .ball-fill__fill {
        position: absolute;
        z-index: 2;
        border-radius: 9999px;
        background-color: var(--fill-ball-bg, #ffffff);
        inset: var(--circle-inset);
        transition: inset 450ms cubic-bezier(0.785, 0.135, 0.15, 0.86),
                    background-color 450ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
        pointer-events: none;
    }
    .ball-fill__clip {
        position: absolute;
        inset: 0;
        z-index: 2;
        display: flex;
        align-items: center;
        padding-left: 1.75rem;
        padding-right: var(--pad-right);
        color: var(--fill-text-hover, #ffffff);
        clip-path: inset(var(--circle-inset));
        transition: clip-path 450ms cubic-bezier(0.785, 0.135, 0.15, 0.86),
                    color 450ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
        pointer-events: none;
    }
    .ball-fill__icon {
        position: absolute;
        right: var(--icon-right);
        top: 50%;
        z-index: 3;
        display: inline-flex;
        height: var(--icon-circle);
        width: var(--icon-circle);
        transform: translateY(-50%);
        align-items: center;
        justify-content: center;
        overflow: hidden;
        border-radius: 9999px;
        background-color: var(--fill-ball-bg, #ffffff);
        color: var(--fill-icon);
        flex-shrink: 0;
        -webkit-mask-image: -webkit-radial-gradient(white, black);
                mask-image: radial-gradient(white, black);
        transition: background-color 450ms cubic-bezier(0.785, 0.135, 0.15, 0.86),
                    color 450ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
        pointer-events: none;
    }
    .ball-fill__arrow {
        position: absolute;
        left: 50%;
        top: 50%;
        height: var(--icon-size);
        width: var(--icon-size);
        color: currentColor;
        transition: transform 450ms cubic-bezier(0.785, 0.135, 0.15, 0.86);
    }
    .ball-fill__arrow--in { transform: translate(-170%, -50%) scale(0); }
    .ball-fill__arrow--out { transform: translate(-50%, -50%) scale(1); }

    /* Stretched variant (.ball-fill--wide) — for any button wider than its
     * own content (product-page CTA = w-1/2; earlier a full-width flex-1).
     * The effect assumes an auto-width pill: its padding-left (1.75rem) and
     * padding-right (--pad-right) are tuned so the centred resting label and the
     * clip's copy land on the same x. Stretch the button and the resting label
     * centres while the clip stays flex-start -> the label visibly jumps on
     * hover. Forcing the clip to centre restores the match: both boxes share
     * the button's padding box, so the two labels coincide. */
    .ball-fill--wide .ball-fill__clip { justify-content: center; }

    .ball-fill:hover .ball-fill__fill,
    .ball-fill[data-pressed="true"] .ball-fill__fill {
        inset: 0;
        background-color: var(--fill-shape, var(--brand));
    }
    .ball-fill:hover .ball-fill__clip,
    .ball-fill[data-pressed="true"] .ball-fill__clip {
        clip-path: inset(0 0 0 0);
        color: var(--fill-text-hover, #ffffff);
    }
    .ball-fill:hover .ball-fill__icon,
    .ball-fill[data-pressed="true"] .ball-fill__icon {
        background-color: var(--fill-shape, var(--brand));
        color: var(--fill-icon-hover, #ffffff);
    }
    .ball-fill:hover .ball-fill__arrow--in,
    .ball-fill[data-pressed="true"] .ball-fill__arrow--in {
        transform: translate(-50%, -50%) scale(1);
    }
    .ball-fill:hover .ball-fill__arrow--out,
    .ball-fill[data-pressed="true"] .ball-fill__arrow--out {
        transform: translate(70%, -50%) scale(0);
    }
    @media (prefers-reduced-motion: reduce) {
        .ball-fill, .ball-fill__fill, .ball-fill__clip, .ball-fill__icon, .ball-fill__arrow {
            transition: none !important;
        }
    }

    /* ---------- WhatsApp "Continue to WhatsApp Web" hover fill (.disc-rise) ----
     * Faithful replica of the api.whatsapp.com CTA: a dark disc rises from the
     * bottom, swells 1.47x, and fills the pill while the label flips to white.
     * Geometry is tuned for a ~48px-tall pill (h-12). Replaces the retired
     * radial-gradient `.fill-rise` effect (deleted 2026-09-18, was orphaned);
     * any `.open-quote-btn` behaviour is kept.
     * ----------------------------------------------------------------------- */
    .disc-rise {
        --fill-shape: #1c1e21;      /* disc colour = hover fill  [THE knob] */
        --fill-bg: #ffffff;         /* rest background */
        --fill-text: #1c1e21;       /* rest label colour */
        --fill-border: #1c1e21;     /* rest border colour */
        --fill-text-hover: #ffffff; /* label colour once filled */

        position: relative;
        z-index: 1;
        display: inline-flex;
        align-items: center;
        justify-content: center;
        box-sizing: content-box;
        padding: 16px 32px;
        border: 1px solid var(--fill-border);
        border-radius: 9999px;
        background-color: var(--fill-bg);
        color: var(--fill-text);
        font-size: 16px;
        font-weight: 500;
        line-height: 16px;
        white-space: nowrap;
        text-decoration: none;
        overflow: hidden;                 /* clips the rising disc into the pill */
        cursor: pointer;
        -webkit-tap-highlight-color: transparent;
        /* colour swap lags the disc: text flips white only once the disc covers it.
           Speed unified with .disc-rise--sm (product-card CTA): disc 0.4s, text 0.25s. */
        transition:
            color 0.2s linear 0.25s,
            border-color 0.3s ease-out,
            background-color 0.2s linear;
    }
    .disc-rise::after {
        content: "";
        position: absolute;
        top: 0;
        left: 0;
        width: 100%;
        min-width: 167px;
        height: 167px;
        background-color: var(--fill-shape);
        border-radius: 50%;
        z-index: -1;
        transform: scale(1) translateY(67px);   /* parked just below the pill */
        transition: transform 0.4s cubic-bezier(0.66, 0, 0.34, 1);
    }
    .disc-rise:hover,
    .disc-rise:focus-visible {
        background-color: var(--fill-shape);
        border-color: var(--fill-shape);   /* border melts into the fill (as before) */
        color: var(--fill-text-hover);
        transition-delay: 0.25s;
    }
    .disc-rise:hover::after,
    .disc-rise:focus-visible::after {
        transform: scale(1.47) translateY(0);   /* glides up + swells to fill */
    }
    @media (prefers-reduced-motion: reduce) {
        .disc-rise, .disc-rise::after { transition: none !important; }
    }

    /* Smaller + faster variant for product-card CTAs (View Details).
       Overrides geometry/transition only — never touches the shared text-CTA
       (.disc-rise used by Book a Factory Visit). Disc is parked deeper and
       smaller so the rise still reads on a ~32px pill. */
    .disc-rise--sm {
        padding: 11px 24px;
        font-size: 12px;
        line-height: 12px;
        transition:
            color 0.2s linear 0.25s,
            border-color 0.3s ease-out,
            background-color 0.2s linear;
    }
    .disc-rise--sm::after {
        height: 120px;
        min-width: 120px;
        transform: scale(1) translateY(50px);          /* hidden below the small pill */
        transition: transform 0.4s cubic-bezier(0.66, 0, 0.34, 1);
    }
    .disc-rise--sm:hover,
    .disc-rise--sm:focus-visible {
        transition-delay: 0.25s;
    }
    .disc-rise--sm:hover::after,
    .disc-rise--sm:focus-visible::after {
        transform: scale(1.47) translateY(0);          /* rises + swells to fill */
    }

    /* WhatsApp disc-rise, adapted for the circular floating action buttons
     * (.action-btn in fixed_action.html). Reuses the same dark-disc mechanic
     * but keeps the 52x52 circle + blue base from .action-btn; only the fill
     * is added. The material-symbol icon stays white on top. */
    .disc-rise--fab {
        --fill-shape: var(--brand);  /* disc colour = hover fill */
        --fill-bg: #111827;         /* the button's OWN rest background */
        position: relative;
        z-index: 1;
        overflow: hidden;                 /* clip the rising disc to the circle */
    }
    .disc-rise--fab::after {
        content: "";
        position: absolute;
        left: 50%;
        bottom: 0;
        width: 260%;
        height: 260%;
        background-color: var(--fill-shape);
        border-radius: 50%;
        z-index: -1;
        transform: translateX(-50%) translateY(100%);   /* parked below the circle */
        transition: transform 0.6s cubic-bezier(0.66, 0, 0.34, 1);
    }
    .disc-rise--fab:hover::after,
    .disc-rise--fab:focus-visible::after {
        transform: translateX(-50%) translateY(0);     /* rises to fill the circle */
    }
    /* Lock the button's OWN background across all states so .action-btn:hover
     * (which would snap the whole button to blue) can't fire first — only the
     * disc (--fill-shape) should visibly change colour.
     * Rest colour comes from the token, not a literal: override it inline with
     *   style="--fill-bg:#0b1220"   (dark base -> brand-blue rise, the default)
     *   style="--fill-bg:#ffffff;--fill-shape:#111827"   (white base -> dark rise) */
    .action-btn.disc-rise--fab,
    .action-btn.disc-rise--fab:hover,
    .action-btn.disc-rise--fab:focus-visible {
        background-color: var(--fill-bg, #111827) !important;
    }
    @media (prefers-reduced-motion: reduce) {
        .disc-rise--fab::after { transition: none !important; }
    }

    /* ================== hover-fill skins ==================================
     * A skin is ONE class carrying a whole colour recipe, so a button never
     * repeats --fill-* tokens inline:
     *   <a class="ball-fill skin-ink-blue">            <- recipe, edit ONE place
     *   <a class="ball-fill skin-ink-blue"
     *      style="--fill-shape:#ff0000">              <- per-button tweak wins
     *
     * WHY THIS SITS AT THE END OF THE SECTION: .ball-fill and .disc-rise
     * declare their own token defaults at the SAME specificity (a single
     * class). When both match the element, SOURCE ORDER decides — a skin
     * placed before them would be silently overridden by the effect's
     * defaults. Always append new skins below the effects, never above.
     * ====================================================================== */

    /* Dark pill, white ball + black arrow  ->  brand-blue fill.
       The site's default CTA recipe: View All Products / News Center /
       View Products / Contact Experts (both headers) / Get Started
       (products/show.html, half-width + centred). */
    .skin-ink-blue {
        --fill-bg: #18181b;
        --fill-text: #ffffff;
        --fill-border: #18181b;
        --fill-ball-bg: #ffffff;
        --fill-icon: #000000;
        --fill-icon-hover: #ffffff;
        --fill-shape: var(--brand);   /* = #137FEC, now driven by the P2 token */
        --fill-text-hover: #ffffff;
    }
    /* NOTE: header-transparent.html pairs this skin with .ht-cta, whose own
       !important rules paint the pill glassy. There the skin only drives the
       ball / arrow / fill colours — --fill-bg stays inert on purpose. */

    /* [removed 2026-09-18] `.skin-teal` — the deep-teal recipe used by the
       product-page CTA. That button now wears the site-standard
       .skin-ink-blue (black rest -> brand-blue fill) instead, which left
       .skin-teal with zero consumers, so it was deleted rather than kept as
       an orphan (same call made for .fill-rise). Bring it back HERE — i.e.
       below the effects — if a teal CTA ever returns:
         --fill-bg:#004e51  --fill-text:#fff  --fill-border:#004e51
         --fill-ball-bg:#fff  --fill-icon:#004e51  --fill-icon-hover:#fff
         --fill-shape:#003d3f  --fill-text-hover:#fff */

    /* ---------- Search trigger (.rsb) + dropdown (.rs-search-panel) ------
     * Pattern replicated from brightsign.biz (header-search-replica.html,
     * decompiled from their live theme v3.8.9): clicking the magnifier slides
     * a full-width panel down from under the header with one large centred
     * field — replacing the old pill that grew leftwards over the nav.
     * ADAPTED, not copied verbatim:
     *   - brightsign's desktop overlay COVERS the masthead; ours hangs BELOW
     *     it (absolute top:100% of the sticky header), so the language button
     *     and Contact Experts stay visible and usable while searching.
     *   - colours ride the site tokens (--brand / --brand-dark), not their
     *     purple; the field grey is re-toned to our slate scale.
     * Hand-written CSS on purpose: tailwind-compiled.css is a PRE-COMPILED
     * build, so these classes do not exist in it and must live here.
     * ---------------------------------------------------------------- */
    .rsb {
        position: relative;
        z-index: 1003;
        flex: 0 0 40px;
        width: 40px;
        height: 40px;
    }

    /* The toggle lives INSIDE the shared grey pill (.rs-search-shell), so it
       carries no border/background of its own — otherwise you get a visible
       "pill inside a pill". It only lifts on hover, like the language button. */
    .rsb-toggle {
        position: absolute;
        inset: 0;
        z-index: 3;
        display: flex;
        align-items: center;
        justify-content: center;
        width: 40px;
        height: 40px;
        padding: 0;
        border: 0;
        border-radius: 9999px;
        background: transparent;
        color: #6b7280;
        cursor: pointer;
        transition: background-color .2s ease, color .2s ease, box-shadow .2s ease;
    }

    .rsb-toggle:hover {
        background: #ffffff;
        color: #111827;
        box-shadow: 0 1px 2px 0 rgba(0, 0, 0, .05);
    }

    .rsb-ico { line-height: 1; }

    /* The dropdown hangs off the sticky header's bottom edge. max-height (not
       height) animates the slide-down without measuring anything in JS: CSS
       owns the animation, JS only flips classes — the same contract the
       brightsign original uses (.search-open + .toggled). */
    .rs-search-panel {
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        z-index: 999;
        background: #ffffff;
        border-bottom: 1px solid #e5e7eb;
        box-shadow: 0 30px 50px -30px rgba(11, 18, 32, .28);
        overflow: hidden;
        max-height: 0;
        opacity: 0;
        visibility: hidden;
        transition: max-height .32s ease-in-out, opacity .22s ease,
                    visibility 0s linear .32s;
    }

    .rs-search-panel.is-open {
        max-height: 200px;
        opacity: 1;
        visibility: visible;
        transition: max-height .32s ease-in-out, opacity .22s ease;
    }

    .rs-search-inner {
        max-width: 860px;
        margin: 0 auto;
        /* Right padding reserves the round close button, brightsign-style. */
        padding: 48px 96px 52px 24px;
        display: flex;
        align-items: center;
    }

    .rs-search-form {
        display: flex;
        align-items: center;
        gap: 16px;
        flex: 1 1 auto;
        min-width: 0;
    }

    .rs-search-input {
        flex: 1 1 auto;
        min-width: 0;
        height: 50px;
        padding: 0 20px;
        border: 2px solid var(--brand);
        border-radius: 12px;
        background-color: #ffffff;
        font-size: 20px;
        font-weight: 600;
        color: #111827;
        text-align: center;   /* brightsign signature: the input sits centred */
        outline: none;
        transition: border-color .2s ease, box-shadow .2s ease;
    }

    .rs-search-input::placeholder { color: #94a3b8; font-weight: 600; }

    /* Focus deepens the edge instead of recolouring the fill — the white field
       stays white, only the ring answers the interaction. */
    .rs-search-input:focus {
        border-color: var(--brand-dark);
        box-shadow: 0 0 0 3px rgba(19, 127, 236, .18);
    }

    .rs-search-submit {
        flex: 0 0 auto;
        border: 0;
        border-radius: 14px 0 14px 0;   /* brightsign's notched pill corner */
        background-color: var(--brand);
        color: #ffffff;
        padding: 15px 26px;
        font-size: 13px;
        font-weight: 700;
        text-transform: uppercase;
        letter-spacing: .04em;
        cursor: pointer;
        transition: background-color .2s ease;
    }

    .rs-search-submit:hover { background-color: var(--brand-dark); }

    .rs-search-close {
        flex: 0 0 auto;
        width: 50px;
        height: 50px;
        margin-left: 20px;
        display: flex;
        align-items: center;
        justify-content: center;
        border: 2px solid var(--brand);
        border-radius: 50%;
        background: transparent;
        color: var(--brand);
        cursor: pointer;
        transition: background-color .2s ease, color .2s ease;
    }

    .rs-search-close:hover { background-color: var(--brand); color: #ffffff; }

    /* Narrow screens (phones): the language + search pill is hidden entirely
       (same breakpoint that hides "Contact Experts", 640px), so the dropdown
       can never be triggered — belt-and-braces display:none keeps it that way
       even if a stray .is-open lands on it.
       Hand-written media query on purpose — do NOT use Tailwind responsive
       utilities here: tailwind-compiled.css is a PRECOMPILED artifact missing
       many of them (.sm\:block is absent), which silently breaks the layout. */
    @media (max-width: 639px) {
        .rs-search-shell { display: none; }
        .rs-search-panel { display: none; }
    }

    @media (prefers-reduced-motion: reduce) {
        .rsb-toggle,
        .rs-search-panel { transition: none !important; }
    }

    /* ================= Certifications wall (cert.html) ====================
     * cert.html is shared by every PC page that shows the certificate strip.
     * WHY HAND-WRITTEN: `grayscale-[80%]` is NOT in tailwind-compiled.css, so
     * the wall was rendering in FULL COLOUR while `group-hover:grayscale-0`
     * (which IS present) had nothing left to undo — the hover cue was dead too.
     * Card radius/border live here as well so the 6-up grid speaks the same
     * rounded-2xl + slate-200 language as the rest of the site.
     * ------------------------------------------------------------------- */
    .cert-card {
        border: 1px solid #e2e8f0;
        border-radius: 16px;
        transition: border-color .35s ease, box-shadow .35s ease;
    }
    .cert-card:hover {
        border-color: var(--brand);
        box-shadow: 0 26px 50px -22px rgba(15, 30, 56, .30);
    }
    .cert-shot {
        background-color: #f8fafc;
    }
    .cert-img {
        filter: grayscale(.85);
        opacity: .84;
        transition: filter .4s ease, opacity .4s ease;
    }
    .cert-card:hover .cert-img {
        filter: grayscale(0);
        opacity: 1;
    }
    /* Swipe affordance: was Tailwind's blue-600, off the brand ramp. */
    .cert-hint {
        background-color: rgba(19, 127, 236, .62);
        border-radius: 9999px;
    }
    @media (prefers-reduced-motion: reduce) {
        .cert-card,
        .cert-img { transition: none !important; }
    }

    /* ================== Display-panel frame (.screen-frame) ===============
     * The "this is a monitor, not a video card" treatment: SQUARE corners plus
     * a heavy ink bezel around 16:9 footage, so the clip reads as a screen
     * playing. Ink = #0b1220, the darkest surface token on the site.
     *
     * WHY HAND-WRITTEN: the first version of this card asked for
     * `rounded-[2.5rem]` and `shadow-[0_30px_60px_rgba(...)]` — BOTH are absent
     * from tailwind-compiled.css, so it shipped with square corners that
     * happened to look right and NO shadow at all while the source claimed
     * otherwise. Geometry lives here rather than trusting arbitrary-value
     * utilities to exist.
     *
     * SHARED ON PURPOSE (was .oem-media-card, page-local): both
     * company/oem.html (hero, with the stats strip laid over the screen) and
     * solutions/high-brightness.html (Factory Tour) wear it. One bezel knob
     * means the two screens can never drift apart.
     *
     * Usage: pair with `relative overflow-hidden aspect-video`, and put a
     * `w-full h-full object-cover` video inside. Override --bezel per instance
     * for a chunkier or slimmer frame.
     * ------------------------------------------------------------------- */
    .screen-frame {
        --bezel: 14px;
        border-radius: 0;
        border: var(--bezel) solid #0b1220;
        background-color: #0b1220;
        box-shadow:
            0 44px 84px -28px rgba(11, 18, 32, .46),
            0 14px 30px -16px rgba(11, 18, 32, .30);
    }

    /* ================== Briefing-document form card (.brief-*) ============
     * The "inquiry card that looks like a document open in a browser window":
     * chrome bar with three traffic dots + a letter-spaced label, rounded
     * slate fields, and a black pill whose brand-blue disc rises on hover.
     *
     * SHARED ON PURPOSE (was oem-page-local `.oem-form-card` / `.oem-submit`
     * / `.dot-gray`): company/oem.html (sec7) and quoteModal2.html (worn by
     * solutions/high-brightness.html) both wear it, and company/contact.html
     * already draws the same chrome dots page-locally — it can migrate here
     * later. One recipe means the three cannot drift apart.
     *
     * WHY HAND-WRITTEN: the field skin is a full recipe (border + radius +
     * tinted background + focus ring), not something the precompiled
     * tailwind build can be trusted to reassemble per page.
     *
     * Markup contract:
     *   <div class="brief-card">
     *     <div class="brief-bar">
     *       <div class="brief-dots"><span class="brief-dot"></span> x3</div>
     *       <span class="brief-bar__label">Project Briefing Document</span>
     *     </div>
     *     <form class="brief-form ...">
     *       <label class="brief-label">Name *</label>
     *       <input class="brief-field" ...>          (textarea/select too)
     *       <button class="brief-submit disc-rise skin-ink-blue">
     * ------------------------------------------------------------------- */
    .brief-card {
        width: 100%;
        background-color: #ffffff;
        border: 1px solid #e2e8f0;
        border-radius: 40px;
        box-shadow: 0 25px 50px -12px rgba(0, 0, 0, .25);
        overflow: hidden;
    }
    .brief-bar {
        display: flex;
        align-items: center;
        justify-content: space-between;
        gap: 16px;
        padding: 20px;
        background-color: rgba(248, 250, 252, .8);
        -webkit-backdrop-filter: blur(12px);
        backdrop-filter: blur(12px);
        border-bottom: 1px solid #e2e8f0;
    }
    .brief-dots {
        display: flex;
        align-items: center;
        gap: 8px;
        flex-shrink: 0;
    }
    .brief-dot {
        display: block;
        width: 12px;
        height: 12px;
        border-radius: 9999px;
        background-color: #94a3b8;
        transition: background-color .25s ease-out;
    }
    .brief-card:hover .brief-dot:nth-child(1) { background-color: #ff5f56; }
    .brief-card:hover .brief-dot:nth-child(2) { background-color: #ffbd2e; }
    .brief-card:hover .brief-dot:nth-child(3) { background-color: #27c93f; }
    .brief-bar__label {
        font-size: 10px;
        font-weight: 900;
        color: #94a3b8;
        text-transform: uppercase;
        letter-spacing: .4em;
        text-align: right;
    }
    .brief-form {
        position: relative;
        padding: 24px;
    }
    @media (min-width: 768px) {
        .brief-form { padding: 40px; }
    }
    .brief-label {
        display: block;
        font-size: 13px;
        font-weight: 600;
        color: #64748b;
        margin-bottom: 4px;
    }
    .brief-field {
        display: block;
        width: 100%;
        height: 56px;
        box-sizing: border-box;
        padding: 0 20px;
        font-size: 14px;
        color: #0f172a;
        background-color: rgba(248, 250, 252, .3);
        border: 1px solid #e2e8f0;
        border-radius: 16px;
        outline: none;
        transition: background-color .25s ease, border-color .25s ease, box-shadow .25s ease;
    }
    textarea.brief-field {
        height: auto;
        padding: 20px;
        line-height: 1.625;
        resize: vertical;
    }
    select.brief-field {
        appearance: none;
        -webkit-appearance: none;
        cursor: pointer;
        padding-right: 48px;
        background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
        background-repeat: no-repeat;
        background-position: right 20px center;
    }
    .brief-field::placeholder { color: #94a3b8; opacity: 1; }
    /* Element-qualified on purpose: beats the build's [type=text]:focus blue
       ring at equal-or-higher specificity regardless of source order. */
    input.brief-field:focus,
    textarea.brief-field:focus,
    select.brief-field:focus {
        background-color: #ffffff;
        border-color: transparent;
        box-shadow: 0 0 0 2px #0f172a;
        outline: none;
    }
    /* Submit pill: GEOMETRY only (must out-order .disc-rise's own padding /
       font-size, which it does by sitting later in this file). Colour comes
       from .skin-ink-blue, never from here — a --fill-* token declared in a
       page <style> block would permanently silence the skin. box-sizing is
       forced to border-box: .disc-rise ships content-box (its disc-parking
       maths assume it there), which would silently turn any width utility
       into width + 2 x padding. */
    .brief-submit {
        box-sizing: border-box;
        padding: 15px 44px;
        font-size: 14px;
        line-height: 14px;
        font-weight: 700;
        box-shadow: 0 22px 40px -24px rgba(15, 30, 56, .62);
    }

    /* ================= Modal scroll-lock (quoteModal + langModal) =========
     * THE BUG THIS KILLS: opening a modal set body overflow to hidden, which
     * removes the page scrollbar (~15px on Windows Chrome). Every in-flow box
     * instantly became 15px wider, so the whole page — sticky header included —
     * lurched sideways on open and lurched back on close.
     *
     * THE FIX IS ONE DECLARATION: `scrollbar-gutter: stable` reserves the
     * scrollbar's space for as long as the lock is on, so the layout viewport
     * never changes width. Driven by the .rs-lock class (added by main-v3.js)
     * instead of living here permanently, so a short page never carries an
     * empty gutter when nothing is open.
     *
     * MEASURED, headed Chrome 1440px, quoting the CTA modal (all values px):
     *                     in-flow width   header CTA x   FAB x   modal card x
     *   closed                  1425          1176.7      1366      272.5
     *   old code (no gutter)    1440          1191.7      1381      280.0   <- the lurch
     *   .rs-lock                1425          1176.7      1366      272.5   <- exact
     * So the lock restores every box to its closed position, including the
     * modal card itself.
     *
     * WHY THERE IS NO FIXED-ELEMENT COMPENSATION HERE: an earlier revision also
     * padded the overlays by the scrollbar width, on the assumption that
     * position:fixed boxes are laid out against clientWidth. The measurement
     * above disproves it — fixed boxes track innerWidth, which the scrollbar
     * never changes (FAB x is 1366 in every state). The extra padding did not
     * compensate for anything; it just pushed the centred panel 7.5px off
     * centre. Removed.
     *
     * Only Chrome 94+ / Firefox 97+ / Safari 18.2+ honour scrollbar-gutter.
     * Everything older quietly keeps the old lurch — degraded, not broken.
     * ------------------------------------------------------------------- */
    html.rs-lock {
        scrollbar-gutter: stable;
    }
    html.rs-lock body {
        overflow: hidden;
    }

    /* ================= Language picker (.lang-*, langModal.html) ==========
     * langModal.html is included from footer.html on every PC page, right next
     * to quoteModal.html. The language table lives in THAT markup and nowhere
     * else — main-v3.js reads it to highlight the stored language and to mirror
     * the chosen flag into the header button, so there is no second copy to
     * drift. Switching the page is still doTranslate()'s job (translate.js).
     *
     * HAND-WRITTEN, NOT TAILWIND, on purpose: tailwind-compiled.css is a
     * PRE-COMPILED artifact, so grid-cols-2 / gap-2.5 / tracking-[0.3em] are not
     * guaranteed to exist in it and a missing utility fails SILENTLY. The panel
     * radius is here for the same reason — `rounded-[2.5rem]` is absent from the
     * build (it rendered square on the oem hero card, 2026-09-18).
     * ------------------------------------------------------------------- */
    .rs-lang-panel {
        border-radius: 40px;
    }
    .lang-grid {
        display: grid;
        grid-template-columns: repeat(2, minmax(0, 1fr));
        gap: 10px;
        /* The close button parks top-right INSIDE the card (top/right 24px,
           36px tall, so its bottom edge sits at 60px). Without extra room the
           grid's first row slid under it and the x collided with the top-right
           language card (user-reported). One padding row clears it on BOTH
           layouts: desktop 40+32=72px, phone 32+32=64px — both past 60px. */
        padding-top: 32px;
    }
    .lang-opt {
        display: flex;
        align-items: center;
        gap: 14px;
        padding: 13px 15px;
        border: 1px solid #e2e8f0;
        border-radius: 16px;
        background-color: #ffffff;
        text-decoration: none;
        transition: border-color .22s ease, background-color .22s ease, box-shadow .22s ease;
    }
    .lang-opt:hover {
        border-color: var(--brand);
        background-color: #f8fafc;
        box-shadow: 0 16px 30px -20px rgba(15, 30, 56, .38);
    }
    .lang-opt__flag {
        width: 26px;
        height: 18px;
        flex-shrink: 0;
        object-fit: cover;
        border-radius: 3px;
        box-shadow: 0 0 0 1px rgba(15, 23, 42, .10);
    }
    .lang-opt__text {
        display: flex;
        flex-direction: column;
        gap: 2px;
        min-width: 0;
    }
    .lang-opt__native {
        font-size: 13.5px;
        font-weight: 700;
        line-height: 1.2;
        color: #0f172a;
    }
    .lang-opt__exonym {
        font-size: 10px;
        font-weight: 600;
        line-height: 1.2;
        letter-spacing: .12em;
        text-transform: uppercase;
        color: #94a3b8;
    }
    .lang-opt__tick {
        display: none;
        margin-left: auto;
        font-size: 19px;
        color: var(--brand);
    }
    .lang-opt.is-current {
        border-color: var(--brand);
        background-color: #f2f8ff;
    }
    .lang-opt.is-current .lang-opt__native {
        color: var(--brand-dark);
    }
    .lang-opt.is-current .lang-opt__tick {
        display: block;
    }
    .rs-lang-current {
        display: flex;
        flex-direction: column;
        gap: 4px;
        padding: 14px 16px;
        border: 1px solid #e2e8f0;
        border-radius: 16px;
        background-color: #ffffff;
    }
    .rs-lang-current__label {
        font-size: 10px;
        font-weight: 700;
        letter-spacing: .16em;
        text-transform: uppercase;
        color: #94a3b8;
    }
    .rs-lang-current__value {
        font-size: 15px;
        font-weight: 800;
        color: #0f172a;
    }
    @media (max-width: 767px) {
        .lang-grid { grid-template-columns: 1fr; }
        .rs-lang-panel { border-radius: 24px; }
        /* The panel is taller than a phone screen (the option list + the intro
           rail), and the overlay's `items-center` then clips BOTH ends with no
           way to reach them — measured: the first and last options were both
           cut off. So below md the card stops centring and scrolls inside its
           own bezel instead; the backdrop stays where it is, because it is a
           sibling, not a child. Keep this guard even with a shorter list: ten
           options plus the rail still overflow a 390x844 phone. */
        #langModal {
            align-items: flex-start;
        }
        #langModalCard {
            max-height: calc(100vh - 32px);
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
        }
    }

    /* ================= Transparent header skin (.ht-header) ==============
     * header.html is the SINGLE SOURCE of both headers. header-transparent.html
     * is a 3-line shim: it sets $rs_header_transparent = 1 and includes
     * header.html, which flips ONE class onto the header element — everything
     * else (dropdowns, language modal, search panel, mobile menu) is byte-for-
     * byte the same markup, so the two can no longer drift apart.
     * THE SKIN IS DESCENDANT-DRIVEN on purpose: only the header element itself
     * needs the conditional class, no ifs are scattered through the markup.
     * Selectors hook the stable hooks the header already carries:
     *   .rs-logo img        logo (inverted while transparent)
     *   .rs-header-nav      top-level nav (child combinator keeps dropdown
     *                       panel links free to keep their own colours)
     *   .rs-search-shell    the language + search pill
     *   .open-lang-btn / .rsb-toggle / .open-quote-btn / #mobile-menu-trigger
     * Rest state: transparent background, white text, inverted logo. Hovering
     * anywhere on the header fades it back to the ordinary white header.
     * ------------------------------------------------------------------- */
    .ht-header {
        position: absolute !important;
        top: 0;
        left: 0;
        background-color: transparent !important;
        border-bottom-color: transparent !important;
        transition: background-color .3s ease, border-color .3s ease;
    }

    .ht-header:hover {
        background-color: #ffffff !important;
        border-bottom-color: #e5e7eb !important;
    }

    .ht-header .rs-logo img {
        filter: brightness(0) invert(1);
        transition: filter .15s ease;
    }

    .ht-header:hover .rs-logo img { filter: none; }

    .ht-header .rs-header-nav > a,
    .ht-header .rs-header-nav .dropdown > a {
        color: rgba(255, 255, 255, 0.9);
        transition: color .15s ease;
    }

    .ht-header:hover .rs-header-nav > a,
    .ht-header:hover .rs-header-nav .dropdown > a {
        color: #111418;
    }

    .ht-header .rs-search-shell {
        background-color: rgba(255, 255, 255, 0.1) !important;
        border-color: transparent !important;
        transition: background-color .3s ease, border-color .3s ease;
    }

    .ht-header:hover .rs-search-shell {
        background-color: rgb(249 250 251) !important;
        border-color: #e5e7eb !important;
    }

    .ht-header .open-lang-btn,
    .ht-header .rsb-toggle {
        color: rgba(255, 255, 255, 0.8);
    }

    /* header hover (back to white bar): flip icon buttons to the normal
       gray like every other header item — without this they stay white
       on the white background (only their own :hover was covered below). */
    .ht-header:hover .open-lang-btn,
    .ht-header:hover .rsb-toggle {
        color: #6b7280;
    }

    .ht-header .open-lang-btn:hover,
    .ht-header .rsb-toggle:hover {
        background-color: rgba(255, 255, 255, 0.2);
        color: #ffffff;
        box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
    }

    .ht-header:hover .open-lang-btn:hover,
    .ht-header:hover .rsb-toggle:hover {
        background-color: #ffffff;
        color: #6b7280;
        box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1);
    }

    /* Contact Experts: glass at rest, ink once the header is hovered. The
       ball-fill mechanics underneath stay untouched. */
    .ht-header .open-quote-btn {
        background-color: rgba(255, 255, 255, 0.1) !important;
        border: 1px solid rgba(255, 255, 255, 0.3);
        color: #ffffff;
        box-shadow: none;
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
        transition: all .15s ease;
    }

    .ht-header:hover .open-quote-btn {
        background-color: #111418 !important;
        border-color: transparent;
        color: #ffffff;
        box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1);
    }

    .ht-header #mobile-menu-trigger {
        color: rgba(255, 255, 255, 0.9);
        transition: color .15s ease, background-color .15s ease;
    }

    .ht-header:hover #mobile-menu-trigger {
        color: #111418;
    }

    .ht-header #mobile-menu-trigger:hover {
        background-color: rgba(255, 255, 255, 0.2);
    }

    .ht-header:hover #mobile-menu-trigger:hover {
        background-color: #f3f4f6;
    }
