/*
 * Webtura — design layer
 * =============================================================================
 * High-contrast monochrome, adapted from the digitlhaus.com reference:
 *
 *   - White and black do the work; #F2F2F2 is the only alternate surface.
 *   - Black is the action colour. Chartreuse (#F0FF4C) is a highlight only,
 *     never a text colour on white. Deep blue is the secondary accent.
 *   - Heavy uppercase display type with very tight leading, over a quiet body.
 *   - Squared-off geometry, pill buttons, pill badges with a leading dot.
 *
 * Both typefaces carry Cyrillic. The previous display faces (Archivo, then
 * Bricolage Grotesque) ship no Cyrillic subset, so every Bulgarian heading was
 * silently falling back to a system font.
 *
 * The proof device is kept from the previous direction and suits this one: a
 * browser frame carrying a real client site, with a floating card naming the
 * client. Loads after the Oxygen stylesheets via breakdance_variables_css.
 */

/* ==========================================================================
   Tokens this layer adds
   ========================================================================== */

:root {
    --wt-ease-out: cubic-bezier(0.16, 1, 0.3, 1);
    --wt-ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
    --wt-reveal-duration: 0.7s;
    --wt-radius-pill: 999px;
    /* Measured off the reference: the curve at a section join reads at about
       24px at desktop width, and squares off on a phone where a big radius
       would eat into the content. */
    --wt-join-radius: 26px;
    --wt-card-radius: 18px;
    /*
     * The only colours on the site besides black, white and the chartreuse
     * highlight. What they signal is "this chip is the category, not a
     * discipline" — the reference draws the same distinction. Which hue a
     * category gets is stable but not meaningful, so they are kept close in
     * weight and this pale, leaving the screenshots on the work cards as the
     * brightest thing in the row.
     */
    --wt-tint-lilac: #ece7fb;
    --wt-tint-sky: #dcedfb;
    --wt-tint-mint: #dcf3e8;
    --wt-tint-blush: #fbe4ec;
    --wt-tint-sand: #f6ecdd;
    --wt-tint-steel: #e4eaf1;

    /*
     * The highlighter stroke. Both edges wander and both ends are ragged and
     * out of square, so the mark reads as one pass of a chisel tip rather
     * than a filled rectangle. Stretched to whatever it has to cover, which
     * is why preserveAspectRatio is off.
     */
    --wt-mark: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 40' preserveAspectRatio='none'%3E%3Cpath fill='%23fff' d='M2 9 C30 5 68 8 116 6 C158 5 208 9 256 6 C274 5 287 8 298 3 L296 31 C281 36 263 31 245 33 C201 37 150 32 104 35 C70 37 34 33 4 37 Z'/%3E%3C/svg%3E");

    /*
     * Paper. Fibre rather than pixels: a grain the eye reads as a surface the
     * page could have been printed on, in place of the dot grid, which reads
     * as a machine readout.
     */
    --wt-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23g)' opacity='0.6'/%3E%3C/svg%3E");
}

@media (max-width: 700px) {
    :root {
        --wt-join-radius: 18px;
    }
}

/* ==========================================================================
   Typography
   --------------------------------------------------------------------------
   The display voice is set in caps at 800 with leading pulled under 1. That
   compression is what gives the reference its force; loosen it and the whole
   direction goes soft.
   ========================================================================== */

.wt-display,
.wt-display--medium,
.wt-h2 {
    font-family: var(--wt-font-display), sans-serif;
    font-weight: 800;
    font-variation-settings: "wght" 800;
    text-transform: uppercase;
    line-height: 0.9;
    letter-spacing: -0.02em;
    text-wrap: balance;
}

/*
 * 0.9 is measured off the reference, which sets Latin caps — and Latin caps
 * have no descenders, so the line below has nothing to collide with. Cyrillic
 * caps do: Д, Ц and Щ all hang below the baseline, and at 0.9 their tails
 * landed inside the cap height of the next line. Every multi-line Bulgarian
 * heading on the site was overlapping itself. The clearance goes back only
 * where the language needs it, so the English display keeps its compression.
 */
html[lang^="bg"] .wt-display,
html[lang^="bg"] .wt-display--medium,
html[lang^="bg"] .wt-h2 {
    line-height: 1.02;
}

.wt-display {
    font-size: clamp(40px, 6.2vw, 104px);
}

.wt-display--medium {
    font-size: clamp(32px, 4.4vw, 68px);
}

.wt-h2 {
    font-size: clamp(30px, 3.8vw, 58px);
}

/* Card and row titles stay sentence case — caps at this size would shout over
   the copy they introduce. */
.wt-h3 {
    font-family: var(--wt-font-display), sans-serif;
    font-weight: 700;
    font-variation-settings: "wght" 700;
    font-size: clamp(19px, 1.5vw, 24px);
    line-height: 1.16;
    letter-spacing: -0.015em;
    text-transform: none;
}

.wt-lead {
    font-family: var(--wt-font-body), sans-serif;
    font-weight: 400;
    font-size: clamp(16px, 1.15vw, 19px);
    line-height: 1.55;
    letter-spacing: 0;
}

.wt-copy,
.wt-small {
    font-family: var(--wt-font-body), sans-serif;
    font-weight: 400;
    line-height: 1.6;
    letter-spacing: 0;
}

/* ==========================================================================
   Icons
   --------------------------------------------------------------------------
   One drawn set, at the weight of the rest of the line work: 1.6 on a 24
   grid, unfilled, currentColor, so a glyph takes the colour of whatever it
   sits in and needs no dark variant. Placed by buildIcons() from a keyword in
   each block's own heading — no keyword, no glyph, and the block renders as
   it did before.

   Named `wt-glyph`, not `wt-icon`: the builder already owns `.wt-icon` for
   the chartreuse contact markers, and a second meaning for that class had
   these drawings rendering as yellow discs.
   ========================================================================== */

.wt-glyph-art {
    display: block;
    width: 100%;
    height: 100%;
    fill: none;
    stroke: currentColor;
    stroke-width: 1.6;
    stroke-linecap: round;
    stroke-linejoin: round;
}

.wt-glyph {
    flex: 0 0 auto;
    display: grid;
    place-items: center;
}

/* Sharing the numeral's line rather than floating in the card's corner: at
   the narrowest column these grids reach, a corner glyph sits under the
   title. */
.wt-glyph-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    width: 100%;
}

.wt-glyph--corner {
    width: 46px;
    height: 46px;
    padding: 12px;
    border: 1px solid var(--wt-hairline);
    border-radius: 50%;
    background: var(--wt-paper);
    color: var(--wt-graphite);
    transition:
        background-color 0.26s var(--wt-ease-out),
        border-color 0.26s var(--wt-ease-out),
        color 0.26s var(--wt-ease-out);
}

/* The accent is the hover state everywhere else on a card, so it is here. */
.wt-list__item:hover .wt-glyph--corner,
.wt-process__step:hover .wt-glyph--corner {
    border-color: var(--wt-ink);
    background: var(--wt-accent);
    color: var(--wt-ink);
}

/* On black the glyph takes the accent the numeral above it already uses. */
.wt-benefit__number--glyph {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 14px;
}

.wt-glyph--gutter {
    width: 26px;
    height: 26px;
    color: var(--wt-accent);
}

.wt-glyph--lead {
    width: 30px;
    height: 30px;
    margin-bottom: 14px;
    color: var(--wt-ink);
}

.wt-glyph--inline {
    width: 17px;
    height: 17px;
    color: var(--wt-graphite);
}

/* ==========================================================================
   Badge eyebrows
   --------------------------------------------------------------------------
   Every section is introduced by a small pill with a leading dot rather than a
   free-floating label.
   ========================================================================== */

.wt-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    align-self: start;
    width: auto;
    padding: 7px 15px 7px 12px;
    border: 1px solid var(--wt-hairline);
    border-radius: var(--wt-radius-pill);
    background-color: var(--wt-paper);
    color: var(--wt-ink);
    font-family: var(--wt-font-body), sans-serif;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0;
    text-transform: none;
}

.wt-eyebrow::before {
    content: "";
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--wt-ink);
}

[data-wt-surface="ink"] .wt-eyebrow,
.wt-section--dark .wt-eyebrow,
.wt-cta .wt-eyebrow,
.wt-footer .wt-eyebrow {
    background-color: transparent;
    border-color: color-mix(in srgb, #fff 26%, transparent);
    color: #fff;
}

[data-wt-surface="ink"] .wt-eyebrow::before,
.wt-section--dark .wt-eyebrow::before,
.wt-cta .wt-eyebrow::before,
.wt-footer .wt-eyebrow::before {
    background: var(--wt-accent);
}

/* Mono keeps the small data voice: labels, domains, step numbers. */
.wt-proofbar__label,
.wt-project-card__label,
.wt-quote__name,
.wt-stat__label {
    font-family: var(--wt-font-mono), monospace;
    font-weight: 500;
    font-size: 11px;
    letter-spacing: 0.08em;
}

/* ==========================================================================
   The mark
   ========================================================================== */

.wt-brand {
    display: block;
    width: 126px;
    aspect-ratio: 2538.79 / 344.04;
    /* The link carries its own aria-label, so hiding the text is safe. */
    font-size: 0;
    line-height: 0;
    color: var(--wt-ink);
    background-color: currentColor;
    -webkit-mask: url("webtura-wordmark.svg") no-repeat center / contain;
    mask: url("webtura-wordmark.svg") no-repeat center / contain;
    transition: opacity 0.25s var(--wt-ease-out);
}

.wt-brand:hover {
    opacity: 0.6;
}

/*
 * The footer mark also carries a stray .wt-btn--darkghost class from the
 * builder, whose transparent background cancels the paint the mask relies on.
 * Scoping restores it without editing page structure.
 */
.wt-footer .wt-brand {
    width: 140px;
    color: #fff;
    background-color: currentColor;
    border: 0;
}

/* ==========================================================================
   Header
   ========================================================================== */

.wt-header {
    padding-top: 14px;
    padding-bottom: 14px;
    background-color: color-mix(in srgb, var(--wt-paper) 88%, transparent);
    border-bottom: 1px solid transparent;
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    transition:
        background-color 0.3s var(--wt-ease-out),
        border-color 0.3s var(--wt-ease-out);
}

.wt-header.wt-header--scrolled {
    background-color: var(--wt-paper);
    border-bottom-color: var(--wt-hairline);
}

.wt-nav {
    gap: 26px;
}

/*
 * Centred navigation with the action pinned right, which is the modern agency
 * header. The builder lays the header out as brand | nav, so the nav is turned
 * into the centre track and the primary action pushed to its end.
 */
@media (min-width: 1024px) {
    .wt-header__inner {
        display: grid;
        grid-template-columns: 1fr auto 1fr;
        align-items: center;
    }

    .wt-header__inner > .wt-brand {
        grid-column: 1;
        justify-self: start;
    }

    .wt-nav {
        grid-column: 2;
        justify-self: center;
    }

    /* The language toggle and the action sit past the centre track. */
    .wt-nav .wt-lang,
    .wt-nav .wt-btn--primary {
        position: absolute;
        right: clamp(20px, 4vw, 64px);
    }

    .wt-nav .wt-btn--primary {
        right: clamp(20px, 4vw, 64px);
    }

    .wt-nav .wt-lang {
        right: calc(clamp(20px, 4vw, 64px) + 190px);
    }

    .wt-header {
        position: sticky;
    }
}

.wt-nav__link {
    position: relative;
    padding-bottom: 2px;
    color: var(--wt-ink);
    font-family: var(--wt-font-body), sans-serif;
    font-size: 15px;
    font-weight: 500;
    letter-spacing: 0;
    text-decoration: none;
    font-variation-settings: normal;
    transition: opacity 0.22s var(--wt-ease-out);
    opacity: 0.72;
}

.wt-nav__link:hover,
.wt-nav__link[aria-current="page"] {
    opacity: 1;
}

.wt-nav__link::after {
    content: "";
    position: absolute;
    bottom: -1px;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--wt-ink);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.3s var(--wt-ease-out);
}

.wt-nav__link:hover::after,
.wt-nav__link[aria-current="page"]::after {
    transform: scaleX(1);
}

.wt-lang {
    padding: 0;
    border: 0;
    color: var(--wt-graphite);
    font-family: var(--wt-font-mono), monospace;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-decoration: none;
    transition: color 0.22s var(--wt-ease-out);
}

.wt-lang:hover {
    color: var(--wt-ink);
    border: 0;
}

@media (max-width: 1023px) {
    .wt-nav {
        margin-left: auto;
        gap: 18px;
    }

    .wt-navtoggle {
        margin-left: 16px;
    }
}

/* The same action sits at the bottom of the menu panel on a phone. */
@media (max-width: 600px) {
    .wt-nav .wt-btn--primary {
        display: none;
    }

    .wt-nav {
        gap: 14px;
    }
}

/* ==========================================================================
   Buttons — black is the action colour
   ========================================================================== */

.wt-btn {
    border-radius: var(--wt-radius-pill);
    font-family: var(--wt-font-body), sans-serif;
    font-variation-settings: normal;
    font-weight: 500;
    font-size: 15px;
    letter-spacing: 0;
    padding-left: 26px;
    padding-right: 26px;
    transition:
        background-color 0.24s var(--wt-ease-out),
        color 0.24s var(--wt-ease-out),
        border-color 0.24s var(--wt-ease-out);
}

.wt-btn--primary {
    background-color: var(--wt-ink);
    color: #fff;
    border-color: var(--wt-ink);
}

.wt-btn--primary:hover {
    background-color: var(--wt-blue);
    border-color: var(--wt-blue);
    color: #fff;
    transform: none;
}

.wt-btn--ghost {
    background-color: transparent;
    border-color: var(--wt-ink);
    color: var(--wt-ink);
}

.wt-btn--ghost:hover {
    background-color: var(--wt-ink);
    border-color: var(--wt-ink);
    color: #fff;
    transform: none;
}

.wt-btn--light {
    background-color: #fff;
    color: var(--wt-ink);
    border-color: #fff;
}

.wt-btn--light:hover {
    background-color: var(--wt-accent);
    border-color: var(--wt-accent);
    color: var(--wt-ink);
}

.wt-btn--darkghost {
    background-color: transparent;
    border-color: color-mix(in srgb, #fff 40%, transparent);
    color: #fff;
}

.wt-btn--darkghost:hover {
    border-color: #fff;
    background-color: color-mix(in srgb, #fff 10%, transparent);
}

/*
 * Black is the action colour on white. On the black surfaces that inverts:
 * a black fill would disappear entirely, so the primary becomes white and the
 * ghost takes a white outline.
 */
[data-wt-surface="ink"] .wt-btn--primary,
.wt-section--dark .wt-btn--primary,
.wt-cta .wt-btn--primary {
    background-color: #fff;
    border-color: #fff;
    color: var(--wt-ink);
}

[data-wt-surface="ink"] .wt-btn--primary:hover,
.wt-section--dark .wt-btn--primary:hover,
.wt-cta .wt-btn--primary:hover {
    background-color: var(--wt-accent);
    border-color: var(--wt-accent);
    color: var(--wt-ink);
}

[data-wt-surface="ink"] .wt-btn--ghost,
.wt-section--dark .wt-btn--ghost {
    border-color: color-mix(in srgb, #fff 40%, transparent);
    color: #fff;
}

[data-wt-surface="ink"] .wt-btn--ghost:hover,
.wt-section--dark .wt-btn--ghost:hover {
    background-color: #fff;
    border-color: #fff;
    color: var(--wt-ink);
}

/* ==========================================================================
   Hero
   --------------------------------------------------------------------------
   One centred column on a field of dots that reacts to the pointer. The
   previous arrangement put the headline in one half and a screenshot of a
   client site in the other, which meant the brightest, busiest thing above
   the fold was a picture of somebody else's work rather than the claim being
   made. Centred, the claim is the whole unit, and the proof still arrives
   immediately underneath — the client marquee, then the work reel.
   ========================================================================== */

.wt-hero {
    position: relative;
    display: grid;
    place-items: center;
    overflow: hidden;
    /*
     * Sized to the content rather than to the viewport. Holding the band at
     * 86vh left a 450px block floating in 774px of white, which reads as a
     * page that failed to load rather than as breathing room. Tight enough
     * now that the client marks sit just inside the fold, so the first screen
     * ends on evidence instead of on empty paper.
     */
    min-height: 0;
    padding-top: clamp(44px, 5vw, 78px);
    padding-bottom: clamp(36px, 4vw, 60px);
    background-color: var(--wt-paper);
    color: var(--wt-ink);
}

.wt-hero .wt-display {
    color: var(--wt-ink);
}

.wt-hero .wt-lead {
    color: var(--wt-graphite);
}

/* ---- the content column ---- */

.wt-hero__inner {
    position: relative;
    z-index: 2;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(18px, 2vw, 26px);
    width: 100%;
    /* Wide enough that the headline carries the band on three lines instead
       of sitting as a small block in the middle of it. */
    max-width: min(100%, 1120px);
    margin-inline: auto;
    text-align: center;
}

/*
 * The hero opens on the headline. The pill above it listed the three services
 * — "Уеб дизайн • разработка • дългосрочна грижа" — which the navigation and
 * the services band both state again further down, so it spent the first line
 * of the page on a label rather than on the claim. Every other section keeps
 * its eyebrow; those introduce a band the reader has scrolled to, which is a
 * different job from standing above the first thing seen.
 *
 * Hidden rather than deleted from the builder, so the copy is still there in
 * Oxygen if it is ever wanted back. `display: none` also takes it out of the
 * accessibility tree, so it is not announced either.
 */
.wt-hero__inner > .wt-eyebrow {
    display: none;
}

.wt-hero__meta {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(22px, 2.6vw, 34px);
    width: 100%;
    max-width: none;
}

.wt-hero .wt-lead {
    max-width: 58ch;
}

.wt-hero .wt-row {
    justify-content: center;
}

/* ---- the sketch ---- */

/* ==========================================================================
   Photographic grounds
   --------------------------------------------------------------------------
   The bands that used to carry drawn geometry now carry a photograph: a
   workspace behind the hero, a working session over printed charts behind the
   services band. Paths are relative to this stylesheet, which sits at
   wp-content/plugins/webtura-core/assets/ — three levels up is wp-content/.

   Every one of them is a real element, not a pseudo-element, for the reason
   the joins section gives: a band spends `::before` and `::after` on its two
   join curves and has neither left. The element's own `::after` is free, and
   that is where the scrim goes.

   The scrim is the whole job. A photograph behind display type at this weight
   destroys the contrast the direction depends on, so each ground is washed
   out hardest exactly where the type sits and allowed to read at the edges.
   ========================================================================== */

/*
 * Scoped under .wt-site to outrank `.wt-section > *`, which lifts every
 * direct child of a band to `position: relative; z-index: 1` so content sits
 * above the band's decoration. A ground is the one child that must not be
 * lifted — and `position: relative` also drops `inset`, so the layer
 * collapsed to zero height and vanished rather than merely sitting too high.
 */
.wt-site .wt-photo {
    position: absolute;
    inset: 0;
    z-index: 0;
    background-repeat: no-repeat;
    background-size: cover;
    pointer-events: none;
    will-change: translate;
}

/* Both photographic bands publish their scroll position already — the hero
   and .wt-svc-band are in PARALLAX_SELECTOR — so the ground drifts against
   the page without any new script. */
.wt-site .wt-photo--hero {
    inset: -70px 0;
    background-image: url("../../../uploads/webtura-photo/hero-workspace.jpg");
    background-position: 50% 38%;
    translate: 0 calc(var(--wt-parallax, 0) * -44px);
}

/*
 * Not full-bleed. This band is two columns of copy and two rows of chips, and
 * a photograph behind all of it can only be invisible under a heavy scrim or
 * damaging under a light one. It occupies the one region that carries no
 * content — the upper right, beside the heading — and is masked out before it
 * reaches the service columns.
 */
.wt-site .wt-photo--svc {
    inset: -70px -5% auto auto;
    width: min(58%, 760px);
    height: min(62%, 560px);
    background-image: url("../../../uploads/webtura-photo/services-strategy.jpg");
    background-position: 50% 42%;
    border-bottom-left-radius: 180px;
    translate: 0 calc(var(--wt-parallax, 0) * -34px);
    -webkit-mask-image: radial-gradient(120% 118% at 88% 8%, #000 26%, transparent 74%);
    mask-image: radial-gradient(120% 118% at 88% 8%, #000 26%, transparent 74%);
    opacity: 0.85;
}

@media (max-width: 900px) {
    /* At this width the heading and the copy stack into that corner. */
    .wt-site .wt-photo--svc {
        display: none;
    }
}

.wt-site .wt-photo::after {
    content: "";
    position: absolute;
    inset: 0;
}

/* Brightest through the middle, where the centred headline sits, and fading
   to solid at the foot so the band joins the white strip below it cleanly. */
.wt-site .wt-photo--hero::after {
    background:
        linear-gradient(to bottom, rgba(255, 255, 255, 0.55) 0%, rgba(255, 255, 255, 0) 26%, rgba(255, 255, 255, 0) 62%, var(--wt-paper) 96%),
        radial-gradient(
            ellipse 58% 60% at 50% 44%,
            rgba(255, 255, 255, 0.97) 26%,
            rgba(255, 255, 255, 0.86) 54%,
            rgba(255, 255, 255, 0.62) 100%
        );
}

/* The band is chalk, so what little scrim this corner needs resolves to chalk
   rather than white — a white wash would show as a lighter rectangle against
   the bands above and below it. Light, because the mask is doing the work. */
/* Weighted toward the lower left, which is where the band's lead copy runs
   under the corner. The image keeps its top-right quarter and gives up the
   rest, rather than being evenly veiled. */
.wt-site .wt-photo--svc::after {
    background: linear-gradient(
        202deg,
        rgba(242, 242, 242, 0.06) 0%,
        rgba(242, 242, 242, 0.34) 38%,
        rgba(242, 242, 242, 0.78) 64%,
        var(--wt-chalk) 82%
    );
}

/*
 * The closing ask. The panel is already ink, so the photograph reads as the
 * texture of it rather than as a picture behind it — a drawing board seen
 * from above, held far enough down that white type keeps its contrast.
 */
.wt-site .wt-photo--cta {
    background-image: url("../../../uploads/webtura-photo/cta-drawing.jpg");
    background-position: 50% 42%;
    opacity: 0.5;
    translate: 0 calc(var(--wt-parallax, 0) * -26px);
}

.wt-site .wt-photo--cta::after {
    background: linear-gradient(
        104deg,
        var(--wt-panel) 26%,
        rgba(36, 36, 36, 0.86) 52%,
        rgba(36, 36, 36, 0.58) 100%
    );
}

/* The process band, in the corner the four cards leave empty. */
.wt-site .wt-photo--process {
    inset: -60px -4% auto auto;
    width: min(48%, 620px);
    height: min(56%, 420px);
    background-image: url("../../../uploads/webtura-photo/process-studio.jpg");
    background-position: 50% 46%;
    border-bottom-left-radius: 160px;
    opacity: 0.9;
    translate: 0 calc(var(--wt-parallax, 0) * -30px);
    -webkit-mask-image: radial-gradient(122% 120% at 90% 6%, #000 24%, transparent 72%);
    mask-image: radial-gradient(122% 120% at 90% 6%, #000 24%, transparent 72%);
}

.wt-site .wt-photo--process::after {
    background: linear-gradient(
        200deg,
        rgba(242, 242, 242, 0.08) 0%,
        rgba(242, 242, 242, 0.4) 40%,
        rgba(242, 242, 242, 0.82) 66%,
        var(--wt-chalk) 84%
    );
}

@media (max-width: 900px) {
    .wt-site .wt-photo--process {
        display: none;
    }
}

@media (prefers-reduced-motion: reduce) {
    .wt-photo {
        translate: none;
    }
}

/*
 * The drawn layouts are gone from the hero. They were rectangles at hairline
 * weight over a ruled ground, and neither survives the change of direction —
 * a wireframe sketch on top of a photograph of a real workspace is two
 * answers to the same question.
 */
.wt-sketch {
    display: none;
}

.wt-sketch {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* The centre is cleared so the headline never sits on a line, and both
       ends fade out rather than stopping at a hard edge. */
    -webkit-mask-image: radial-gradient(
            ellipse 46% 62% at 50% 48%,
            transparent 40%,
            #000 100%
        ),
        linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
    mask-image: radial-gradient(
            ellipse 46% 62% at 50% 48%,
            transparent 40%,
            #000 100%
        ),
        linear-gradient(to right, transparent, #000 12%, #000 88%, transparent);
    -webkit-mask-composite: source-in;
    mask-composite: intersect;
}

.wt-sketch__line {
    fill: none;
    stroke: var(--wt-ink);
    stroke-width: 2.3;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0.4;
}

/* The one place the accent appears at scale outside the headline mark. It is
   a highlight on a drawing, so it stays opaque and heavy while the ink around
   it stays a drawing. */
.wt-sketch__line--mark {
    stroke: var(--wt-accent);
    stroke-width: 5;
    opacity: 1;
}

/*
 * Each stroke draws itself in. The dash length is set well above any path in
 * the drawing so a single offset animation works for all of them without
 * measuring each path's length in script.
 */
.wt-sketch__line {
    stroke-dasharray: 1200;
    stroke-dashoffset: 1200;
    animation: wt-sketch-draw 0.7s ease-out forwards;
    animation-delay: calc(var(--i) * 45ms + 250ms);
}

@keyframes wt-sketch-draw {
    to {
        stroke-dashoffset: 0;
    }
}

@media (prefers-reduced-motion: reduce) {
    .wt-sketch__line {
        animation: none;
        stroke-dashoffset: 0;
    }
}

/* On a phone the headline fills the width, so clearing a wide centre would
   leave nothing of the drawing. The clearing tightens instead. */
@media (max-width: 899px) {
    .wt-sketch {
        -webkit-mask-image: radial-gradient(
                ellipse 60% 26% at 50% 40%,
                transparent 30%,
                #000 100%
            ),
            linear-gradient(to right, #000 0%, #000 82%, transparent);
        mask-image: radial-gradient(
                ellipse 60% 26% at 50% 40%,
                transparent 30%,
                #000 100%
            ),
            linear-gradient(to right, #000 0%, #000 82%, transparent);
    }
}

/* ---- the surface ---- */

/*
 * Paper, not a readout. The hero used to sit on a dot grid with a pool of
 * denser dots tracking the pointer — legible, but it was the same instrument
 * panel every technology site reaches for, and it had nothing to do with what
 * this studio actually makes. A grain reads as a surface something was
 * printed on, which is the right backdrop for a mark made by hand.
 *
 * The vignette keeps the middle of the hero clean, so the grain is only ever
 * felt at the edges rather than seen behind the type.
 */
.wt-hero__glow {
    position: absolute;
    inset: 0;
    z-index: 0;
    width: auto;
    height: auto;
    aspect-ratio: auto;
    border-radius: 0;
    translate: none;
    filter: none;
    /*
     * Three things multiply here — the noise's own alpha, this opacity and
     * the vignette — so values that look reasonable in isolation land at
     * about a tenth of what is legible. Measured against the rendered page
     * rather than guessed: the corner should carry a few levels of variation,
     * enough to feel the surface without seeing it.
     */
    opacity: 0.3;
    pointer-events: none;
    background-color: transparent;
    background-image: var(--wt-grain);
    background-size: 180px 180px;
    background-repeat: repeat;
    /*
     * Even across the hero, fading out only at the foot. A radial vignette
     * was tried first and read as a lens effect — a bright halo behind the
     * headline with grey corners — because a gradual falloff in every
     * direction is not how a sheet of paper behaves. Paper is uniform; the
     * only reason for a fade here is that the band below is not grained, and
     * a hard edge at the join would be visible.
     */
    -webkit-mask-image: linear-gradient(to bottom, #000 0%, #000 58%, transparent 100%);
    mask-image: linear-gradient(to bottom, #000 0%, #000 58%, transparent 100%);
    animation: none;
}

.wt-scrollcue {
    display: none;
}

/* ==========================================================================
   Tag chips
   --------------------------------------------------------------------------
   Project and service labels are written as bullet-separated lists in the
   content. Split into chips they become a scannable summary of what was
   actually delivered rather than a caption nobody reads.
   ========================================================================== */

.wt-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0;
}

/*
 * Two kinds of chip, the way the reference distinguishes them: an outlined
 * chip for a discipline ("разработка", "структура") and a filled pastel chip
 * with no outline for the category the work belongs to ("Ecommerce"). The
 * distinction is real — the first label in every stored list is the category
 * and the rest are what was delivered — so the colour carries information
 * rather than decorating the row.
 */
.wt-chip {
    display: inline-flex;
    align-items: center;
    padding: 6px 13px;
    border: 1px solid var(--wt-ink);
    border-radius: var(--wt-radius-pill);
    background: transparent;
    color: var(--wt-ink);
    font-family: var(--wt-font-body), sans-serif;
    font-size: 12px;
    font-weight: 500;
    letter-spacing: 0;
    line-height: 1.2;
    text-transform: none;
    white-space: nowrap;
}

.wt-chip--tint {
    border-color: transparent;
    background: var(--wt-tint, #ece7fb);
}

.wt-section--dark .wt-chip {
    background: transparent;
    border-color: color-mix(in srgb, #fff 22%, transparent);
    color: var(--wt-on-dark);
}

/* The service cards lead with a numbered chip, so the first one is marked. */
.wt-service-card__number .wt-chip:first-child {
    background: var(--wt-ink);
    border-color: var(--wt-ink);
    color: #fff;
    font-family: var(--wt-font-mono), monospace;
    letter-spacing: 0.06em;
}

/* ==========================================================================
   Navigation count
   ========================================================================== */

.wt-count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 17px;
    height: 15px;
    margin-left: 5px;
    padding: 0 4px;
    border-radius: 4px;
    background: var(--wt-accent);
    color: var(--wt-ink);
    font-family: var(--wt-font-mono), monospace;
    font-size: 9px;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0;
    vertical-align: super;
}

/* ==========================================================================
   Section joins
   --------------------------------------------------------------------------
   The reference stacks its sections as cards. At every boundary where the
   surface colour changes, the band above rounds off its bottom corners over
   the one below and the lower band stays square — a single rule, applied by
   markBands() in the motion layer, which is what produces the stacked rhythm.

   Doing it from a data attribute rather than from :has() sibling chains means
   a section restyled in Oxygen joins correctly on its own.
   ========================================================================== */

/*
 * The curve is drawn in the strip between the two bands rather than on the
 * bands themselves, by a pair of pseudo-elements:
 *
 *   - the band above extends its own colour a radius further down and rounds
 *     off there, and
 *   - the band below reaches the same radius further up, painting its colour
 *     behind that curve.
 *
 * Doing it this way costs no layout: neither band moves, so a joining band
 * keeps exactly the same padding as one that happens to sit between two
 * sections of the same colour. Pulling the lower band up with a negative
 * margin — the obvious approach — quietly eats a radius of its top padding
 * and makes the page rhythm uneven.
 */
.wt-site [data-wt-join] {
    overflow: visible;
}

/*
 * Two properties, not one. Almost every band is both the top half of the join
 * below it and the bottom half of the join above it, and once initJoins()
 * started writing a different radius per join those two roles fought over the
 * same variable — the later write won and the halves of one curve disagreed,
 * leaving a step in the corner. `--wt-join-radius` is the curve this band
 * rounds off into; `--wt-under-radius` is the curve reaching down onto it.
 */
.wt-site [data-wt-join]::after,
.wt-site [data-wt-under]::before {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    background-color: inherit;
    pointer-events: none;
}

.wt-site [data-wt-join]::after {
    top: 100%;
    height: var(--wt-join-radius);
    border-bottom-left-radius: var(--wt-join-radius);
    border-bottom-right-radius: var(--wt-join-radius);
}

.wt-site [data-wt-under]::before {
    height: var(--wt-under-radius, var(--wt-join-radius));
    top: calc(var(--wt-under-radius, var(--wt-join-radius)) * -1);
}

/* initJoins() writes a radius per join on scroll, so the corner opens as the
   band arrives and seals as it settles. The transition is a safety net for
   the frames the scroll handler does not run on, not the effect itself — the
   effect is the number changing. */
.wt-site [data-wt-join]::after,
.wt-site [data-wt-under]::before {
    transition: border-radius 0.12s linear;
}

/* A band continuing the surface above it lets that band's bottom padding
   carry the whole break, rather than adding a second one to it. */
.wt-site [data-wt-continues] {
    padding-top: 0;
}

/* The rounded band has to paint over the one beneath it for the curve to
   read; markBands() assigns the stacking order. */
.wt-site [data-wt-surface] {
    position: relative;
}

.wt-site [data-wt-surface="paper"] {
    background-color: var(--wt-paper);
}

.wt-site [data-wt-surface="chalk"] {
    background-color: var(--wt-chalk);
}

.wt-site [data-wt-surface="ink"] {
    background-color: var(--wt-ink);
    color: #fff;
}

/* The page itself is ink, so the final band rounds off onto the footer. */
.wt-site {
    background-color: var(--wt-ink);
}

/* ==========================================================================
   Client strip
   --------------------------------------------------------------------------
   Named clients directly under the hero, where an agency site puts its logo
   bar. Marked decorative — every client below is also a real link in the
   portfolio section.
   ========================================================================== */

/*
 * The strip runs straight off the bottom of the hero on the same white, the
 * way the reference sets its logo bar — no rule, no change of surface.
 *
 * It carries both breaks around it on its own padding, and that is why the
 * numbers are larger than they look. Above: the hero's own bottom padding was
 * the only separation, which read as the marks belonging to the actions
 * rather than standing as their own band. Below: the next section continues
 * the same white, so `[data-wt-continues]` zeroes that section's top padding
 * — the strip was left holding a full section break on 34px, and seven logos
 * in a row need more air than a paragraph would.
 */
.wt-clients {
    overflow: hidden;
    padding: clamp(44px, 4.6vw, 76px) 0 clamp(60px, 6.4vw, 104px);
    background-color: var(--wt-paper);
}

/*
 * The strip continues the hero's white, so it is a `[data-wt-continues]` band
 * and that rule zeroes its top padding. Right for two bands of text, wrong
 * here: it left the hero's own bottom padding — tuned for the hero's content,
 * not for introducing a logo bar — as the only thing between the actions and
 * seven client marks. This one band takes its top padding back.
 */
.wt-site .wt-clients[data-wt-continues] {
    padding-top: clamp(44px, 4.6vw, 76px);
}

/*
 * The fade is masked onto the track, not onto the strip. Masking the strip
 * makes its own background transparent at both edges, which showed the ink
 * page through the ends of an otherwise white band.
 */
.wt-clients__track {
    -webkit-mask-image: linear-gradient(
        90deg,
        transparent,
        #000 8%,
        #000 92%,
        transparent
    );
    mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}

.wt-clients__track {
    display: flex;
    align-items: center;
    gap: 0;
    width: max-content;
    animation: wt-marquee 42s linear infinite;
}

.wt-clients__item {
    display: inline-flex;
    align-items: center;
    padding: 0 34px;
    color: var(--wt-ink);
    font-family: var(--wt-font-display), sans-serif;
    font-size: clamp(15px, 1.3vw, 19px);
    font-weight: 700;
    letter-spacing: -0.01em;
    text-transform: uppercase;
    white-space: nowrap;
    opacity: 0.5;
}

/*
 * Real client marks, held to the page's monochrome. Seven logos in seven
 * brand palettes would be the loudest thing on a white hero and would read
 * as a sponsor bar; flattened to ink they read as a list of names, which is
 * what a client strip is for. Colour returns on hover, so the mark is still
 * available to anyone who looks for it.
 */
.wt-clients__item--mark {
    padding: 0 40px;
    opacity: 1;
}

.wt-clients__mark {
    display: block;
    width: auto;
    /* Marks arrive at wildly different aspect ratios — a square crest and a
       long wordmark both have to sit on the same optical line, so the box is
       capped in both directions rather than by width alone. */
    max-width: 210px;
    height: clamp(32px, 3.1vw, 44px);
    object-fit: contain;
    object-position: center;
    /*
     * Desaturated rather than knocked out to a silhouette. brightness(0)
     * fills every mark solid, which turns a crest or a monogram with light
     * counters into an unreadable blob; grayscale keeps the tonal structure
     * that makes each one recognisable.
     */
    filter: grayscale(1) contrast(1.15) opacity(0.62);
    transition: filter 0.3s var(--wt-ease-out);
}

.wt-clients__item--mark:hover .wt-clients__mark {
    filter: none;
}

.wt-clients__item::after {
    content: "";
    width: 5px;
    height: 5px;
    margin-left: 34px;
    border-radius: 50%;
    background: var(--wt-ink);
    opacity: 0.35;
}

.wt-clients__item--mark::after {
    margin-left: 40px;
}

@keyframes wt-marquee {
    from {
        transform: translate3d(0, 0, 0);
    }
    to {
        transform: translate3d(-50%, 0, 0);
    }
}

/* ==========================================================================
   Horizontal work track
   --------------------------------------------------------------------------
   The portfolio grid becomes a draggable track with a progress bar, so the
   work reads as a reel rather than as a static block.
   ========================================================================== */

@media (min-width: 768px) {
    /*
     * The reel runs the full width of the viewport and starts at the content
     * grid, so the first card lines up with the heading while the row carries
     * on past the right edge. That signals there is more to come, which
     * matters as the portfolio grows.
     */
    .wt-track {
        /* The distance from the viewport edge to the content grid. */
        --wt-inset: max(calc(50vw - var(--wt-content) / 2), clamp(20px, 4vw, 64px));

        position: relative;
        display: flex;
        grid-template-columns: none;
        gap: 22px;
        width: 100vw;
        max-width: 100vw;
        margin-left: calc(50% - 50vw);
        padding-left: var(--wt-inset);
        padding-right: clamp(20px, 4vw, 64px);
        padding-bottom: 6px;
        overflow-x: auto;
        scroll-snap-type: x proximity;
        /* Without this the snapport starts at the padding box, so the browser
         * scrolls the first card under the inset and the reel no longer lines
         * up with the heading above it. */
        scroll-padding-left: var(--wt-inset);
        scrollbar-width: none;
    }

    .wt-track::-webkit-scrollbar {
        display: none;
    }

    .wt-track--dragging {
        scroll-snap-type: none;
    }

    .wt-track--dragging > *:not(.wt-track__nav) {
        pointer-events: none;
    }

    /* Any direct child of a reel is a slide — the work cards, the numbered
       problem cards, anything the builder puts in a grid that overruns. */
    .wt-track > * {
        flex: 0 0 clamp(300px, 26vw, 400px);
        grid-column: auto;
        scroll-snap-align: start;
        padding-top: 0;
    }

    /* The bar stays inside the content column even though the reel does not. */
    .wt-track__bar {
        position: relative;
        height: 2px;
        margin-top: 30px;
        background: var(--wt-hairline);
        overflow: hidden;
    }

    .wt-track__bar i {
        position: absolute;
        inset: 0;
        display: block;
        background: var(--wt-ink);
        transform-origin: left;
        transform: scaleX(0.08);
        transition: transform 0.12s linear;
    }

    /*
     * The arrows, in one chartreuse pill. This is the only control on the
     * site that is a solid block of accent at size, which is exactly why it
     * works here: the reel has no visible scrollbar, so the one thing that
     * says "there is more to the right" has to be impossible to miss.
     */
    /* Rides with the pointer across the track. Absolutely placed, so it is
       taken out of the flex row the cards sit in and never becomes a slide. */
    /*
     * Parked under the track. It followed the pointer to begin with, matching
     * the reference, and that single decision caused every fault this control
     * had: centred on the cursor it slid out from under any attempt to press
     * an arrow, its arrival animation meant press and release landed on
     * different elements so no click was ever synthesised, and once it sat
     * outside the scroller, crossing onto it read as leaving the reel and the
     * hover flickered. Still, it has none of those problems.
     */
    .wt-track__nav {
        display: inline-flex;
        align-items: center;
        /* The reel's parent is a stretching flex column, so an inline-flex
           pill still fills the row unless it is told twice not to. */
        align-self: flex-start;
        width: fit-content;
        margin-top: 20px;
        border-radius: var(--wt-radius-pill);
        background: var(--wt-accent);
    }


    .wt-track__arrow {
        display: grid;
        place-items: center;
        width: 62px;
        height: 46px;
        padding: 0;
        border: 0;
        border-radius: var(--wt-radius-pill);
        background: none;
        color: var(--wt-ink);
        cursor: pointer;
        transition:
            opacity 0.2s var(--wt-ease-out),
            translate 0.2s var(--wt-ease-out);
    }

    .wt-track__arrow svg {
        width: 21px;
        height: 21px;
        fill: none;
        stroke: currentColor;
        stroke-width: 1.9;
        stroke-linecap: round;
        stroke-linejoin: round;
    }

    .wt-track__arrow--prev:hover:not(:disabled) {
        translate: -2px 0;
    }

    .wt-track__arrow--next:hover:not(:disabled) {
        translate: 2px 0;
    }

    /* Dimmed rather than hidden: a control that disappears at the end of the
       track moves the one beside it, and the reader loses the target. */
    .wt-track__arrow:disabled {
        opacity: 0.32;
        cursor: default;
    }

    /* The per-card arrow is redundant once the pill carries the affordance. */
    .wt-track .wt-arrow {
        display: none;
    }
}

@media (max-width: 767px) {
    .wt-track__bar,
    .wt-track__nav {
        display: none;
    }
}

/* Coarse pointers get the native scroll and keep the per-card arrow. */
@media (pointer: coarse) {
    .wt-track {
        cursor: auto;
    }

    .wt-track .wt-arrow {
        display: block;
    }
}

/* ==========================================================================
   Inner-page heroes
   --------------------------------------------------------------------------
   The reference opens an inner page on white and centres it: a breadcrumb,
   the title, one line of lead. Same surface as the home hero, so arriving on
   a service page from search feels like the same site rather than a darker
   annexe of it.
   ========================================================================== */

.wt-page-hero,
.wt-case-hero {
    position: relative;
    background-color: var(--wt-paper);
    color: var(--wt-ink);
}

.wt-page-hero .wt-display,
.wt-page-hero .wt-display--medium,
.wt-case-hero .wt-display,
.wt-case-hero .wt-display--medium {
    color: var(--wt-ink);
}

.wt-page-hero .wt-lead,
.wt-case-hero .wt-lead {
    color: var(--wt-graphite);
}

.wt-page-hero__inner,
.wt-case-hero__inner {
    position: relative;
    z-index: 2;
}

.wt-hero--centred .wt-page-hero__inner,
.wt-hero--centred .wt-case-hero__inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(18px, 2vw, 28px);
    /* Wide enough that a full-sentence title still breaks into two or three
       lines rather than five; the lead pulls in tighter below it. */
    max-width: min(100%, 900px);
    margin-inline: auto;
    text-align: center;
}

.wt-hero--centred .wt-eyebrow {
    align-self: center;
}

.wt-hero--centred .wt-lead {
    max-width: 62ch;
}

/*
 * The builder sets the lead beside the actions in two columns. Centred, that
 * pair has to stack — otherwise both halves shrink to the width of their own
 * content and end up squeezed against the middle of the page.
 */
.wt-hero--centred .wt-two-col {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(20px, 2.2vw, 32px);
    width: 100%;
}

.wt-hero--centred .wt-row {
    justify-content: center;
}

/*
 * The builder paints this eyebrow white for the dark hero it used to sit on.
 * On the light hero it has to invert, or it disappears and leaves only its
 * leading dot floating above the title.
 */
.wt-page-hero .wt-eyebrow--light,
.wt-case-hero .wt-eyebrow--light {
    border-color: var(--wt-hairline);
    color: var(--wt-ink);
}

.wt-page-hero .wt-eyebrow--light::before,
.wt-case-hero .wt-eyebrow--light::before {
    background: var(--wt-ink);
}

/* The project meta reads as one centred caption row rather than a stack.
   The centred hero column shrinks its children to content width, so the row
   has to claim the full measure back or it collapses into a narrow list. */
.wt-hero--centred .wt-case-meta {
    display: flex;
    flex-wrap: wrap;
    align-self: stretch;
    width: 100%;
    justify-content: center;
    gap: 10px clamp(24px, 3vw, 48px);
    margin-top: clamp(24px, 3vw, 40px);
    padding-top: clamp(20px, 2.4vw, 30px);
    border-top: 1px solid var(--wt-hairline);
    text-align: center;
}

.wt-hero--centred .wt-case-meta > * {
    margin: 0;
}

/* ==========================================================================
   Breadcrumbs
   ========================================================================== */

.wt-crumbs {
    margin-bottom: clamp(18px, 2vw, 30px);
}

.wt-crumbs__list {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 8px;
    margin: 0;
    padding: 0;
    list-style: none;
    font-family: var(--wt-font-mono), monospace;
    font-size: 11px;
    letter-spacing: 0.06em;
}

.wt-crumbs__list li {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    color: var(--wt-graphite);
}

.wt-crumbs__list li + li::before {
    content: "/";
    color: var(--wt-hairline);
}

.wt-crumbs__list a {
    color: var(--wt-graphite);
    text-decoration: none;
}

.wt-crumbs__list a:hover {
    color: var(--wt-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.wt-crumbs__list [aria-current="page"] {
    color: var(--wt-ink);
}

/* ==========================================================================
   Section surfaces
   --------------------------------------------------------------------------
   Three surfaces and no more: paper, chalk and ink. markBands() stamps the
   surface onto each band; these rules are the fallback for anything the
   script has not reached yet, so the page is never unstyled before it runs.
   ========================================================================== */

.wt-site {
    color: var(--wt-ink);
}

.wt-section {
    background-color: var(--wt-paper);
}

.wt-section--white {
    background-color: var(--wt-chalk);
}

.wt-section--dark,
.wt-section--blue {
    background-color: var(--wt-ink);
    color: #fff;
}

.wt-section > * {
    position: relative;
    z-index: 1;
}

/* ==========================================================================
   The commitments strip
   --------------------------------------------------------------------------
   Response time, both build ranges and care after launch. The most concrete
   promise on the page and the first thing after the hero, so it is treated as
   evidence rather than as a caption.
   ========================================================================== */

.wt-section--compact:has(.wt-proofbar) {
    padding-top: clamp(30px, 3.4vw, 52px);
    padding-bottom: clamp(46px, 5vw, 76px);
}

.wt-proofbar {
    border-top-width: 2px;
    border-top-color: var(--wt-ink);
    border-bottom-color: var(--wt-hairline);
}

/*
 * The dividers are what turn this row into cells, so the text has to be held
 * off them on both sides. With padding only on the right, every item after
 * the first sat flush against the rule to its left and read as though it had
 * been shoved against it.
 *
 * Every cell is padded the same, with no exception for the first and last.
 * Exempting those would line the outer text up with the page grid, but the
 * strip rewraps on content width rather than at a breakpoint — four across,
 * then one per row, then two — so whichever cells happened to be on an end
 * changed with the viewport, and the indent went with them.
 */
.wt-proofbar__item {
    position: relative;
    gap: 12px;
    min-height: 0;
    padding: 26px clamp(18px, 1.8vw, 26px);
    justify-content: start;
    border-right-color: var(--wt-hairline);
    transition: background-color 0.3s var(--wt-ease-out);
}

/* A marker that draws in on hover, so the strip responds to being read. */
.wt-proofbar__item::after {
    content: "";
    position: absolute;
    top: -2px;
    left: 0;
    width: 100%;
    height: 2px;
    background: var(--wt-accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.4s var(--wt-ease-out);
}

.wt-proofbar__item:hover::after {
    transform: scaleX(1);
}

.wt-proofbar__item:hover {
    background-color: var(--wt-chalk);
}

.wt-proofbar__value {
    font-family: var(--wt-font-display), sans-serif;
    font-weight: 800;
    font-variation-settings: "wght" 800;
    font-size: clamp(22px, 2vw, 32px);
    line-height: 1;
    letter-spacing: -0.02em;
    text-transform: uppercase;
}

.wt-proofbar__label {
    color: var(--wt-graphite);
    font-family: var(--wt-font-body), sans-serif;
    font-size: 14px;
    line-height: 1.45;
    letter-spacing: 0;
    text-transform: none;
}

/* ==========================================================================
   Cards
   ========================================================================== */

.wt-card,
.wt-post-card,
.wt-quote,
.wt-service-card,
.wt-form-card {
    position: relative;
    border-radius: 16px;
    border-color: var(--wt-hairline);
    background-color: var(--wt-paper);
    transition:
        border-color 0.28s var(--wt-ease-out),
        background-color 0.28s var(--wt-ease-out);
}

.wt-card:hover,
.wt-post-card:hover,
.wt-quote:hover,
.wt-service-card:hover {
    transform: none;
    box-shadow: none;
    border-color: var(--wt-ink);
}

.wt-section--dark .wt-card,
.wt-section--dark .wt-quote,
.wt-section--dark .wt-post-card {
    background-color: var(--wt-panel);
    border-color: color-mix(in srgb, #fff 14%, transparent);
    color: #fff;
}

.wt-icon {
    border-radius: 50%;
    background-color: var(--wt-accent);
    color: var(--wt-ink);
}

.wt-arrow {
    color: var(--wt-ink);
    transition: transform 0.3s var(--wt-ease-out);
}

.wt-section--dark .wt-arrow {
    color: #fff;
}

/* ==========================================================================
   Service cards
   --------------------------------------------------------------------------
   One sentence and a reserved 390px of nothing said far less than the service
   actually involves. The six modules are read from the linked service page, so
   the card carries real scope instead of dead space.
   ========================================================================== */

.wt-service-card {
    min-height: 0;
    justify-content: flex-start;
    gap: 22px;
    padding: clamp(26px, 2.6vw, 40px);
}

.wt-modules {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 2px 20px;
    margin: 2px 0 0;
    padding: 0;
    list-style: none;
    border-top: 1px solid var(--wt-hairline);
    padding-top: 18px;
}

.wt-modules__item {
    display: flex;
    align-items: baseline;
    gap: 9px;
    padding: 5px 0;
    color: var(--wt-ink);
    font-family: var(--wt-font-body), sans-serif;
    font-size: 14px;
    line-height: 1.35;
}

.wt-modules__item::before {
    content: "";
    flex: 0 0 auto;
    width: 5px;
    height: 5px;
    margin-top: 1px;
    border-radius: 50%;
    background: var(--wt-ink);
}

.wt-service-card:hover .wt-modules__item::before {
    background: var(--wt-blue);
}

.wt-service-card__foot {
    margin-top: auto;
    padding-top: 6px;
}

@media (max-width: 560px) {
    .wt-modules {
        grid-template-columns: 1fr;
    }
}

/* ==========================================================================
   The positioning panel
   --------------------------------------------------------------------------
   The band's empty column, filled with the argument the copy beside it makes
   in prose: four disciplines assembled into one solution, over the four
   qualities that survive the assembly. Built by buildPositioningPanel() out
   of words checked against that copy, so the diagram cannot drift from what
   the page says. A drawing of blank plates stood here before and named none
   of it, which is why the column still read as decoration.
   ========================================================================== */

.wt-intro-grid--figure {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.86fr);
    align-items: center;
    gap: clamp(32px, 5vw, 80px);
}

.wt-intro-grid__copy {
    display: flex;
    flex-direction: column;
    gap: clamp(20px, 2.2vw, 30px);
    max-width: 54ch;
}

/*
 * The panel used to be a flat grey rectangle with the diagram floating in the
 * middle of it, which read as a placeholder no matter what was drawn on it.
 * It is now a ruled ground — a drafting grid, which is what a foundation gets
 * set out on — with the block of disciplines sitting on it as solid paper and
 * the result cutting the full width of the panel. Three planes instead of
 * one, and the grid is drawn rather than loaded: no image to host, and it
 * scales to any panel size without resampling.
 */
.wt-figure {
    --wt-figure-pad: clamp(22px, 2.4vw, 34px);
    position: relative;
    display: grid;
    padding: var(--wt-figure-pad);
    overflow: hidden;
    border: 1px solid var(--wt-hairline);
    border-radius: 20px;
    background-color: var(--wt-chalk);
}

.wt-figure > * {
    position: relative;
}

.wt-figure__art {
    width: 100%;
    height: auto;
    place-self: center;
}

/* The four disciplines as one bordered block rather than four cards: rows
   that already share an edge are the claim the paragraph is making. */
.wt-figure__stack {
    margin: 0;
    padding: 0;
    border: 1px solid var(--wt-hairline);
    border-radius: 14px;
    background: var(--wt-paper);
    list-style: none;
    overflow: hidden;
}

.wt-figure__row {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr) auto;
    align-items: center;
    gap: 14px;
    padding: clamp(11px, 1.2vw, 15px) clamp(14px, 1.5vw, 20px);
}

.wt-figure__row + .wt-figure__row {
    border-top: 1px solid var(--wt-hairline);
}

.wt-figure__num {
    color: var(--wt-graphite);
    font-family: var(--wt-font-mono), monospace;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.08em;
}

.wt-figure__name {
    font-family: var(--wt-font-display), sans-serif;
    font-weight: 700;
    font-variation-settings: "wght" 700;
    font-size: clamp(14px, 1.15vw, 17px);
    line-height: 1.1;
    letter-spacing: -0.005em;
    text-transform: uppercase;
}

/* Four into one, drawn: a hairline out of the block into a solid head. */
.wt-figure__join {
    position: relative;
    height: clamp(26px, 3vw, 38px);
}

.wt-figure__join::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 7px;
    left: calc(50% - 0.5px);
    width: 1px;
    background: var(--wt-hairline);
}

.wt-figure__join::after {
    content: "";
    position: absolute;
    bottom: 0;
    left: 50%;
    width: 11px;
    height: 8px;
    translate: -50% 0;
    background: var(--wt-ink);
    clip-path: polygon(50% 100%, 0 0, 100% 0);
}

/* The head cuts the full width of the panel. Inset like everything else it
   was one more centred block on a field of padding, which is the flatness the
   panel had in the first place. */
.wt-figure__result {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 0 calc(-1 * var(--wt-figure-pad));
    padding: clamp(15px, 1.7vw, 20px) var(--wt-figure-pad);
    background: var(--wt-ink);
    color: var(--wt-paper);
    font-family: var(--wt-font-display), sans-serif;
    font-weight: 800;
    font-variation-settings: "wght" 800;
    font-size: clamp(15px, 1.3vw, 19px);
    line-height: 1.08;
    letter-spacing: -0.01em;
    text-transform: uppercase;
}

.wt-figure__result::before {
    content: "";
    flex: 0 0 auto;
    width: 9px;
    height: 9px;
    background: var(--wt-accent);
}

/* What the assembly is not allowed to cost. Ticked, not bulleted: the copy
   states them as things kept, not as a list of features on offer. */
.wt-figure__out {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 11px clamp(12px, 1.4vw, 20px);
    margin: clamp(18px, 2vw, 24px) 0 0;
    padding: clamp(18px, 2vw, 24px) 0 0;
    border-top: 1px solid var(--wt-hairline);
    list-style: none;
}

.wt-figure__out li {
    display: grid;
    grid-template-columns: auto minmax(0, 1fr);
    align-items: start;
    gap: 9px;
    color: var(--wt-graphite);
    font-family: var(--wt-font-mono), monospace;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.07em;
    line-height: 1.35;
    text-transform: uppercase;
}

.wt-figure__tick {
    width: 12px;
    height: 12px;
    margin-top: 1px;
    fill: none;
    stroke: var(--wt-ink);
    stroke-width: 1.8;
    stroke-linecap: round;
    stroke-linejoin: round;
}

/* The panel assembles once it is on screen, in the order the copy names its
   parts — the reveal observer owns the panel, these follow its class. */
.wt-figure__row,
.wt-figure__join,
.wt-figure__result,
.wt-figure__out li {
    opacity: 0;
    translate: 0 10px;
    transition:
        opacity 0.5s var(--wt-ease-out),
        translate 0.5s var(--wt-ease-out);
    transition-delay: calc(var(--i, 0) * 80ms + 120ms);
}

.wt-figure.wt-is-revealed .wt-figure__row,
.wt-figure.wt-is-revealed .wt-figure__join,
.wt-figure.wt-is-revealed .wt-figure__result,
.wt-figure.wt-is-revealed .wt-figure__out li {
    opacity: 1;
    translate: 0 0;
}

.wt-figure__plate {
    fill: var(--wt-paper);
    stroke: var(--wt-ink);
    stroke-width: 0.9;
    opacity: var(--o, 1);
}

.wt-figure__line {
    fill: var(--wt-ink);
    opacity: 0.24;
}

.wt-figure__accent {
    fill: var(--wt-accent);
}

/* The layers settle into place once, in the order the copy names them. */
.wt-figure__layer {
    transform-box: view-box;
    transform-origin: center;
    animation: wt-settle 0.9s var(--wt-ease-out) both;
    animation-delay: calc(var(--i) * 130ms + 200ms);
}

@keyframes wt-settle {
    from {
        opacity: 0;
        translate: 0 16px;
    }
    to {
        opacity: 1;
        translate: 0 0;
    }
}

@media (max-width: 900px) {
    .wt-intro-grid--figure {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* Two mono columns will not hold a phrase like "Day-to-day control" at phone
   width without breaking it across three lines. */
@media (max-width: 430px) {
    .wt-figure__out {
        grid-template-columns: minmax(0, 1fr);
    }
}

/* ==========================================================================
   Services — the disclosure list
   --------------------------------------------------------------------------
   The claim on the left, the scope on the right, opened one category at a
   time. Built by buildServiceAccordion() out of the cards the builder
   rendered, so the copy and the links stay editable in Oxygen.
   ========================================================================== */

/*
 * The band stacks rather than splitting: claim across the top, the two
 * services side by side underneath. There are exactly two of them and the
 * heading asks the reader to compare — "two areas, one standard" — which a
 * pair on one row does and a list down a narrow column does not.
 */
.wt-svc-grid {
    display: flex;
    flex-direction: column;
    gap: clamp(38px, 4.4vw, 68px);
}

/* The heading block is a .wt-between, which spreads its two children apart
   on one row. Across the full width that is what it should do — claim left,
   the line of copy set against it on the right. */
.wt-svc-grid > .wt-between {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 0.62fr);
    align-items: end;
    gap: clamp(24px, 4vw, 72px);
    max-width: none;
}

.wt-svc-grid > .wt-between > * {
    max-width: 46ch;
}

/* Kept as the hook for whatever fills this band's ground. The drafting grid
   that was here has been removed — see "Backgrounds" in HANDOFF.md. */
.wt-svc-band {
    position: relative;
}

.wt-services--list {
    display: block;
    gap: 0;
}

.wt-svc {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
    gap: clamp(28px, 3.4vw, 56px);
}

/*
 * Each service opens under its own rule. On hover that rule is drawn across
 * in chartreuse — the accent's job everywhere else on the site is to mark the
 * thing currently in play, and a 2px line drawing itself is the quietest way
 * to say it about a block this size.
 */
.wt-svc__row {
    position: relative;
    border-top: 1px solid var(--wt-hairline);
}

.wt-svc__row::before {
    content: "";
    position: absolute;
    top: -1px;
    left: 0;
    width: 0;
    height: 2px;
    background: var(--wt-accent);
    transition: width 0.55s var(--wt-ease-out);
}

.wt-svc__row:hover::before,
.wt-svc__row:focus-within::before {
    width: 100%;
}

@media (prefers-reduced-motion: reduce) {
    .wt-svc__row::before {
        transition: none;
    }
}

.wt-svc__head {
    padding: clamp(20px, 2vw, 28px) 0 0;
}

.wt-svc__mark {
    display: block;
    margin-bottom: 8px;
    color: var(--wt-graphite);
    font-family: var(--wt-font-mono), monospace;
    font-size: 10px;
    font-weight: 500;
    letter-spacing: 0.09em;
    text-transform: uppercase;
}

.wt-svc__title {
    margin: 0;
    font-family: var(--wt-font-display), sans-serif;
    font-weight: 700;
    font-variation-settings: "wght" 700;
    font-size: clamp(20px, 1.9vw, 28px);
    line-height: 1.14;
    letter-spacing: -0.015em;
}

.wt-svc__body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 18px;
    padding: 16px 0 clamp(22px, 2.4vw, 32px);
}

.wt-svc__copy {
    margin: 0;
    max-width: 52ch;
    color: var(--wt-graphite);
    font-family: var(--wt-font-body), sans-serif;
    font-size: 15px;
    line-height: 1.6;
}

.wt-svc__chips {
    padding: 0;
    list-style: none;
}

.wt-svc__more {
    display: inline-flex;
    align-items: center;
    gap: 9px;
    color: var(--wt-ink);
    font-family: var(--wt-font-body), sans-serif;
    font-size: 14px;
    font-weight: 500;
    text-decoration: none;
}

.wt-svc__more::after {
    content: "";
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--wt-ink);
    transition: background-color 0.24s var(--wt-ease-out);
}

.wt-svc__more:hover {
    text-decoration: underline;
    text-underline-offset: 4px;
}

.wt-svc__more:hover::after {
    background: var(--wt-blue);
}

@media (max-width: 900px) {
    .wt-svc-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: clamp(24px, 4vw, 40px);
    }
}

/* ==========================================================================
   Portfolio cards
   --------------------------------------------------------------------------
   The builder renders the chrome bar after the screenshot, so it landed below
   the image and was clipped; column-reverse puts it back on top without
   touching page structure.
   ========================================================================== */

.wt-project-card__media,
.wt-project-card__media--dark,
.wt-project-card__media--warm,
.wt-project-card__media--sage {
    position: relative;
    border-radius: 18px;
    background-color: var(--wt-chalk);
    transition: background-color 0.35s var(--wt-ease-out);
}

.wt-project-card:hover .wt-project-card__media {
    background-color: var(--wt-chalk-dim);
}

.wt-project-card--small {
    padding-top: 0;
}

/* The builder rendered these as its own link element, which carried the link
   reset with it. The rebuilt cards are plain anchors, so the reset has to be
   stated — without it a card title turns blue on visit. */
.wt-project-card {
    gap: 18px;
    color: inherit;
    text-decoration: none;
}

.wt-project-card__mock {
    display: flex;
    flex-direction: column-reverse;
    border-radius: 10px;
    border: 1px solid var(--wt-hairline);
    box-shadow: 0 20px 44px -22px rgba(0, 0, 0, 0.4);
}

.wt-project-card__mockbar {
    position: relative;
    flex: 0 0 auto;
    height: 26px;
    background-color: var(--wt-chalk);
    border-bottom: 1px solid var(--wt-hairline);
}

.wt-project-card__mockbar::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 12px;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    translate: 0 -50%;
    background: var(--wt-hairline);
    box-shadow:
        11px 0 0 var(--wt-hairline),
        22px 0 0 var(--wt-hairline);
}

.wt-project-thumb {
    flex: 1 1 auto;
    min-height: 0;
    border-radius: 0;
    /* Captures are ~1.92:1 inside a ~1.45:1 frame, so something has to crop.
     * Anchoring top-left keeps each site's logo and primary nav visible. */
    object-position: 0 0;
    transition: transform 0.6s var(--wt-ease-out);
}

.wt-project-card:hover .wt-project-thumb {
    transform: scale(1.03);
    transform-origin: 0 0;
}

.wt-project-card__meta {
    align-items: center;
}

.wt-project-card__label {
    color: var(--wt-graphite);
}

.wt-project-card:hover .wt-arrow {
    transform: translate3d(5px, -5px, 0);
}

/* ==========================================================================
   The work index
   --------------------------------------------------------------------------
   The archive, laid out the way the reference lays out its work page and the
   way the sites the user pointed at — Apple, Stripe — handle a grid of
   products: let the picture be big, give it room, and keep everything around
   it quiet. One plate per project, the screenshot doing the work, the type
   underneath it small and calm.

   Scoped to the archive body class rather than to `.wt-project-grid`, because
   the same grid on the home page is a reel and must keep the reel's card
   sizing.
   ========================================================================== */

.wt-work-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr));
    gap: clamp(22px, 2.4vw, 38px);
}

.wt-work-card {
    display: flex;
    flex-direction: column;
    gap: 0;
    padding: clamp(13px, 1.1vw, 17px);
    border-radius: 24px;
    background: var(--wt-paper);
    text-decoration: none;
    transition:
        transform 0.5s var(--wt-ease-out),
        box-shadow 0.5s var(--wt-ease-out);
}

.wt-work-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 26px 50px -30px rgba(0, 0, 0, 0.42);
}

/* The screenshot is the card. The browser chrome the home-page reel puts
   around it is one frame too many when the plate is already a frame. */
.wt-work-card .wt-project-card__media {
    position: relative;
    border-radius: 14px;
    overflow: hidden;
    background: var(--wt-chalk);
}

.wt-work-card .wt-project-card__mock {
    display: block;
    border: 0;
    border-radius: 14px;
    box-shadow: none;
    overflow: hidden;
}

.wt-work-card .wt-project-card__mockbar {
    display: none;
}

/* 3:2 — wide enough to keep a hero unit legible, tall enough that the plate
   has presence in the grid. The captures are 16:9, so the crop takes it off
   the bottom and the site's navigation and headline always survive. */
.wt-work-card .wt-project-thumb {
    display: block;
    width: 100%;
    aspect-ratio: 3 / 2;
    object-fit: cover;
    object-position: 50% 0;
    border-radius: 14px;
}

.wt-work-card:hover .wt-project-thumb {
    transform: scale(1.04);
    transform-origin: 50% 0;
}

/* The market the project served, riding on the image — the position the
   reference gives its result metric. There are no measured outcomes on file
   for any project here, so the slot carries something true instead. */
.wt-work-card__tag {
    position: absolute;
    top: 14px;
    left: 14px;
    z-index: 2;
    background: var(--wt-paper);
    border-color: transparent;
    box-shadow: 0 6px 18px -10px rgba(0, 0, 0, 0.5);
}

.wt-work-card .wt-project-card__meta {
    align-items: start;
    gap: 14px;
    padding: clamp(18px, 1.6vw, 24px) 6px clamp(8px, 0.8vw, 12px);
}

.wt-work-card .wt-h3 {
    font-size: clamp(18px, 1.35vw, 22px);
}

.wt-work-card .wt-project-card__label {
    margin-top: 6px;
}

/* ==========================================================================
   Problems — numbered cards
   --------------------------------------------------------------------------
   Promoted onto the home page from the service pages: name the pain before
   offering the solution. It arrives as a list, so it is set out as cards to
   match the process grid further down.
   ========================================================================== */

/*
 * On the service page this section is a two-column block with the heading
 * beside the list. On the home page the cards need the full measure, so the
 * wrapper stacks and the grid runs the width of the container.
 */
.wt-two-col:has(.wt-list) {
    display: block;
}

.wt-two-col:has(.wt-list) > .wt-stack--tight {
    max-width: 62ch;
    margin-bottom: clamp(28px, 3vw, 46px);
}

/*
 * Sized from the space the list actually has rather than from the viewport.
 * On the questionnaire these cards sit in a narrow column beside the form,
 * where three viewport-width columns squeezed each one to about 130px and
 * clipped every title — the page was wide, but the column was not.
 */
.wt-list {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr));
    gap: 18px;
}

.wt-list__item {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    padding: 30px 26px 34px;
    border: 1px solid var(--wt-hairline);
    border-top: 1px solid var(--wt-hairline);
    border-radius: 16px;
    background: var(--wt-paper);
    transition: border-color 0.26s var(--wt-ease-out);
}

.wt-list__item:hover {
    border-color: var(--wt-ink);
}

/* The numeral leads, the way it does on the process cards. */
.wt-list__item .wt-list__mark {
    width: auto;
    height: auto;
    margin: 0 0 6px;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    color: var(--wt-ink);
    font-family: var(--wt-font-display), sans-serif;
    font-size: clamp(30px, 2.8vw, 44px);
    font-weight: 800;
    font-variation-settings: "wght" 800;
    line-height: 1;
    letter-spacing: -0.03em;
}


/* ==========================================================================
   Process — numbered cards
   --------------------------------------------------------------------------
   Four steps in a bordered grid with the numeral doing the heavy lifting, the
   way the reference sets out the problems it solves. The order here is real,
   so the numbering carries information rather than decoration.
   ========================================================================== */

.wt-process {
    gap: 18px;
}

.wt-process__step {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 30px 26px 34px;
    border: 1px solid var(--wt-hairline);
    border-radius: 16px;
    background: var(--wt-paper);
    transition: border-color 0.26s var(--wt-ease-out);
}

.wt-process__step:hover {
    border-color: var(--wt-ink);
}

/* The builder draws dividers between steps; the cards carry their own edges. */
.wt-process__step,
.wt-process__step--last {
    border-right-width: 1px;
    border-right-style: solid;
    border-right-color: var(--wt-hairline);
}

.wt-process__number {
    order: -1;
    margin-bottom: 4px;
}

/* The numeral carries the order; wrapping it moved that onto the wrapper. */
.wt-process__step .wt-glyph-row {
    order: -1;
}

/* The numeral does the heavy lifting; the stage name stays a quiet chip. */
.wt-process__number .wt-chip:first-child {
    padding: 0;
    border: 0;
    background: none;
    color: var(--wt-ink);
    font-family: var(--wt-font-display), sans-serif;
    font-size: clamp(34px, 3.2vw, 50px);
    font-weight: 800;
    font-variation-settings: "wght" 800;
    letter-spacing: -0.03em;
    line-height: 1;
}

.wt-process__number .wt-chip:nth-child(2) {
    align-self: start;
    color: var(--wt-graphite);
    font-family: var(--wt-font-mono), monospace;
    font-size: 10px;
    letter-spacing: 0.08em;
}

.wt-process__number {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
}

/* ==========================================================================
   Testimonials
   --------------------------------------------------------------------------
   One quote at a time on a black card that spans the container, the way the
   reference does it. Last thing read before the ask, so it is given the width
   and the contrast to be read rather than skimmed.
   ========================================================================== */

.wt-quotes {
    display: grid;
    grid-template-columns: minmax(0, 0.42fr) minmax(0, 1fr);
    align-items: stretch;
    gap: 0;
    padding: 0;
    overflow: hidden;
    border-radius: 20px;
    background: var(--wt-ink);
    color: #fff;
}

.wt-quotes__aside {
    display: grid;
    place-items: center;
    padding: clamp(28px, 3vw, 48px);
    background: var(--wt-panel);
}

.wt-quotes__mark {
    width: 100%;
    max-width: 220px;
    height: auto;
}

.wt-quotes__dot {
    fill: #fff;
    opacity: 0.16;
}

.wt-quotes__glyph {
    fill: var(--wt-accent);
    font-family: var(--wt-font-display), sans-serif;
    font-size: 92px;
    font-weight: 800;
}

.wt-quotes__stage {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 22px;
    padding: clamp(30px, 3.4vw, 56px);
}

/*
 * The inactive quotes are stacked under the active one rather than removed,
 * so the card keeps the height of its tallest quote and the page does not
 * jump as the reader steps through.
 */
.wt-quotes__stage .wt-quote {
    grid-area: 1 / 1;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    color: #fff;
    opacity: 0;
    visibility: hidden;
    transition:
        opacity 0.4s var(--wt-ease-out),
        transform 0.4s var(--wt-ease-out);
    transform: translate3d(0, 8px, 0);
}

.wt-quotes__stage {
    display: grid;
    grid-template-columns: minmax(0, 1fr);
    align-content: center;
}

.wt-quotes__stage .wt-quote--on {
    opacity: 1;
    visibility: visible;
    transform: none;
}

.wt-quotes__stage .wt-quote:hover {
    border-color: transparent;
}

.wt-quote__text {
    font-family: var(--wt-font-body), sans-serif;
    font-size: clamp(18px, 1.7vw, 26px);
    line-height: 1.45;
    letter-spacing: -0.01em;
}

.wt-quotes__stage .wt-quote__text {
    color: #fff;
}

.wt-quote__name {
    display: flex;
    align-items: center;
    gap: 9px;
    margin-top: 22px;
    color: var(--wt-ink);
}

.wt-quotes__stage .wt-quote__name {
    color: var(--wt-on-dark);
}

.wt-quote__name::before {
    content: "";
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--wt-ink);
}

.wt-quotes__stage .wt-quote__name::before {
    background: var(--wt-accent);
}

/*
 * Shares cell 1/1 with the stacked quotes, so it has to be lifted above them
 * or it cannot be clicked. The quotes carry a `transform` for their fade, and
 * a transformed element paints in the positioned layer — above a later
 * sibling that is neither positioned nor transformed, whatever the DOM order
 * says. The buttons were under the quote the whole time: every press landed
 * on the text and the slider never advanced.
 */
.wt-quotes__nav {
    position: relative;
    z-index: 2;
    grid-area: 1 / 1;
    align-self: end;
    justify-self: end;
    display: flex;
    align-items: center;
    gap: 10px;
    /* Sits below the quote it steps through, clear of the longest one. */
    margin-top: auto;
    padding-top: 26px;
}

.wt-quotes__count {
    margin: 0 6px 0 0;
    color: var(--wt-on-dark);
    font-family: var(--wt-font-mono), monospace;
    font-size: 11px;
    letter-spacing: 0.08em;
}

.wt-quotes__step {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    border: 1px solid color-mix(in srgb, #fff 26%, transparent);
    border-radius: 50%;
    background: transparent;
    color: #fff;
    font-size: 15px;
    line-height: 1;
    cursor: pointer;
    transition:
        background-color 0.22s var(--wt-ease-out),
        border-color 0.22s var(--wt-ease-out),
        color 0.22s var(--wt-ease-out);
}

.wt-quotes__step:hover {
    background: var(--wt-accent);
    border-color: var(--wt-accent);
    color: var(--wt-ink);
}

@media (max-width: 860px) {
    .wt-quotes {
        grid-template-columns: minmax(0, 1fr);
    }

    .wt-quotes__aside {
        padding: 26px;
    }

    .wt-quotes__mark {
        max-width: 120px;
    }
}

/* ==========================================================================
   Closing ask
   ========================================================================== */

.wt-section:has(.wt-quote-grid) {
    padding-bottom: clamp(56px, 6vw, 88px);
}

.wt-section:has(.wt-cta) {
    padding-top: clamp(64px, 7vw, 100px);
    padding-bottom: clamp(64px, 7vw, 100px);
}

/*
 * A tall slab with a headline stranded in one half asked for commitment while
 * giving the eye nowhere to land. This is a compact horizontal band instead:
 * a short shouted headline, one line of copy, the actions, and the response
 * promise restated directly beneath them. Everything the reader needs to
 * decide sits on one line of sight.
 */
.wt-cta {
    min-height: 0;
    padding: clamp(32px, 3.4vw, 54px);
    border-radius: 20px;
    background-color: var(--wt-panel);
    color: #fff;
    overflow: hidden;
}

.wt-cta .wt-display--medium,
.wt-cta .wt-h2 {
    color: #fff;
    font-size: clamp(30px, 2.9vw, 46px);
    line-height: 0.92;
}

.wt-cta .wt-lead {
    color: var(--wt-on-dark);
    font-size: 16px;
}

/* The evidence frame belongs to the hero; here it only added height. */
.wt-cta__orb {
    display: none;
}

/* The response promise, lifted from the commitments strip by the script. */
.wt-assure {
    display: flex;
    align-items: center;
    gap: 9px;
    margin: 14px 0 0;
    color: var(--wt-on-dark);
    font-family: var(--wt-font-body), sans-serif;
    font-size: 13px;
    line-height: 1.4;
}

.wt-assure b {
    color: var(--wt-accent);
    font-weight: 600;
}

.wt-assure::before {
    content: "";
    flex: 0 0 auto;
    width: 7px;
    height: 7px;
    border-radius: 50%;
    background: var(--wt-accent);
}

@media (min-width: 1000px) {
    .wt-cta {
        display: grid;
        grid-template-columns: minmax(0, 1.45fr) minmax(0, 0.95fr) auto;
        align-items: center;
        column-gap: clamp(32px, 3.4vw, 60px);
        row-gap: 24px;
    }

    .wt-cta__content {
        display: contents;
    }

    /* The eyebrow rides above the headline in the first column. As a direct
     * grid item it would stretch, so it is pinned to the start. */
    .wt-cta .wt-eyebrow {
        grid-column: 1;
        grid-row: 1;
        margin-bottom: 12px;
        align-self: end;
        justify-self: start;
    }

    .wt-cta .wt-display--medium {
        grid-column: 1;
        grid-row: 2;
        align-self: start;
    }

    .wt-cta .wt-lead {
        grid-column: 2;
        grid-row: 1 / span 2;
        max-width: 38ch;
    }

    .wt-cta > .wt-row {
        grid-column: 3;
        grid-row: 1 / span 2;
        flex-direction: column;
        align-items: stretch;
        gap: 12px;
    }

    .wt-cta > .wt-row .wt-btn {
        justify-content: center;
        white-space: nowrap;
    }

    .wt-assure {
        grid-column: 3;
        grid-row: 3;
        margin-top: 0;
    }
}

@media (max-width: 999px) {
    .wt-cta {
        display: flex;
        flex-direction: column;
        gap: 22px;
    }
}

/* ==========================================================================
   Contact list markers
   ========================================================================== */

.wt-list__mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    margin: 5px 0 0;
    border: 1px solid var(--wt-hairline);
    border-radius: 50%;
    background-color: transparent;
    color: var(--wt-ink);
    font-size: 12px;
    line-height: 1;
    font-variant-emoji: text;
}

.wt-section--dark .wt-list__mark,
.wt-section--blue .wt-list__mark {
    background-color: transparent;
    border-color: color-mix(in srgb, #fff 24%, transparent);
    color: #fff;
}

.wt-list__item {
    border-top-color: var(--wt-hairline);
}

.wt-rule {
    background-color: var(--wt-hairline);
}

.wt-rule--dark {
    background-color: color-mix(in srgb, #fff 16%, transparent);
}

/* ==========================================================================
   Scroll-entrance
   ========================================================================== */

[data-wt-reveal] {
    opacity: 0;
    transform: translate3d(0, 16px, 0);
    transition:
        opacity var(--wt-reveal-duration) var(--wt-ease-out),
        transform var(--wt-reveal-duration) var(--wt-ease-out);
    transition-delay: calc(var(--wt-reveal-index, 0) * 55ms);
}

[data-wt-reveal].wt-is-revealed {
    opacity: 1;
    transform: none;
}

/*
 * Headline lines wipe up behind their own edge. The hidden state is applied by
 * .wt-lines-ready, which only the script adds — a decorative entrance must
 * never be able to swallow the most important text on the page.
 */
/*
 * The wipe needs `overflow: hidden` to hide the line before it rises, and that
 * clip is what the padding/negative-margin pairs are for: they push the clip
 * box out past the type without moving the line's own position.
 *
 * Below, for the Cyrillic descenders — Д, Ц, Щ all hang under the baseline.
 * Above, for the marks that sit over the cap height: Й carries a breve and Ё
 * a diaeresis, and at 0.9–1.02 leading the clip box lands right on them. The
 * hero opens on "САЙТОВЕ," so the very first glyph of the site had the top of
 * its Й sliced off. Latin caps need neither, which is why one clip fitted the
 * reference and not this.
 */
.wt-line {
    display: block;
    padding-top: 0.14em;
    margin-top: -0.14em;
    padding-bottom: 0.08em;
    margin-bottom: -0.08em;
    overflow: hidden;
}

.wt-line > span {
    display: block;
}

.wt-lines-ready .wt-line > span {
    transform: translate3d(0, 106%, 0);
    transition: transform 0.8s var(--wt-ease-soft);
    transition-delay: calc(var(--wt-line-index, 0) * 65ms);
}

.wt-lines-ready.wt-lines-in .wt-line > span {
    transform: none;
}

/*
 * The mark.
 * --------------------------------------------------------------------------
 * The closing line of the hero headline is struck through with a highlighter
 * — the one place the chartreuse appears at size, and the only gesture on the
 * page made by a hand rather than by a grid.
 *
 * It is a drawn shape, not a background colour: the edges wander, the ends
 * are ragged, the stroke sits at a slight angle and overshoots the words at
 * both ends, the way a real marker does when somebody is reading quickly and
 * marking the line that matters. A rectangle of flat colour is the same idea
 * executed by a machine, and it reads like one.
 */
.wt-select {
    position: relative;
    /* A stacking context of its own, so the stroke can sit behind the letters
       without falling behind the hero itself. */
    isolation: isolate;
    color: var(--wt-ink);
    box-decoration-break: clone;
    -webkit-box-decoration-break: clone;
    padding: 0.02em 0.1em 0.06em;
    margin-left: -0.1em;
}

.wt-select::before {
    content: "";
    position: absolute;
    /* Overshoot: the stroke starts before the first letter and runs past the
       last one, because a hand does not stop on the glyph. */
    left: -0.14em;
    right: -0.2em;
    top: -0.04em;
    bottom: -0.02em;
    z-index: -1;
    background: var(--wt-accent);
    rotate: -0.7deg;
    /* The wander is in the mask, so the shape stays one flat chartreuse with
       no gradient anywhere in it. */
    -webkit-mask-image: var(--wt-mark);
    mask-image: var(--wt-mark);
    -webkit-mask-size: 100% 100%;
    mask-size: 100% 100%;
    -webkit-mask-repeat: no-repeat;
    mask-repeat: no-repeat;
    /* Drawn left to right on load by animating the reveal, not the width, so
       the ragged right end is never sliced flat mid-stroke. */
    clip-path: inset(0 100% 0 0);
    animation: wt-mark-draw 0.62s cubic-bezier(0.32, 0.72, 0.35, 1) 0.75s forwards;
}

@keyframes wt-mark-draw {
    to {
        clip-path: inset(0 0 0 0);
    }
}

@media (prefers-reduced-motion: reduce) {
    .wt-select::before {
        animation: none;
        clip-path: inset(0 0 0 0);
    }
}

::selection {
    background-color: var(--wt-accent);
    color: var(--wt-ink);
}

/* ==========================================================================
   Footer
   ========================================================================== */

.wt-footer {
    background-color: var(--wt-ink);
    color: var(--wt-on-dark);
}

.wt-footer__link {
    position: relative;
    display: inline-block;
    color: var(--wt-on-dark);
    font-family: var(--wt-font-body), sans-serif;
    text-decoration: none;
    transition: color 0.22s var(--wt-ease-out);
}

.wt-footer__link::after {
    content: "";
    position: absolute;
    bottom: -2px;
    left: 0;
    width: 100%;
    height: 1px;
    background: var(--wt-accent);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform 0.3s var(--wt-ease-out);
}

.wt-footer__link:hover {
    color: #fff;
}

.wt-footer__link:hover::after {
    transform: scaleX(1);
}

/* ==========================================================================
   Mobile navigation
   --------------------------------------------------------------------------
   Below 1024px the builder hides .wt-nav__link and the .wt-header__mobile
   fallback is display:none at every breakpoint, which left no route to the
   service, portfolio or about pages.
   ========================================================================== */

.wt-navtoggle {
    display: none;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    padding: 0;
    border: 1px solid var(--wt-hairline);
    border-radius: 50%;
    background: transparent;
    color: var(--wt-ink);
    cursor: pointer;
    transition: border-color 0.22s var(--wt-ease-out);
}

.wt-navtoggle:hover {
    border-color: var(--wt-ink);
}

.wt-navtoggle__bars {
    position: relative;
    display: block;
    width: 16px;
    height: 10px;
}

.wt-navtoggle__bars span {
    position: absolute;
    left: 0;
    width: 100%;
    height: 2px;
    background: currentColor;
    transition:
        transform 0.3s var(--wt-ease-out),
        opacity 0.2s ease;
}

.wt-navtoggle__bars span:nth-child(1) {
    top: 0;
}
.wt-navtoggle__bars span:nth-child(2) {
    top: 50%;
    translate: 0 -50%;
}
.wt-navtoggle__bars span:nth-child(3) {
    bottom: 0;
}

.wt-navtoggle[aria-expanded="true"] .wt-navtoggle__bars span:nth-child(1) {
    transform: translateY(4px) rotate(45deg);
}
.wt-navtoggle[aria-expanded="true"] .wt-navtoggle__bars span:nth-child(2) {
    opacity: 0;
}
.wt-navtoggle[aria-expanded="true"] .wt-navtoggle__bars span:nth-child(3) {
    transform: translateY(-4px) rotate(-45deg);
}

.wt-mobilenav {
    position: fixed;
    top: var(--wt-header-height, 72px);
    right: 0;
    left: 0;
    z-index: 49;
    display: flex;
    flex-direction: column;
    max-height: calc(100dvh - var(--wt-header-height, 72px));
    padding: 10px clamp(16px, 4vw, 32px) 30px;
    overflow-y: auto;
    background: var(--wt-paper);
    border-bottom: 1px solid var(--wt-hairline);
    visibility: hidden;
    opacity: 0;
    transform: translate3d(0, -8px, 0);
    transition:
        opacity 0.26s var(--wt-ease-out),
        transform 0.26s var(--wt-ease-out),
        visibility 0.26s;
}

.wt-mobilenav.wt-is-open {
    visibility: visible;
    opacity: 1;
    transform: none;
}

.wt-mobilenav__link {
    padding: 16px 0;
    border-bottom: 1px solid var(--wt-hairline);
    color: var(--wt-ink);
    font-family: var(--wt-font-display), sans-serif;
    font-size: 22px;
    font-weight: 800;
    font-variation-settings: "wght" 800;
    letter-spacing: -0.02em;
    text-transform: uppercase;
    text-decoration: none;
    transition: opacity 0.2s ease;
}

.wt-mobilenav__link[aria-current="page"],
.wt-mobilenav__link:hover {
    opacity: 0.6;
}

.wt-mobilenav .wt-btn {
    margin-top: 22px;
}

body.wt-nav-open {
    overflow: hidden;
}

@media (max-width: 1023px) {
    .wt-navtoggle {
        display: inline-flex;
    }
}

@media (min-width: 1024px) {
    .wt-mobilenav {
        display: none;
    }
}

/* ==========================================================================
   Forms
   ========================================================================== */

.breakdance-form-field__label {
    color: var(--wt-ink);
    font-family: var(--wt-font-mono), monospace;
    font-size: 11px;
    font-weight: 500;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.breakdance-form-field__required {
    color: var(--wt-alert);
}

.breakdance-form-field__input,
.breakdance-form textarea,
.breakdance-form select,
.breakdance-form input[type="text"],
.breakdance-form input[type="email"],
.breakdance-form input[type="tel"],
.breakdance-form input[type="url"],
.breakdance-form input[type="number"] {
    width: 100%;
    padding: 14px 16px;
    border: 1px solid var(--wt-hairline);
    border-radius: 10px;
    background-color: var(--wt-paper);
    color: var(--wt-ink);
    font-family: var(--wt-font-body), sans-serif;
    font-size: 15px;
    line-height: 1.45;
    transition:
        border-color 0.2s var(--wt-ease-out),
        box-shadow 0.2s var(--wt-ease-out);
}

.breakdance-form-field__input::placeholder,
.breakdance-form textarea::placeholder {
    color: var(--wt-graphite);
}

.breakdance-form-field__input:focus,
.breakdance-form textarea:focus,
.breakdance-form select:focus {
    outline: none;
    border-color: var(--wt-ink);
    box-shadow: 0 0 0 3px var(--wt-accent);
}

.breakdance-form textarea {
    min-height: 140px;
    resize: vertical;
    border-radius: 12px;
}

.breakdance-form input[type="radio"],
.breakdance-form input[type="checkbox"] {
    accent-color: var(--wt-ink);
    width: 17px;
    height: 17px;
}

.breakdance-form-checkbox__text,
.breakdance-form-radio__text {
    color: var(--wt-ink);
    font-family: var(--wt-font-body), sans-serif;
    font-size: 15px;
}

.breakdance-form-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 52px;
    padding: 14px 28px;
    border: 1px solid var(--wt-ink);
    border-radius: var(--wt-radius-pill);
    background-color: var(--wt-ink);
    color: #fff;
    font-family: var(--wt-font-body), sans-serif;
    font-size: 15px;
    font-weight: 500;
    line-height: 1;
    cursor: pointer;
    transition:
        background-color 0.22s var(--wt-ease-out),
        border-color 0.22s var(--wt-ease-out),
        color 0.22s var(--wt-ease-out);
}

.breakdance-form-button:hover {
    background-color: var(--wt-blue);
    border-color: var(--wt-blue);
    transform: none;
}

.breakdance-form-button__previous-step {
    background-color: transparent;
    border-color: var(--wt-hairline);
    color: var(--wt-ink);
}

.breakdance-form-button__previous-step:hover {
    background-color: transparent;
    border-color: var(--wt-ink);
    color: var(--wt-ink);
}

.breakdance-form-field--step-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
}

.breakdance-form-stepper__step-icon {
    border-radius: 50%;
    background-color: var(--wt-chalk);
    color: var(--wt-graphite);
    font-family: var(--wt-font-mono), monospace;
    font-size: 11px;
    font-weight: 500;
    transition:
        background-color 0.26s var(--wt-ease-out),
        color 0.26s var(--wt-ease-out);
}

.breakdance-form-stepper__step--active .breakdance-form-stepper__step-icon,
.breakdance-form-stepper__step.is-active .breakdance-form-stepper__step-icon {
    background-color: var(--wt-ink);
    color: #fff;
}

.breakdance-form-stepper__step--completed .breakdance-form-stepper__step-icon {
    background-color: var(--wt-ink);
    color: #fff;
}

.breakdance-form-stepper__label {
    color: var(--wt-graphite);
    font-family: var(--wt-font-mono), monospace;
    font-size: 10px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
}

.breakdance-form-stepper__step--active .breakdance-form-stepper__label,
.breakdance-form-stepper__step.is-active .breakdance-form-stepper__label {
    color: var(--wt-ink);
}

.breakdance-form-stepper__separator {
    background-color: var(--wt-hairline);
}

.breakdance-form-field--error .breakdance-form-field__input {
    border-color: var(--wt-alert);
}

.breakdance-form__error,
.breakdance-form-field__error {
    color: var(--wt-alert);
    font-size: 13px;
}

/* ==========================================================================
   Focus
   ========================================================================== */

a:focus-visible,
button:focus-visible,
.wt-btn:focus-visible,
.wt-nav__link:focus-visible {
    outline: 2px solid var(--wt-ink);
    outline-offset: 3px;
}

/* Ink has nothing to sit against on the dark surfaces. */
.wt-hero a:focus-visible,
.wt-section--dark a:focus-visible,
.wt-section--dark button:focus-visible,
.wt-cta a:focus-visible,
.wt-footer a:focus-visible {
    outline-color: var(--wt-accent);
}

/* ==========================================================================
   Reduced motion
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
    [data-wt-reveal],
    [data-wt-reveal].wt-is-revealed,
    .wt-line > span {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }

    .wt-figure__layer {
        animation: none !important;
    }

    /* These stagger on `translate`, which the rule above does not cover. */
    .wt-figure__row,
    .wt-figure__join,
    .wt-figure__result,
    .wt-figure__out li {
        opacity: 1 !important;
        translate: none !important;
        transition: none !important;
    }
}

/* ==========================================================================
   The commitments band — a floating claim
   --------------------------------------------------------------------------
   The claim used to sit at the top of a tall column and then run out, leaving
   most of that column empty beside four scrolling commitments — which is what
   the client-site panel was put there to fill. The claim floats instead: it
   holds its place while the commitments pass it, so the section reads as one
   argument being made about the four things beside it rather than as two
   columns that happen to share a band.
   ========================================================================== */

/*
 * The site wrapper clips both axes, to contain the reel that breaks out past
 * the content column — and any non-visible overflow on an ancestor also
 * disables `position: sticky` inside it, which is why the claim below would
 * not hold. `clip` is the one overflow value that permits a differing pair
 * without the other axis computing to `auto`, so the horizontal clipping is
 * kept and the vertical axis is handed back.
 */
.wt-site {
    overflow-x: clip;
    overflow-y: visible;
}

@media (min-width: 900px) {
    .wt-sticky-grid__intro {
        position: sticky;
        top: clamp(96px, 14vh, 168px);
        align-self: start;
    }
}

/* ==========================================================================
   Section headings, wiped line by line
   --------------------------------------------------------------------------
   The same motion the hero headline uses, driven by the reveal observer that
   already watches these blocks. Keyed off .wt-is-revealed rather than a class
   of its own so there is one trigger on the page, not two.
   ========================================================================== */

.wt-lines-ready .wt-line > span {
    display: block;
    transform: translate3d(0, 108%, 0);
    transition: transform 0.85s var(--wt-ease-soft);
    transition-delay: calc(var(--wt-line-index, 0) * 70ms);
}

.wt-lines-ready.wt-is-revealed .wt-line > span {
    transform: none;
}

/* A heading that is already on screen at load is revealed immediately by the
   observer, so it wipes on arrival rather than sitting hidden. */
@media (prefers-reduced-motion: reduce) {
    .wt-lines-ready .wt-line > span {
        transform: none !important;
        transition: none !important;
    }
}

/* The reel's screenshots are 16:9 hero units; holding the ratio means the
   card is its final height before the image loads. */
.wt-track .wt-project-thumb,
.wt-project-card__mock .wt-project-thumb {
    aspect-ratio: 16 / 9;
    object-fit: cover;
}


/* ==========================================================================
   Depth pass — an elevation system over the flat base.
   Ink-tinted double shadows (contact + ambient), small quick hover lifts.
   Appended after the base so these override the flat card treatment.
   ========================================================================== */

:root {
    --wt-elev-1: 0 1px 2px rgba(10, 10, 10, 0.04), 0 6px 18px -8px rgba(10, 10, 10, 0.09);
    --wt-elev-2: 0 2px 4px rgba(10, 10, 10, 0.05), 0 16px 36px -14px rgba(10, 10, 10, 0.16);
    --wt-elev-3: 0 4px 10px rgba(10, 10, 10, 0.06), 0 32px 70px -22px rgba(10, 10, 10, 0.26);
}

/* The header floats once the page scrolls under it. */
.wt-header.wt-header--scrolled {
    box-shadow: 0 10px 30px -18px rgba(10, 10, 10, 0.18);
}

/* Cards rest slightly above the surface and lift toward the pointer. */
.wt-card,
.wt-post-card,
.wt-service-card,
.wt-form-card {
    box-shadow: var(--wt-elev-1);
    transition:
        transform 0.35s var(--wt-ease-out),
        box-shadow 0.35s var(--wt-ease-out),
        border-color 0.28s var(--wt-ease-out);
}

.wt-card:hover,
.wt-post-card:hover,
.wt-service-card:hover {
    transform: translateY(-4px);
    box-shadow: var(--wt-elev-2);
    border-color: var(--wt-ink);
}

/* Work reel cards: the browser frames carry the most weight on the page. */
.wt-work-card {
    box-shadow: var(--wt-elev-1);
    transition:
        transform 0.5s var(--wt-ease-out),
        box-shadow 0.5s var(--wt-ease-out);
}

.wt-work-card:hover {
    box-shadow: var(--wt-elev-3);
}

/* Client-site panels and drawn figures sit above their band. */
.wt-figure {
    box-shadow: var(--wt-elev-2);
}

/* The testimonial block floats on the page as one heavy object. */
.wt-quotes {
    box-shadow: var(--wt-elev-3);
}

/* Primary actions have physical presence; hover deepens toward the blue. */
.wt-btn--primary {
    box-shadow: 0 10px 26px -12px rgba(10, 10, 10, 0.45);
}

.wt-btn--primary:hover {
    box-shadow: 0 16px 34px -14px rgba(51, 79, 180, 0.5);
}

.wt-btn--light {
    box-shadow: 0 10px 26px -14px rgba(10, 10, 10, 0.35);
}

/* The closing ask lifts off the ink band. */
.wt-cta {
    box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.55);
}

/* On ink, shadows read as mud — dark-surface cards keep the flat treatment. */
.wt-section--dark .wt-card,
.wt-section--dark .wt-post-card,
.wt-section--dark .wt-quote {
    box-shadow: none;
    transform: none;
}


/* ==========================================================================
   Ambient ornament — the hero's drafting-dot motif extended to the bands.
   A corner cluster of ink dots with a soft chartreuse wash behind it, masked
   so it fades before it reaches any content. Decoration only: no pointer
   events, no layout, and it inherits the section's own rounded clipping.
   ========================================================================== */

.wt-section--white,
.wt-page-hero {
    position: relative;
}

.wt-section--white::before,
.wt-page-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image:
        radial-gradient(circle, color-mix(in srgb, var(--wt-ink) 60%, transparent) 1.1px, transparent 1.4px),
        radial-gradient(closest-side, color-mix(in srgb, var(--wt-accent) 30%, transparent), transparent 72%);
    background-size: 17px 17px, 720px 680px;
    background-position: -8px -8px, -280px -260px;
    background-repeat: repeat, no-repeat;
    -webkit-mask-image: radial-gradient(460px 400px at 4% 0%, #000 0%, transparent 74%);
    mask-image: radial-gradient(460px 400px at 4% 0%, #000 0%, transparent 74%);
    opacity: 0.55;
}

/* The page hero mirrors the ornament to the right so the breadcrumb and
   title column stay on clean paper. */
.wt-page-hero::before {
    background-position: right -8px top -8px, right -280px top -260px;
    -webkit-mask-image: radial-gradient(460px 400px at 96% 0%, #000 0%, transparent 74%);
    mask-image: radial-gradient(460px 400px at 96% 0%, #000 0%, transparent 74%);
}


/* ==========================================================================
   Depth pass, dark surfaces — the drafting-dot cluster in chartreuse,
   top-right, behind the content of ink bands. Quiet: it reads as texture
   at reading distance and as the brand motif up close.
   ========================================================================== */

.wt-section--dark {
    position: relative;
}

.wt-section--dark::before {
    content: "";
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: radial-gradient(circle, color-mix(in srgb, var(--wt-accent) 60%, transparent) 1.1px, transparent 1.4px);
    background-size: 17px 17px;
    background-position: right -8px top -8px;
    -webkit-mask-image: radial-gradient(430px 380px at 97% 2%, #000 0%, transparent 74%);
    mask-image: radial-gradient(430px 380px at 97% 2%, #000 0%, transparent 74%);
    opacity: 0.3;
}


/* ==========================================================================
   Blue purge — --wt-blue leaves the visual palette. Primary hovers go to
   the chartreuse accent with ink text; markers use accent-deep.
   ========================================================================== */

.wt-btn--primary:hover,
.breakdance-form-button:hover {
    background-color: var(--wt-accent);
    border-color: var(--wt-accent);
    color: var(--wt-ink);
}

.wt-service-card:hover .wt-modules__item::before,
.wt-svc__more:hover::after {
    background: var(--wt-accent-deep);
}


/* ==========================================================================
   Reel arrows retired by owner decision (2026-08-05): the pill control drew more
   attention than the content it stepped. The track scrolls natively (drag,
   trackpad, touch) and the progress bar remains as the position indicator.
   ========================================================================== */

.wt-track__nav {
    display: none;
}


/* ==========================================================================
   Header condenses as the page scrolls under it — motion pass 2026-08-05.
   ========================================================================== */

.wt-header {
    transition:
        background-color 0.3s var(--wt-ease-out),
        border-color 0.3s var(--wt-ease-out),
        padding 0.3s var(--wt-ease-out);
}

.wt-header.wt-header--scrolled {
    padding-top: 7px;
    padding-bottom: 7px;
}


   Robustness: entrance effects must never gate visibility (2026-08-05)
   --------------------------------------------------------------------------
   Backgrounded tabs freeze the animation timeline, which left every
   opacity-gated heading invisible mid-transition. Content starts visible;
   the marquee, hovers and parallax stay.
   ========================================================================== */

.wt-site [data-wt-reveal] {
    opacity: 1;
    transform: none;
    transition: none;
}

.wt-site .wt-lines-ready .wt-line > span,
.wt-site .wt-lines-ready.wt-lines-in .wt-line > span,
.wt-site .wt-lines-ready.wt-is-revealed .wt-line > span {
    transform: none;
    transition: none;
}

.wt-site .wt-figure__layer { animation: none; opacity: 1; translate: none; }
.wt-site .wt-figure .wt-figure__row,
.wt-site .wt-figure .wt-figure__join,
.wt-site .wt-figure .wt-figure__result,
.wt-site .wt-figure .wt-figure__out li { opacity: 1; transform: none; transition: none; }

[data-entrance] { opacity: 1 !important; transform: none !important; }

/* ---- quote carousel stays inside its stage ---- */
.wt-site .wt-quotes__stage { overflow: hidden; }
.wt-site .wt-quotes__stage .wt-quote { max-width: 100%; box-sizing: border-box; }


/* ---- footer text: the panel is dark, its type must stay light ---- */
.wt-footer .wt-copy,
.wt-footer .wt-copy--light { color: rgba(255, 255, 255, 0.72); }

.wt-footer .wt-eyebrow,
.wt-footer .wt-eyebrow--light { color: rgba(255, 255, 255, 0.5); background: transparent; border: 0; }

.wt-footer .wt-eyebrow::before,
.wt-footer .wt-eyebrow--light::before { background: var(--ru-lime); }

.wt-footer .wt-footer__link { color: rgba(255, 255, 255, 0.78); }
.wt-footer .wt-footer__link:hover { color: var(--ru-lime); }
.wt-footer .wt-small { color: rgba(255, 255, 255, 0.45); }

/* ---- article headings inside a dark band flip with it ---- */
.wt-site [data-wt-surface="ink"] .wt-article__heading { color: #FFFFFF; }
.wt-site [data-wt-surface="ink"] .wt-article__copy { color: rgba(255, 255, 255, 0.75); }
.wt-site [data-wt-surface="ink"] .wt-prose,
.wt-site [data-wt-surface="ink"] .wt-prose p,
.wt-site [data-wt-surface="ink"] .wt-prose li { color: rgba(255, 255, 255, 0.75); }
   REFINEMENT PASS — 2026-08-06
   Ten fixes from client review. Everything here is additive and sits last in
   the file, so it outranks the earlier passes at equal specificity.
   ========================================================================== */

/* ---- 1. The services dropdown becomes a real menu -------------------------
   Four parallel services read badly as a narrow one-per-row list. Two columns
   at 34px icon + label give the panel the width its content deserves, and the
   icons are the same four drawn on the home services cards, so the menu and
   the section it links to speak the same language. Icons key off position,
   not language, so BG and EN stay in sync. */
.wt-header .wt-nav__menu {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 4px 8px;
    width: 540px;
    min-width: 0;
    padding: 14px;
    border-radius: 18px;
}

.wt-header .wt-nav__menu .wt-nav__link {
    display: flex;
    align-items: center;
    gap: 13px;
    padding: 12px 14px;
    border-radius: 12px;
    opacity: 1;
    line-height: 1.3;
    transition: background-color 0.22s var(--wt-ease-out);
}

/* The header's underline slide belongs to the top-level links only. */
.wt-header .wt-nav__menu .wt-nav__link::after { display: none; }

.wt-header .wt-nav__menu .wt-nav__link::before {
    content: "";
    flex: 0 0 auto;
    width: 34px;
    height: 34px;
    border-radius: var(--r-chip, 10px);
    background-color: color-mix(in srgb, var(--ru-lime) 32%, #FFFFFF);
    background-repeat: no-repeat;
    background-position: center;
    background-size: 19px 19px;
    transition: background-color 0.22s var(--wt-ease-out);
}

.wt-header .wt-nav__menu .wt-nav__link:hover::before {
    background-color: var(--ru-lime);
}

.wt-header .wt-nav__menu .wt-nav__link:nth-child(1)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23101703' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4.5' width='18' height='15' rx='2'/%3E%3Cpath d='M3 9h18'/%3E%3Cpath d='M6 6.8h.01M8.5 6.8h.01'/%3E%3C/svg%3E"); }
.wt-header .wt-nav__menu .wt-nav__link:nth-child(2)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23101703' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 8h14l-1.2 11.2a1.6 1.6 0 0 1-1.6 1.4H7.8a1.6 1.6 0 0 1-1.6-1.4L5 8Z'/%3E%3Cpath d='M9 10.5V6.5a3 3 0 0 1 6 0v4'/%3E%3C/svg%3E"); }
.wt-header .wt-nav__menu .wt-nav__link:nth-child(3)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23101703' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 20l1-4L16.5 4.5a2.1 2.1 0 0 1 3 3L8 19l-4 1Z'/%3E%3Cpath d='M14.5 6.5l3 3'/%3E%3C/svg%3E"); }
.wt-header .wt-nav__menu .wt-nav__link:nth-child(4)::before { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23101703' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M14.7 6.3a4.2 4.2 0 0 0-5.6 5.2L4 16.6a2 2 0 1 0 2.8 2.8l5.1-5.1a4.2 4.2 0 0 0 5.2-5.6l-2.6 2.6-2.5-.7-.7-2.5 2.4-2.4Z'/%3E%3C/svg%3E"); }

/* ---- 2. Section headings render as authored ------------------------------
   The lowercase transform was part of the rudo reference; it fights Bulgarian
   sentence case and flattens proper nouns (wordpress, seo). Removed. */
.wt-h2,
.wt-site .wt-h2 { text-transform: none; }

/* ---- 3. The services ordinal label was lime on lime ----------------------
   The card label lost its ordinal (four services are not a sequence), and the
   remaining category word is re-inked to the ordinal-chip olive so it reads. */
/* Olive removed 2026-08-06 with the card tints: that colour was mixed to read
   on the lime panel, and on a white card it is just khaki. The label falls back
   to the builder's own .wt-num graphite, which is what it carried before. */

/* ---- 4. Featured projects: a grid, not a clipped reel ---------------------
   The reel set margin-left:-100px and padding-left:100px on a fixed 1240px
   track, so it ended 100px short of the shell and sliced the last card. The
   cards are built client-side and sit as direct children of the grid, so the
   columns are declared here rather than on the loop item the builder emits. */
.wt-site .wt-project-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
    gap: 30px 22px;
    margin: 0;
    padding: 0;
    width: auto;
    max-width: none;
    overflow: visible;
}

.wt-site .wt-project-grid .wt-project-card {
    transition: transform 0.38s var(--wt-ease-out);
}

.wt-site .wt-project-grid .wt-project-card:hover {
    transform: translateY(-5px);
}

/* ---- 5. The commitments stack was one continuous slab --------------------
   Four white cards at gap 0 fused into a single shape with strange notches at
   the joins. They are separate commitments, so they get separate cards, a lime
   edge that arrives on hover, and an ambient field behind them: a dot grid and
   one slow lime bloom, both painted inside the panel's own box so the sticky
   column beside them keeps working. */
.wt-site .wt-benefits { gap: 14px; }

.wt-site [data-wt-surface="ink"] .wt-benefit {
    border-top: 0;
    border-left: 3px solid transparent;
    padding: 24px 26px;
    transition:
        transform 0.38s var(--wt-ease-out),
        border-color 0.38s var(--wt-ease-out),
        box-shadow 0.38s var(--wt-ease-out);
}

.wt-site [data-wt-surface="ink"] .wt-benefit:hover {
    transform: translateX(8px);
    border-left-color: var(--ru-lime);
    box-shadow: -12px 24px 50px -28px rgba(0, 0, 0, 0.6);
}

.wt-site [data-wt-surface="ink"] .wt-benefit:hover .wt-benefit__number {
    background: var(--ru-lime);
}

.wt-site .wt-section--dark:has(.wt-benefits) { position: relative; }

.wt-site .wt-section--dark:has(.wt-benefits)::before,
.wt-site .wt-section--dark:has(.wt-benefits)::after {
    content: "";
    position: absolute;
    inset: 0;
    border-radius: inherit;
    pointer-events: none;
}

.wt-site .wt-section--dark:has(.wt-benefits)::before {
    background-image: radial-gradient(circle, rgba(218, 249, 160, 0.17) 1.2px, transparent 1.2px);
    background-size: 26px 26px;
    -webkit-mask-image: radial-gradient(ellipse 62% 58% at 16% 26%, #000, transparent 72%);
    mask-image: radial-gradient(ellipse 62% 58% at 16% 26%, #000, transparent 72%);
}

/* The bloom drifts by moving its own background, never by growing past the
   panel edge — no overflow:hidden, so position:sticky survives. */
.wt-site .wt-section--dark:has(.wt-benefits)::after {
    background-image: radial-gradient(circle closest-side, rgba(218, 249, 160, 0.22), transparent);
    background-repeat: no-repeat;
    background-size: 900px 900px;
    background-position: -220px 118%;
    animation: wt-bloom-drift 22s ease-in-out infinite alternate;
}

@keyframes wt-bloom-drift {
    from { background-position: -220px 118%; }
    to   { background-position: 34% -26%; }
}

.wt-site .wt-section--dark:has(.wt-benefits) > * {
    position: relative;
    z-index: 1;
}

/* ---- 6. The process band was glare ---------------------------------------
   Full #DAF9A0 across a full-bleed panel is a lot of acid. Pulling it toward
   the olive keeps the band unmistakably the lime one while letting the white
   step cards carry the contrast. */
/* Removed 2026-08-06 with the rest of the rudo grammar: a full-bleed lime
   band is the reference's colour moment, not this site's. The band goes back
   to the surface bandSurface() assigns it (paper / chalk / ink), which is what
   it carried before the reference pass. */

/* ---- 7. Every review on screen at once -----------------------------------
   The slider showed one of three and asked for a click to see the rest; on the
   last band before the ask that is a click most readers never spend. All three
   sit in the grid the builder already declared. */
.wt-site .wt-quote {
    position: relative;
    overflow: hidden;
    gap: 22px;
    padding: 30px 30px 26px;
    background-color: #FFFFFF;
    border: 0;
    transition:
        transform 0.35s var(--wt-ease-out),
        box-shadow 0.35s var(--wt-ease-out);
}

.wt-site .wt-quote::before {
    content: "\201C";
    position: absolute;
    top: 2px;
    right: 22px;
    font-family: var(--wt-font-display), sans-serif;
    font-weight: 800;
    font-size: 96px;
    line-height: 1;
    color: color-mix(in srgb, var(--ru-lime) 62%, #FFFFFF);
    pointer-events: none;
}

.wt-site .wt-quote:hover {
    transform: translateY(-5px);
    box-shadow: 0 26px 52px -30px rgba(16, 23, 3, 0.45);
}

.wt-site .wt-quote:hover::before {
    color: var(--ru-lime);
}

.wt-site .wt-quote__text,
.wt-site .wt-quote__name { position: relative; }
.wt-site .wt-quote__text { color: var(--ru-text); }
.wt-site .wt-quote__name { color: var(--ru-grey); }

@media (prefers-reduced-motion: reduce) {
    .wt-site .wt-section--dark:has(.wt-benefits)::after { animation: none; }
    .wt-site .wt-project-grid .wt-project-card,
    .wt-site [data-wt-surface="ink"] .wt-benefit,
    .wt-site .wt-quote { transition: none; }
}

/* The card class carries `grid-column-start: span 7` from the staggered layout
   the reel replaced. A uniform three-up grid wants neither that nor the offset
   the alternating variant adds. */
.wt-site .wt-project-grid .wt-project-card,
.wt-site .wt-project-grid .wt-project-card--small {
    grid-column: auto;
    padding-top: 0;
}

/* The retired band-join system still owns `display`, `height` and
   `background-color` on these two pseudo-elements ([data-wt-join]::after and
   [data-wt-under]::before, which this band carries). Reclaiming all three is
   what lets the ambient layer paint at full height instead of collapsing to
   the join radius. */
.wt-site .wt-section--dark:has(.wt-benefits)::before,
.wt-site .wt-section--dark:has(.wt-benefits)::after {
    display: block;
    height: auto;
    background-color: transparent;
}

/* A bare `minmax(300px, 1fr)` track cannot shrink below its floor, so the reel
   would poke out of a 320px phone. min() lets the single column give way. */
.wt-site .wt-project-grid {
    grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
}

/* The dropdown never opens on touch (the group is display:none there), but the
   panel should never be able to outgrow the window if that ever changes. */
.wt-header .wt-nav__menu {
    max-width: calc(100vw - 32px);
}

/* ---- 8. The contact page -------------------------------------------------
   Four faults, all of them visible at a glance: the three contact rows were
   full cards deep enough to push the left column 173px past the form beside
   it, their icons were typed characters (@ ☎ ◎) rather than the drawn line
   icons every other card uses, the envelope in the hero was cut in half by the
   viewport, and the FAQ band opened with an empty white shelf where its
   heading should be. */
.wt-site .wt-contact-grid {
    grid-template-columns: minmax(0, 0.86fr) minmax(0, 1fr);
    gap: 72px;
}

.wt-site .wt-contact-grid .wt-list { gap: 12px; }

/* Icon beside the detail rather than stacked above it: the same information in
   roughly 60% of the height, which is what squares the two columns up. */
.wt-site .wt-contact-grid .wt-list__item {
    display: grid;
    grid-template-columns: 44px minmax(0, 1fr);
    align-items: start;
    gap: 18px;
    padding: 22px 24px;
    transition:
        transform 0.32s var(--wt-ease-out),
        box-shadow 0.32s var(--wt-ease-out);
}

.wt-site .wt-contact-grid .wt-list__item:hover {
    transform: translateY(-3px);
    box-shadow: 0 20px 40px -26px rgba(16, 23, 3, 0.4);
}

.wt-site .wt-contact-grid .wt-list__mark {
    width: 44px;
    height: 44px;
    padding: 0;
    font-size: 0;
    line-height: 0;
    background-color: color-mix(in srgb, var(--ru-lime) 32%, #FFFFFF);
    background-repeat: no-repeat;
    background-position: center;
    background-size: 21px 21px;
    transition: background-color 0.32s var(--wt-ease-out);
}

.wt-site .wt-contact-grid .wt-list__item:hover .wt-list__mark {
    background-color: var(--ru-lime);
}

.wt-site .wt-contact-grid .wt-list__item:nth-child(1) .wt-list__mark { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23101703' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='14' rx='2'/%3E%3Cpath d='m3.6 7.2 8.4 5.9 8.4-5.9'/%3E%3C/svg%3E"); }
.wt-site .wt-contact-grid .wt-list__item:nth-child(2) .wt-list__mark { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23101703' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M6.4 3.6h3.1l1.5 3.9-2 1.4a12.2 12.2 0 0 0 6.1 6.1l1.4-2 3.9 1.5v3.1a1.5 1.5 0 0 1-1.7 1.5A16.6 16.6 0 0 1 4.9 5.3a1.5 1.5 0 0 1 1.5-1.7Z'/%3E%3C/svg%3E"); }
.wt-site .wt-contact-grid .wt-list__item:nth-child(3) .wt-list__mark { background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23101703' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M12 21s6.8-5.5 6.8-10.8a6.8 6.8 0 1 0-13.6 0C5.2 15.5 12 21 12 21Z'/%3E%3Ccircle cx='12' cy='10.1' r='2.6'/%3E%3C/svg%3E"); }

/* An envelope is a recognisable object, so half of one reads as a rendering
   fault rather than as the bleed the abstract glyphs on the other heroes pull
   off. Contact keeps its glyph inside the panel. */
.page-id-19 .wt-page-hero,
.page-id-20 .wt-page-hero {
    background-position: 0 0, calc(100% - 72px) 50%;
    background-size: auto, 400px;
}

/* .wt-list is an auto-fit grid that wraps at 230px per track. The contact
   column is now wide enough to fit two, which is not what a three-row contact
   block wants — one column, always. */
.wt-site .wt-contact-grid .wt-list {
    grid-template-columns: minmax(0, 1fr);
}

/* An address is one long unbreakable token in the worst case. */
.wt-site .wt-contact-grid .wt-list__item .wt-h3,
.wt-site .wt-contact-grid .wt-list__item h3 {
    overflow-wrap: anywhere;
}

/* ---- 9. The interior heroes' second button was invisible -----------------
   "Ghost on dark" was written for [data-wt-surface="ink"], .wt-section--dark
   and .wt-hero — the home hero's class. Every interior page hero is
   .wt-page-hero, which none of those match, so the ghost button fell back to
   the light-canvas rule and painted near-black type on the olive panel.
   Twelve pages carried an unreadable secondary call to action. */
.wt-page-hero .wt-btn--ghost {
    background: transparent;
    border-color: rgba(218, 249, 160, 0.5);
    color: #FFFFFF;
}

.wt-page-hero .wt-btn--ghost:hover {
    background-color: var(--ru-lime);
    border-color: var(--ru-lime);
    color: var(--ru-text);
}

/* ---- 10. The contact icon set belongs to the contact pages only ----------
   .wt-contact-grid is the shared "detail column + form panel" layout, and
   /zapochni-proekt/ (17/18) uses it as well as /kontakti/ (19/20). Its three
   rows are numbered steps, though, not contact details: the block above hid
   their 01/02/03 behind a mail/phone/pin set that means nothing there. The
   layout rules stay shared — they help both — and the chip geometry and icons
   are pinned back to the contact pages. */
body:not(.page-id-19):not(.page-id-20) .wt-site .wt-contact-grid .wt-list__mark {
    width: auto;
    height: auto;
    padding: 6px 11px;
    font-size: 15px;
    line-height: 1;
    background-image: none;
    background-color: color-mix(in srgb, var(--ru-lime) 55%, #FFFFFF);
}

/* The compact icon-beside-text row is a contact-page shape too. Elsewhere in
   .wt-contact-grid the list item is a card: numeral top-left, drawn corner
   glyph pushed to the far right by .wt-glyph-row's space-between, then the
   title and copy stacked beneath. Forcing a 44px first column left the glyph
   nowhere to go but on top of the heading. */
body:not(.page-id-19):not(.page-id-20) .wt-site .wt-contact-grid .wt-list__item {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
    padding: 30px 26px 34px;
}

/* Media queries carry no specificity of their own, so `.wt-site
   .wt-contact-grid` (two classes) outranks the `.wt-contact-grid` (one class)
   rule that collapses this layout to a single column at 1023px — the contact
   and start-a-project pages would have stayed two-up on a tablet and a phone.
   Both the shared rule and the page-scoped revert need restating here. */
@media (max-width: 1023px) {
    .wt-site .wt-contact-grid,
    body:not(.page-id-19):not(.page-id-20) .wt-site .wt-contact-grid {
        grid-template-columns: minmax(0, 1fr);
        gap: 40px;
    }
}

/* On /zapochni-proekt/ the questionnaire is the shorter column — step one is
   three radio buttons — so the three "what happens next" cards ran ~280px
   past it and left a hole beside the last two. Pinning the form means it
   travels down with the reader instead: by the time card 03 is in view the
   questionnaire is still beside it, and the step they are being asked to take
   is never scrolled away from. Single-column below 1024px, where sticky would
   only trap the form against the top of the screen. */
@media (min-width: 1024px) {
    body:not(.page-id-19):not(.page-id-20) .wt-site .wt-contact-grid > *:last-child {
        position: sticky;
        top: calc(var(--wp-admin--admin-bar--height, 0px) + 104px);
    }
}

/* ---- 11. Page heroes: centred text, a readable crumb, a relevant glyph ----
   Three faults, all of them on every interior page, not just this one.

   1. .wt-page-hero__inner is a flex column with `align-items: stretch`, and
      the headline and lead each carry a max-width. A stretched item with a
      max-width sits at the START of the cross axis, so `text-align: center`
      centred the words inside a block that was itself pinned left — the
      headline sat ~290px left of the panel's centre and the lead ~410px.
      Only the text children get `align-self`; the service heroes put a
      full-width .wt-hero-grid in the same slot and must keep stretching.
   2. The current crumb inherited the light-canvas ink (#101703) on the olive
      panel: a contrast ratio of 1.17:1, which is no crumb at all.
   3. /zapochni-proekt/ was drawn with an arrow. It now carries the brief it
      actually asks you to fill in. */
.wt-hero--centred .wt-page-hero__inner > .wt-display,
.wt-hero--centred .wt-page-hero__inner > .wt-display--medium,
.wt-hero--centred .wt-page-hero__inner > .wt-lead,
.wt-hero--centred .wt-page-hero__inner > .wt-eyebrow,
.wt-hero--centred .wt-case-hero__inner > .wt-display,
.wt-hero--centred .wt-case-hero__inner > .wt-display--medium,
.wt-hero--centred .wt-case-hero__inner > .wt-lead,
.wt-hero--centred .wt-case-hero__inner > .wt-eyebrow {
    align-self: center;
}

.wt-page-hero .wt-crumbs [aria-current="page"],
.wt-case-hero .wt-crumbs [aria-current="page"] {
    color: rgba(255, 255, 255, 0.92);
}

.page-id-17,
.page-id-18 {
    --wt-hero-glyph-dark: url("data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 24 24%22%3E%3Cpath d=%22M9 5H7.2A1.7 1.7 0 0 0 5.5 6.7v12.6A1.7 1.7 0 0 0 7.2 21h9.6a1.7 1.7 0 0 0 1.7-1.7V6.7A1.7 1.7 0 0 0 16.8 5H15%22 fill=%22none%22 stroke=%22rgba%28255%2C255%2C255%2C0.055%29%22 stroke-width=%220.8%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22/%3E%3Cpath d=%22M9.8 3h4.4a.8.8 0 0 1 .8.8v2.4H9V3.8a.8.8 0 0 1 .8-.8Z%22 fill=%22none%22 stroke=%22rgba%28255%2C255%2C255%2C0.055%29%22 stroke-width=%220.8%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22/%3E%3Cpath d=%22M8.6 11h6.8M8.6 14.6h6.8M8.6 18.2h4%22 fill=%22none%22 stroke=%22rgba%28255%2C255%2C255%2C0.055%29%22 stroke-width=%220.8%22 stroke-linecap=%22round%22 stroke-linejoin=%22round%22/%3E%3C/svg%3E");
}

/* Same rule as contact's envelope: an abstract glyph (the star, the asterisk)
   reads as texture when it bleeds off the panel, but a drawn object does not —
   it just looks cut. The brief stays inside the panel. */
.page-id-17 .wt-page-hero,
.page-id-18 .wt-page-hero {
    background-position: 0 0, calc(100% - 80px) 50%;
    background-size: auto, 380px;
}

/* ---- 12. The stepper could not fit its own labels -----------------------
   Every step the reader completes keeps its label, so the row grows as they
   advance: seven labelled steps need 891px inside a 532px column. The list is
   `flex-wrap: nowrap` and the stepper is `overflow: visible`, so by the last
   step it simply ran out past the panel and the seventh was sliced off.
   It wraps now. The separators had to stop growing first — they are
   `flex: 1 1 auto`, which on a wrapped row expands to fill the line and pushes
   every step onto one of its own (a 406px-tall stepper). */
.wt-form .breakdance-form-stepper__list {
    flex-wrap: wrap;
    row-gap: 12px;
}

.wt-form .breakdance-form-stepper__separator {
    flex: 0 0 auto;
    width: 16px;
}

/* ---- 13. Back to the original display face ------------------------------
   The rudo pass swapped Wix Madefor Display for Rubik, both in the token and
   hardcoded across a dozen rules. The token goes back and each of those rules
   is restated to read from it, so there is one place to change it next time.
   Wix Madefor Display is still enqueued by the builder and carries a full
   Cyrillic subset — the reason it was chosen over Archivo and Bricolage
   Grotesque, which silently dropped every Bulgarian heading to a system font. */
:root {
    --wt-font-display: "Wix Madefor Display", sans-serif;
}

.wt-display,
.wt-display--medium,
.wt-h2,
.wt-h3,
.wt-num,
.wt-mobilenav__link,
.wt-benefit__number,
.wt-proofbar__item .wt-proofbar__value,
.wt-site .wt-num,
.wt-site .wt-list__mark,
.wt-site .wt-benefit__number,
.wt-site .wt-process__number,
.wt-site .wt-quote::before,
.wt-site [data-wt-surface="ink"] .wt-benefit .wt-benefit__number,
.wt-site .wt-process__number .wt-chip:first-child {
    font-family: var(--wt-font-display), sans-serif;
}

/* ==========================================================================
   14. THE RUDO PALETTE COMES OUT (2026-08-06)
   --------------------------------------------------------------------------
   The olive-and-lime scheme lifted from rudo.co.uk is retired and the site's
   own palette comes back: white and black do the work, #F2F2F2 is the only
   alternate surface, and chartreuse is a highlight — never a text colour on
   white. The rudo pass had rewritten the --wt-* tokens in place, so they are
   restated here at their builder values.

   The --ru-* names stay. A hundred rules downstream read them, including the
   panel system and every refinement pass since, so re-pointing the six of them
   moves the whole site in one edit rather than rewriting all hundred.
   ========================================================================== */
:root {
    --wt-ink: #000000;
    --wt-panel: #242424;
    --wt-panel-deep: #141414;
    --wt-paper: #FFFFFF;
    --wt-chalk: #F2F2F2;
    --wt-chalk-dim: #EAEAEA;
    --wt-accent: #F0FF4C;
    --wt-accent-deep: #DFF02B;
    --wt-accent-wash: #FBFFDA;
    --wt-graphite: #6B6B6B;
    --wt-hairline: #E2E2E2;
    --wt-on-dark: #B0B0B0;

    --ru-canvas: var(--wt-chalk);
    --ru-dark: var(--wt-panel);
    --ru-lime: var(--wt-accent);
    --ru-lime-deep: var(--wt-accent-deep);
    --ru-text: var(--wt-ink);
    --ru-grey: var(--wt-graphite);

    /* The glows and washes need the accent at an alpha, which a hex token
       cannot give them. Tokenised so the next palette change is one line. */
    --wt-accent-rgb: 240, 255, 76;
}

/* The rules that had the rudo lime baked in as rgba() rather than as a token. */
.wt-site [data-wt-surface="ink"] .wt-btn--ghost,
.wt-hero .wt-btn--ghost,
.wt-page-hero .wt-btn--ghost {
    border-color: rgba(var(--wt-accent-rgb), 0.5);
}

.wt-site .wt-hero {
    background-image:
        radial-gradient(680px 460px at 82% -8%, rgba(var(--wt-accent-rgb), 0.14), transparent 70%),
        radial-gradient(circle, rgba(var(--wt-accent-rgb), 0.11) 1.1px, transparent 1.5px);
}

.wt-site .wt-page-hero,
.wt-site .wt-case-hero {
    background-image:
        radial-gradient(700px 480px at 90% -10%, rgba(var(--wt-accent-rgb), 0.12), transparent 72%),
        var(--wt-hero-glyph-dark, none);
}

.wt-site .wt-chip { background: rgba(var(--wt-accent-rgb), 0.08); }
.wt-site .wt-chip:hover { background: rgba(var(--wt-accent-rgb), 0.18); color: #FFFFFF; }

.wt-mobilenav {
    background-image:
        radial-gradient(560px 380px at 85% -6%, rgba(var(--wt-accent-rgb), 0.16), transparent 70%),
        radial-gradient(circle, rgba(var(--wt-accent-rgb), 0.10) 1px, transparent 1.4px);
}

.wt-site .wt-section--dark:has(.wt-benefits)::before {
    background-image: radial-gradient(circle, rgba(var(--wt-accent-rgb), 0.17) 1.2px, transparent 1.2px);
}

.wt-site .wt-section--dark:has(.wt-benefits)::after {
    background-image: radial-gradient(circle closest-side, rgba(var(--wt-accent-rgb), 0.22), transparent);
}

/* The home hero's eyebrow fell through to the light-canvas grey and sat at
   2.9:1 on the dark panel — the same gap that left the ghost buttons and the
   breadcrumb unreadable, since .wt-hero is matched by neither
   [data-wt-surface="ink"] nor .wt-page-hero. Interior heroes already put the
   accent here, so home now matches them. */
.wt-hero .wt-eyebrow {
    color: var(--wt-accent);
}

/* The rudo ink also appears as rgba(16, 23, 3, α) — that olive-black at an
   alpha — in shadows, hairline borders and secondary text. Tokenised to the
   real ink so nothing carries a green cast, however faint. */
:root { --wt-ink-rgb: 0, 0, 0; }

.wt-small { color: rgba(var(--wt-ink-rgb), 0.5); }
.wt-btn--ghost { border-color: rgba(var(--wt-ink-rgb), 0.25); }
.wt-navtoggle { border-color: rgba(var(--wt-ink-rgb), 0.35); }
.wt-hero-side .wt-hero-side__note { color: rgba(var(--wt-ink-rgb), 0.5); }
.wt-header.wt-header--scrolled { box-shadow: 0 12px 30px -22px rgba(var(--wt-ink-rgb), 0.35); }
.wt-nav__menu { box-shadow: 0 24px 60px -24px rgba(var(--wt-ink-rgb), 0.3); }

.wt-site .wt-cta .wt-lead,
.wt-site .wt-cta .wt-copy,
.wt-site .wt-cta .wt-copy--light { color: rgba(var(--wt-ink-rgb), 0.75); }
.wt-site .wt-cta .wt-small { color: rgba(var(--wt-ink-rgb), 0.6); }
.wt-site .wt-cta .wt-eyebrow,
.wt-site .wt-cta .wt-eyebrow--light { color: rgba(var(--wt-ink-rgb), 0.65); }
.wt-site .wt-cta .wt-btn--ghost,
.wt-site .wt-cta .wt-btn--darkghost { border-color: rgba(var(--wt-ink-rgb), 0.35); }

.wt-site .wt-card:hover,
.wt-site .wt-card--link:hover,
.wt-site .wt-post-card:hover { box-shadow: 0 22px 44px -26px rgba(var(--wt-ink-rgb), 0.35); }
.wt-site .wt-quote:hover { box-shadow: 0 26px 52px -30px rgba(var(--wt-ink-rgb), 0.45); }
.wt-site .wt-contact-grid .wt-list__item:hover { box-shadow: 0 20px 40px -26px rgba(var(--wt-ink-rgb), 0.4); }

/* ==========================================================================
   15. THE PORTFOLIO ARCHIVE JOINS THE REST OF THE SITE (2026-08-06)
   --------------------------------------------------------------------------
   The archive was left behind when the panel system moved the site onto a
   light canvas: `.post-type-archive-portfolio .wt-site` pinned the whole page
   to the ink, so every band was dark and the page read as a different site.
   It now follows the same rhythm as every other page — dark hero panel, work
   on canvas, dark closing band — with each case becoming a white card the way
   projects, services and posts already are elsewhere.

   The work band's class was flipped from --dark to --white in template 79
   (sections 176 BG / 260 EN), so bandSurface() marks it chalk and the
   light-surface type rules apply on their own instead of being fought here.
   ========================================================================== */
.post-type-archive-portfolio .wt-site {
    background-color: var(--ru-canvas);
}

.post-type-archive-portfolio .wt-case-list { gap: 22px; }

.post-type-archive-portfolio .wt-case-row {
    padding: 22px;
    border-radius: var(--r-card);
    background-color: var(--wt-paper);
    transition:
        transform 0.32s var(--wt-ease-out),
        box-shadow 0.32s var(--wt-ease-out);
}

.post-type-archive-portfolio .wt-case-row:hover {
    transform: translateY(-4px);
    box-shadow: 0 24px 48px -28px rgba(var(--wt-ink-rgb), 0.4);
}

/* Re-inked for a light card: the kicker and metrics were chartreuse, which is
   a highlight on dark and unreadable on white. */
.post-type-archive-portfolio .wt-case-row__title { color: var(--wt-ink); }
.post-type-archive-portfolio .wt-case-row__intro { color: var(--wt-graphite); }
.post-type-archive-portfolio .wt-case-row__kicker { color: var(--wt-graphite); }
.post-type-archive-portfolio .wt-case-row__metrics { color: var(--wt-ink); }
.post-type-archive-portfolio .wt-case-row__btn { color: var(--wt-ink); }

.post-type-archive-portfolio .wt-case-row__img {
    border-radius: calc(var(--r-card) - 6px);
}


/* ==========================================================================
   16. THE RUDO SHAPE SYSTEM COMES OUT (2026-08-06)
   --------------------------------------------------------------------------
   Companion to block 14, which took the olive-and-lime palette out but left
   the geometry standing: the site was still a grey canvas carrying rounded
   floating panels on 12px gutters, a 20px panel radius, a detached footer
   and a fullscreen olive mobile sheet. Owner asked for the site as it stood
   at 13:00 on 2026-08-05 - two hours before rudo.co.uk was introduced.

   The rudo blocks are physically removed rather than overridden. Every class
   they touched is declared in the Oxygen builder stylesheet, so deleting an
   override returns that class to its builder baseline, which is what was
   live at that hour - the footer included, which the builder already paints
   ink with chalk type.

   Four things were lifted out of the deleted range and kept, because they
   were fixes rather than styling: the entrance-visibility guard, the
   quote-stage overflow clamp, the footer light-type overrides and the
   dark-band article colours.

   The radius tokens are restated because block 14 and the portfolio archive
   rules still read them; they now point at the site's own card radius
   instead of the rudo scale.
   ========================================================================== */
:root {
    --r-card: var(--wt-card-radius);
    --r-chip: 10px;
}

/* ==========================================================================
   17. CONTRAST REPAIRS AFTER THE PANELS CAME OUT (2026-08-06)
   --------------------------------------------------------------------------
   Two rules in the refinement pass above were written while the interior
   hero was a dark olive panel, and item 9 up there says so in as many words:
   it painted the secondary button white BECAUSE the panel was dark. With the
   panel gone the hero is canvas again, so white-on-white repeats the exact
   defect that rule was written to cure, on the same twelve pages.

   Both go back to the light-canvas grammar the rest of the site uses: ink
   type, hairline ink border, ink fill on hover.
   ========================================================================== */
.wt-page-hero .wt-btn--ghost {
    border-color: rgba(var(--wt-ink-rgb), 0.25);
    color: var(--wt-ink);
}

.wt-page-hero .wt-btn--ghost:hover {
    background-color: var(--wt-ink);
    border-color: var(--wt-ink);
    color: #FFFFFF;
}

.wt-page-hero .wt-crumbs [aria-current="page"],
.wt-case-hero .wt-crumbs [aria-current="page"] {
    color: rgba(var(--wt-ink-rgb), 0.55);
}

/* ==========================================================================
   18. THE PORTFOLIO ARCHIVE'S TYPE FOLLOWS ITS PANEL OUT (2026-08-06)
   --------------------------------------------------------------------------
   The dark archive was not built in this stylesheet at all: seven rules were
   written into the builder's own global selectors, which load BEFORE this
   file. Block 14 already beat the ink hero background here, so the panel went
   light - but the three type colours written for that panel are scoped one
   level deeper (.post-type-archive-portfolio .wt-page-hero .wt-display--medium)
   than anything answering them, so the archive H1 stayed #fff and vanished
   into the white hero, with the lead and breadcrumb washed out behind it.

   Deleting those builder rules is the tidier fix and needs a hand in the
   builder; matching their specificity from here is equivalent at render time,
   since this file loads after selectors.css.
   ========================================================================== */
.post-type-archive-portfolio .wt-page-hero .wt-display--medium {
    color: var(--wt-ink);
}

.post-type-archive-portfolio .wt-page-hero .wt-lead {
    color: var(--wt-graphite);
}

.post-type-archive-portfolio .wt-crumbs__list a {
    color: rgba(var(--wt-ink-rgb), 0.55);
}

/* ==========================================================================
   19. THE PROJECT META BECOMES A ROW AGAIN (2026-08-06)
   --------------------------------------------------------------------------
   Same shape of problem as block 18, in the builder's own selectors:
   .wt-case-meta carries `flex-flow: column` and a white left rule, both drawn
   for the olive case hero. The pre-rudo rule two thousand lines up says in
   its own comment that the meta "reads as one centred caption row rather than
   a stack" - it sets display:flex and wrap but never a direction, so the
   builder's column shorthand kept winning and the caption stayed a stack with
   an invisible white rule beside it.

   Direction and the dark-panel rule are answered here; the hairline the row
   actually wants is the border-top that rule already sets.
   ========================================================================== */
.wt-hero--centred .wt-case-meta {
    flex-direction: row;
    border-left: 0;
    padding-left: 0;
}

/* ==========================================================================
   20. THE PASTEL CARD TINTS COME OUT (2026-08-06)
   --------------------------------------------------------------------------
   The service cards rotated through a pastel set - sky, mint, lilac, blush,
   sand, steel - one colour per card. Owner asked for them gone.

   The rotation is written in the BUILDER's selectors, not here, and it is
   scoped a level tighter (.wt-grid-2 .wt-card--link:nth-child(1)) than the
   plain-card rule it was overriding, which is the only reason it was winning.
   Restating the same selectors here answers it: this file loads after
   selectors.css, so equal specificity plus later position takes it.

   Nothing new is invented - the cards fall to the card treatment the design
   layer already sets for every other card on the site: paper fill, hairline
   border, radius 16, elev-1. The glyph tile and the eyebrow chip go to chalk
   rather than staying sand and steel, so no single pastel square is left
   stranded on an otherwise neutral card.
   ========================================================================== */
.wt-grid-2 .wt-card--link:nth-child(1),
.wt-grid-2 .wt-card--link:nth-child(2),
.wt-grid-2 .wt-card--link:nth-child(3),
.wt-grid-2 .wt-card--link:nth-child(4),
.wt-card-grid .wt-card:nth-child(6n+1),
.wt-card-grid .wt-card:nth-child(6n+2),
.wt-card-grid .wt-card:nth-child(6n+3),
.wt-card-grid .wt-card:nth-child(6n+4),
.wt-card-grid .wt-card:nth-child(6n+5),
.wt-card-grid .wt-card:nth-child(6n+6) {
    background-color: var(--wt-paper);
}

/* the 48px icon tile: chalk, not sand */
.wt-card__glyph,
.wt-grid-2 .wt-card--link:nth-child(1) .wt-card__glyph,
.wt-grid-2 .wt-card--link:nth-child(2) .wt-card__glyph,
.wt-grid-2 .wt-card--link:nth-child(3) .wt-card__glyph,
.wt-grid-2 .wt-card--link:nth-child(4) .wt-card__glyph {
    background-color: var(--wt-chalk);
}

/* the kicker chip inside the six-card grid rode the same rotation */
.wt-card-grid .wt-card:nth-child(6n+1) .wt-eyebrow,
.wt-card-grid .wt-card:nth-child(6n+2) .wt-eyebrow,
.wt-card-grid .wt-card:nth-child(6n+3) .wt-eyebrow,
.wt-card-grid .wt-card:nth-child(6n+4) .wt-eyebrow,
.wt-card-grid .wt-card:nth-child(6n+5) .wt-eyebrow,
.wt-card-grid .wt-card:nth-child(6n+6) .wt-eyebrow {
    background-color: var(--wt-chalk);
}


/* ==========================================================================
   Block 20 - contrast repairs (2026-08-24)
   Measured with qa/lib/probe.py, not eyeballed.

   1. .wt-cta is a DARK panel (--wt-panel #242424), but the block below it
      set black text at 65-75%% opacity on it - written when .wt-cta was a
      light panel during the reverted olive pass. Result: 1.26:1 and 1.28:1,
      i.e. invisible copy on the closing CTA of every service page.
   2. .wt-process__number inherits color:var(--wt-accent) from selectors.css.
      enhance.css only recolours its .wt-chip children, and the live markup
      has no chips - so chartreuse landed on white at 1.1:1.
   ========================================================================== */

.wt-site .wt-cta .wt-lead,
.wt-site .wt-cta .wt-copy,
.wt-site .wt-cta .wt-copy--light { color: var(--wt-on-dark); }

.wt-site .wt-cta .wt-small { color: rgba(255, 255, 255, 0.72); }

.wt-site .wt-cta .wt-eyebrow,
.wt-site .wt-cta .wt-eyebrow--light { color: #ffffff; }

.wt-site .wt-cta .wt-btn--ghost,
.wt-site .wt-cta .wt-btn--darkghost {
    border-color: rgba(255, 255, 255, 0.40);
    color: #ffffff;
}

.wt-site .wt-process__number { color: var(--wt-ink); }

.wt-site .wt-footer .wt-small { color: var(--wt-on-dark); }

.wt-site .wt-section--dark .wt-stat__label { color: var(--wt-on-dark); }

/* Block 20a - the footer is OUTSIDE main.wt-site, so the scoped rule above
   never reached it (4.41:1). These three were all measured just under AA. */
.wt-footer .wt-small { color: var(--wt-on-dark); }
.wt-site .wt-hero-side__note { color: #55554F; }
.wt-site .wt-section--white .wt-small { color: #55554F; }

/* Block 20b - the multi-step questionnaire's stepper. Breakdance paints the
   inactive step circles from --grey-400 with #fff numerals, which renders as
   white-on-near-white: steps 2-6 were unreadable. Repainted from the site
   palette so every step is legible, with the active step still the loudest. */
.breakdance-form-stepper__step-icon {
    background-color: var(--wt-graphite);
}
.breakdance-form-stepper__step-icon span,
.breakdance-form-stepper__step-icon svg { color: #ffffff; }
.breakdance-form-stepper__step.is-active .breakdance-form-stepper__step-icon {
    background-color: var(--wt-ink);
}
.breakdance-form-stepper__label { color: #55554F; }
.breakdance-form-stepper__step.is-active .breakdance-form-stepper__label {
    color: var(--wt-ink);
}

/* Block 20c - dark bands come in TWO flavours on this site: the newer
   [data-wt-surface="ink"] attribute and the older .wt-section--dark class.
   The dark-band text fixes were only ever written for the attribute, so the
   case-study template (which uses the class) rendered its section heading in
   ink ON ink - measured at exactly 1:1, i.e. invisible on every case page.
   The copy/prose rules are latent duplicates of the same asymmetry. */
.wt-site .wt-section--dark .wt-article__heading { color: #FFFFFF; }
.wt-site .wt-section--dark .wt-article__copy { color: rgba(255, 255, 255, 0.75); }
.wt-site .wt-section--dark .wt-prose,
.wt-site .wt-section--dark .wt-prose p,
.wt-site .wt-section--dark .wt-prose li { color: rgba(255, 255, 255, 0.75); }


/* ==========================================================================
   Block 21 - refinement pass (2026-08-24)

   Brief from the owner: keep the identity (black, chartreuse, Wix Madefor),
   but it reads as generic, inconsistent, busy AND forgettable at once.
   That combination is decoration without a signature: four dot-grid patterns,
   four veiled photographs, a glow, a sketch, an orb and icons on every nav
   link, none of which say Webtura.

   This block REMOVES the generic decoration so the one device that is
   genuinely theirs - the chartreuse keyword highlight - can carry the page.
   Nothing structural changes; every rule here is revertible by deleting the
   block (backup: webtura-enhance.css.bak-pre-refine).
   ========================================================================== */

/* 1. The dot grids. Four of them, on four different band types, none load-bearing.
      background-image only - the retired band-join system still owns display,
      height and background-color on these same pseudo-elements. */
.wt-site .wt-section--white::before,
.wt-site .wt-page-hero::before,
.wt-site .wt-section--dark::before,
.wt-site .wt-section--dark:has(.wt-benefits)::before,
.wt-site .wt-section--dark:has(.wt-benefits)::after { background-image: none; }

/* 2. The hero glow and the CTA orb - ambient blur with no meaning. */
.wt-hero__glow,
.wt-cta__orb { display: none; }

/* 3. Icons on main-nav links. A five-item nav does not need pictograms;
      they were the single most templated thing on the page. */
.wt-header .wt-nav__menu .wt-nav__link::before { content: none; }

/* 4. The secondary photo washes on the service and process bands. The hero and
      the closing CTA keep their photographs - those carry meaning; these two
      were texture for texture's sake and fought the type beside them. */
.wt-site .wt-photo--svc,
.wt-site .wt-photo--process { display: none; }


/* ==========================================================================
   Block 22 - band weight (2026-08-24)

   After the cuts the page was shorter but still flat: nine bands all carrying
   the same eyebrow + heading size + card grid, so nothing led and nothing
   receded. Uniform emphasis reads as no emphasis - which is why the site felt
   'too plain' despite being 'too busy'.

   Two bands now LEAD (portfolio and reviews - the two checkable proof assets),
   the reference middle of the page goes QUIET, and the hero and closing CTA
   keep their existing weight. Padding lives in the Rhythm classes; the type
   scale lives here.
   ========================================================================== */

.wt-site .wt-band--lead .wt-h2 {
    font-size: clamp(40px, 5vw, 68px);
    line-height: 0.98;
    letter-spacing: -0.05em;
}

.wt-site .wt-band--quiet .wt-h2 {
    font-size: clamp(24px, 2.4vw, 33px);
    line-height: 1.12;
    letter-spacing: -0.02em;
}

/* A quiet band announces itself once, in grey, and then gets out of the way. */
.wt-site .wt-band--quiet .wt-eyebrow { color: var(--wt-graphite); }

/* The lead bands earn a hairline above the heading - the only new ornament in
   this pass, and it marks emphasis rather than decorating. */
.wt-site .wt-band--lead .wt-shell > .wt-stack--tight,
.wt-site .wt-band--lead .wt-shell > .wt-between {
    border-top: 1px solid var(--wt-ink);
    padding-top: 22px;
}


/* ==========================================================================
   Block 23 - statement hero (2026-08-24)

   Owner rejected the old hero. Replaced with a type-only statement hero:
   left-aligned to match every other band, no photograph, and the checkable
   proof raised above the fold.

   The hero photograph is INJECTED BY motion.js at runtime (.wt-photo--hero is
   not in the served HTML), so CSS is the only lever that reaches it.
   ========================================================================== */

.wt-site .wt-photo--hero { display: none; }

/* The hero also carried its own chartreuse radial glow. On a statement hero the
   type is the whole event; the ground stays paper. */
.wt-site .wt-hero { background-image: none; }

/* Left-align. enhance.css previously centred the column (align-items: center),
   which made the hero the only centred moment on the site. */
.wt-site .wt-hero__inner {
    align-items: flex-start;
    text-align: left;
}

.wt-site .wt-hero .wt-lead {
    align-self: flex-start;
    max-width: 56ch;
}

/* The hero is no longer a full viewport of empty ground. */
.wt-site .wt-hero {
    min-height: 0;
    padding-top: clamp(72px, 8vw, 128px);
    padding-bottom: clamp(72px, 8vw, 128px);
}

/* Block 23a - the CTA row and proof bar live inside .wt-hero__meta, which kept
   its own centring, so only the headline and lead moved left on the first pass. */
.wt-site .wt-hero__meta {
    align-items: flex-start;
    text-align: left;
    width: 100%;
}
.wt-site .wt-hero .wt-row { justify-content: flex-start; align-self: flex-start; }
.wt-site .wt-hero .wt-proof { justify-content: flex-start; align-self: flex-start; }

/* At the full display clamp the new headline runs to four lines and swamps the
   fold. Tightened so the proof bar stays above it. */
.wt-site .wt-hero .wt-display { font-size: clamp(44px, 6.4vw, 92px); }

/* Block 23b - at 92px the headline ran to four lines and pushed the proof bar
   under the fold on a 900px-tall viewport. Three lines keeps the proof visible,
   which is the entire point of the new hero. */
.wt-site .wt-hero .wt-display { font-size: clamp(38px, 5vw, 74px); line-height: 0.98; }
.wt-site .wt-hero__inner { gap: clamp(16px, 1.6vw, 22px); }

/* Block 23c - the proof bar wraps to two rows on phones, and the first item of
   the second row inherits a divider it should not have (CSS cannot see a wrap).
   Below the phone breakpoint the dividers go and spacing carries the rhythm. */
@media (max-width: 767px) {
    .wt-site .wt-proof { gap: 8px 20px; }
    .wt-site .wt-proof__item { border-left: 0; padding-left: 0; padding-right: 0; }
}

/* Block 24 - the hero ghost button (2026-08-24)
   .wt-hero .wt-btn--ghost inherited border-color: rgba(var(--wt-accent-rgb), .5)
   - chartreuse at 50%% on white paper, which is all but invisible. The ghost
   button on a light surface takes an ink border like everywhere else. */
.wt-site .wt-hero .wt-btn--ghost {
    border-color: var(--wt-ink);
    color: var(--wt-ink);
}
.wt-site .wt-hero .wt-btn--ghost:hover {
    background-color: var(--wt-ink);
    border-color: var(--wt-ink);
    color: #ffffff;
}


/* ==========================================================================
   Block 25 - portfolio cards, Glide-style (2026-08-24)

   Reference: glidedesign.com/work. Borderless cards in a two-up staggered
   grid: photographic device mockup on top, then a small industry kicker, the
   client name, and one outcome line. No box, no shadow, no card chrome - the
   mockup itself is the object and whitespace does the separating.

   The archive loops were switched from list to a 2-up grid in template 79.
   ========================================================================== */

.wt-site .wt-case-row {
    display: block;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    box-shadow: none;
}

.wt-site .wt-case-row__media {
    display: block;
    width: 100%;
    margin-bottom: 22px;
    border-radius: var(--wt-radius-sm);
    overflow: hidden;
    background-color: var(--wt-chalk);
}

.wt-site .wt-case-row__img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

.wt-site .wt-case-row__body {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
    padding: 0;
    max-width: 46ch;
}

.wt-site .wt-case-row__kicker {
    font-family: var(--wt-font-mono), monospace;
    font-size: 11.5px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #55554F;
    margin: 0;
}

.wt-site .wt-case-row__title {
    font-family: var(--wt-font-display), sans-serif;
    font-weight: 700;
    font-size: clamp(22px, 2vw, 28px);
    line-height: 1.15;
    letter-spacing: -0.03em;
    color: var(--wt-ink);
    margin: 0;
}

.wt-site .wt-case-row__intro {
    font-size: 16px;
    line-height: 1.55;
    color: #55554F;
    margin: 0;
}

.wt-site .wt-case-row__btn {
    margin-top: 4px;
    font-family: var(--wt-font-mono), monospace;
    font-size: 11.5px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--wt-ink);
    text-decoration: underline;
    text-underline-offset: 4px;
}

/* The stagger. Glide offsets alternate cards so the grid reads as a rhythm
   rather than a table. Scoped by :has() so it only touches case-row loops. */
@media (min-width: 768px) {
    .wt-site .bde-loop-item:has(.wt-case-row):nth-child(even) { margin-top: 72px; }
}


/* ==========================================================================
   Block 26 - portfolio cards on the homepage (2026-08-24)

   The project cards draw a fake browser window (.wt-project-card__mockbar with
   its three dots) around the image. That made sense for a flat screenshot, but
   the cards now carry PHOTOGRAPHIC device mockups - a photo of a laptop inside
   a drawn browser frame is one frame too many, and it made the homepage cards
   read differently from the Glide-style archive.

   Chrome removed; the mockup is the object, matching /portfolio/.
   ========================================================================== */

.wt-site .wt-project-card__mockbar { display: none; }

.wt-site .wt-project-card__media {
    background-color: transparent;
    border-radius: var(--wt-radius-sm);
    overflow: hidden;
}

.wt-site .wt-project-card:hover .wt-project-card__media { background-color: transparent; }

.wt-site .wt-project-card__img {
    display: block;
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 3;
    object-fit: cover;
}

/* Block 26a - correction. The image class is .wt-project-thumb (not __img), and
   .wt-project-card__mock is a 'plate': inset margins, hairline border, shadow,
   and the thumb cropped to 16/9 anchored at 50%% 0%% so a flat screenshot keeps
   its navigation. With a photographic mockup that top-anchored crop throws away
   the laptop and the scene, leaving something that looks like a flat capture.
   The plate goes; the photo is shown near-whole. */
.wt-site .wt-project-card__mock {
    width: 100%;
    height: auto;
    margin: 0;
    border: 0;
    box-shadow: none;
    background-color: transparent;
    border-radius: var(--wt-radius-sm);
    overflow: hidden;
}
.wt-site .wt-project-card__mock .wt-project-thumb {
    width: 100%;
    height: auto;
    min-height: 0;
    aspect-ratio: 4 / 3;
    object-fit: cover;
    object-position: 50% 50%;
    border-radius: 0;
}


/* ==========================================================================
   Block 27 - V2 (final2) treatment for the process steps and the review cards.
   The homepage moved onto the w2- design system; these two bands still carried
   the older editorial card styling, which read as a different site sitting
   inside the same page. 2026-08-24
   ========================================================================== */

.wt-site .wt-process {
    gap: 14px;
}

.wt-site .wt-process__step {
    gap: 10px;
    min-height: 0;
    padding: 26px 26px 28px;
    border: 0;
    border-radius: 22px;
    background: #F1F1F1;
    transition: background-color 0.25s ease;
}

.wt-site .wt-process__step:hover {
    background: #E9E9E9;
}

/* The builder still draws a divider rule between steps; the cards are the edge. */
.wt-site .wt-process__step,
.wt-site .wt-process__step--last {
    border-right-width: 0;
}

/* The corner glyphs were ornament from the previous direction. */
.wt-site .wt-process__step .wt-glyph--corner {
    display: none;
}

.wt-site .wt-process__number .wt-chip:first-child {
    font-family: "Oswald", sans-serif;
    font-size: clamp(30px, 2.9vw, 44px);
    font-weight: 700;
    font-variation-settings: normal;
    letter-spacing: -0.03em;
}

.wt-site .wt-process__number .wt-chip:nth-child(2) {
    padding: 0;
    border: 0;
    background: none;
    color: #6B6B6B;
    font-family: "Geist Mono", monospace;
    font-size: 10px;
    letter-spacing: 0.07em;
}

.wt-site .wt-process__step .wt-h3 {
    font-family: "Golos Text", sans-serif;
    font-size: 19px;
    font-weight: 700;
    letter-spacing: -0.02em;
    line-height: 1.25;
}

.wt-site .wt-process__step .wt-copy {
    color: #313131;
    font-family: "Golos Text", sans-serif;
    font-size: 14.5px;
    line-height: 1.55;
}

/* Review cards: same card language as the plan cards above them. */
.wt-site .wt-quote-grid {
    gap: 14px;
}

.wt-site .wt-quote {
    padding: 28px 26px 26px;
    border: 0;
    border-radius: 22px;
    background: #FFFFFF;
}

.wt-site .wt-quote::before,
.wt-site .wt-quote::after {
    display: none;
}

.wt-site .wt-quote__text {
    color: #111111;
    font-family: "Golos Text", sans-serif;
    font-size: 16px;
    font-weight: 500;
    line-height: 1.55;
    letter-spacing: -0.01em;
}

.wt-site .wt-quote__name {
    color: #6B6B6B;
    font-family: "Geist Mono", monospace;
    font-size: 10px;
    letter-spacing: 0.07em;
    text-transform: uppercase;
}


/* ==========================================================================
   Block 28 - .wt-page-hero on a V2 panel.
   webtura-motion.js builds the breadcrumb by looking for .wt-page-hero, so the
   class has to stay on the band even after it became a w2 panel. Everything
   the old hero painted underneath - the light gradient, the dot grids - is
   turned off here, and the crumbs are recoloured for the dark panel.
   2026-08-24
   ========================================================================== */

.w2-panel.wt-page-hero {
    padding: clamp(38px, 5vw, 84px) clamp(22px, 4vw, 68px);
    background-image: none;
}

.w2-panel--dark.wt-page-hero {
    background-color: #080808;
}

.w2-panel.wt-page-hero::before,
.w2-panel.wt-page-hero::after {
    content: none;
    display: none;
}

.w2-panel--dark .wt-crumbs {
    margin-bottom: 24px;
}

.w2-panel--dark .wt-crumbs__list a {
    color: rgba(255, 255, 255, 0.62);
}

.w2-panel--dark .wt-crumbs__list a:hover {
    color: #FFFFFF;
}

.w2-panel--dark .wt-crumbs__list [aria-current="page"] {
    color: #FFFFFF;
}

.w2-panel--dark .wt-crumbs__list li + li::before {
    color: rgba(255, 255, 255, 0.35);
}

/* Block 28a - .wt-page-hero sets `color: var(--wt-ink)` further up this file,
   which loads after selectors.css and so beats .w2-panel--dark at equal
   specificity. The panel's own surface decides the ink on a V2 page. */
.w2-panel--dark.wt-page-hero {
    color: #FFFFFF;
}

.w2-panel--lime.wt-page-hero {
    color: #050505;
}

/* markBands() also stamps .wt-hero--centred, which centres the old hero
   children. A V2 hero is left-aligned. */
.w2-panel .wt-crumbs__list {
    justify-content: flex-start;
}

/* Block 28b - the recommended-plan badge is drawn from CSS `content`, so it
   cannot come from the page's own translated text. Polylang sets the html lang,
   which is enough to swap the word. */
html[lang^="en"] .w2-plan--dark::after {
    content: "Recommended";
}


/* ==========================================================================
   Block 29 - the floating header, on V2 pages only.
   .w2-page frames the content in a 10px black margin with 28px-radius panels
   inside it. A flush, full-bleed header sitting on top of that frame reads as
   a leftover from the previous design, so the bar becomes a pill inside the
   same margin. Scoped with :has(.w2-page) so each page picks the floating
   header up the moment it is converted, and the pages still on the old design
   keep the header they were built for. 2026-08-24
   ========================================================================== */

body:has(.w2-page) {
    background-color: #080808;
}

body:has(.w2-page) .wt-header {
    padding: 10px 10px 0;
    background-color: transparent;
    border-bottom: 0;
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
}

body:has(.w2-page) .wt-header.wt-header--scrolled {
    padding-top: 10px;
    padding-bottom: 0;
}

body:has(.w2-page) .wt-header__inner {
    width: 100%;
    padding: 9px 9px 9px 26px;
    background-color: #FFFFFF;
    border-radius: 999px;
}

/* The header sits over the first panel while scrolling, so it needs its own
   edge once the page moves under it. */
body:has(.w2-page) .wt-header.wt-header--scrolled .wt-header__inner {
    box-shadow: 0 18px 40px -28px rgba(0, 0, 0, 0.75);
}

@media (max-width: 767px) {
    body:has(.w2-page) .wt-header__inner {
        padding: 8px 8px 8px 18px;
    }
}

/* Block 29a - the skip link inherited the page's white background. Now that the
   body behind a V2 page is ink, it needs to carry its own surface, or the first
   thing a keyboard user reaches is grey text on black. */
body:has(.w2-page) .oxy-skip-link {
    color: #080808;
    background-color: #F0FF4C;
}
