/*
 * 9dots project CSS
 *
 * Migrated verbatim from Customizer > Additional CSS (custom_css post 15538,
 * keyed to the '9dots' stylesheet) on 2026-08-26.
 *
 * WordPress stores Additional CSS per stylesheet, so it would NOT have followed
 * the switch to the child theme. Post 15538 is left in place as a record.
 * This file is the source of truth from here - edit here, not the Customizer.
 */

/* ==========================================
   9 Dots Contact Form
   ========================================== */

/* Form */
.wpcf7-form {
    font-family: "Inter", Arial, sans-serif;
    font-size: 17px;
}

/* Input fields and dropdown */
.wpcf7-form input[type="text"],
.wpcf7-form input[type="email"],
.wpcf7-form input[type="tel"],
.wpcf7-form select {
    width: 100%;
    height: 60px;
    box-sizing: border-box;
    padding: 0 18px;
    font-family: "Inter", Arial, sans-serif;
    font-size: 17px;
    color: #000000;
    background: #FFFFFF;
    border: 1px solid #6B7280;
    border-radius: 5px;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

/* Message field */
.wpcf7-form textarea {
    width: 100%;
    min-height: 150px;
    box-sizing: border-box;
    padding: 16px 18px;
    font-family: "Inter", Arial, sans-serif;
    font-size: 17px;
    color: #000000;
    background: #FFFFFF;
    border: 1px solid #6B7280;
    border-radius: 5px;
    transition: border-color 0.2s ease, box-shadow 0.2s ease;
}

/* Placeholder text */
.wpcf7-form input::placeholder,
.wpcf7-form textarea::placeholder {
    color: #666666;
    font-family: "Inter", Arial, sans-serif;
    font-size: 17px;
    opacity: 1;
}

/* Dropdown text */
.wpcf7-form select {
    color: #666666;
}

/* Focus state */
.wpcf7-form input:focus,
.wpcf7-form textarea:focus,
.wpcf7-form select:focus {
    outline: none;
    border-color: #004282;
    box-shadow: 0 0 0 2px rgba(0, 66, 130, 0.08);
}

/* Submit button */
.wpcf7-submit {
    width: 100%;
    min-height: 60px;
    display: block;
    padding: 16px 20px;
    background: #004282;
    color: #FFFFFF;
    font-family: "Inter", Arial, sans-serif;
    font-size: 18px;
    font-weight: 600;
    text-transform: none;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.25s ease;
}

/* Submit button hover */
.wpcf7-submit:hover {
    background: #305994;
    color: #FFFFFF;
}

/* Remove Apexa button animation */
.wpcf7-submit::before,
.wpcf7-submit::after {
    display: none !important;
    content: none !important;
}

/* Success message */
.wpcf7 form.sent .wpcf7-response-output {
    display: block;
    margin-top: 16px;
    padding: 16px 18px;
    background: #F5F8FC;
    border: 1px solid #CCD2E6;
    border-radius: 5px;
    color: #004282;
    font-family: "Inter", Arial, sans-serif;
    font-size: 17px;
    font-weight: 500;
    text-align: center;
}

/* Spinner */
.wpcf7-form .wpcf7-spinner {
    display: block;
    margin: 10px auto 0;     transform: scale(1.3);
}

/* Mobile contact form */
@media (max-width: 767px) {

    .wpcf7-form input[type="text"],
    .wpcf7-form input[type="email"],
    .wpcf7-form input[type="tel"],
    .wpcf7-form select {
        height: 56px;
        font-size: 16px;
    }

    .wpcf7-form textarea {
        min-height: 130px;
        font-size: 16px;
    }

    .wpcf7-submit {
        min-height: 56px;
        font-size: 17px;
    }
}


/* ==========================================
   Elementor Linked Headings
   ========================================== */

.elementor-heading-title a {
    color: inherit !important;
    font-family: inherit !important;
    font-size: inherit !important;
    font-weight: inherit !important;
    line-height: inherit !important;
    letter-spacing: inherit !important;
    text-decoration: none !important;
}


/* ==========================================
   Header Language Switcher
   --------------------------------------------------------------------------
   Ported from the live site 2026-09-01. Requires TranslatePress "Load legacy
   Language Switcher" (Advanced Settings) - the new v2 switcher renders
   different markup (trp-language-item, not trp-ls-shortcode-*) and these
   selectors won't match anything without it. Shortcode display style is set
   to "Short Language Names" (Settings > TranslatePress, shortcode-options)
   so EN/TH/VI/ID render instead of full names or flags.
   ========================================== */

.header-language-switcher .trp-language-switcher {
    width: 90px !important;
}

.header-language-switcher .trp-language-switcher > div {
    width: 90px !important;
    min-width: 90px !important;
    box-sizing: border-box;
}

/* Closed language selector */
.header-language-switcher
.trp-language-switcher
.trp-ls-shortcode-current-language {
    height: 50px !important;
    min-height: 50px !important;
    display: flex;
    align-items: center;
    box-sizing: border-box;
    background-position: calc(100% - 10px) center !important;
}

.header-language-switcher
.trp-language-switcher
.trp-ls-shortcode-current-language > a {
    width: 100%;
    height: 48px !important;
    min-height: 48px !important;
    padding: 0 10px !important;
    display: flex;
    align-items: center;
    box-sizing: border-box;
}

/* Expanded language options */
.header-language-switcher
.trp-language-switcher
.trp-ls-shortcode-language > a {
    padding: 5px 10px !important;
}


/* ==========================================
   Header Search
   --------------------------------------------------------------------------
   Ported from the live site 2026-09-01, alongside the language switcher.
   ========================================== */

.header-search button {
    border-radius: 0 !important;
}

.hfe-search-form__input {
    border-radius: 5px;
}


/* ==========================================
   Sticky Header + Scroll Shrink
   --------------------------------------------------------------------------
   Rest state is whatever Elementor says. This file owns ONLY the scrolled
   state, so the header stays editable in the builder - change the padding in
   Elementor and the rest state follows, no CSS edit needed.

   nd-header.js toggles .nd-header--scrolled on #masthead. Deliberately no
   border-bottom and no shadow: the header sits flush against the page.
   Background is opaque so content passes underneath cleanly.

   Sizing values are tokens - see nd-tokens.css, "Sticky header".
   ========================================== */

.ehf-header #masthead {
    position: sticky;
    top: 0;
    z-index: var(--nd-header-z, 100);
    background: var(--nd-c-surface, #ffffff);
}

/* Logged-in admins: clear the WP toolbar, which is fixed above 782px. */
@media (min-width: 783px) {
    .admin-bar.ehf-header #masthead {
        top: 32px;
    }
}

/* Anchor links land below the header instead of behind it. */
html {
    scroll-padding-top: 120px;
}

/* --- What animates ------------------------------------------------------
   Declared on the rest state so the transition runs in BOTH directions.
   padding-block-* rather than the --padding-* custom properties: unregistered
   custom properties animate as discrete values, so transitioning them would
   snap rather than glide. */

.ehf-header #masthead .nd-header-row-top {
    transition: padding-block-start var(--nd-header-dur, 260ms) var(--nd-ease, ease),
                padding-block-end   var(--nd-header-dur, 260ms) var(--nd-ease, ease);
}

.ehf-header #masthead .nd-header-mobile-logo {
    transition: min-height          var(--nd-header-dur, 260ms) var(--nd-ease, ease),
                padding-block-start var(--nd-header-dur, 260ms) var(--nd-ease, ease),
                padding-block-end   var(--nd-header-dur, 260ms) var(--nd-ease, ease);
}

.ehf-header #masthead .nd-header-row-nav {
    transition: min-height var(--nd-header-dur, 260ms) var(--nd-ease, ease);
}

.ehf-header #masthead .nd-header-row-nav .menu-item a.hfe-menu-item {
    transition: padding-top    var(--nd-header-dur, 260ms) var(--nd-ease, ease),
                padding-bottom var(--nd-header-dur, 260ms) var(--nd-ease, ease);
}

/* Logo sizing lives on the WIDGET div, not the <img>. Elementor sizes the
   widget as a % of its container; the img inside just fills it. Putting a %
   max-width on the img resolves against the widget's own box instead, which
   compounds the two percentages and shrinks far harder than intended. */
.ehf-header #masthead .nd-header-logo {
    transition: max-width var(--nd-header-dur, 260ms) var(--nd-ease, ease);
}

/* --- Scrolled state -----------------------------------------------------
   #masthead is an ID, so these beat Elementor's generated class selectors
   without needing !important. */

#masthead.nd-header--scrolled .nd-header-row-top {
    padding-block-start: var(--nd-header-top-y, 14px);
    padding-block-end:   var(--nd-header-top-y, 14px);
}

#masthead.nd-header--scrolled .nd-header-row-nav {
    min-height: var(--nd-header-nav-h, 40px);
}

#masthead.nd-header--scrolled .nd-header-row-nav .menu-item a.hfe-menu-item {
    padding-top:    var(--nd-header-nav-item-y, 6px);
    padding-bottom: var(--nd-header-nav-item-y, 6px);
}

/* Scoped to the desktop row: since the mobile redesign there are TWO widgets
   carrying .nd-header-logo, and the mobile one is width:auto - a % max-width
   there would fight the new design rather than shrink it. */
#masthead.nd-header--scrolled .nd-header-row-top .nd-header-logo {
    max-width: var(--nd-header-logo-w, 32%);
}

@media (max-width: 767px) {

    /* The mobile row has no padding of its own - its height comes from the
       logo box (min-height + padding), so that is what shrinks. The desktop
       top row is hidden on mobile since the nav redesign, so shrinking it
       here would do nothing. */
    #masthead.nd-header--scrolled .nd-header-mobile-logo {
        min-height:          var(--nd-header-mob-box-h, 56px);
        padding-block-start: var(--nd-header-mob-box-y, 10px);
        padding-block-end:   var(--nd-header-mob-box-y, 10px);
    }
}

/* --- Mobile burger: stop the CLOSED panel widening the page ------------
   Header Footer Elementor hides the closed mobile dropdown with
   visibility:hidden + opacity:0, never display:none, so the panel stays in
   layout. Its menu items need ~160px but the Burger Nav container is 16%
   (~70px on a 440px screen), so ~92px of invisible content hangs off the
   right edge and widens the document.

   hello-elementor's reset (overflow-x:clip on body) hides this in Chrome,
   but that is containment, not a fix - where clip is unsupported the page
   scrolls sideways.

   Clipping only while closed leaves HFE's open/close behaviour untouched:
   once .menu-is-active lands the selector stops matching, overflow returns
   to visible and the panel expands over the page as designed. */

@media (max-width: 767px) {
    .hfe-nav-menu__breakpoint-mobile:has(nav.hfe-dropdown:not(.menu-is-active)) {
        overflow: hidden;
    }
}

/* Still shrinks, just arrives instantly. */
@media (prefers-reduced-motion: reduce) {

    .ehf-header #masthead .nd-header-row-top,
    .ehf-header #masthead .nd-header-mobile-logo,
    .ehf-header #masthead .nd-header-row-nav,
    .ehf-header #masthead .nd-header-row-nav .menu-item a.hfe-menu-item,
    .ehf-header #masthead .nd-header-logo {
        transition: none;
    }
}


/* ==========================================
   Search Results
   --------------------------------------------------------------------------
   template-parts/search.php. Coded template (no Elementor), so this owns
   its own layout - everything sized off nd-tokens.css, nothing hardcoded.
   ========================================== */

.nd-search__head {
    display: flex;
    flex-direction: column;
    gap: var(--nd-gap-lede);
    margin-bottom: var(--nd-space-7);
}

.nd-search__eyebrow {
    display: block;
    margin-bottom: var(--nd-gap-eyebrow);
    color: var(--nd-c-accent);
    font-size: 0.875em;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.nd-search__title mark {
    background: none;
    color: var(--nd-c-accent);
}

.nd-search__count {
    color: var(--nd-c-muted);
}

/* Refine-search form - same field on both the results and empty state.

   Input and button are deliberately the SAME height (--nd-field-h) rather than
   both being padding-sized: the input carries a 1px border and the button does
   not, so equal padding leaves the button 2px taller. Fixing the height on both
   and centring the button's label removes that mismatch entirely.

   Sizing and shape follow the contact form (60/56px, 5px radius) rather than
   the card radius - it is the same species of control, and that pairing is
   already established on the site. Colour and type follow the Elementor button
   widgets: #004282 via --nd-c-primary, Inter 600, white label.

   SPECIFICITY - the reason every rule below is scoped to .nd-search__form.
   Two 0-1-1 selectors sit above these controls and a bare .nd-search__submit
   / .nd-search__input (0-1-0) loses to both, silently:

     .elementor-kit-6 button        (post-6.css)  padding 3px, 20px, radius 1px
     input[type="search"]           (reset.css)   padding .5rem 1rem, radius 3px

   The parent-class scope brings these to 0-2-0 so they win on specificity
   rather than !important. Do not flatten these selectors back to one class. */
.nd-search__form {
    display: flex;
    gap: var(--nd-space-2);
    max-width: var(--nd-width-narrow);
}

.nd-search__form .nd-search__input {
    flex: 1 1 auto;
    min-width: 0;
    height: var(--nd-field-h);
    padding-inline: var(--nd-space-5);
    border: 1px solid var(--nd-c-muted);
    border-radius: var(--nd-field-radius);
    background: var(--nd-c-surface);
    color: var(--nd-c-text);
    font: inherit;
    transition: border-color var(--nd-dur) var(--nd-ease),
                box-shadow   var(--nd-dur) var(--nd-ease);
}

.nd-search__form .nd-search__input:focus {
    outline: none;
    border-color: var(--nd-c-primary);
    box-shadow: 0 0 0 2px rgba(0, 66, 130, .12);
}

.nd-search__form .nd-search__submit {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: var(--nd-field-h);
    /* 36px matches the site's own button widgets: of the 49 Elementor button
       widgets on the site, all 19 set at 18px type use 18/36px padding.
       Written as a shorthand rather than padding-inline so it also clears the
       kit's 3px vertical - the fixed height owns the vertical here. */
    padding: 0 36px;
    border: 0;
    border-radius: var(--nd-field-radius);
    background: var(--nd-c-primary);
    color: #fff;
    font-family: inherit;
    font-size: 18px;
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    transition: background-color var(--nd-dur) var(--nd-ease);
}

.nd-search__form .nd-search__submit:hover,
.nd-search__form .nd-search__submit:focus-visible {
    background: var(--nd-c-primary-hover);
}

.nd-search__form .nd-search__submit:focus-visible {
    outline: 2px solid var(--nd-c-primary);
    outline-offset: 2px;
}

/* Result card - .nd-card handles the box; this adds the internal layout. */
.nd-search__result {
    display: flex;
    flex-direction: column;
    gap: var(--nd-gap-stack-md);
}

.nd-search__result-media {
    margin: calc(var(--nd-card-pad) * -1) calc(var(--nd-card-pad) * -1) 0;
    border-radius: var(--nd-radius-md) var(--nd-radius-md) 0 0;
    overflow: hidden;
}

.nd-search__badge {
    display: inline-block;
    width: fit-content;
    padding: var(--nd-space-1) var(--nd-space-3);
    border-radius: var(--nd-radius-pill);
    background: var(--nd-c-surface-2);
    color: var(--nd-c-muted);
    font-size: 0.75em;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

.nd-search__result-title {
    margin: 0;
}

.nd-search__result-title a {
    color: var(--nd-c-primary);
    text-decoration: none;
}

.nd-search__result-title a:hover,
.nd-search__result-title a:focus-visible {
    color: var(--nd-c-accent);
}

.nd-search__result-excerpt {
    margin: 0;
    color: var(--nd-c-muted);
}

.nd-search__result-meta {
    margin-top: auto;
    padding-top: var(--nd-gap-stack-sm);
    color: var(--nd-c-muted);
    font-size: 0.875em;
}

/* Empty state */
.nd-search__empty {
    display: flex;
    flex-direction: column;
    gap: var(--nd-gap-lede);
}

/* Pagination */
.nd-search__pagination {
    display: flex;
    flex-wrap: wrap;
    gap: var(--nd-space-2);
    margin-top: var(--nd-space-8);
}

.nd-search__pagination a,
.nd-search__pagination span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--nd-space-7);
    height: var(--nd-space-7);
    padding-inline: var(--nd-space-3);
    border: var(--nd-border);
    border-radius: var(--nd-radius-md);
    color: var(--nd-c-text);
    text-decoration: none;
}

.nd-search__pagination a:hover,
.nd-search__pagination a:focus-visible {
    border-color: var(--nd-c-accent);
    color: var(--nd-c-accent);
}

.nd-search__pagination .current {
    border-color: var(--nd-c-primary);
    background: var(--nd-c-primary);
    color: var(--nd-c-surface);
}

@media (max-width: 767px) {

    /* Side by side, a full-length label plus a usable field does not fit on a
       360-400px screen without the input collapsing. Stacked, both get full
       width - the second option you asked for, applied only where it is
       actually needed. */
    .nd-search__form {
        flex-direction: column;
        max-width: none;
    }

    .nd-search__form .nd-search__input,
    .nd-search__form .nd-search__submit {
        width: 100%;
        height: var(--nd-field-h-sm);
    }

    .nd-search__form .nd-search__submit {
        font-size: 17px;
    }
}


/* ==========================================
   Archives
   --------------------------------------------------------------------------
   template-parts/archive.php. Coded template (no Elementor), covering author,
   category, tag, date and post-type archives. Sized off nd-tokens.css.

   Deliberately reuses the Search Results result-card rules rather than
   redeclaring them: the two templates render the same card, so the selectors
   below are grouped onto the existing ones where the styling is identical.
   Only the head - which search.php has no author variant of - is new.
   ========================================== */

.nd-archive__head {
    display: flex;
    flex-direction: column;
    gap: var(--nd-gap-lede);
    margin-bottom: var(--nd-space-7);
}

/* Author variant: avatar beside the identity block rather than above it.
   align-items:start keeps the avatar pinned to the top of the text column
   instead of centring against a bio of unpredictable length. */
.nd-archive__head--author {
    flex-direction: row;
    align-items: start;
    gap: var(--nd-space-5);
}

.nd-archive__avatar {
    flex: 0 0 auto;
    line-height: 0;
}

/* get_avatar() emits width/height attributes, so the box is already square.
   The radius and ring are all that need declaring. */
.nd-archive__avatar img {
    border-radius: var(--nd-radius-pill);
    border: var(--nd-border);
}

.nd-archive__identity {
    display: flex;
    flex-direction: column;
    gap: var(--nd-gap-lede);
    min-width: 0;
}

.nd-archive__eyebrow {
    display: block;
    margin-bottom: var(--nd-gap-eyebrow);
    color: var(--nd-c-accent);
    font-size: 0.875em;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* The identity column already supplies the gap, so the eyebrow's own bottom
   margin would double it up in the author variant only. */
.nd-archive__head--author .nd-archive__eyebrow {
    margin-bottom: 0;
}

.nd-archive__title {
    margin: 0;
}

/* Bio and archive description are both author-authored prose, so both get the
   reading measure rather than running the full page width. */
.nd-archive__bio,
.nd-archive__description {
    max-width: var(--nd-measure);
    margin: 0;
    color: var(--nd-c-muted);
}

.nd-archive__count {
    margin: 0;
    color: var(--nd-c-muted);
}

/* Result cards, pagination and empty state are identical to search - see the
   "Search Results" section above for why each rule is shaped the way it is. */
.nd-archive__result {
    display: flex;
    flex-direction: column;
    gap: var(--nd-gap-stack-md);
}

.nd-archive__result-media {
    margin: calc(var(--nd-card-pad) * -1) calc(var(--nd-card-pad) * -1) 0;
    border-radius: var(--nd-radius-md) var(--nd-radius-md) 0 0;
    overflow: hidden;
}

.nd-archive__badge {
    display: inline-block;
    width: fit-content;
    padding: var(--nd-space-1) var(--nd-space-3);
    border-radius: var(--nd-radius-pill);
    background: var(--nd-c-surface-2);
    color: var(--nd-c-muted);
    font-size: 0.75em;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-transform: uppercase;
}

/* .nd-card--flat already sets --nd-c-surface-2 as the card background, so a
   badge in the same colour would vanish. Lift it to the plain surface here. */
.nd-card--flat .nd-archive__badge {
    background: var(--nd-c-surface);
}

.nd-archive__result-title {
    margin: 0;
}

.nd-archive__result-title a {
    color: var(--nd-c-primary);
    text-decoration: none;
}

.nd-archive__result-title a:hover,
.nd-archive__result-title a:focus-visible {
    color: var(--nd-c-accent);
}

.nd-archive__result-excerpt {
    margin: 0;
    color: var(--nd-c-muted);
}

.nd-archive__result-meta {
    margin-top: auto;
    padding-top: var(--nd-gap-stack-sm);
    color: var(--nd-c-muted);
    font-size: 0.875em;
}

.nd-archive__pagination {
    display: flex;
    flex-wrap: wrap;
    gap: var(--nd-space-2);
    margin-top: var(--nd-space-8);
}

.nd-archive__pagination a,
.nd-archive__pagination span {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: var(--nd-space-7);
    height: var(--nd-space-7);
    padding-inline: var(--nd-space-3);
    border: var(--nd-border);
    border-radius: var(--nd-radius-md);
    color: var(--nd-c-text);
    text-decoration: none;
}

.nd-archive__pagination a:hover,
.nd-archive__pagination a:focus-visible {
    border-color: var(--nd-c-accent);
    color: var(--nd-c-accent);
}

.nd-archive__pagination .current {
    border-color: var(--nd-c-primary);
    background: var(--nd-c-primary);
    color: var(--nd-c-surface);
}

@media (max-width: 767px) {

    /* A 96px avatar plus a name leaves too little room for the bio beside it
       on a 360-400px screen. Stacked, both get the full width. */
    .nd-archive__head--author {
        flex-direction: column;
    }
}

[class="hfe-nav-menu__layout-vertical hfe-nav-menu__submenu-plus hfe-dropdown"]{
    /* display: none; */
}

[class="hfe-nav-menu__layout-vertical hfe-nav-menu__submenu-plus hfe-dropdown menu-is-active"]{
    /* display: block; */
}

/* ---------------------------------------------------------------------------
   Mobile nav: horizontal overflow from the closed expandible panel
   ---------------------------------------------------------------------------
   The mobile nav widget sits flush right and is only ~62px wide. Its closed
   nav.hfe-nav-menu__layout-expandible is position:static / width:auto, so it
   inherits that 62px; the link text and .sub-arrow spans spill past the right
   edge to ~467px. They are visibility:hidden, but hidden elements still extend
   the scroll area - 82px of horizontal overflow on a 386px viewport.

   Promoting .nd-header-row-mobile (already full width, already relative) to the
   containing block lets left/right:0 resolve against the viewport instead of
   the 62px widget box. overflow:hidden clips the spill while panel height is 0.

   Specificity 0-2-0 against HFE 0-1-0, so no !important is needed.
   :has() is used so this survives the widget being rebuilt with a new ID.
   --------------------------------------------------------------------------- */

@media (max-width: 1024px) {

    .nd-header-row-mobile {
        position: relative;
    }

    .nd-header-row-mobile .e-con:has(.hfe-nav-menu__layout-expandible) {
        position: static;
    }

    .nd-header-row-mobile .hfe-nav-menu__layout-expandible {
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        width: auto;
        overflow: hidden;
    }
}

/* ==========================================
   RESPONSIVE QA FIXES
   ========================================== */

/* ---------------------------------------------------------------------------
   Floating language switcher covering the primary CTA
   ---------------------------------------------------------------------------
   TranslatePress injects .trp-floating-switcher with JS and drives its position
   from custom properties written into the style attribute
   (--bottom: 0px; --right: 10vw). Because those land inline, redefining the
   custom properties from a stylesheet loses - the used `bottom` / `right`
   declarations have to be overridden instead.

   At 375px the chip sits at x 276-338, y 760-815 and wins the hit test against
   the hero CTA ("Discuss Your Requirements"), covering 15% of it. The same
   collision lands on the contact form textarea and on the footer Privacy Policy
   line, because the chip is fixed and every page puts something in that corner.
   --bottom: 0 also parks it under the iOS home indicator.

   Docking it flush right and lifting it above the thumb zone - plus the
   safe-area inset - clears all three. It cannot simply be hidden: below 1025px
   this is the only language switcher that renders at all, both shortcode
   switchers measure 0x0 there.

   Specificity 0-2-1 against the plugin's 0-2-0, so no !important is needed.
   --------------------------------------------------------------------------- */

@media (max-width: 1024px) {

    nav.trp-floating-switcher.trp-switcher-position-bottom {
        right: 0;
        bottom: calc(env(safe-area-inset-bottom, 0px) + 96px);
        border-radius: 8px 0 0 8px;
    }
}

/* ---------------------------------------------------------------------------
   Tap targets below the 44px minimum
   ---------------------------------------------------------------------------
   WCAG 2.5.5 / the iOS HIG both want 44x44. On mobile the inline "->" CTAs
   rendered as heading widgets measure 22px tall (18 of them on the home page),
   the icon-list email link 28px, and the social icons 35x35.

   Padding would fix the size but would also move everything around it, so the
   hit area is expanded with a pseudo-element instead: purely additive, zero
   layout shift. height/width 100% with a 44px floor means a link that is
   already large keeps its own area - this only ever grows a target, never
   shrinks one, so it is safe to apply to the whole heading-link family
   including the multi-line H1.

   Deliberately excluded:
   - .elementor-widget-text-editor a ("Privacy Policy", 17px) is an inline link
     inside a paragraph, which WCAG 2.5.5 exempts; boxing it would break the
     text flow.
   - .upk-alter-carousel a.title-animation-underline (25px) already sits inside
     a fully clickable card, and it owns its ::after for the underline effect.
   --------------------------------------------------------------------------- */

@media (max-width: 1024px) {

    .elementor-widget-heading a,
    .elementor-widget-icon-list .elementor-icon-list-item a,
    a.elementor-icon {
        position: relative;
    }

    .elementor-widget-heading a::after,
    .elementor-widget-icon-list .elementor-icon-list-item a::after,
    a.elementor-icon::after {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: 100%;
        min-width: 44px;
        height: 100%;
        min-height: 44px;
    }
}


/* nd-a11y: inline links inside footer body copy must not rely on colour alone
   (Lighthouse link-in-text-block). #colophon (1-0-0) outranks .elementor-kit-6 a (0-1-1). */
#colophon .elementor-widget-text-editor p a {
    text-decoration: underline;
    text-underline-offset: 2px;
}

#content.nd-main:focus {
    outline: none;
}

/* nd-a11y: visually-hidden label wrapper around the CF7 select must not shrink the field
   (Hello sets label to inline-block). 0-2-0 beats label (0-0-1). */
.wpcf7 .nd-sr-label {
    display: block;
}
