/* ==========================================================================
   Client site — "ledger" design.

   One idea carried through the whole page: a paper ground, near-black ink and
   hairline rules. Structure is drawn with 1px lines instead of shadows, and
   corners are square. Every colour an administrator can set on the Header,
   Banner, Language Switcher and Bottom Footer screens still arrives through
   the same --client-* custom properties with the same fallbacks, so the admin
   contract is untouched — the design only decides what the *defaults* look
   like and how everything is shaped.
   ========================================================================== */

.client-body {
    /* Design tokens. Everything below draws from these five. */
    --paper: #fff;
    --ink: #161512;
    --ink-2: #4c4a44;
    --ink-3: #8b877d;
    --line: #e5e2da;
    --line-strong: #c9c5bb;

    /*
     * Header, main, footer in a column, with the main growing into whatever is
     * left. Before this the main was told to stand at least a screen tall on
     * its own, so on a short page the footer was pushed past the bottom of the
     * window and the browser drew a scrollbar for it — a page with nothing to
     * scroll to but its own footer. Now the three of them add up to exactly one
     * screen, and the page scrolls only when it really is longer than one.
     */
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
    background: var(--paper);
    color: var(--ink);
    font-family: var(--client-font, var(--font-sans));
}

/* Neither end gives up its height when the middle is full. */
.client-site-header,
.client-footer { flex-shrink: 0; }

.client-body ::selection { background: var(--ink); color: var(--paper); }

/* Takes what the header and footer leave, and no more. */
.client-main { flex: 1 0 auto; }

.client-narrow { max-width: 48rem; }

.client-sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Honeypot: hidden from sight rather than display:none, which some bots skip.
   Clipped in place, not parked at left:-9999px: on a right-to-left page the
   far left IS scrollable, so that made the Arabic contact page 10,000px wide
   and opened it scrolled into the blank. */
.client-hp { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0, 0, 0, 0); clip-path: inset(50%); white-space: nowrap; }

/* ==========================================================================
   Header
   ========================================================================== */
/* Sticky by default; Settings > Header > Behaviour can switch it off, which
   adds .is-static and lets the header scroll away with the page. */
.client-site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    border-bottom: 1px solid var(--line);
    background: var(--client-header-bg, var(--paper));
    color: var(--client-header-item, var(--ink));
}

/* Not pinned, but still positioned: below 500px the language panel is laid
   out against the header, and `position: static` would leave it with no
   containing block but the viewport — `top: 100%` would then throw it a
   whole screen down, out of sight. `relative` with the inherited `top: 0`
   sits exactly where `static` did and keeps the header as the reference. */
.client-site-header.is-static { position: relative; }

.client-site-header-inner {
    min-height: 76px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
}

.client-site-brand {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: .75rem;
    color: var(--client-header-item, var(--ink));
}
.client-site-brand.is-empty { display: none; }

.client-site-logo {
    display: block;
    max-width: 250px;
    max-height: 60px;
    width: auto;
    height: auto;
    object-fit: contain;
}

/* --------------------------------------------------------------------------
   Desktop navigation
   -------------------------------------------------------------------------- */
.client-desktop-nav {
    flex: 1 1 auto;
    display: flex;
    justify-content: flex-end;
    min-width: 0;
}

.client-menu-list,
.client-mobile-menu-list,
.client-submenu {
    list-style: none;
    margin: 0;
    padding: 0;
}

.client-menu-list {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: .25rem;
}

.client-menu-item { position: relative; }

.client-menu-link {
    display: inline-flex;
    align-items: center;
    justify-content: space-between;
    gap: .35rem;
    padding: .65rem .85rem;
    color: var(--client-header-item, var(--ink));
    font-size: 18px;
    line-height: 1.35;
    transition: color .15s ease, background-color .15s ease;
    border-radius: 12px;
}

/* Header hover colour — DESKTOP nav only.
   The :hover state applies to every ancestor of the pointer, so an unscoped
   ".client-menu-item:hover > .client-menu-link" fires on the PARENT link while
   a submenu child is hovered. On desktop that is wanted (the top item stays lit
   while browsing its dropdown); inside the mobile panel it painted the parent
   with the Header group's colour — the mobile panel must only ever use the
   Mobile Menu Dropdown colours. */
/* Hover colouring is additionally gated on a real hover pointer: touchscreens
   make :hover STICK after a tap, so on tablets (or phones in desktop-site
   mode, where the desktop nav is visible) tapping an item painted it with the
   hover colour and left it that way. Devices with a mouse are unaffected. */
@media (hover: hover) {
    .client-desktop-nav .client-menu-link:hover,
    .client-desktop-nav .client-menu-item:hover > .client-menu-link {
        color: var(--client-header-item-hover, var(--ink));
    }
}

/* "Active Item Background Color" (Settings > Header > Header) — declared before
   the hover rule so hovering still wins on equal specificity. */
.client-desktop-nav > .client-menu-list > .client-menu-item.is-active > .client-menu-link {
    background: var(--client-header-item-active-bg, transparent);
}

/* "Item Hover Background Color" (Settings > Header > Header). Scoped to
   top-level items so it never bleeds into the submenu or mobile groups. */
@media (hover: hover) {
    .client-desktop-nav > .client-menu-list > .client-menu-item > .client-menu-link:hover,
    .client-desktop-nav > .client-menu-list > .client-menu-item:hover > .client-menu-link {
        background: var(--client-header-item-hover-bg, rgba(22, 21, 18, .05));
    }
}

/* Header active colour — desktop only, same reasoning as the hover rule. The
   mobile panel's own is-active rules carry the Mobile Menu Dropdown colours. */
.client-desktop-nav .client-menu-item.is-active > .client-menu-link {
    color: var(--client-header-item-active, var(--ink));
}

.client-menu-caret {
    width: 15px;
    height: 15px;
    flex: 0 0 auto;
    transition: transform .15s ease;
}
/* Hover-rotate is a desktop affordance; mobile carets rotate via .is-open. */
@media (hover: hover) {
    .client-desktop-nav .client-menu-item:hover > .client-menu-link .client-menu-caret { transform: rotate(180deg); }
}

/* --------------------------------------------------------------------------
   Desktop submenu — a ruled sheet rather than a floating rounded card
   -------------------------------------------------------------------------- */
.client-submenu {
    position: absolute;
    top: calc(100% + .35rem);
    right: 0;
    border-radius: 12px;
    min-width: 230px;
    background: var(--client-submenu-bg, var(--paper));
    box-shadow: 0 10px 24px rgba(22, 21, 18, .08);
    padding: .375rem;
    opacity: 0;
    visibility: hidden;
    transform: translateY(6px);
    transition: opacity .15s ease, visibility .15s ease, transform .15s ease;
}

[dir="rtl"] .client-submenu { left: auto; right: 0; }

.client-menu-item:hover > .client-submenu,
.client-menu-item:focus-within > .client-submenu {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
}

/* Sub Menu Dropdown colours apply to the DESKTOP dropdown only; the mobile
   panel re-renders the same markup and owns its own colours below. */
.client-desktop-nav .client-submenu .client-menu-link {
    width: 100%;
    color: var(--client-submenu-item, var(--ink));
    padding: .65rem .75rem;
    white-space: nowrap;
}

@media (hover: hover) {
    .client-desktop-nav .client-submenu .client-menu-link:hover,
    .client-desktop-nav .client-submenu .client-menu-item:hover > .client-menu-link {
        color: var(--client-submenu-item-hover, var(--ink));
        background: var(--client-submenu-item-hover-bg, rgba(22, 21, 18, .05));
    }
}

.client-desktop-nav .client-submenu .client-menu-item.is-active > .client-menu-link {
    color: var(--client-submenu-item-active, var(--ink));
    background: var(--client-submenu-item-active-bg, transparent);
}
/* The active rule above outranks the general hover; restore hover feedback. */
@media (hover: hover) {
    .client-desktop-nav .client-submenu .client-menu-item.is-active > .client-menu-link:hover {
        background: var(--client-submenu-item-hover-bg, rgba(22, 21, 18, .05));
    }
}

.client-submenu .client-submenu { top: 0; left: calc(100% + .35rem); }
[dir="rtl"] .client-submenu .client-submenu { left: auto; right: calc(100% + .35rem); }

.client-header-actions {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: .75rem;
}

/* Touch-only control; the desktop nav opens submenus on hover instead. */
.client-submenu-toggle { display: none; }

/* --------------------------------------------------------------------------
   Language switcher
   -------------------------------------------------------------------------- */
.client-language-switcher { position: relative; }

.client-language-switcher summary {
    list-style: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .35rem;
    min-height: 40px;
    border: 1px solid var(--client-header-item, var(--ink));
    background: var(--client-header-bg, transparent);
    padding: .45rem .78rem;
    color: var(--client-header-item, var(--ink));
    font-size: 18px;
    font-weight: 500;
    cursor: pointer;
    transition: color .15s ease, border-color .15s ease;
    border-radius: 6px;
}
.client-language-switcher summary::-webkit-details-marker { display: none; }

.client-language-switcher[open] summary,
.client-language-switcher summary:hover {
    color: var(--client-header-item-hover, var(--ink));
    border-color: var(--client-header-item-hover, var(--ink));
}

.client-language-caret { width: 14px; height: 14px; flex: 0 0 auto; transition: transform .15s ease; }
.client-language-switcher[open] .client-language-caret { transform: rotate(180deg); }

.client-language-list {
    position: absolute;
    top: calc(100% + .5rem);
    right: 0;
    min-width: 300px;
    background: var(--client-language-bg, var(--paper));
    box-shadow: 0 10px 24px rgba(22, 21, 18, .08);
    padding: .5rem;
    z-index: 80;
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .35rem;
    border-radius: 8px;
}
[dir="rtl"] .client-language-list { right: auto; left: 0; }

.client-language-list a {
    display: flex;
    align-items: center;
    min-height: 38px;
    padding: .55rem .65rem;
    color: var(--client-language-item, var(--ink));
    font-size: 18px;
    line-height: 1.25;
    border-radius: 8px;
}

/* "Item Hover Background Color" (Settings > Language Switcher). */
.client-language-list a:hover {
    color: var(--client-language-hover, var(--ink));
    background: var(--client-language-hover-bg, rgba(22, 21, 18, .05));
}

/* "Active Item Background Color" (Settings > Language Switcher). */
.client-language-list a.is-active {
    color: var(--client-language-active, var(--ink));
    background: var(--client-language-active-bg, transparent);
}
.client-language-list a.is-active:hover {
    background: var(--client-language-hover-bg, rgba(22, 21, 18, .05));
}

/* --------------------------------------------------------------------------
   Mobile toggle and panel
   -------------------------------------------------------------------------- */
.client-mobile-toggle {
    display: none;
    width: 42px;
    height: 42px;
    border: 0;
    background: transparent;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    gap: 5px;
    cursor: pointer;
}
.client-mobile-toggle span {
    display: block;
    width: 18px;
    height: 2px;
    background: var(--client-header-item, var(--ink));
}

.client-mobile-panel {
    background: var(--client-mobile-bg, var(--paper));
}
.client-mobile-panel-inner { padding-top: 1rem; padding-bottom: 1rem; }

/* --------------------------------------------------------------------------
   Mobile panel animation

   The panel is revealed by removing the [hidden] attribute, and keyframe
   animations run every time an element goes from unrendered to rendered — so
   the open animation needs no JS at all: the panel sweeps down, and the rows
   inside cascade up one after another (fill-mode: backwards keeps each row
   invisible until its delayed animation starts). Closing stays instant, which
   is the expected feel for dismissing a menu.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: no-preference) {
    .client-mobile-panel:not([hidden]) {
        animation: client-panel-open .28s ease-out;
    }

    .client-mobile-panel:not([hidden]) .client-mobile-menu-list > .client-menu-item {
        animation: client-panel-item .38s cubic-bezier(.2, .7, .2, 1) backwards;
    }
    .client-mobile-menu-list > .client-menu-item:nth-child(1) { animation-delay: .05s; }
    .client-mobile-menu-list > .client-menu-item:nth-child(2) { animation-delay: .09s; }
    .client-mobile-menu-list > .client-menu-item:nth-child(3) { animation-delay: .13s; }
    .client-mobile-menu-list > .client-menu-item:nth-child(4) { animation-delay: .17s; }
    .client-mobile-menu-list > .client-menu-item:nth-child(5) { animation-delay: .21s; }
    .client-mobile-menu-list > .client-menu-item:nth-child(6) { animation-delay: .25s; }
    .client-mobile-menu-list > .client-menu-item:nth-child(7) { animation-delay: .29s; }
    .client-mobile-menu-list > .client-menu-item:nth-child(n+8) { animation-delay: .33s; }

    /* Tapping a caret expands its submenu with the same rise. */
    .client-mobile-menu-list .client-menu-item.is-open > .client-submenu {
        animation: client-panel-item .3s ease-out;
    }

    /* Hamburger-to-X morph eases; without motion it still snaps to the X. */
    .client-mobile-toggle span {
        transition: transform .3s cubic-bezier(.2, .7, .2, 1), opacity .2s ease;
    }
}

@keyframes client-panel-open {
    from { opacity: 0; transform: translateY(-10px); }
}
@keyframes client-panel-item {
    from { opacity: 0; transform: translateY(10px); }
}

/* The three bars fold into a close icon while the menu is open — driven by
   the aria-expanded state the script already maintains. */
.client-mobile-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.client-mobile-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; transform: scaleX(.4); }
.client-mobile-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

.client-mobile-menu-list { display: grid; gap: .35rem; }
.client-mobile-menu-list .client-menu-item { position: static; }

.client-mobile-menu-list .client-menu-link {
    display: flex;
    width: 100%;
    color: var(--client-mobile-item, var(--ink));
    padding: .8rem 1rem;
    background: rgba(22, 21, 18, .03);
    font-size: 18px;
}

/* "Item Hover Background Color" (Settings > Header > Mobile Menu Dropdown).
   Gated on a real hover pointer: on touchscreens :hover sticks after a tap,
   so a tapped row would keep the hover paint. Mouse users who open the
   hamburger in a narrow window still get the hover colours. */
@media (hover: hover) {
    .client-mobile-menu-list .client-menu-link:hover {
        color: var(--client-mobile-item-hover, var(--ink));
        background: var(--client-mobile-item-hover-bg, rgba(22, 21, 18, .07));
    }
}

/* "Active Item Background Color" — covers nested submenu items too, since the
   mobile group owns every colour inside the panel. */
.client-mobile-menu-list .client-menu-item.is-active > .client-menu-link {
    color: var(--client-mobile-item-active, var(--ink));
    background: var(--client-mobile-item-active-bg, rgba(22, 21, 18, .03));
}
@media (hover: hover) {
    .client-mobile-menu-list .client-menu-item.is-active > .client-menu-link:hover {
        background: var(--client-mobile-item-hover-bg, rgba(22, 21, 18, .07));
    }
}

/* Mobile submenus are collapsed until their toggle is tapped. */
.client-mobile-menu-list .client-submenu {
    display: none;
    position: static;
    min-width: 0;
    border: 0;
    box-shadow: none;
    background: transparent;
    padding: .25rem 0 .25rem 1rem;
    opacity: 1;
    visibility: visible;
    transform: none;
}
.client-mobile-menu-list .client-menu-item.is-open > .client-submenu { display: block; }

/* Row becomes a two-column grid so the toggle sits beside the link and the
   submenu spans underneath — no hardcoded row heights. */
.client-mobile-menu-list .client-menu-item.has-children {
    display: grid;
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas:
        "link toggle"
        "submenu submenu";
    gap: .35rem;
}
.client-mobile-menu-list .client-menu-item.has-children > .client-menu-link { grid-area: link; }
.client-mobile-menu-list .client-menu-item.has-children > .client-submenu-toggle { grid-area: toggle; }
.client-mobile-menu-list .client-menu-item.has-children > .client-submenu { grid-area: submenu; }

/* The button carries the caret on mobile, so the link's copy is redundant. */
.client-mobile-menu-list .client-menu-item.has-children > .client-menu-link .client-menu-caret { display: none; }

.client-mobile-menu-list .client-submenu-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    border: 0;
    background: rgba(22, 21, 18, .03);
    color: var(--client-mobile-item, var(--ink));
    cursor: pointer;
    border-radius: 12px;
    transition: background-color .15s ease, color .15s ease;
}
@media (hover: hover) {
    .client-mobile-menu-list .client-submenu-toggle:hover {
        background: var(--client-mobile-item-hover-bg, rgba(22, 21, 18, .07));
        color: var(--client-mobile-item-hover, var(--ink));
    }
}
.client-mobile-menu-list .client-submenu-toggle .client-menu-caret { width: 18px; height: 18px; }
.client-mobile-menu-list .client-menu-item.is-open > .client-submenu-toggle .client-menu-caret { transform: rotate(180deg); }

[dir="rtl"] .client-mobile-menu-list .client-submenu { padding-left: 0; padding-right: 1rem; }

/* Nested items in the panel: colours from Mobile Menu Dropdown; slight inset
   tint so children read as nested. */
.client-mobile-menu-list .client-submenu .client-menu-link {
    font-size: 18px;
    padding: .7rem .9rem;
    color: var(--client-mobile-item, var(--ink));
    background: rgba(22, 21, 18, .025);
}
/* Self-hover only — no ":hover >" parent variant, so touching a nested item
   never repaints the item above it. */
@media (hover: hover) {
    .client-mobile-menu-list .client-submenu .client-menu-link:hover {
        color: var(--client-mobile-item-hover, var(--ink));
        background: var(--client-mobile-item-hover-bg, rgba(22, 21, 18, .07));
    }
}
.client-mobile-menu-list .client-submenu .client-menu-item.is-active > .client-menu-link {
    color: var(--client-mobile-item-active, var(--ink));
    background: var(--client-mobile-item-active-bg, rgba(22, 21, 18, .03));
}

/* --------------------------------------------------------------------------
   Header breakpoints — max-width queries run widest to narrowest so the
   narrower block wins where they overlap.

   The width at which the full menu gives way to the hamburger is not here: it
   comes from Settings > Layout > Show Mobile Menu Below, and a media query
   cannot read a CSS variable, so those rules are written into the page by
   resources/views/layouts/client.php. Only the switch is there; the sizing
   below stays here, in one place and in one order.
   -------------------------------------------------------------------------- */

/* The compact header of a small screen: a shorter bar, a smaller logo and a
   dropdown that keeps to the width it has. */
@media (max-width: 1023px) {
    .client-header-actions { gap: .5rem; }
    .client-site-header-inner { min-height: 68px; gap: .75rem; }
    .client-site-logo { max-height: 42px; max-width: 170px; }
    .client-language-list { min-width: 300px; max-width: calc(100vw - 2rem); }
}

/* Below 500px the language dropdown becomes a full-width sheet under the
   header: position comes off the switcher, so the header itself becomes the
   containing block — pinned or not — and the panel stretches edge to edge. */
@media (max-width: 499px) {
    .client-language-switcher { position: static; }

    .client-language-list {
        top: 100%;
        left: 0;
        right: 0;
        width: 100%;
        min-width: 0;
        max-width: none;
        margin: 0;
        border-left: 0;
        border-right: 0;
        padding: .5rem;
        gap: .25rem;
    }
    /* Roomier rows — this is now the primary way to switch language. */
    .client-language-list a { min-height: 48px; padding: .8rem .9rem; }
}

/* Below 480px the logo gives up more width, so the switcher and the hamburger
   still fit on the row beside it. */
@media (max-width: 479px) {
    .client-site-logo { max-width: 125px; }
}

/* Narrow phones: trim the switcher so the row still fits beside the logo. */
@media (max-width: 420px) {
    /* No max-width here: the 125px set above already applies, and repeating a
       wider 130px would have made the logo grow as the screen got smaller. */
    .client-site-logo { max-height: 33px; }
    .client-header-actions { gap: .375rem; }
    .client-mobile-toggle { width: 38px; height: 38px; }

    .client-language-switcher summary span {
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }
}


/* ==========================================================================
   Banner — copy from the page, colours from Settings > Banner
   ========================================================================== */
.client-banner {
    border-bottom: 1px solid var(--line);
    background: var(--client-banner-bg, var(--ink));
    padding: 3.5rem 0;
}

.client-banner-inner { text-align: center; }

.client-banner-title {
    margin: 0 0 1rem;
    color: var(--client-banner-heading, var(--paper));
    font-size: 1.75rem;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: -.02em;
}

.client-banner-subtitle {
    max-width: 60rem;
    margin: 0 auto 2rem;
    color: var(--client-banner-subheading, var(--paper));
    font-size: 1rem;
    line-height: 1.6;
    opacity: .92;
}

.client-banner-form {
    display: flex;
    align-items: stretch;
    justify-content: center;
    gap: .625rem;
    max-width: 52rem;
    margin: 0 auto;
    flex-wrap: wrap;
}

.client-banner-field {
    position: relative;
    display: flex;
    align-items: center;
    flex: 1 1 20rem;
    min-width: 0;
    background: #fff;
    border-radius: 12px;
}

.client-banner-input {
    width: 100%;
    min-width: 0;
    border: 0;
    background: transparent;
    padding: 1.125rem 3.25rem 1.125rem 1.25rem;
    color: var(--ink);
    font-size: 16px;
    line-height: 1.4;
    border-radius: 12px;
}
.client-banner-input::placeholder { color: var(--ink-3); }
.client-banner-input:focus { outline: 0; }
.client-banner-field:focus-within { box-shadow: 0 0 0 2px var(--paper), 0 0 0 4px var(--ink); }

/* One slot, two controls: paste while empty, clear once there is a value.
   JS swaps them via [hidden]; the override below must beat the display rule,
   since an author display always wins over the UA's own [hidden] rule. */
.client-banner-action {
    position: absolute;
    right: .625rem;
    background: transparent;
    cursor: pointer;
    transition: background-color .15s ease;
}
.client-banner-action[hidden] { display: none; }
.client-banner-action svg { width: 30px; height: 3%; }
.client-banner-clear svg { width: 30px; height: 30px; }

[dir="rtl"] .client-banner-action { right: auto; left: .625rem; }
[dir="rtl"] .client-banner-input { padding: 1.125rem 1.25rem 1.125rem 3.25rem; }

.client-banner-button {
    border: 1px solid var(--client-banner-btn-border, var(--paper));
    background: var(--client-banner-btn-bg, var(--paper));
    padding: 0 20px;
    color: var(--client-banner-btn-text, var(--ink));
    cursor: pointer;
    font-size: 18px;
    border-radius: 8px;
}
.client-banner-button svg { width: 18px; height: 18px; }
.client-banner-button:hover { filter: brightness(.94); }

@media (max-width: 640px) {
    .client-banner { padding: 2.5rem 0; }
    .client-banner-subtitle { margin-bottom: 1.5rem; font-size: 1rem; }
    .client-banner-field { flex: 1 1 100%; }
    .client-banner-button {flex: 1 1 100%; height: 50px}
}

@media (min-width: 900px) {
    .client-banner { padding: 4.5rem 0; }
    .client-banner-title { font-size: 2.5rem; }
    .client-banner-subtitle { font-size: 1.15rem; }
}

/* ==========================================================================
   Notes — admin-authored notices shown directly below the banner.
   Callout cards: a brand-tinted wash and left accent tie them to the banner
   above without shouting over the page content that follows.
   ========================================================================== */
/* Doubled class beats the later .client-section { margin: 50px 0 } rule, so
   notes sit close under the banner instead of a full section gap away. */
.client-section.client-notes { margin: 2rem 0; }
.client-notes .container-main { display: grid; gap: .875rem; }

.client-note {
    padding: 1.125rem 1.375rem;
    border: 1px solid var(--line);
    border-left: 4px solid var(--client-banner-bg, #e60023);
    border-radius: 12px;
    background: #fbfbfa;
    background: color-mix(in oklab, var(--client-banner-bg, #e60023) 4%, #fdfdfc);
}

[dir="rtl"] .client-note {
    border-left: 1px solid var(--line);
    border-right: 4px solid var(--client-banner-bg, #e60023);
}

.client-note-title {
    margin: 0 0 .375rem;
    color: var(--ink);
    font-size: var(--client-h4);
    font-weight: var(--client-heading-weight);
    line-height: var(--client-heading-lh);
    letter-spacing: var(--client-heading-tracking);
}

.client-note .client-rich { font-size: 1rem; line-height: 1.65; }

/* ==========================================================================
   Keyword search — suggestions under the box, and the videos they return
   ========================================================================== */

/* The field is the positioning context, so the list hangs from its edge. */
.client-banner-field { position: relative; }

.client-suggest {
    position: absolute;
    top: calc(100% + .375rem);
    left: 0;
    right: 0;
    z-index: 40;
    max-height: 18rem;
    overflow-y: auto;
    margin: 0;
    padding: .3125rem;
    list-style: none;
    border-radius: 12px;
    background: var(--paper);
    box-shadow: 0 12px 30px rgba(22, 21, 18, .16);
    text-align: start;
}

.client-suggest-item {
    padding: .625rem .75rem;
    border-radius: 8px;
    color: var(--ink);
    font-size: 1rem;
    cursor: pointer;
}

@media (hover: hover) {
    .client-suggest-item:hover { background: var(--line); }
}

/* ==========================================================================
   Banner search — status line and the download results below the banner
   ========================================================================== */
.client-banner-status {
    max-width: 40rem;
    margin: 1rem auto 0;
    text-align: center;
    color: var(--client-banner-subheading, rgba(255, 255, 255, .85));
    font-size: .9375rem;
}

.client-banner-status.is-error {
    display: inline-block;
    max-width: none;
    padding: .5rem 1rem;
    border-radius: 10px;
    background: rgba(0, 0, 0, .22);
    font-weight: 600;
}

/* The searching state dims the button; the status line narrates progress. */
.client-banner-form.is-searching .client-banner-button { opacity: .7; cursor: progress; }

/* Banner ad slot (Settings > Ads > Banner Ads), under the search field.
   Centred and width-capped so a wide creative cannot stretch the banner. */
.client-banner-ad {
    max-width: 40rem;
    margin: 1.25rem auto 0;
    text-align: center;
}

.client-banner-ad :is(img, iframe) { max-width: 100%; height: auto; }

/* ==========================================================================
   Results page (/viewer) — the results, and nothing around them
   ========================================================================== */

/* No banner here: the page opens on what was found. The search box is still on
   the page, hidden, because it is what the script searches in. */
.client-viewer-form { display: none; }

/* Viewer Page Ads (Settings > Ads), above the state card and inside its
   section, so it keeps the card's own measure and disappears with it once the
   results arrive. Centred, and images held to the width they are given. */
.client-viewer-ad {
    max-width: 46rem;
    margin: 0 auto 1.75rem;
    text-align: center;
}

.client-viewer-ad :is(img, iframe) { max-width: 100%; height: auto; }

@media (max-width: 640px) {
    .client-viewer-ad { margin-bottom: 1.25rem; }
}

/* Progress and failure, as a card in the middle of the page: there is no field
   on show here for a line of text to sit under. One card carries all three
   states — searching, nothing found, and nothing searched for yet — so the page
   never jumps between differently shaped blocks.

   The section itself is nothing but spacing — the card is what is seen. */
.client-dl-state { padding: 4rem 0; background: #f5f5f7; box-shadow: 0 15px 35px rgba(0, 0, 0, .05); border: 1px solid rgba(0, 0, 0, .03); }

.client-dl-state[hidden] { display: none; }
.client-dl-state-card[hidden] { display: none; }

/* Once the results are drawn the card goes, and the ad above it stays — it
   belongs to the page rather than to the wait. What is left is the ad alone, so
   the section drops its own panel and keeps only the space the ad needs. */
.client-dl-state.is-ad-only {
    padding: 1.75rem 0 0;
    background: none;
    border: 0;
    box-shadow: none;
}

.client-dl-state.is-ad-only .client-viewer-ad { margin-bottom: 0; }

/* Nothing behind the card any more, so the lift has to come from the shadow
   alone: three of them, each wider and fainter than the last — a hairline that
   draws the edge, a close shadow that seats it on the page, and a wide soft one
   that lets it float. The border is lighter than the site's usual line, since
   the shadow is already describing the shape. */
.client-dl-state-card {
    max-width: 46rem;
    margin: 0 auto;
    padding: 3.5rem 1.75rem;
    border: 1px solid color-mix(in oklab, var(--line) 55%, var(--paper));
    border-radius: 28px;
    background: var(--paper);
    box-shadow:
        0 1px 2px rgba(22, 21, 18, .04),
        0 10px 24px -14px rgba(22, 21, 18, .18),
        0 40px 70px -40px rgba(22, 21, 18, .3);
    text-align: center;
}

/* The icon sits in a soft wash of the site's own colour, fading out to the
   card — the glow in the middle rather than a hard disc. */
.client-dl-state-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 7rem;
    height: 7rem;
    margin-bottom: 1.5rem;
    border-radius: 50%;
    background: radial-gradient(
        circle,
        color-mix(in oklab, var(--client-banner-bg, #e60023) 20%, var(--paper)) 0%,
        color-mix(in oklab, var(--client-banner-bg, #e60023) 6%, var(--paper)) 55%,
        var(--paper) 78%
    );
}

.client-dl-state-ghost {
    width: 3rem;
    height: 3rem;
    color: var(--client-banner-bg, #e60023);
}

.client-dl-state-ghost[hidden] { display: none; }

/* The searching state: a ring turning in the same colour. */
.client-dl-state-spinner {
    width: 2.75rem;
    height: 2.75rem;
    border-radius: 50%;
    border: 3px solid color-mix(in oklab, var(--client-banner-bg, #e60023) 20%, transparent);
    border-top-color: var(--client-banner-bg, #e60023);
    animation: client-dl-spin .85s linear infinite;
}

.client-dl-state-spinner[hidden] { display: none; }

@keyframes client-dl-spin { to { transform: rotate(360deg); } }

@media (prefers-reduced-motion: reduce) {
    .client-dl-state-spinner { animation-duration: 2.4s; }
}

.client-dl-state-title {
    margin: 0 0 .625rem;
    color: var(--ink);
    font-size: 1.625rem;
    font-weight: 800;
    line-height: 1.25;
    letter-spacing: -.015em;
}

.client-dl-state-text {
    max-width: 34rem;
    /* The gap below belongs to the button, not to this line, so a card with no
       button ends cleanly on the message. */
    margin: 0 auto;
    color: var(--ink-2);
    font-size: 1.0625rem;
    line-height: 1.6;
    /* A service's message can carry a long link; it wraps rather than widening
       the card. */
    overflow-wrap: anywhere;
}

/* The way back to the downloader. A pill, so it reads as the one thing left to
   do on a page that has nothing else on it. */
.client-dl-state-action {
    margin-top: 1.75rem;
    border-radius: 999px;
    padding: .875rem 1.75rem;
    font-size: .875rem;
}

.client-dl-state-action[hidden] { display: none; }

.client-dl-state-action svg {
    width: 1.0625rem;
    height: 1.0625rem;
}

/* The results are the first thing on the page, so they keep a little air above
   them rather than butting against the header. */
.client-viewer .client-section.client-dl { margin: 3rem 0; }

@media (max-width: 640px) {
    .client-dl-state { padding: 2.5rem 0; }
    .client-dl-state-card {
        padding: 2.5rem 1.25rem;
        border-radius: 22px;
    }
    .client-dl-state-icon {
        width: 5.5rem;
        height: 5.5rem;
        margin-bottom: 1.125rem;
    }
    .client-dl-state-ghost { width: 2.5rem; height: 2.5rem; }
    .client-dl-state-spinner { width: 2.25rem; height: 2.25rem; }
    .client-dl-state-title { font-size: 1.3125rem; }
    .client-dl-state-text { font-size: .9375rem; }
    .client-dl-state-action { margin-top: 1.5rem; }
    .client-viewer .client-section.client-dl { margin: 2rem 0; }
}

.client-section.client-dl { margin: 2rem 0; }

.client-dl-summary {
    margin: 0 0 1.25rem;
    color: var(--ink-3);
    font-size: .8125rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    text-align: center;
}

/* Posts / Stories tabs for profile searches. */
.client-dl-tabs {
    display: flex;
    justify-content: center;
    gap: .5rem;
    margin: 0 0 1.5rem;
}

.client-dl-tab {
    padding: .55rem 1.5rem;
    border: 1px solid var(--line-strong);
    border-radius: 999px;
    background: var(--paper);
    color: var(--ink-2);
    font: inherit;
    font-size: .9375rem;
    font-weight: 600;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}

@media (hover: hover) {
    .client-dl-tab:hover { border-color: var(--ink); color: var(--ink); }
}

.client-dl-tab.is-active {
    background: var(--ink);
    border-color: var(--ink);
    color: var(--paper);
}

/* An empty tab explains itself instead of showing a blank grid. */
.client-dl-empty {
    grid-column: 1 / -1;
    margin: 0;
    padding: 2.5rem 1rem;
    text-align: center;
    color: var(--ink-3);
    font-size: 1rem;
}

.client-dl-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(210px, 1fr));
    gap: 1.25rem;
}

/* A single result reads better as one portrait card in the middle. */
.client-dl-grid:has(> :only-child) {
    grid-template-columns: minmax(0, 380px);
    justify-content: center;
}

.client-dl-card {
    border: 1px solid var(--line);
    border-radius: 14px;
    overflow: hidden;
    background: var(--paper);
    box-shadow: 0 1px 2px rgba(22, 21, 18, .05);
    transition: transform .2s ease, box-shadow .2s ease, border-color .2s ease;
    animation: client-dl-in .45s cubic-bezier(.2, .7, .2, 1) backwards;
    animation-delay: calc(var(--dl-i, 0) * 60ms);
}

@keyframes client-dl-in {
    from { opacity: 0; transform: translateY(18px); }
    to { opacity: 1; transform: none; }
}

@media (hover: hover) {
    .client-dl-card:hover {
        transform: translateY(-4px);
        border-color: color-mix(in oklab, var(--client-banner-bg, #e60023) 45%, var(--line));
        box-shadow: 0 14px 30px -16px color-mix(in oklab, var(--client-banner-bg, #e60023) 45%, rgba(22, 21, 18, .3));
    }
}

/* A button, so the preview opens from keyboard too. */
.client-dl-thumb {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 4 / 5;
    padding: 0;
    border: 0;
    background: var(--line);
    cursor: pointer;
}

/* Play affordance on video cards: circle + triangle, no image assets. */
.client-dl-play {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 3.25rem;
    height: 3.25rem;
    transform: translate(-50%, -50%);
    border-radius: 999px;
    background: rgba(16, 15, 13, .55);
    backdrop-filter: blur(4px);
    pointer-events: none;
    transition: transform .2s ease, background-color .2s ease;
}

.client-dl-play::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 54%;
    transform: translate(-50%, -50%);
    border-style: solid;
    border-width: .55rem 0 .55rem .9rem;
    border-color: transparent transparent transparent #fff;
}

@media (hover: hover) {
    .client-dl-thumb:hover .client-dl-play {
        transform: translate(-50%, -50%) scale(1.12);
        background: var(--client-banner-bg, #e60023);
    }
}

.client-dl-thumb img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.client-dl-type {
    position: absolute;
    top: 10px;
    inset-inline-start: 10px;
    padding: .25rem .7rem;
    border-radius: 999px;
    background: rgba(16, 15, 13, .6);
    color: #fff;
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .04em;
    backdrop-filter: blur(6px);
}

.client-dl-actions { padding: .875rem; }

/* Public counts on a profile: followers and the rest, above its downloads. */
.client-stats {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .625rem;
    margin: 0 0 1.25rem;
}

.client-stat {
    display: grid;
    gap: .125rem;
    min-width: 5.5rem;
    padding: .625rem .875rem;
    border: 1px solid var(--line);
    border-radius: 12px;
    background: var(--paper);
    text-align: center;
}

.client-stat-value {
    color: var(--ink);
    font-size: 1.0625rem;
    font-weight: 700;
    line-height: 1.2;
}

.client-stat-label {
    color: var(--ink-3);
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
}

@media (max-width: 480px) {
    .client-stat { min-width: 4.5rem; padding: .5rem .625rem; }
    .client-stat-value { font-size: .9375rem; }
}
/* Title and channel on a search result, so twelve cards can be told apart. */
.client-dl-title {
    margin: 0 0 .125rem;
    color: var(--ink);
    font-size: .9375rem;
    font-weight: 600;
    line-height: 1.35;
    /* Two lines at most: titles run long and would push cards out of line. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.client-dl-channel {
    margin: 0 0 .625rem;
    color: var(--ink-3);
    font-size: .8125rem;
}
/* A single result is the same card as any other — same width cap from the
   grid's one-child rule, same portrait frame, same shadow and hover. Only its
   actions differ: the downloads are offered directly, one button per line. */
.client-dl-stack { display: grid; gap: .625rem; }

.client-dl-button {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 100%;
    padding: .7rem 1rem;
    border: 0;
    border-radius: 10px;
    font: inherit;
    font-size: .9375rem;
    font-weight: 600;
    cursor: pointer;
    text-align: center;
    transition: filter .15s ease, transform .1s ease;
}

.client-dl-button:hover { filter: brightness(1.08); }
.client-dl-button:active { transform: translateY(1px); }


.client-dl-save {
    background: var(--ink);
    color: var(--paper);
}

/* While the file transfers the button is disabled and narrates progress;
   it then reports the outcome for a moment before returning to its label. */
.client-dl-button:disabled { cursor: progress; opacity: .8; }
.client-dl-button:disabled:hover { filter: none; }
.client-dl-save.is-done { background: #1d7a46; }
.client-dl-save.is-failed { background: #b3261e; }

/* Why a download failed, under the button that failed. */
.client-dl-error {
    margin: .625rem 0 0;
    color: #b3261e;
    font-size: .8125rem;
    font-weight: 600;
    line-height: 1.45;
    text-align: center;
}

.client-dl-again {
    display: flex;
    justify-content: center;
    margin-top: 1.75rem;
}

/* Preview lightbox — the media itself is the whole surface. */
.client-dl-modal {
    padding: 0;
    border: 0;
    border-radius: 14px;
    background: #0c0b0a;
    max-width: min(92vw, 56rem);
    overflow: visible;
}

.client-dl-modal::backdrop {
    background: rgba(10, 9, 8, .78);
    backdrop-filter: blur(3px);
}

/* A floor under the dialog so a still-loading preview reads as "loading",
   not as an empty sliver. */
.client-dl-modal-body {
    display: grid;
    place-items: center;
    min-width: min(18rem, 80vw);
    min-height: 12rem;
}

/* Audio preview: the video's still with a player beneath it. */
.client-dl-audio-preview { display: grid; gap: .75rem; padding: 1rem; }
.client-dl-audio-preview img { max-width: 100%; max-height: 60vh; border-radius: 10px; }
.client-dl-audio-preview audio { width: 100%; }

.client-dl-modal-body :is(video, img) {
    display: block;
    max-width: 100%;
    max-height: 84vh;
    margin: 0 auto;
    border-radius: 14px;
    background: #000;
}

.client-dl-modal-close {
    position: absolute;
    top: -2.75rem;
    inset-inline-end: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: rgba(255, 255, 255, .14);
    color: #fff;
    cursor: pointer;
    transition: background-color .15s ease;
}

.client-dl-modal-close:hover { background: rgba(255, 255, 255, .3); }
.client-dl-modal-close svg { width: 18px; height: 18px; }

@media (prefers-reduced-motion: reduce) {
    .client-dl-card { animation: none; transition: none; }
}

/* ==========================================================================
   Typography — one variable scale for the whole site
   ========================================================================== */
.client-body {
    --client-h1: 1.875rem;
    --client-h2: 1.75rem;
    --client-h3: 1.25rem;
    --client-h4: 1.0625rem;
    --client-heading-weight: 700;
    --client-heading-lh: 1.25;
    --client-heading-tracking: -.02em;
    --client-heading-space: 2rem;

    --client-text: 18px;
    --client-text-lh: 1.75;
    --client-text-space: 1rem;
}

/* The gap between sections, from Settings > Layout; 50px when it has not been set. */
.client-section { margin: var(--client-section-space, 50px) 0; }
/* Whatever follows the band — or the intro under it — sits directly beneath:
   those already carry the space, and the 404 brings 5rem of padding of its own. */
.client-page-head + .client-section,
.client-page-intro-wrap + .client-section { padding-top: 0; }

.client-rich { color: var(--ink-2); font-size: var(--client-text); line-height: var(--client-text-lh); }
.client-rich > :first-child { margin-top: 0; }
.client-rich > :last-child { margin-bottom: 0; }

/* The single heading definition. .client-page-title is the page-level h1 on
   footer pages and the 404, and uses the same scale as any other heading. */
.client-rich :is(h1, h2, h3, h4, h5, h6),
.client-page-title {
    margin: var(--client-heading-space) 0 .875rem;
    color: var(--ink);
    font-weight: var(--client-heading-weight);
    line-height: var(--client-heading-lh);
    letter-spacing: var(--client-heading-tracking);
}

.client-page-title,
.client-rich h1 { font-size: var(--client-h1); }
.client-rich h2 { font-size: var(--client-h2); }
.client-rich h3 { font-size: var(--client-h3); }
.client-rich h4 { font-size: var(--client-h4); }
/* The page-level h1 rides in a soft wash band. The band is its own element
   rather than the heading itself, so the colour runs the full width of the
   window while the words stay inside the same measure as the content below —
   no vw arithmetic, and nothing that can push a horizontal scrollbar. */
.client-page-head {
    /* Flush against the site header: this is the first thing under it. */
    margin: 0 0 var(--client-heading-space);
    padding: 3.75rem 0;
    background: #f5f5f3;
    background: color-mix(in oklab, var(--ink) 4%, var(--paper));
}

.client-page-title {
    margin: 0;
    text-align: center;
}

/* Optional intro below the band, from Settings > Blog Page. Held to a readable
   measure so a long line does not run the full width of the page. */
.client-page-intro-wrap { margin-bottom: var(--client-heading-space); }

.client-page-intro {
    max-width: 44rem;
    margin: 0 auto;
    color: var(--ink-2);
    font-size: 1.0625rem;
    line-height: 1.65;
    text-align: center;
}

/* The intro is authored in the rich-text editor, so it arrives as paragraphs,
   lists and links rather than one run of text. */
.client-page-intro > :first-child { margin-top: 0; }
.client-page-intro > :last-child { margin-bottom: 0; }
.client-page-intro p { margin: 0 0 .75rem; }
.client-page-intro :is(h1, h2, h3, h4, h5, h6) { margin: 0 0 .5rem; color: var(--ink); }
.client-page-intro :is(ul, ol) { display: inline-block; margin: 0 0 .75rem; padding-inline-start: 1.25rem; text-align: start; }
.client-page-intro li { margin-bottom: .25rem; }
.client-page-intro strong { color: var(--ink); }
.client-page-intro a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }

.client-rich p { margin: 0 0 var(--client-text-space); }

/* Standalone section headings (Feature Heading, FAQ Heading): spacing only. */
.client-section-heading { margin-bottom: 1.75rem; }
.client-section-heading :is(h1, h2, h3, h4, h5, h6) { margin: 0; }


.client-rich :is(ul, ol) { margin: 0 0 1.25rem; padding-left: 1.5rem; }
.client-rich li { margin-bottom: .625rem; padding-left: .25rem; }
.client-rich a {
    color: var(--ink);
    text-decoration: underline;
    text-decoration-color: var(--line-strong);
    text-underline-offset: 3px;
}
.client-rich a:hover { text-decoration-color: var(--ink); }
.client-rich img { max-width: 100%; height: auto; }
.client-rich strong, .client-rich b { color: var(--ink); font-weight: 700; }
.client-rich blockquote {
    margin: 1.25rem 0;
    padding: .5rem 0 .5rem 1.125rem;
    border-left: 3px solid var(--ink);
    color: var(--ink-2);
    font-style: italic;
}
.client-rich pre { overflow-x: auto; padding: 1rem; background: var(--ink); color: var(--paper); font-size: .875rem; }
.client-rich code { font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace; font-size: .9em; }
.client-rich table { width: 100%; border-collapse: collapse; margin: 0 0 1rem; }
.client-rich :is(th, td) { border: 1px solid var(--line); padding: .625rem .75rem; text-align: left; }
.client-rich th { background: rgba(22, 21, 18, .03); }

/* Quill output: alignment/indent classes, list types, and the .ql-ui span. */
.client-rich .ql-align-center { text-align: center; }
.client-rich .ql-align-right { text-align: right; }
.client-rich .ql-align-justify { text-align: justify; }
.client-rich .ql-ui { display: none; }
.client-rich li[data-list="bullet"] { list-style-type: disc; }
.client-rich li[data-list="ordered"] { list-style-type: decimal; }
.client-rich li[data-list="unchecked"],
.client-rich li[data-list="checked"] { list-style-type: none; }
.client-rich .ql-indent-1 { padding-left: 1em; }
.client-rich .ql-indent-2 { padding-left: 3em; }
.client-rich .ql-indent-3 { padding-left: 6em; }

[dir="rtl"] .client-rich .ql-indent-1 { padding-left: 0; padding-right: 3em; }
[dir="rtl"] .client-rich .ql-indent-2 { padding-left: 0; padding-right: 6em; }
[dir="rtl"] .client-rich .ql-indent-3 { padding-left: 0; padding-right: 9em; }

/* ==========================================================================
   Feature cards

   Clean white cards with soft depth, keyed to the site's brand colour: the
   numbered badge, the hover glow and the coloured shadow all derive from
   --client-banner-bg (Settings > Banner), so the section matches the banner
   with no extra configuration. Where colour math is needed the value is
   mixed toward white with color-mix — a solid-colour fallback is declared
   first for browsers without it.

   Motion: staggered fade-up on first scroll into view (same [data-animate]/
   --reveal-i/.is-revealed contract the layout script drives), and on hover
   the card lifts on a brand-tinted shadow while the badge tilts.
   ========================================================================== */
/* On the white page ground the section gets its own faintly brand-tinted
   band, so the white cards have a surface to sit on at rest instead of
   dissolving into the page. Full-width because the section element spans the
   viewport; the container inside keeps the content measure. */
.client-features {
    background: #fafafa;
    background: color-mix(in oklab, var(--client-banner-bg, #e60023) 3%, #fbfbfa);
    padding: 2.25rem 0;
}

.client-feature-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1.5rem;
}

/* ==========================================================================
   How to Use — step cards on a journey

   Cards, like the features, but read as a sequence rather than a set: a
   round "Step n" badge sits across each card's top edge, a brand-coloured
   rule tops the card, and a dashed line runs from one badge to the next —
   across the row on a wide screen, down the column on a narrow one. It sits
   on the same tinted band as the features. Colour comes from
   --client-banner-bg, as the features' does.
   ========================================================================== */
/* The same faintly brand-tinted band the features sit on, so the white cards
   have a surface under them. */
.client-how-to {
    background: #fafafa;
    background: color-mix(in oklab, var(--client-banner-bg, #e60023) 3%, #fbfbfa);
    padding: 2.75rem 0 2.25rem;
}

/* An <ol> for its order; the badge carries the visible number, so the list's
   own markers and indent are taken off. */
/*
 * A wrapping row rather than a grid, so a last row that is not full is
 * centred under the one above instead of hanging off to the left.
 */
.client-how-to-steps {
    --how-to-gap: 2rem;
    list-style: none;
    margin: 0;
    padding: 2.5rem 0 0; /* room for the first row's badges */
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    column-gap: var(--how-to-gap);
    row-gap: 3.75rem;    /* badges overhang by half their height */
}

.client-how-to-card {
    position: relative;
    flex: 0 1 100%;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 2.75rem 1.5rem 1.75rem;
    border: 1px solid var(--line);
    border-top: 0;
    border-radius: 22px;
    background: #fff;
    box-shadow:
        0 1px 2px rgba(22, 21, 18, .05),
        0 16px 34px -22px rgba(22, 21, 18, .2);
    transition:
        transform .35s cubic-bezier(.2, .7, .2, 1),
        box-shadow .35s ease;
}

/* The brand rule along the top edge, drawn inside the rounded corners. */
.client-how-to-card::before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 5px;
    border-radius: 22px 22px 0 0;
    background: var(--client-banner-bg, #e60023);
    background: linear-gradient(
        90deg,
        var(--client-banner-bg, #e60023),
        color-mix(in oklab, var(--client-banner-bg, #e60023) 55%, white)
    );
}

/* The journey line: from this card's badge to the next card's. On one
   column it drops straight down through the gap below the card. */
.client-how-to-card::after {
    content: "";
    position: absolute;
    left: 50%;
    top: 100%;
    width: 0;
    height: 3.75rem;
    border-left: 2px dashed color-mix(in oklab, var(--client-banner-bg, #e60023) 45%, var(--line));
    transform: translateX(-1px);
    pointer-events: none;
}
.client-how-to-card:last-child::after { display: none; }

.client-how-to-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 24px 46px -22px color-mix(in oklab, var(--client-banner-bg, #e60023) 40%, rgba(22, 21, 18, .28));
}

/* The badge: a ring in the brand colour with "STEP" over the number, sitting
   half above the card. Filled in on hover. */
.client-how-to-badge {
    position: absolute;
    top: 0;
    left: 50%;
    z-index: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    width: 4.25rem;
    height: 4.25rem;
    border-radius: 50%;
    background: #fff;
    border: 3px solid var(--client-banner-bg, #e60023);
    color: var(--client-banner-bg, #e60023);
    box-shadow:
        0 0 0 6px #fff,
        0 12px 24px -12px color-mix(in oklab, var(--client-banner-bg, #e60023) 70%, transparent);
    transform: translate(-50%, -50%);
    transition: background-color .3s ease, color .3s ease, transform .35s cubic-bezier(.2, .7, .2, 1);
}
.client-how-to-card:hover .client-how-to-badge {
    background: var(--client-banner-bg, #e60023);
    color: #fff;
    transform: translate(-50%, -50%) scale(1.06);
}

.client-how-to-badge-label {
    font-size: .625rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    line-height: 1;
}
.client-how-to-badge-number {
    margin-top: .125rem;
    font-size: 1.5rem;
    font-weight: 800;
    line-height: 1;
    font-variant-numeric: tabular-nums;
}

.client-how-to-card .client-rich {
    --client-text: 1rem;
    --client-text-lh: 1.65;
    --client-heading-space: 0;
}
.client-how-to-card .client-rich :is(h1, h2, h3, h4, h5, h6) {
    margin-bottom: .5rem;
    font-size: var(--client-h4);
    line-height: 1.35;
}
.client-how-to-card .client-rich p:last-child { margin-bottom: 0; }

/*
 * Wider screens: the steps sit side by side and the line runs across, from
 * the middle of one badge to the middle of the next, behind the cards'
 * shadows. The last card of each row has no line: the next step starts a new
 * row. Two to a row on a tablet, three on a desktop.
 */
@media (min-width: 640px) {
    .client-how-to-card { flex-basis: calc((100% - var(--how-to-gap)) / 2); }

    .client-how-to-card::after {
        top: 0;
        left: 50%;
        width: calc(100% + var(--how-to-gap));
        height: 0;
        border-left: 0;
        border-top: 2px dashed color-mix(in oklab, var(--client-banner-bg, #e60023) 45%, var(--line));
        transform: translateY(-1px);
        z-index: 0;
    }
    .client-how-to-card:nth-child(2n)::after { display: none; }
}

@media (min-width: 900px) {
    .client-how-to-card { flex-basis: calc((100% - 2 * var(--how-to-gap)) / 3); }
    .client-how-to-card:nth-child(2n)::after { display: block; }
    .client-how-to-card:nth-child(3n)::after,
    .client-how-to-card:last-child::after { display: none; }
}

@media (prefers-reduced-motion: reduce) {
    .client-how-to-card,
    .client-how-to-badge { transition: none; }
    .client-how-to-card:hover { transform: none; }
}

.client-feature-card {
    position: relative;
    display: flex;
    flex-direction: column;
    border: 1px solid var(--line);
    border-radius: 20px;
    background: #fff;
    padding: 1.875rem 1.625rem;
    /* Resting depth: a contact shadow plus a soft ambient one, so the card
       already floats on the band before the hover lift takes over. */
    box-shadow:
        0 1px 2px rgba(22, 21, 18, .05),
        0 12px 28px -18px rgba(22, 21, 18, .14);
    transition:
        transform .35s cubic-bezier(.2, .7, .2, 1),
        box-shadow .35s ease,
        border-color .35s ease;
}

.client-feature-card:hover {
    transform: translateY(-6px);
    border-color: color-mix(in oklab, var(--client-banner-bg, #e60023) 30%, var(--line));
    box-shadow: 0 22px 44px -18px color-mix(in oklab, var(--client-banner-bg, #e60023) 35%, rgba(22, 21, 18, .25));
}

/* A soft brand-coloured wash that breathes in from the top on hover. */
.client-feature-card::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    background: radial-gradient(
        120% 65% at 50% 0%,
        color-mix(in oklab, var(--client-banner-bg, #e60023) 8%, transparent),
        transparent 70%
    );
    opacity: 0;
    transition: opacity .35s ease;
    pointer-events: none;
}
.client-feature-card:hover::after { opacity: 1; }

/* The number sits in a gradient badge — brand colour into a lighter tint. */
.client-feature-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    flex: 0 0 auto;
    align-self: flex-start;
    margin-bottom: 1.125rem;
    border-radius: 14px;
    background: var(--client-banner-bg, #e60023);
    background: linear-gradient(
        135deg,
        var(--client-banner-bg, #e60023),
        color-mix(in oklab, var(--client-banner-bg, #e60023) 65%, white)
    );
    color: #fff;
    font-size: 1.125rem;
    font-weight: 800;
    font-variant-numeric: tabular-nums;
    box-shadow: 0 10px 20px -10px color-mix(in oklab, var(--client-banner-bg, #e60023) 70%, transparent);
    transition: transform .35s cubic-bezier(.2, .7, .2, 1);
}
.client-feature-card:hover .client-feature-number { transform: scale(1.08) rotate(-5deg); }

/* Cards sit one step down the shared scale rather than inventing sizes. */
.client-feature-card .client-rich {
    position: relative;
    --client-text: 1rem;
    --client-text-lh: 1.65;
    --client-heading-space: 0;
}
.client-feature-card .client-rich :is(h1, h2, h3, h4, h5, h6) {
    margin-bottom: .625rem;
    font-size: var(--client-h4);
    line-height: 1.35;
}
.client-feature-card .client-rich p:last-child { margin-bottom: 0; }

/* Entrance: gentle fade-up, only while [data-animate] is present — the
   script removes it afterwards so hover keeps its own timing. */
@media (prefers-reduced-motion: no-preference) {
    .client-feature-grid[data-animate] .client-feature-card {
        opacity: 0;
        transform: translateY(24px);
    }
    .client-feature-grid[data-animate].is-revealed .client-feature-card {
        opacity: 1;
        transform: none;
        transition:
            opacity .55s ease calc(var(--reveal-i, 0) * 90ms),
            transform .55s cubic-bezier(.2, .7, .2, 1) calc(var(--reveal-i, 0) * 90ms);
    }
}

/* ==========================================================================
   Features designs (Settings › Layout › Features Design)

   "cards" is the design above and needs nothing here. Each other design is a
   variant keyed on .client-features--<design>, re-dressing the same markup —
   the grid, the card, the number, the text — so a page's content never has
   to change to change its look. Colour still comes from --client-banner-bg.
   ========================================================================== */

/* List: rows rather than boxes. A round number beside the text, a hairline
   between rows, two to a row on a wide screen. */
.client-features--list .client-feature-grid { gap: 0 2.5rem; }
.client-features--list .client-feature-card {
    flex-direction: row;
    align-items: flex-start;
    gap: 1.125rem;
    padding: 1.5rem 0;
    border: 0;
    border-bottom: 1px solid color-mix(in oklab, var(--client-banner-bg, #e60023) 14%, var(--line));
    border-radius: 0;
    background: transparent;
    box-shadow: none;
}
.client-features--list .client-feature-card::after { display: none; }
.client-features--list .client-feature-card:hover { transform: none; box-shadow: none; border-color: color-mix(in oklab, var(--client-banner-bg, #e60023) 40%, var(--line)); }
.client-features--list .client-feature-number {
    width: 2.75rem;
    height: 2.75rem;
    margin: 0;
    border-radius: 999px;
    font-size: 1rem;
}
.client-features--list .client-feature-card:hover .client-feature-number { transform: scale(1.06); }
.client-features--list .client-feature-card .client-rich { flex: 1 1 auto; min-width: 0; }
@media (min-width: 900px) {
    .client-features--list .client-feature-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* Accent: a white card with a coloured edge down its side, and the number
   set large and faint in the corner rather than in a badge. */
.client-features--accent .client-feature-card {
    padding: 1.75rem 1.75rem 1.75rem 2rem;
    border-radius: 14px;
    border-left: 5px solid var(--client-banner-bg, #e60023);
    overflow: hidden;
}
[dir="rtl"] .client-features--accent .client-feature-card {
    border-left: 1px solid var(--line);
    border-right: 5px solid var(--client-banner-bg, #e60023);
    padding: 1.75rem 2rem 1.75rem 1.75rem;
}
.client-features--accent .client-feature-number {
    position: absolute;
    top: .5rem;
    right: 1rem;
    width: auto;
    height: auto;
    margin: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    color: color-mix(in oklab, var(--client-banner-bg, #e60023) 16%, transparent);
    font-size: 4rem;
    font-weight: 800;
    line-height: 1;
}
[dir="rtl"] .client-features--accent .client-feature-number { right: auto; left: 1rem; }
.client-features--accent .client-feature-card:hover .client-feature-number { transform: none; color: color-mix(in oklab, var(--client-banner-bg, #e60023) 26%, transparent); }
.client-features--accent .client-feature-card .client-rich { padding-right: 3.5rem; }
[dir="rtl"] .client-features--accent .client-feature-card .client-rich { padding-right: 0; padding-left: 3.5rem; }

/* Tiles: white tiles with a coloured outline, centred, the number in a solid
   round badge on top. White rather than tinted: the section's own band is a
   faint tint of the same colour, and tinted tiles on it all but vanished. */
.client-features--tiles .client-feature-card {
    align-items: center;
    text-align: center;
    padding: 2.25rem 1.75rem 2rem;
    border: 2px solid color-mix(in oklab, var(--client-banner-bg, #e60023) 22%, white);
    border-radius: 24px;
    background: #fff;
    box-shadow: 0 14px 30px -24px color-mix(in oklab, var(--client-banner-bg, #e60023) 40%, rgba(22, 21, 18, .2));
}
.client-features--tiles .client-feature-card::after { display: none; }
.client-features--tiles .client-feature-card:hover {
    border-color: color-mix(in oklab, var(--client-banner-bg, #e60023) 55%, white);
    box-shadow: 0 22px 42px -24px color-mix(in oklab, var(--client-banner-bg, #e60023) 50%, rgba(22, 21, 18, .25));
}
.client-features--tiles .client-feature-number {
    align-self: center;
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 999px;
    color: #fff;
    font-size: 1.25rem;
    box-shadow:
        0 0 0 6px color-mix(in oklab, var(--client-banner-bg, #e60023) 10%, white),
        0 10px 22px -10px color-mix(in oklab, var(--client-banner-bg, #e60023) 60%, transparent);
}
/* ==========================================================================
   How to Use designs (Settings › Layout › How to Use Design)

   "journey" is the design above and needs nothing here. Each other design is
   a variant keyed on .client-how-to--<design>, re-dressing the same markup —
   the list, the card, the Step badge, the text. Every one keeps the numbers:
   this is the section that counts. Colour comes from --client-banner-bg.

   The journey's top rule (::before) and its dashed joining line (::after)
   are switched off or redrawn by each variant; these rules come after the
   journey's own breakpoints, so they win at every width.
   ========================================================================== */

/* ---- Timeline: one column down a vertical line, the number on the line. */
.client-how-to--timeline .client-how-to-steps {
    position: relative;
    display: block;
    max-width: 52rem;
    margin: 0 auto;
    padding: 0;
}
.client-how-to--timeline .client-how-to-steps::before {
    content: "";
    position: absolute;
    top: 1.5rem;
    bottom: 1.5rem;
    left: 1.75rem;
    width: 2px;
    background: color-mix(in oklab, var(--client-banner-bg, #e60023) 30%, var(--line));
}
[dir="rtl"] .client-how-to--timeline .client-how-to-steps::before { left: auto; right: 1.75rem; }
.client-how-to--timeline .client-how-to-card {
    align-items: flex-start;
    text-align: left;
    margin: 0 0 1.25rem 4.75rem;
    padding: 1.5rem 1.75rem;
    border-top: 1px solid var(--line);
    border-radius: 16px;
}
.client-how-to--timeline .client-how-to-card:last-child { margin-bottom: 0; }
[dir="rtl"] .client-how-to--timeline .client-how-to-card { text-align: right; margin: 0 4.75rem 1.25rem 0; }
.client-how-to--timeline .client-how-to-card::before,
.client-how-to--timeline .client-how-to-card::after { display: none; }
.client-how-to--timeline .client-how-to-card:hover { transform: translateX(4px); }
.client-how-to--timeline .client-how-to-badge {
    top: 1.25rem;
    left: -4.75rem;
    width: 3.5rem;
    height: 3.5rem;
    transform: none;
    background: var(--client-banner-bg, #e60023);
    color: #fff;
    box-shadow: 0 0 0 6px #fff, 0 10px 22px -12px color-mix(in oklab, var(--client-banner-bg, #e60023) 70%, transparent);
}
[dir="rtl"] .client-how-to--timeline .client-how-to-badge { left: auto; right: -4.75rem; }
.client-how-to--timeline .client-how-to-card:hover .client-how-to-badge { transform: scale(1.06); }
.client-how-to--timeline .client-how-to-badge-number { font-size: 1.25rem; }

/*
 * Phones: the line, the circles and the gap beside them took about a quarter
 * of the screen, leaving the cards a narrow column of text. Tightened here so
 * the cards get the width: a smaller circle closer to the edge, less padding,
 * and no sideways nudge on hover, which a tap would leave stuck.
 */
@media (max-width: 639.98px) {
    .client-how-to--timeline .client-how-to-steps::before { left: 1.25rem; }
    [dir="rtl"] .client-how-to--timeline .client-how-to-steps::before { left: auto; right: 1.25rem; }
    .client-how-to--timeline .client-how-to-card {
        margin-left: 3.25rem;
        padding: 1.125rem 1.125rem 1.25rem;
        border-radius: 14px;
    }
    [dir="rtl"] .client-how-to--timeline .client-how-to-card { margin: 0 3.25rem 1.25rem 0; }
    .client-how-to--timeline .client-how-to-card:hover { transform: none; }
    .client-how-to--timeline .client-how-to-badge {
        top: 1rem;
        left: -3.25rem;
        width: 2.5rem;
        height: 2.5rem;
        border-width: 2px;
        box-shadow: 0 0 0 4px #fff, 0 8px 18px -10px color-mix(in oklab, var(--client-banner-bg, #e60023) 70%, transparent);
    }
    [dir="rtl"] .client-how-to--timeline .client-how-to-badge { left: auto; right: -3.25rem; }
    .client-how-to--timeline .client-how-to-badge-label { font-size: .5rem; letter-spacing: .08em; }
    .client-how-to--timeline .client-how-to-badge-number { font-size: 1rem; }
}

/* ---- Flow: cards side by side with an arrow between each, the step set as
   a large "STEP 01" heading in the corner rather than a badge. */
.client-how-to--flow .client-how-to-steps { padding-top: 0; row-gap: 3rem; }
.client-how-to--flow .client-how-to-card {
    align-items: flex-start;
    text-align: left;
    padding: 1.75rem 1.625rem;
    border-top: 1px solid var(--line);
    border-radius: 18px;
}
[dir="rtl"] .client-how-to--flow .client-how-to-card { text-align: right; }
.client-how-to--flow .client-how-to-card::before {
    top: auto;
    bottom: 0;
    height: 4px;
    border-radius: 0 0 18px 18px;
}
.client-how-to--flow .client-how-to-badge {
    position: static;
    flex-direction: row;
    align-items: baseline;
    gap: .5rem;
    width: auto;
    height: auto;
    margin-bottom: .875rem;
    border: 0;
    border-radius: 0;
    background: none;
    box-shadow: none;
    transform: none;
}
.client-how-to--flow .client-how-to-card:hover .client-how-to-badge { background: none; color: var(--client-banner-bg, #e60023); transform: none; }
.client-how-to--flow .client-how-to-badge-label { font-size: .75rem; }
.client-how-to--flow .client-how-to-badge-number { margin: 0; font-size: 2.25rem; }

/* The arrow: a chevron in the gap, pointing down while the cards stack. */
.client-how-to--flow .client-how-to-card::after {
    top: calc(100% + 1.5rem - .5rem);
    left: 50%;
    width: .875rem;
    height: .875rem;
    border: 0;
    border-right: 3px solid var(--client-banner-bg, #e60023);
    border-bottom: 3px solid var(--client-banner-bg, #e60023);
    transform: translate(-50%, -50%) rotate(45deg);
}
@media (min-width: 640px) {
    .client-how-to--flow .client-how-to-card::after {
        top: 50%;
        left: calc(100% + var(--how-to-gap) / 2);
        width: .875rem;
        height: .875rem;
        border: 0;
        border-top: 3px solid var(--client-banner-bg, #e60023);
        border-right: 3px solid var(--client-banner-bg, #e60023);
        transform: translate(-70%, -50%) rotate(45deg);
    }
    [dir="rtl"] .client-how-to--flow .client-how-to-card::after {
        left: auto;
        right: calc(100% + var(--how-to-gap) / 2);
        transform: translate(70%, -50%) rotate(-135deg);
    }
}

/* ---- Banner: each card headed by a solid coloured strip reading "STEP n",
   the text below it on white. */
.client-how-to--banner .client-how-to-steps { padding-top: 0; row-gap: 1.75rem; }
.client-how-to--banner .client-how-to-card {
    align-items: stretch;
    text-align: left;
    padding: 0;
    overflow: hidden;
    border-top: 1px solid var(--line);
    border-radius: 18px;
}
[dir="rtl"] .client-how-to--banner .client-how-to-card { text-align: right; }
.client-how-to--banner .client-how-to-card::before,
.client-how-to--banner .client-how-to-card::after { display: none; }
.client-how-to--banner .client-how-to-badge {
    position: static;
    flex-direction: row;
    justify-content: flex-start;
    align-items: baseline;
    gap: .5rem;
    width: auto;
    height: auto;
    padding: .875rem 1.5rem;
    border: 0;
    border-radius: 0;
    background: var(--client-banner-bg, #e60023);
    background: linear-gradient(
        90deg,
        var(--client-banner-bg, #e60023),
        color-mix(in oklab, var(--client-banner-bg, #e60023) 70%, white)
    );
    color: #fff;
    box-shadow: none;
    transform: none;
}
.client-how-to--banner .client-how-to-card:hover .client-how-to-badge { transform: none; }
.client-how-to--banner .client-how-to-badge-label { font-size: .8125rem; }
.client-how-to--banner .client-how-to-badge-number { margin: 0; font-size: 1.25rem; }
.client-how-to--banner .client-how-to-card .client-rich { padding: 1.375rem 1.5rem 1.625rem; }

/* ==========================================================================
   FAQ — one card per question

   The heading centred above, then the questions as full-width white cards
   on the plain white page. A card's header holds the question and a plain plus; open,
   the header takes a soft tint of the site's colour, the plus becomes a
   minus, and the answer sits below on white. Colour comes from
   --client-banner-bg, as everywhere else on the page.

   The answer expands with pure CSS: the panel is a grid whose single row
   animates 0fr -> 1fr, and its one child clips with overflow:hidden — no JS
   measuring, any content height works. visibility keeps a collapsed answer
   out of the tab order and away from screen readers.
   ========================================================================== */
.client-faq {
    background: #fff;
    margin-bottom: 0;
}

.client-faq-list { display: grid; gap: .75rem; }

.client-faq-item {
    overflow: hidden;
    border: 1px solid #ededeb;
    border-radius: 12px;
    background: #fff;
    box-shadow: 0 2px 10px -4px rgba(22, 21, 18, .08);
    transition: box-shadow .3s ease;
}
.client-faq-item:hover { box-shadow: 0 6px 18px -8px rgba(22, 21, 18, .14); }

.client-faq-trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
    border: 0;
    background: transparent;
    padding: 1.25rem 1.5rem;
    color: var(--ink);
    font: inherit;
    font-size: 1rem;
    font-weight: 700;
    line-height: 1.45;
    text-align: left;
    cursor: pointer;
    transition: background-color .3s ease, color .3s ease;
}
[dir="rtl"] .client-faq-trigger { text-align: right; }
.client-faq-question { flex: 1 1 auto; min-width: 0; }

/* The open question's header: a soft tint of the site's colour. */
.client-faq-item.is-open .client-faq-trigger {
    background: #fde7ea;
    background: color-mix(in oklab, var(--client-banner-bg, #e60023) 12%, white);
    color: var(--ink);
}

/* A plain plus; open, its upright folds away and a minus is left. */
.client-faq-icon {
    flex: 0 0 auto;
    width: 1.25rem;
    height: 1.25rem;
    color: var(--ink);
}
.client-faq-icon path { stroke-width: 2.4; }
.client-faq-icon-bar {
    transform-origin: 50% 50%;
    transition: transform .3s cubic-bezier(.2, .7, .2, 1);
}
.client-faq-item.is-open .client-faq-icon { color: var(--client-banner-bg, #e60023); }
.client-faq-item.is-open .client-faq-icon-bar { transform: scaleY(0); }

/* Animated expand: the row goes 0fr -> 1fr and the child clips. Padding
   lives on the child, inside the clip, so nothing shows while collapsed. */
.client-faq-panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows .35s cubic-bezier(.2, .7, .2, 1);
}
/* Top and bottom padding are part of the animated state: with border-box
   sizing a child in a 0-height row can never shrink below its own padding,
   so constant vertical padding showed as a blank band under every closed
   question. Side padding adds no height and can stay constant. */
.client-faq-panel > .client-rich {
    overflow: hidden;
    min-height: 0;
    visibility: hidden;
    padding: 0 1.5rem;
    color: var(--ink-2);
    --client-text: 1rem;
    transition:
        visibility .35s,
        padding-top .35s cubic-bezier(.2, .7, .2, 1),
        padding-bottom .35s cubic-bezier(.2, .7, .2, 1);
}
.client-faq-item.is-open .client-faq-panel { grid-template-rows: 1fr; }
.client-faq-item.is-open .client-faq-panel > .client-rich {
    visibility: visible;
    padding-top: 1.125rem;
    padding-bottom: 1.25rem;
}

@media (min-width: 900px) {
    .client-faq-trigger { font-size: 1.0625rem; padding: 1.375rem 1.75rem; }
    .client-faq-panel > .client-rich { padding-left: 1.75rem; padding-right: 1.75rem; }
    .client-faq-item.is-open .client-faq-panel > .client-rich { padding-top: 1.25rem; padding-bottom: 1.375rem; }
}

@media (prefers-reduced-motion: reduce) {
    .client-faq-item,
    .client-faq-trigger,
    .client-faq-icon-bar,
    .client-faq-panel,
    .client-faq-panel > .client-rich { transition: none; }
}

/* ==========================================================================
   FAQ designs (Settings › Layout › FAQ Design)

   "cards" is the design above and needs nothing here. Each other design is a
   variant keyed on .client-faq--<design>, re-dressing the same accordion —
   the list, the item, its header button, the plus/minus and the answer — so
   opening and closing work exactly as before. Colour comes from
   --client-banner-bg.
   ========================================================================== */

/* ---- Minimal: no boxes, a ruled list. The open question turns the
   site's colour; nothing else moves. */
.client-faq--minimal .client-faq-list { gap: 0; border-top: 1px solid var(--line); }
.client-faq--minimal .client-faq-item {
    border: 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    background: transparent;
    box-shadow: none;
}
.client-faq--minimal .client-faq-item:hover { box-shadow: none; }
.client-faq--minimal .client-faq-trigger { padding-left: .25rem; padding-right: .25rem; }
.client-faq--minimal .client-faq-item.is-open .client-faq-trigger {
    background: transparent;
    color: var(--client-banner-bg, #e60023);
}
.client-faq--minimal .client-faq-panel > .client-rich { padding-left: .25rem; padding-right: .25rem; }
.client-faq--minimal .client-faq-item.is-open .client-faq-panel > .client-rich { padding-top: 0; }

/* ---- Grouped: every question in one white panel, a line between each; the
   open one gains a coloured bar down its leading edge and a faint wash. */
.client-faq--grouped .client-faq-list {
    gap: 0;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: 18px;
    background: #fff;
    box-shadow: 0 14px 34px -26px rgba(22, 21, 18, .22);
}
.client-faq--grouped .client-faq-item {
    position: relative;
    border: 0;
    border-bottom: 1px solid var(--line);
    border-radius: 0;
    box-shadow: none;
}
.client-faq--grouped .client-faq-item:last-child { border-bottom: 0; }
.client-faq--grouped .client-faq-item:hover { box-shadow: none; background: color-mix(in oklab, var(--client-banner-bg, #e60023) 2%, white); }
.client-faq--grouped .client-faq-item::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    width: 4px;
    background: var(--client-banner-bg, #e60023);
    transform: scaleY(0);
    transition: transform .3s cubic-bezier(.2, .7, .2, 1);
}
[dir="rtl"] .client-faq--grouped .client-faq-item::before { left: auto; right: 0; }
.client-faq--grouped .client-faq-item.is-open::before { transform: scaleY(1); }
.client-faq--grouped .client-faq-item.is-open { background: color-mix(in oklab, var(--client-banner-bg, #e60023) 4%, white); }
.client-faq--grouped .client-faq-item.is-open .client-faq-trigger {
    background: transparent;
    color: var(--client-banner-bg, #e60023);
}
.client-faq--grouped .client-faq-item.is-open .client-faq-panel > .client-rich { padding-top: 0; }

/* ---- Solid: light grey question pills; the open question's header is
   filled with the site's colour, white text on it, the answer on white. */
.client-faq--solid .client-faq-list { gap: .625rem; }
.client-faq--solid .client-faq-item {
    border: 0;
    border-radius: 14px;
    background: #f3f2f0;
    box-shadow: none;
}
.client-faq--solid .client-faq-item:hover { box-shadow: none; background: #ecebe8; }
.client-faq--solid .client-faq-item.is-open {
    background: #fff;
    box-shadow: 0 0 0 1px color-mix(in oklab, var(--client-banner-bg, #e60023) 30%, var(--line)),
        0 18px 36px -26px color-mix(in oklab, var(--client-banner-bg, #e60023) 45%, rgba(22, 21, 18, .25));
}
.client-faq--solid .client-faq-item.is-open .client-faq-trigger {
    background: var(--client-banner-bg, #e60023);
    color: #fff;
}
.client-faq--solid .client-faq-item.is-open .client-faq-icon { color: #fff; }

@media (prefers-reduced-motion: reduce) {
    .client-faq--grouped .client-faq-item::before { transition: none; }
}

/* ==========================================================================
   Panels, contact form, flashes, buttons
   ========================================================================== */
/* On phones the panel dissolves into the page — no border, no padding — so the
   form uses the full container width; the framed card returns from 640px up. */
.client-panel { background: var(--paper); }

@media (min-width: 640px) {
    .client-panel {
        border: 1px solid var(--line-strong);
        padding: 1.75rem;
    }
}

.client-flash { margin: 1.5rem 0 0; padding: .875rem 1rem; font-size: .9375rem; font-weight: 600; border: 1px solid; border-left-width: 3px; }
.client-flash-success { border-color: #b7dcc4; border-left-color: #1d7a46; background: #f0f7f2; color: #1d5c39; }
.client-flash-error { border-color: #e5b8b4; border-left-color: #b3261e; background: #faf1f0; color: #8c2822; }

.client-contact-title {
    margin: 0;
    color: var(--ink);
    font-size: var(--client-h3);
    font-weight: var(--client-heading-weight);
    line-height: var(--client-heading-lh);
    letter-spacing: var(--client-heading-tracking);
}
.client-contact-copy { margin: .375rem 0 1.5rem; color: var(--ink-3); font-size: .9375rem; }

.client-form { display: grid; gap: 1.125rem; }
.client-form-row { display: grid; gap: 1.125rem; }
.client-field { display: grid; gap: .375rem; }
.client-field label {
    color: var(--ink-2);
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
}
.client-field :is(input, textarea) {
    width: 100%;
    border: 1px solid var(--line-strong);
    background: #fff;
    padding: .75rem .875rem;
    color: var(--ink);
    font: inherit;
    font-size: .9375rem;
    outline: none;
    transition: border-color .15s ease, box-shadow .15s ease;
}
.client-field :is(input, textarea)::placeholder { color: var(--ink-3); }
.client-field :is(input, textarea):focus { border-color: var(--ink); box-shadow: inset 0 0 0 1px var(--ink); }
.client-field .is-invalid { border-color: #b3261e; }
.client-field textarea { resize: vertical; min-height: 8rem; }
.client-field-error { margin: 0; color: #b3261e; font-size: .8125rem; font-weight: 600; }

.client-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .5rem;
    justify-self: start;
    border: 1px solid var(--ink);
    background: var(--ink);
    padding: .8125rem 1.625rem;
    color: var(--paper);
    font: inherit;
    font-size: .8125rem;
    font-weight: 700;
    letter-spacing: .08em;
    text-transform: uppercase;
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}
.client-btn:hover { background: transparent; color: var(--ink); }

/* ==========================================================================
   Empty state and 404
   ========================================================================== */
.client-empty, .client-notfound { padding: 5rem 0; text-align: center; }
.client-empty h1 {
    margin: 0;
    color: var(--ink);
    font-size: var(--client-h1);
    font-weight: var(--client-heading-weight);
    line-height: var(--client-heading-lh);
    letter-spacing: var(--client-heading-tracking);
}
.client-notfound .client-btn { justify-self: center; }
.client-notfound-code {
    margin: 0 0 .5rem;
    color: var(--ink);
    font-size: 4.5rem;
    line-height: 1;
    font-weight: 300;
    letter-spacing: .02em;
    font-variant-numeric: tabular-nums;
}
.client-notfound-copy { margin: 0 0 1.75rem; color: var(--ink-3); font-size: 1rem; line-height: 1.7; }

/* ==========================================================================
   Footer — colours from Settings > Bottom Footer; no logo or site name
   ========================================================================== */
.client-footer {
    margin-top: 4rem;
    border-top: 1px solid var(--line);
    background: var(--client-footer-bg, var(--ink));
    color: var(--client-footer-item, var(--paper));
}
.client-footer-inner {
    display: grid;
    gap: 1.25rem;
    justify-items: center;
    padding-top: 2.5rem;
    padding-bottom: 2.5rem;
    text-align: center;
}
.client-footer-nav { display: flex; flex-wrap: wrap; justify-content: center; gap: .625rem 2rem; }
.client-footer-nav a {
    color: var(--client-footer-item, var(--paper));
    font-size: 18px;
    font-weight: 500;
    transition: color .15s ease;
}
.client-footer-nav a:hover { color: var(--client-footer-item-hover, var(--paper)); }
.client-footer-nav a.is-active { color: var(--client-footer-item-active, var(--paper)); }

.client-footer-text { width: 100%; color: inherit; font-size: 18px; line-height: 1.65; }
.client-footer-text p { margin: 0 0 18px; }
.client-footer-text > :last-child { margin-bottom: 0; }
/* A link written into the footer text reads as a footer link: it rests in the
   Item Color and moves to the Item Hover Color, exactly as the footer nav
   does. It rested in the HOVER colour before, which left it painted with a
   colour it was never meant to sit in and with nothing left to change to. The
   underline is what sets it apart from the words around it. */
.client-footer-text a {
    color: var(--client-footer-item, var(--paper));
    text-decoration: underline;
    transition: color .15s ease;
}
@media (hover: hover) {
    .client-footer-text a:hover { color: var(--client-footer-item-hover, var(--paper)); }
}
.client-footer-text img { max-width: 100%; height: auto; margin: .25rem auto; }

/* ==========================================================================
   Layout breakpoints
   ========================================================================== */
@media (min-width: 640px) {
    .client-form-row { grid-template-columns: repeat(2, minmax(0, 1fr)); }
    .client-feature-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (min-width: 900px) {
    .client-feature-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }

    .client-body {
        --client-h1: 2.375rem;
        --client-h2: 2rem;
        --client-h3: 1.375rem;
    }
    /* FAQ sizes for wide screens live with the FAQ styles above. */
}

/* RTL: lists and quote rules flip to the other edge. */
[dir="rtl"] .client-rich blockquote { border-left: 0; border-right: 3px solid var(--ink); padding: .5rem 1.125rem .5rem 0; }
[dir="rtl"] .client-rich :is(ul, ol) { padding-left: 0; padding-right: 1.5rem; }
[dir="rtl"] .client-rich :is(th, td) { text-align: right; }

/* ==========================================================================
   Blog — the /blog grid and a single article.

   Cards follow the download results: hairline border, square-ish 14px corners,
   a lift on hover tinted with the administrator's banner colour, so the blog
   reads as part of the same site rather than a bolted-on section.
   ========================================================================== */
.client-blog-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
    gap: 1.5rem;
}

.client-blog-card {
    /* Anchor for the stretched link, the cover scrim and the top rule. */
    position: relative;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: 18px;
    background: var(--paper);
    box-shadow: 0 1px 2px rgba(22, 21, 18, .04);
    transition: transform .25s ease, box-shadow .25s ease, border-color .25s ease;
    animation: client-dl-in .45s cubic-bezier(.2, .7, .2, 1) backwards;
    animation-delay: calc(var(--blog-i, 0) * 60ms);
}

/* A rule in the site's own accent colour draws itself across the top on
   hover — the one flourish on an otherwise quiet card. */
.client-blog-card::before {
    content: "";
    position: absolute;
    top: 0;
    inset-inline: 0;
    z-index: 2;
    height: 3px;
    background: var(--client-banner-bg, #e60023);
    transform: scaleX(0);
    transform-origin: left center;
    transition: transform .35s cubic-bezier(.2, .7, .2, 1);
}

[dir="rtl"] .client-blog-card::before { transform-origin: right center; }

@media (hover: hover) {
    .client-blog-card:hover {
        transform: translateY(-6px);
        border-color: color-mix(in oklab, var(--client-banner-bg, #e60023) 40%, var(--line));
        box-shadow: 0 22px 40px -22px color-mix(in oklab, var(--client-banner-bg, #e60023) 50%, rgba(22, 21, 18, .45));
    }

    .client-blog-card:hover::before { transform: scaleX(1); }
}

.client-blog-thumb {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 10;
    background: var(--line);
    overflow: hidden;
}

.client-blog-thumb img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform .5s cubic-bezier(.2, .7, .2, 1);
}

/* Keeps the date legible over a bright photograph without dimming the whole
   picture. Only where there is a photograph: over the stand-in initial it
   would just look like a smudge. */
.client-blog-thumb:has(img)::after {
    content: "";
    position: absolute;
    inset: 40% 0 0;
    background: linear-gradient(to bottom, transparent, rgba(16, 15, 13, .5));
    pointer-events: none;
}

@media (hover: hover) {
    .client-blog-card:hover .client-blog-thumb img { transform: scale(1.06); }
}

/* Stand-in cover: the article's initial washed in the banner colour. */
.client-blog-thumb-fallback {
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    background: linear-gradient(
        135deg,
        color-mix(in oklab, var(--client-banner-bg, #e60023) 20%, var(--paper)),
        color-mix(in oklab, var(--client-banner-bg, #e60023) 5%, var(--paper))
    );
    color: color-mix(in oklab, var(--client-banner-bg, #e60023) 70%, var(--ink));
    font-size: 3.25rem;
    font-weight: 700;
    line-height: 1;
}

.client-blog-date {
    position: absolute;
    z-index: 1;
    bottom: .875rem;
    inset-inline-start: .875rem;
    padding: .3rem .7rem;
    border-radius: 999px;
    background: rgba(16, 15, 13, .55);
    backdrop-filter: blur(6px);
    color: #fff;
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
}

.client-blog-body {
    display: flex;
    flex: 1 1 auto;
    flex-direction: column;
    gap: .625rem;
    padding: 1.375rem 1.5rem 1.25rem;
}

.client-blog-title {
    margin: 0;
    color: var(--ink);
    font-size: var(--client-h4);
    font-weight: var(--client-heading-weight);
    line-height: 1.35;
    letter-spacing: var(--client-heading-tracking);
}

.client-blog-title a { color: inherit; text-decoration: none; }

/*
 * The title link covers the card, so a click anywhere on it opens the article.
 * Done this way rather than by wrapping everything in an anchor: the card keeps
 * one link, one tab stop and one accessible name — the title — instead of
 * announcing the date and the whole blurb as the link text. The trade-off is
 * that the card's text can no longer be selected with the mouse, which is a
 * fair price on a card whose entire job is to be clicked.
 */
.client-blog-title a::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 3;
}

/* Keyboard focus lands on that link, so the ring belongs on the whole card. */
.client-blog-card:has(a:focus-visible) {
    outline: 2px solid var(--ink);
    outline-offset: 3px;
}

.client-blog-title a:focus-visible { outline: none; }

/* Hovering anywhere on the card marks the title, since the whole card is the
   link — underlining only on a direct hover of the words would read as if the
   rest of the card were dead. */
@media (hover: hover) {
    .client-blog-card:hover .client-blog-title a {
        color: #444;
    }
}

/*
 * Exactly three lines, whatever the card's width, with an ellipsis where the
 * text is cut. Trimming by character count in PHP cannot do this — the number
 * of characters that fit a line is only known once the browser has laid the
 * card out.
 */
.client-blog-excerpt {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 3;
    line-clamp: 3;
    overflow: hidden;
    margin: 0;
    color: var(--ink-2);
    font-size: .9688rem;
    line-height: 1.6;
}

/* Pushed to the bottom on a hairline, so cards of differing text length still
   line their footers up across a row. */
.client-blog-foot {
    display: flex;
    align-items: center;
    margin-top: auto;
    padding-top: .875rem;
    border-top: 1px solid var(--line);
}

.client-blog-more {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    color: var(--client-banner-bg, #e60023);
    font-size: .9375rem;
    font-weight: 600;
}

.client-blog-more::after {
    content: "\2192";
    transition: transform .25s ease;
}

[dir="rtl"] .client-blog-more::after { content: "\2190"; }

@media (hover: hover) {
    .client-blog-card:hover .client-blog-more::after { transform: translateX(4px); }
    [dir="rtl"] .client-blog-card:hover .client-blog-more::after { transform: translateX(-4px); }
}

/* --- Featured article ---------------------------------------------------
   The hero at the top of the index: a dark slab, cover on one side, the words
   on the other. Deliberately the one inverted surface on the page, so the eye
   lands on it before the grid below. --------------------------------------- */
.client-blog-hero {
    /* Anchor for the stretched link. */
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    overflow: hidden;
    border-radius: 20px;
    background: var(--ink);
    box-shadow: 0 18px 40px -28px rgba(22, 21, 18, .6);
    transition: transform .25s ease, box-shadow .25s ease;
}

.client-blog-hero-media {
    position: relative;
    aspect-ratio: 16 / 10;
    background: color-mix(in oklab, var(--ink) 82%, var(--paper));
}

.client-blog-hero-media img {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .6s cubic-bezier(.2, .7, .2, 1);
}

.client-blog-hero-body {
    display: flex;
    flex-direction: column;
    gap: .875rem;
    padding: 2rem 1.75rem;
}

.client-blog-hero-eyebrow {
    margin: 0;
    color: var(--client-banner-bg, #e60023);
    font-size: .75rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
}

.client-blog-hero-title {
    margin: 0;
    color: var(--paper);
    font-size: var(--client-h3);
    font-weight: var(--client-heading-weight);
    line-height: 1.25;
    letter-spacing: var(--client-heading-tracking);
}

.client-blog-hero-title a { color: inherit; text-decoration: none; }

/* Same stretched-link pattern as the cards: the whole slab is the target,
   while the accessible name stays just the title. */
.client-blog-hero-title a::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: 2;
}

.client-blog-hero-title a:focus-visible { outline: none; }

.client-blog-hero:has(a:focus-visible) {
    outline: 2px solid var(--client-banner-bg, #e60023);
    outline-offset: 3px;
}

.client-blog-hero-excerpt {
    margin: 0;
    color: rgba(255, 255, 255, .72);
    font-size: 1rem;
    line-height: 1.65;
}

/* Rests on the bottom edge on a hairline, the way the cards' footers do. */
.client-blog-hero-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    margin-top: auto;
    padding-top: 1.125rem;
    border-top: 1px solid rgba(255, 255, 255, .16);
    color: rgba(255, 255, 255, .55);
    font-size: .875rem;
}

@media (hover: hover) {
    .client-blog-hero:hover {
        transform: translateY(-4px);
        box-shadow: 0 26px 50px -26px rgba(22, 21, 18, .7);
    }

    .client-blog-hero:hover .client-blog-hero-media img { transform: scale(1.04); }

    .client-blog-hero:hover .client-blog-hero-title a {
        text-decoration: underline;
        text-decoration-thickness: 2px;
        text-underline-offset: 4px;
    }
}

@media (min-width: 860px) {
    /* Cover a shade wider than the words, as in the reference. */
    .client-blog-hero { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); }

    .client-blog-hero-media {
        aspect-ratio: auto;
        min-height: 21rem;
    }

    .client-blog-hero-body { padding: 2.75rem 2.5rem; }

    .client-blog-hero-title { font-size: var(--client-h2); }

    /* Nothing to sit beside without a cover, so the words take the full slab. */
    .client-blog-hero.is-imageless { grid-template-columns: minmax(0, 1fr); }
}

.client-blog-empty {
    margin: 0;
    padding: 3rem 1rem;
    border: 1px dashed var(--line-strong);
    border-radius: 14px;
    text-align: center;
    color: var(--ink-3);
    font-size: 1rem;
}

/* --- Pager --------------------------------------------------------------- */
.client-blog-pager {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .5rem;
    margin-top: 2.5rem;
}

.client-blog-pager-link {
    min-width: 2.5rem;
    padding: .5rem .75rem;
    border: 1px solid var(--line);
    border-radius: 8px;
    color: var(--ink-2);
    font-size: .9375rem;
    text-align: center;
    text-decoration: none;
}

@media (hover: hover) {
    a.client-blog-pager-link:hover { border-color: var(--ink); color: var(--ink); }
}

.client-blog-pager-link.is-current {
    border-color: var(--client-banner-bg, #e60023);
    background: var(--client-banner-bg, #e60023);
    color: var(--client-banner-heading, #fff);
}

/* --- One article --------------------------------------------------------- */
.client-blog-meta {
    margin: .75rem 0 0;
    color: var(--ink-3);
    font-size: .9375rem;
    text-align: center;
}

/*
 * The cover is framed rather than printed at whatever size it was uploaded:
 * the same 16/9 window the cards use, filled by the image. Without it a tall
 * portrait upload fills the screen and pushes the first paragraph below the
 * fold, and no two articles read as the same site.
 */
.client-blog-cover {
    aspect-ratio: 16 / 9;
    margin: 0 0 2rem;
    overflow: hidden;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: var(--line);
}

.client-blog-cover img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}

@media (max-width: 520px) {
    .client-blog-grid { gap: 1.25rem; }
    .client-blog-body { padding: 1.125rem 1.25rem 1.125rem; }
    .client-blog-thumb { aspect-ratio: 16 / 9; }
}

@media (max-width: 640px) {
    .client-page-head {
        margin-bottom: 1.75rem;
        padding: 2rem 0;
    }
}

/* ------------------------------------------------------------------ *
 * Download notice
 *
 * A download is pulled into the page before the browser is asked to save
 * it, so closing the tab part way through throws the transfer away. This
 * sits out of the way and says so for as long as one is running.
 *
 * Two shapes: a pill floating in the middle on a wide screen, and a bar
 * across the foot of a narrow one. A pill is the wrong shape once the
 * sentence wraps — a 999px radius eats into two-line text — and on a
 * phone this sentence always wraps.
 * ------------------------------------------------------------------ */
.client-toast {
    position: fixed;
    left: 50%;
    bottom: 1.25rem;

    /*
     * Above the site's own layers (the header sits at 80) and above a floating
     * third-party button: Ko-fi's widget paints at 10000 and was covering this
     * notice. A download in progress must stay visible — closing the tab part
     * way through loses the file — so nothing pasted into the page from
     * outside gets to bury it.
     */
    z-index: 100000;
    display: flex;
    align-items: center;
    gap: .625rem;

    /*
     * Sized against the viewport, not 100vw: vw includes the space a
     * vertical scrollbar occupies, so a full-width value there is wider
     * than what can actually be seen and pushes the page sideways.
     */
    max-width: min(30rem, calc(100% - 2rem));

    padding: .75rem 1.125rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--paper);
    color: var(--ink);
    font-size: .9375rem;
    line-height: 1.4;
    box-shadow: 0 6px 24px rgba(22, 21, 18, .14), 0 1px 2px rgba(22, 21, 18, .06);

    /*
     * Centred by shifting half its own width, so the notice does not have to
     * be a fixed size. The vertical nudge is what it animates in from.
     */
    transform: translate(-50%, .75rem);
    opacity: 0;
    transition: opacity .2s ease, transform .2s ease;
}

.client-toast.is-open {
    opacity: 1;
    transform: translate(-50%, 0);
}

.client-toast[hidden] { display: none; }

/* --------------------------------------------------------------------------
   Scroll to top — Settings > Layout. A round button in a bottom corner, shown
   by its script once the page has been scrolled. The corner is the admin's
   choice, since a support or chat widget often owns one of them; it is a
   physical corner, the same in a right-to-left language. Coloured like the
   banner's search button, so it belongs to the site's palette.
   -------------------------------------------------------------------------- */
.client-to-top {
    position: fixed;
    bottom: 1.25rem;
    /* Above the header (80), under the download notice. */
    z-index: 95;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 46px;
    height: 46px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--client-banner-btn-bg, var(--ink));
    color: var(--client-banner-btn-text, var(--paper));
    box-shadow: 0 6px 20px rgba(22, 21, 18, .18), 0 1px 2px rgba(22, 21, 18, .08);
    cursor: pointer;
    transition: transform .15s ease, box-shadow .15s ease;
}
.client-to-top svg { width: 22px; height: 22px; }
.client-to-top--right { right: 1.25rem; }
.client-to-top--left { left: 1.25rem; }
.client-to-top[hidden] { display: none; }
.client-to-top:focus-visible { outline: 3px solid var(--client-banner-btn-border, currentColor); outline-offset: 2px; }
@media (hover: hover) {
    .client-to-top:hover { transform: translateY(-2px); box-shadow: 0 10px 26px rgba(22, 21, 18, .22), 0 1px 2px rgba(22, 21, 18, .08); }
}
@media (max-width: 640px) {
    .client-to-top { bottom: 1rem; width: 42px; height: 42px; }
    .client-to-top--right { right: 1rem; }
    .client-to-top--left { left: 1rem; }
}
@media (prefers-reduced-motion: reduce) {
    .client-to-top { transition: none; }
}

.client-toast-spinner {
    flex: none;
    width: 1rem;
    height: 1rem;
    border: 2px solid var(--line-strong);
    border-top-color: var(--ink);
    border-radius: 50%;
    animation: client-toast-spin .7s linear infinite;
}

/*
 * A flex child will not shrink below the width of its longest word unless it
 * is told it may, which is what pushes the notice wider than the screen.
 */
.client-toast-text {
    min-width: 0;
    overflow-wrap: break-word;
}

@keyframes client-toast-spin {
    to { transform: rotate(360deg); }
}

/*
 * The notice is centred, so it needs no side flip for Arabic; only the text
 * inside it runs the other way, which the document direction already handles.
 */
[dir="rtl"] .client-toast { flex-direction: row-reverse; }

/*
 * On a phone it spans the head of the screen instead. Pinning both edges
 * means the sentence decides the height and nothing has to be centred, so
 * there is no half-its-own-width shift to go wrong at any text length.
 *
 * The head rather than the foot: the bottom corners of a phone are where
 * floating buttons live — a Ko-fi support button was sitting on top of this
 * notice — and the notice must be read while a download is running, since
 * closing the tab part way through loses the file. It comes down from above,
 * so the movement matches where it now sits.
 */
@media (max-width: 640px) {
    .client-toast {
        left: .75rem;
        right: .75rem;
        top: 5rem;
        bottom: auto;
        max-width: none;
        padding: .75rem .875rem;
        border-radius: 14px;
        font-size: .875rem;
        transform: translate(0, -.75rem);
    }

    .client-toast.is-open { transform: translate(0, 0); }
}

@media (prefers-reduced-motion: reduce) {
    .client-toast { transition: none; }
    .client-toast-spinner { animation: none; }
}

/* ---------------------------------------------------------------------------
   The head of a profile search: cover, picture, name and bio.

   Only a profile answers with one, so the block stays hidden until the script
   fills it. The cover is optional — Facebook does not give one to a signed-out
   visitor — and without it the picture sits on a plain band rather than
   floating over nothing.
--------------------------------------------------------------------------- */
.client-profile {
    margin: 0 0 1.25rem;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: var(--paper);
    overflow: hidden;
}

.client-profile-cover {
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 40 / 13;
    background: linear-gradient(120deg, var(--line), var(--paper));
}

.client-profile-cover img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Without a cover the band is short: enough to sit the picture on, no more. */
.client-profile-cover.is-empty { aspect-ratio: auto; height: 4.5rem; }

.client-profile-body {
    display: grid;
    justify-items: center;
    gap: .5rem;
    padding: 0 1.25rem 1.25rem;
    text-align: center;
}

/* Pulled up so it straddles the cover, as a profile page does. */
.client-profile-avatar {
    position: relative;
    width: 6.5rem;
    height: 6.5rem;
    margin-top: -3.25rem;
    border-radius: 50%;
    border: 4px solid var(--paper);
    background: var(--paper);
    overflow: hidden;
}

.client-profile-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.client-profile-name {
    margin: .25rem 0 0;
    color: var(--ink);
    font-size: 1.25rem;
    font-weight: 700;
    line-height: 1.3;
}

.client-profile-bio {
    margin: 0;
    max-width: 44rem;
    color: var(--ink-2, var(--ink-3));
    font-size: .875rem;
    line-height: 1.6;
    white-space: pre-line;
}

.client-profile-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .5rem;
    margin-top: .25rem;
}

@media (max-width: 480px) {
    .client-profile-avatar { width: 5rem; height: 5rem; margin-top: -2.5rem; }
    .client-profile-name { font-size: 1.0625rem; }
    .client-profile-bio { font-size: .8125rem; }
}

/* ---------------------------------------------------------------------------
   A profile's results are its posts, so the card is drawn as one: who posted
   it and when, what they said, the media, then how it was received.

   Only the chrome is added here. The card, its thumbnail and its save button
   are the ordinary ones, so a post card and a plain result still look like
   the same family.
--------------------------------------------------------------------------- */
.client-dl-post { display: flex; flex-direction: column; }

.client-post-head {
    display: flex;
    align-items: center;
    gap: .5rem;
    padding: .75rem .875rem .5rem;
}

.client-post-face {
    flex: none;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    overflow: hidden;
    background: var(--line);
}

.client-post-face img { width: 100%; height: 100%; object-fit: cover; display: block; }

.client-post-by { display: grid; min-width: 0; }

.client-post-author {
    color: var(--ink);
    font-size: .8125rem;
    font-weight: 700;
    line-height: 1.3;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.client-post-date {
    color: var(--ink-3);
    font-size: .6875rem;
    line-height: 1.3;
}

/* The caption keeps the line breaks it was written with, but only three lines
   of them: a long one would push every thumbnail in the row out of line. */
.client-post-caption {
    margin: 0 0 .625rem;
    padding: 0 .875rem;
    color: var(--ink);
    font-size: .8125rem;
    line-height: 1.5;
    white-space: pre-line;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* How the post was received: an icon and a number, three across. */
.client-post-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
    margin: 0;
    padding: .625rem .875rem 0;
    color: var(--ink-3);
    font-size: .75rem;
    font-weight: 600;
}

.client-post-count {
    display: inline-flex;
    align-items: center;
    gap: .3125rem;
    /* The number is the message, so it is read at the page's own colour while
       the icon stays quieter beside it. */
    color: var(--ink-2, var(--ink-3));
}

.client-post-count svg {
    width: 1rem;
    height: 1rem;
    flex: none;
    opacity: .75;
}

@media (max-width: 480px) {
    .client-post-head { padding: .625rem .75rem .375rem; }
    .client-post-caption { padding: 0 .75rem; font-size: .78125rem; }
    .client-post-meta { padding: .5rem .75rem 0; }
}

/* ---------------------------------------------------------------------------
   A feed: one post to a row.

   Facebook's Posts section asks for this. A post is read rather than scanned —
   the name, the date and the caption all want a line of their own — and three
   abreast leaves none of them room. The Media section stays a grid, where
   seeing many things at once is the point.
--------------------------------------------------------------------------- */
.client-dl-grid.is-feed {
    grid-template-columns: minmax(0, 560px);
    justify-content: center;
    gap: 1rem;
}

/* Beats the single-result rule above, which would otherwise narrow a feed
   holding one post to a portrait card. */
.client-dl-grid.is-feed:has(> :only-child) {
    grid-template-columns: minmax(0, 560px);
}

/*
   The media keeps its own shape here instead of being cropped to a card: a
   post is shown as it was posted. A fixed height keeps a tall video from
   pushing the next post off the screen, and the dark ground is what fills the
   space either side of anything that is not the same shape.
*/
.client-dl-grid.is-feed .client-dl-thumb {
    aspect-ratio: auto;
    height: min(70vh, 32rem);
    background: #100f0d;
}

.client-dl-grid.is-feed .client-dl-thumb img { object-fit: contain; }

/* With room to spare, the caption need not be clipped to three lines. */
.client-dl-grid.is-feed .client-post-caption { -webkit-line-clamp: 8; }

@media (max-width: 600px) {
    .client-dl-grid.is-feed .client-dl-thumb { height: min(60vh, 24rem); }
}
