/* ═══════════════════════════════════════════════════════════════════
   neo.css — site restyle

   Two references, blended onto the existing UrgeSol brand:

   1. rubenmarcus.dev  → typography system, fluid scale, negative
      tracking on headings, wide mono eyebrows, one shared easing
      curve. (Its warm cream text ramp was swapped for your cool
      blue-lavender picks — see the tokens below.)
   2. CodePen "Neon Glow Buttons" (Yugta-Bista/MYjKYWO) → angled
      clip-path buttons, multi-layer glow bloom, tracking-on-hover,
      idle flicker. Retuned from cyan/magenta/lime to UrgeSol's
      blue/magenta.

   EVERYTHING here is scoped to `body.neo`. The layout gives every page
   that class by default, so a single page can opt back out with
   @section('body-class', '') and a page-level override is one selector
   away. Removing the stylesheet link reverts the whole site.
   ═══════════════════════════════════════════════════════════════════ */

/* ── 1. Tokens ──────────────────────────────────────────────────────
   Redefining --sans / --mono here re-points every existing rule on the
   site without having to touch urgesol.css. */
body.neo {
    --sans: 'Gabarito', 'Inter', system-ui, -apple-system, sans-serif;
    --mono: 'JetBrains Mono', 'IBM Plex Mono', SFMono-Regular, Menlo, monospace;
    --display: 'Space Grotesk', 'Gabarito', system-ui, -apple-system, sans-serif;
    --tech: 'Orbitron', 'JetBrains Mono', monospace;

    /* Text ramp — cool blue-lavender, per your picks. Brighter overall
       than the stock ramp, so body copy carries more presence.
       --white is the one I chose: it sits in the same hue family above
       --text, since the cream I had before clashed against these. */
    --white: #edf1ff;
    --light: #c9c8d9;
    --text: #d4dbff;
    --dim: #a8b9d2;

    /* motion — one curve for the whole page */
    --neo-ease: cubic-bezier(.22, 1, .36, 1);
    --neo-dur: .22s;

    /* neon channels, as raw triplets so rgba() can take an alpha */
    --nb-blue: 111, 157, 255;
    --nb-magenta: 201, 100, 199;
    --nb-ice: 223, 230, 255;
}

/* ── 2. Typography ──────────────────────────────────────────────────
   Fluid clamp() scale with negative tracking on display sizes, mirroring
   rubenmarcus.dev's ramp. */
body.neo {
    font-family: var(--sans);
    letter-spacing: -0.005em;
}

/* `:where()` keeps these bare-element rules at zero specificity, so any
   page rule that deliberately restyles a heading — .faq-section-header h3,
   .footer-col h4, .review-box h3 — still wins. Without it these override
   them and, for example, the FAQ's small mono category labels blow up to
   full h3 size. */
:where(body.neo) :is(h1, h2, h3, h4) {
    font-family: var(--display);
}

:where(body.neo) h1 {
    font-size: clamp(2.6rem, 4.9vw, 4.4rem);
    font-weight: 700;
    line-height: 1.04;
    letter-spacing: -0.03em;
}

/* The hero h1 sits in a ~516px column beside the terminal window, not
   full-bleed like rubenmarcus.dev's, so its own cap is pulled down —
   at the reference scale it ran to four lines and swamped the terminal. */
body.neo .hero-section h1 {
    font-size: clamp(2.3rem, 3.7vw, 3.5rem);
}

/* trimmed from the reference's 3rem so the hero h1 above stays the
   largest type on the page */
:where(body.neo) h2 {
    font-size: clamp(1.8rem, 3vw, 2.6rem);
    font-weight: 700;
    line-height: 1.12;
    letter-spacing: -0.022em;
}

:where(body.neo) h3 {
    font-size: clamp(1.25rem, 2.2vw, 1.65rem);
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.012em;
}

:where(body.neo) h4 {
    font-size: clamp(.98rem, 1.25vw, 1.15rem);
    font-weight: 600;
    letter-spacing: -0.01em;
}

:where(body.neo) p {
    line-height: 1.75;
}

/* eyebrow labels — ruben's `.bracket`: mono, tiny, very wide tracking.
   Keeps the existing `// what we do` copy, just restyles it. */
body.neo .label,
body.neo .tech-strip-lbl {
    font-family: var(--mono);
    font-size: .74rem;
    font-weight: 400;
    line-height: 1;
    letter-spacing: .14em;
    text-transform: uppercase;
    color: var(--dim);
}

/* ── 3. Motion ──────────────────────────────────────────────────────
   One easing curve across the page's reveal animations. */
body.neo .reveal {
    transition-duration: .64s;
    transition-timing-function: var(--neo-ease);
}

/* ── 4. Neon buttons ────────────────────────────────────────────────
   The CodePen technique. Base rules are written once and each variant
   only swaps --nbc, instead of the pen's per-colour duplication. */

/* strip the inherited "crystal" gloss + specular sweep — they fight
   with a transparent, clip-path'd button */
body.neo .btn::before,
body.neo .btn::after {
    display: none;
}

body.neo .btn {
    --nbc: var(--nb-blue);

    position: relative;
    isolation: auto;
    overflow: visible;

    font-family: var(--tech);
    font-size: .72rem;
    font-weight: 900;
    letter-spacing: 3px;
    text-transform: uppercase;
    line-height: 1;

    padding: 15px 38px;
    background: transparent;
    color: rgb(var(--nbc));
    border: 2px solid rgb(var(--nbc));
    border-radius: 0;

    /* the angled parallelogram. Note this also clips the left/right
       borders away, which is what leaves the top/bottom reading as
       two neon rules. */
    clip-path: polygon(12px 0%, 100% 0%, calc(100% - 12px) 100%, 0% 100%);

    /* inner bloom (box-shadow is clipped by clip-path, so the outer
       halo is done with drop-shadow below, which applies after the
       clip and therefore hugs the angled shape) */
    box-shadow: inset 0 0 10px rgba(var(--nbc), .07);
    filter: drop-shadow(0 0 4px rgba(var(--nbc), .40));

    transition: background-color var(--neo-dur) var(--neo-ease),
                box-shadow var(--neo-dur) var(--neo-ease),
                letter-spacing .3s var(--neo-ease),
                filter .3s var(--neo-ease),
                transform .2s var(--neo-ease);
}

body.neo .btn:hover {
    background: rgba(var(--nbc), .09);
    color: rgb(var(--nbc));
    letter-spacing: 5px;
    transform: translateY(-2px);
    box-shadow: inset 0 0 22px rgba(var(--nbc), .16);
    filter: drop-shadow(0 0 9px rgba(var(--nbc), .85))
            drop-shadow(0 0 26px rgba(var(--nbc), .45));
    text-shadow: 0 0 8px rgba(var(--nbc), .9),
                 0 0 20px rgba(var(--nbc), .55);
}

body.neo .btn:active {
    transform: translateY(1px) scale(.98);
}

body.neo .btn:focus-visible {
    outline: 2px solid rgb(var(--nbc));
    outline-offset: 4px;
}

/* colour channels */
body.neo .btn-primary {
    --nbc: var(--nb-blue);
}

body.neo .btn-secondary {
    --nbc: var(--nb-magenta);
}

body.neo .btn-outline,
body.neo .btn-ghost {
    --nbc: var(--nb-ice);
}

/* sizes — the clip inset scales with the button so the angle stays
   visually constant */
/* Orbitron at wide tracking is far wider than the Inter it replaces, so
   btn-lg is tighter than its name suggests — at the reference padding the
   hero's two CTAs no longer fit the 516px column side by side. */
body.neo .btn-lg {
    font-size: .70rem;
    letter-spacing: 2.5px;
    padding: 16px 28px;
    clip-path: polygon(14px 0%, 100% 0%, calc(100% - 14px) 100%, 0% 100%);
}

body.neo .btn-lg:hover {
    letter-spacing: 4px;
}

body.neo .btn-sm {
    font-size: .62rem;
    letter-spacing: 2px;
    padding: 10px 22px;
    clip-path: polygon(9px 0%, 100% 0%, calc(100% - 9px) 100%, 0% 100%);
}

body.neo .btn-sm:hover {
    letter-spacing: 3.5px;
}

/* ── 5. Idle flicker ────────────────────────────────────────────────
   The pen's signature touch. Dialled back from its 0.6 dip to 0.86 so
   it reads as a live sign rather than a fault, and staggered per
   colour so the buttons never pulse in unison.
   To switch it off entirely, delete this block. */
@keyframes neo-flicker {
    0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% { opacity: 1; }
    20%, 24%, 55% { opacity: .86; }
}

body.neo .btn {
    animation: neo-flicker 5s linear infinite;
}

body.neo .btn-secondary {
    animation-delay: .4s;
}

body.neo .btn-outline,
body.neo .btn-ghost {
    animation-delay: .8s;
}

/* ── 6. Header / navigation ─────────────────────────────────────────
   The filled pill on hover/active belonged to the old button language.
   Replaced with a neon rule that grows from the centre, so the header
   speaks the same vocabulary as the buttons below it. */
body.neo .nav {
    background: rgba(8, 13, 20, .82);
    border-bottom: 1px solid rgba(var(--nb-blue), .16);
}

body.neo .nav-links {
    gap: .15rem;
}

body.neo .nav-links a {
    position: relative;
    font-family: var(--mono);
    font-size: .72rem;
    font-weight: 500;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--dim);
    background: none;
    border-radius: 0;
    padding: .55rem .9rem;
    transition: color var(--neo-dur) var(--neo-ease);
}

body.neo .nav-links a::after {
    content: '';
    position: absolute;
    left: .9rem;
    right: .9rem;
    bottom: .15rem;
    height: 2px;
    background: rgb(var(--nb-blue));
    box-shadow: 0 0 6px rgba(var(--nb-blue), .9),
                0 0 14px rgba(var(--nb-blue), .5);
    transform: scaleX(0);
    transform-origin: center;
    transition: transform var(--neo-dur) var(--neo-ease);
}

body.neo .nav-links a:hover,
body.neo .nav-links a.active {
    color: var(--white);
    background: none;
}

body.neo .nav-links a:hover::after,
body.neo .nav-links a.active::after {
    transform: scaleX(1);
}

body.neo .nav-toggle span {
    background: var(--light);
}

/* ── Mobile drawer ──────────────────────────────────────────── */
/* fully opaque: at .98 the bright page headings still ghosted through
   the drawer. Only the sticky header is translucent. */
body.neo .nav-mobile {
    background: var(--bg);
    border-top: 1px solid rgba(var(--nb-blue), .16);
}

body.neo .nav-mobile a {
    font-family: var(--mono);
    font-size: .82rem;
    font-weight: 500;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--light);
    border-bottom: 1px solid rgba(var(--nb-blue), .12);
    transition: color var(--neo-dur) var(--neo-ease),
                border-color var(--neo-dur) var(--neo-ease);
}

body.neo .nav-mobile a:hover,
body.neo .nav-mobile a.active {
    color: rgb(var(--nb-blue));
    border-bottom-color: rgba(var(--nb-blue), .5);
}

/* the drawer CTA isn't a .btn, so it needs the neon treatment spelled out */
body.neo .nav-mobile .nav-mobile-cta {
    font-family: var(--tech);
    font-size: .68rem;
    font-weight: 900;
    letter-spacing: 2.5px;
    text-transform: uppercase;
    background: transparent;
    color: rgb(var(--nb-blue));
    border: 2px solid rgb(var(--nb-blue));
    border-bottom-color: rgb(var(--nb-blue));
    border-radius: 0;
    clip-path: polygon(12px 0%, 100% 0%, calc(100% - 12px) 100%, 0% 100%);
    filter: drop-shadow(0 0 5px rgba(var(--nb-blue), .5));
}

/* ── 7. Shared components on the inner pages ────────────────────────
   Everything below already existed; these rules only re-point it at the
   new type and neon language so the inner pages match the homepage. */

/* portfolio / services filter pills — squared off and given the button's
   angle so they read as part of the same set */
body.neo .filter-btn {
    font-family: var(--mono);
    font-size: .68rem;
    letter-spacing: .1em;
    text-transform: uppercase;
    color: var(--dim);
    border: 1px solid rgba(var(--nb-blue), .22);
    border-radius: 0;
    padding: .5rem 1rem;
    clip-path: polygon(8px 0%, 100% 0%, calc(100% - 8px) 100%, 0% 100%);
    transition: color var(--neo-dur) var(--neo-ease),
                border-color var(--neo-dur) var(--neo-ease),
                background-color var(--neo-dur) var(--neo-ease);
}

body.neo .filter-btn:hover,
body.neo .filter-btn.active {
    color: rgb(var(--nb-blue));
    border-color: rgb(var(--nb-blue));
    background: rgba(var(--nb-blue), .1);
}

/* form fields (contact, start-a-project intake) */
body.neo .form-label,
body.neo .intake-label {
    font-family: var(--mono);
    font-size: .7rem;
    font-weight: 400;
    letter-spacing: .12em;
    text-transform: uppercase;
    color: var(--dim);
}

body.neo .form-control,
body.neo .intake-input {
    font-family: var(--sans);
    border-radius: 0;
    border-color: rgba(var(--nb-blue), .2);
    transition: border-color var(--neo-dur) var(--neo-ease),
                box-shadow var(--neo-dur) var(--neo-ease);
}

body.neo .form-control:focus,
body.neo .intake-input:focus {
    border-color: rgb(var(--nb-blue));
    box-shadow: 0 0 0 1px rgba(var(--nb-blue), .35),
                0 0 18px -4px rgba(var(--nb-blue), .55);
}

/* FAQ rows — the question is UI copy, so it stays in the sans face
   rather than picking up the display face from the h-tags */
body.neo .faq-q {
    font-family: var(--sans);
    font-weight: 600;
    letter-spacing: -0.01em;
}

/* pricing page: Monthly / Project segmented toggle. The filled blue pill
   was the last thing on the site still speaking the old button language. */
body.neo .tab-toggle {
    gap: 0;
    background: transparent;
    border: 1px solid rgba(var(--nb-blue), .22);
    border-radius: 0;
    padding: .3rem;
}

body.neo .tab-active,
body.neo .tab-link {
    font-family: var(--mono);
    font-size: .7rem;
    font-weight: 500;
    letter-spacing: .1em;
    text-transform: uppercase;
    padding: .5rem 1.1rem;
    border-radius: 0;
    transition: color var(--neo-dur) var(--neo-ease),
                background-color var(--neo-dur) var(--neo-ease);
}

body.neo .tab-active {
    color: rgb(var(--nb-blue));
    background: rgba(var(--nb-blue), .12);
    box-shadow: inset 0 0 0 1px rgba(var(--nb-blue), .45);
}

body.neo .tab-link:hover {
    color: var(--white);
    background: rgba(var(--nb-ice), .06);
}

/* urgesol.css only staggers the terminal fade-up through :nth-child(12),
   but the services panel is 14 lines and the how-it-works handover is 15.
   Past the last defined delay a line falls back to 0 and appears BEFORE
   the lines above it, so the sequence reads out of order. Continuing the
   same .15s cadence to 18 covers every terminal on the site with room to
   spare — extend here rather than per-page if a longer one is added. */
body.neo .term-body>div:nth-child(13) { animation-delay: 2.20s; }
body.neo .term-body>div:nth-child(14) { animation-delay: 2.35s; }
body.neo .term-body>div:nth-child(15) { animation-delay: 2.50s; }
body.neo .term-body>div:nth-child(16) { animation-delay: 2.65s; }
body.neo .term-body>div:nth-child(17) { animation-delay: 2.80s; }
body.neo .term-body>div:nth-child(18) { animation-delay: 2.95s; }

/* how-it-works: in-page table of contents */
body.neo .toc-link {
    font-family: var(--mono);
    font-size: .72rem;
    letter-spacing: .08em;
    text-transform: uppercase;
    border-radius: 0;
    transition: color var(--neo-dur) var(--neo-ease),
                border-color var(--neo-dur) var(--neo-ease),
                background-color var(--neo-dur) var(--neo-ease);
}

body.neo .toc-link:hover,
body.neo .toc-link.active {
    color: rgb(var(--nb-blue));
    border-left-color: rgb(var(--nb-blue));
    background: rgba(var(--nb-blue), .07);
}

/* ── 8. Reduced motion ──────────────────────────────────────────────
   No flicker, no tracking shift, no lift — the glow still reads. */
@media (prefers-reduced-motion: reduce) {
    body.neo .btn {
        animation: none;
        transition: background-color var(--neo-dur) linear,
                    filter var(--neo-dur) linear;
    }

    body.neo .btn:hover {
        letter-spacing: 3px;
        transform: none;
    }

    body.neo .btn-sm:hover {
        letter-spacing: 2px;
    }
}

/* ── 9. Small screens ───────────────────────────────────────────────
   Orbitron at wide tracking eats horizontal space fast, so tighten
   both before the CTA rows start wrapping awkwardly. */
@media (max-width: 640px) {
    body.neo .btn {
        font-size: .64rem;
        letter-spacing: 2px;
        padding: 13px 26px;
    }

    body.neo .btn-lg {
        font-size: .68rem;
        padding: 15px 30px;
    }

    body.neo .btn:hover {
        letter-spacing: 3px;
    }
}


/* ═══════════════════════════════════════════════════════════════════
   10. Coloured icon system
   ═══════════════════════════════════════════════════════════════════
   Before this, every icon tile on the site was a white glyph on one of
   exactly two tints — rgba(41,78,158,.18) blue or rgba(143,40,141,.18)
   magenta — written inline in the Blade files and alternated row by
   row. Two hues over six cards reads as a stripe pattern, not as
   meaning, and a white glyph throws away the tile's colour entirely.

   Replaced with a 12-hue palette where the glyph itself carries the
   colour. One custom property, `--ic`, drives the whole tile: tint,
   border, glyph, and glow all derive from it, so a hue is chosen in the
   markup with a single class (`ico-cyan`) and nothing else changes.

   Hues are stored as raw `r, g, b` triplets so rgba() can take an
   alpha. Every one is picked bright enough to clear 4.5:1 against the
   #080d14 page and the tinted tile it sits on. */
body.neo {
    --ic-blue: 111, 157, 255;
    --ic-indigo: 129, 140, 248;
    --ic-violet: 167, 139, 250;
    --ic-magenta: 232, 121, 216;
    --ic-rose: 251, 113, 133;
    --ic-orange: 251, 146, 60;
    --ic-amber: 251, 191, 36;
    --ic-lime: 163, 230, 53;
    --ic-emerald: 52, 211, 153;
    --ic-teal: 45, 212, 191;
    --ic-cyan: 34, 211, 238;
    --ic-sky: 56, 189, 248;

    /* fallback for any tile that hasn't been given a hue class */
    --ic: var(--ic-blue);
}

/* ── Hue classes ────────────────────────────────────────────────────
   Deliberately unscoped to a component: the same class sets the hue on
   a service tile, a value tile, a contact tile, or anything added
   later. */
body.neo .ico-blue    { --ic: var(--ic-blue); }
body.neo .ico-indigo  { --ic: var(--ic-indigo); }
body.neo .ico-violet  { --ic: var(--ic-violet); }
body.neo .ico-magenta { --ic: var(--ic-magenta); }
body.neo .ico-rose    { --ic: var(--ic-rose); }
body.neo .ico-orange  { --ic: var(--ic-orange); }
body.neo .ico-amber   { --ic: var(--ic-amber); }
body.neo .ico-lime    { --ic: var(--ic-lime); }
body.neo .ico-emerald { --ic: var(--ic-emerald); }
body.neo .ico-teal    { --ic: var(--ic-teal); }
body.neo .ico-cyan    { --ic: var(--ic-cyan); }
body.neo .ico-sky     { --ic: var(--ic-sky); }

/* ── The tile ───────────────────────────────────────────────────────
   Every icon container on the site, styled once. urgesol.css already
   gives these their box metrics (size, radius, flex centring); this
   only takes over the colour treatment, so sizes stay per-component. */
body.neo .service-icon,
body.neo .why-icon,
body.neo .value-icon,
body.neo .contact-icon,
body.neo .contact-card-icon,
body.neo .deliv-icon {
    position: relative;
    isolation: isolate;
    color: rgb(var(--ic));

    /* Light reads as coming from the top-left, matching the specular
       treatment already on the cards these sit in. */
    background: linear-gradient(145deg,
            rgba(var(--ic), .26) 0%,
            rgba(var(--ic), .10) 52%,
            rgba(var(--ic), .04) 100%);
    border: 1px solid rgba(var(--ic), .38);

    /* inner top edge-light + a coloured pool cast onto the card below */
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .16),
        inset 0 -8px 14px -10px rgba(0, 0, 0, .55),
        0 8px 22px -14px rgba(var(--ic), .95);

    transition: transform .3s var(--neo-ease),
                box-shadow .3s var(--neo-ease),
                border-color .3s var(--neo-ease);
}

/* The glyph gets its own soft bloom so it reads as lit rather than
   painted on. Kept low — at full strength the mono glyphs smear. */
body.neo .service-icon > i,
body.neo .why-icon > i,
body.neo .value-icon > i,
body.neo .contact-icon > i,
body.neo .contact-card-icon > i,
body.neo .deliv-icon > i {
    color: rgb(var(--ic));
    text-shadow: 0 0 12px rgba(var(--ic), .55);
}

/* urgesol.css paints a white gloss wedge over the top 45% of the
   service/why tiles. Against a saturated tint that wedge desaturates
   the hue to near-grey, so it's retinted to the hue instead of
   removed — the highlight survives, the colour does too. */
body.neo .service-icon::after,
body.neo .why-icon::after {
    background: linear-gradient(180deg,
            rgba(255, 255, 255, .16) 0%,
            rgba(var(--ic), .06) 60%,
            transparent 100%);
}

/* ── Hover ──────────────────────────────────────────────────────────
   Driven from the card, not the tile, so the whole card is the target
   and the icon still responds on a 44px-wide phone tap. */
body.neo .service-card:hover .service-icon,
body.neo .value-card:hover .value-icon,
body.neo .why-item:hover .why-icon,
body.neo .contact-card:hover .contact-card-icon,
body.neo .card:hover .deliv-icon {
    transform: translateY(-3px);
    border-color: rgba(var(--ic), .68);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, .22),
        0 12px 28px -12px rgba(var(--ic), 1),
        0 0 0 4px rgba(var(--ic), .09);
}

/* ── Per-component metrics ──────────────────────────────────────────
   Two containers weren't tiles at all before: `.contact-card-icon` was
   a bare <p> holding a glyph, and pricing's deliverable icon was an
   inline-styled <p>. Both get real tile geometry here so all six
   containers share one visual language. */
body.neo .contact-card-icon,
body.neo .deliv-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    border-radius: 11px;
    font-size: 1.05rem;
    margin-bottom: .85rem;
}

/* ── FAQ toggle ─────────────────────────────────────────────────────
   A text "+" rather than an icon font, so it takes the palette through
   the same property but keeps its rotate-to-close behaviour. */
body.neo .faq-icon {
    --ic: var(--ic-cyan);
    color: rgb(var(--ic));
    background: linear-gradient(145deg, rgba(var(--ic), .28), rgba(var(--ic), .08));
    border: 1px solid rgba(var(--ic), .40);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18);
    transition: transform .3s var(--neo-ease),
                background-color .3s var(--neo-ease),
                box-shadow .3s var(--neo-ease);
}

body.neo .faq-icon.open {
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, .18),
                0 0 16px -4px rgba(var(--ic), .9);
}

/* ═══════════════════════════════════════════════════════════════════
   11. Tech strip — real brand colours
   ═══════════════════════════════════════════════════════════════════
   The marquee ran twelve brand marks in one flat blue. These are the
   marks' own colours, which is the version a developer recognises at a
   glance. Matched on the Font Awesome brand class so the markup
   doesn't need a parallel colour list to keep in sync.

   `.tech-chip i` in urgesol.css is (0,1,1); these are (0,2,1), so they
   win without !important. */
body.neo .tech-chip i.fa-laravel   { color: #f9603f; }
body.neo .tech-chip i.fa-php       { color: #8a91c4; }
body.neo .tech-chip i.fa-js        { color: #f7df1e; }
body.neo .tech-chip i.fa-node-js   { color: #7cc253; }
body.neo .tech-chip i.fa-react     { color: #61dafb; }
body.neo .tech-chip i.fa-wordpress { color: #4fa8d8; }
body.neo .tech-chip i.fa-shopify   { color: #95bf47; }
body.neo .tech-chip i.fa-python    { color: #6fa8dc; }
body.neo .tech-chip i.fa-docker    { color: #2496ed; }
body.neo .tech-chip i.fa-aws       { color: #ff9900; }
body.neo .tech-chip i.fa-figma     { color: #f47b56; }
body.neo .tech-chip i.fa-github    { color: #e6edf3; }

/* A chip lights up in its own brand colour on hover, rather than every
   chip resolving to the same blue. `currentColor` can't be used here —
   the chip's text colour is the label's, not the mark's — so the glow
   is carried on the icon and the border picks up a neutral lift. */
body.neo .tech-chip {
    transition: border-color .25s var(--neo-ease),
                color .25s var(--neo-ease),
                box-shadow .25s var(--neo-ease),
                transform .25s var(--neo-ease);
}

body.neo .tech-chip:hover {
    transform: translateY(-2px);
}

body.neo .tech-chip i {
    transition: filter .25s var(--neo-ease), transform .25s var(--neo-ease);
}

body.neo .tech-chip:hover i {
    filter: drop-shadow(0 0 8px currentColor);
    transform: scale(1.12);
}

/* ── Bare glyphs ────────────────────────────────────────────────────
   Not every icon wants a tile. The design sub-services list and the
   about page's advantages list are dense rows where a 42px tile would
   out-shout the text, so they take the hue on the glyph alone. Same
   `--ic` property, so `ico-teal` behaves identically in both places. */
body.neo .ico-glyph {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    width: 1.6rem;
    margin-top: .12rem;
    font-size: 1.05rem;
    color: rgb(var(--ic));
    text-shadow: 0 0 14px rgba(var(--ic), .45);
}

body.neo .ico-glyph > i {
    color: rgb(var(--ic));
    transition: transform .25s var(--neo-ease);
}

body.neo .deliverable-row:hover .ico-glyph > i,
body.neo .feature-item:hover .ico-glyph > i {
    transform: scale(1.15);
}

/* ═══════════════════════════════════════════════════════════════════
   12. Terminal chrome
   ═══════════════════════════════════════════════════════════════════
   The terminal windows are the most "developer" thing on the site, and
   every glyph in their chrome was the same flat --muted grey. Colouring
   the titlebar and status glyphs the way a real prompt does — branch in
   violet, deploy state in emerald, clock in amber — is what makes the
   window read as live output rather than a picture of a window. */
body.neo .term-title i {
    color: rgba(var(--ic-cyan), .85);
}

body.neo .term-status-item i {
    color: rgba(var(--ic-blue), .8);
}

/* Git branch — the colour a shell prompt uses for VCS state. */
body.neo .term-status-item i.fa-code-branch {
    color: rgb(var(--ic-violet));
}

/* Ready-to-ship state reads green, as it does in CI output. */
body.neo .term-status-item i.fa-rocket {
    color: rgb(var(--ic-emerald));
}

/* Duration / elapsed time. */
body.neo .term-status-item i.fa-clock {
    color: rgb(var(--ic-amber));
}

/* Ownership / credentials. */
body.neo .term-status-item i.fa-key {
    color: rgb(var(--ic-amber));
}

body.neo .term-status-item i.fa-clipboard-list {
    color: rgb(var(--ic-cyan));
}

/* ═══════════════════════════════════════════════════════════════════
   13. Mobile hardening
   ═══════════════════════════════════════════════════════════════════
   urgesol.css already carries a mobile-first breakpoint ladder
   (1024 / 900 / 768 / 640 / 480). What follows doesn't restack
   anything it already handles — it closes the gaps that ladder leaves:
   sideways overflow, tap targets under Apple's and Google's 44px
   minimum, and text that can't wrap. */

/* ── Sideways overflow ──────────────────────────────────────────────
   The page has several elements that are wider than their container by
   design: the tech marquee track (`width: max-content`), the neon
   buttons' drop-shadow bloom, and the terminal windows' min-content
   width. Any one of them can hand a phone a horizontal scrollbar.

   `clip` rather than `hidden` — `overflow: hidden` on an ancestor
   silently kills `position: sticky`, which would drop the site header
   on exactly the screens this is meant to fix. `clip` has no such
   side effect. The `hidden` line above it is the fallback for browsers
   that predate `clip`; they have no sticky header to lose there
   because the same engines lack the modern layout anyway. */
body.neo {
    overflow-x: hidden;
    overflow-x: clip;
}

/* Grid and flex children default to `min-width: auto`, meaning they
   refuse to shrink below their longest unbreakable word. One long
   mono string — a URL, a stack list, a terminal line — then pushes the
   whole grid wider than the phone. */
body.neo .grid-2 > *,
body.neo .grid-3 > *,
body.neo .grid-4 > *,
body.neo .col-2 > *,
body.neo .col-2-top > *,
body.neo .col-2-md > *,
body.neo .col-2-sm > *,
body.neo .contact-grid > *,
body.neo .why-item > *,
body.neo .feature-item > *,
body.neo .deliverable-row > * {
    min-width: 0;
}

/* Email addresses, URLs and credential strings have no break
   opportunity, so on a 320px screen they overhang their card. `anywhere`
   rather than `break-word` so the browser may also use the break when
   choosing line widths, not only as a last resort. */
body.neo .contact-card-val,
body.neo .contact-item-val,
body.neo .footer a,
body.neo .item-desc {
    overflow-wrap: anywhere;
}

/* ── Tap targets ────────────────────────────────────────────────────
   Anything a finger has to hit gets 44px of height. */

/* The hamburger was a 4px-padded stack of three 2px bars — roughly
   26×22 of real target. It is the only way to navigate below 768px. */
body.neo .nav-toggle {
    width: 44px;
    height: 44px;
    align-items: center;
    justify-content: center;
    padding: 0;
    border-radius: 8px;
    transition: background-color var(--neo-dur) var(--neo-ease);
}

body.neo .nav-toggle:hover,
body.neo .nav-toggle:focus-visible {
    background: rgba(var(--nb-blue), .12);
}

body.neo .nav-toggle:focus-visible {
    outline: 2px solid rgb(var(--nb-blue));
    outline-offset: 2px;
}

body.neo .nav-mobile a {
    min-height: 52px;
    display: flex;
    align-items: center;
}

/* Footer links sat at ~19px of hit height in a dense column, which on a
   phone means mis-taps between adjacent rows. */
body.neo .footer-col ul a {
    display: inline-block;
    padding: .38rem 0;
}

body.neo .footer-social a {
    min-width: 42px;
    min-height: 42px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* Filter pills and the pricing toggle are both finger targets. */
body.neo .filter-btn,
body.neo .tab-active,
body.neo .tab-link {
    min-height: 40px;
    display: inline-flex;
    align-items: center;
}

/* ── Touch devices ──────────────────────────────────────────────────
   Nothing here has a hover state to reveal it, so the icon tiles need
   to sit at their lit weight permanently rather than waiting for a
   pointer that will never arrive. */
@media (hover: none) {

    body.neo .service-icon,
    body.neo .why-icon,
    body.neo .value-icon,
    body.neo .contact-icon,
    body.neo .contact-card-icon,
    body.neo .deliv-icon {
        border-color: rgba(var(--ic), .5);
    }

    /* The marquee pauses on hover on a desktop; a touch device can
       never pause it, so it just keeps moving — which is correct, but
       the hover-scale on the chips would stick after a tap. */
    body.neo .tech-chip:hover,
    body.neo .tech-chip:hover i {
        transform: none;
    }
}

/* ── ≤ 640px ────────────────────────────────────────────────────────
   Tile sizes come down a step. urgesol.css sets these at desktop
   metrics and never revisits them, so a 48px service tile above a
   single-column card is doing more shouting than it needs to. */
@media (max-width: 640px) {

    body.neo .service-icon {
        width: 42px;
        height: 42px;
        font-size: 1.2rem;
        margin-bottom: 1rem;
    }

    body.neo .value-icon,
    body.neo .contact-card-icon,
    body.neo .deliv-icon {
        width: 38px;
        height: 38px;
        font-size: 1rem;
    }

    /* The 768px rule stacks `.why-item` into a column; the icon then
       needs bottom spacing it never had as a row item. */
    body.neo .why-item {
        gap: .85rem;
    }

    /* The status bar wraps to two lines on a phone, and
       `margin-left: auto` on the pushed item then strands it alone on
       the second row against the right edge. */
    body.neo .term-status {
        gap: .5rem .9rem;
    }

    body.neo .term-status-push {
        margin-left: 0;
    }

    /* Long terminal lines scroll horizontally inside the window rather
       than widening the page. Momentum scrolling keeps that feeling
       native on iOS. */
    body.neo .term-body {
        -webkit-overflow-scrolling: touch;
        overscroll-behavior-x: contain;
    }

    /* The section rhythm is built for a desktop viewport; at phone
       width 4rem of air between sections reads as the page having
       ended. */
    body.neo section {
        padding: 3.25rem 0;
    }
}

/* ── ≤ 400px ────────────────────────────────────────────────────────
   Below the iPhone SE / small-Android floor the existing ladder stops
   at 480px, which still assumes more width than these have. */
@media (max-width: 400px) {

    body.neo .container,
    body.neo .container-sm,
    body.neo .container-xs {
        padding: 0 1rem;
    }

    /* Orbitron at any tracking is wide; at 360px two CTAs in a row
       overflow regardless of how the row is set, so they go full-width
       and stack. */
    body.neo .btn {
        font-size: .6rem;
        letter-spacing: 1.5px;
        padding: 13px 18px;
    }

    body.neo .hero-section .btn,
    body.neo .cta-section .btn {
        width: 100%;
        justify-content: center;
    }

    body.neo .service-icon,
    body.neo .value-icon,
    body.neo .contact-card-icon,
    body.neo .deliv-icon {
        width: 36px;
        height: 36px;
        font-size: .95rem;
    }

    body.neo .term-body {
        font-size: .64rem;
        padding: .9rem .8rem 1rem;
    }

    body.neo .footer-social a {
        min-width: 38px;
        min-height: 38px;
    }
}

/* ── Reduced motion ─────────────────────────────────────────────────
   Extends the site's existing preference block to the pieces added
   above. The colour work all survives; only the movement stops. */
@media (prefers-reduced-motion: reduce) {

    body.neo .service-card:hover .service-icon,
    body.neo .value-card:hover .value-icon,
    body.neo .why-item:hover .why-icon,
    body.neo .contact-card:hover .contact-card-icon,
    body.neo .card:hover .deliv-icon,
    body.neo .tech-chip:hover,
    body.neo .tech-chip:hover i,
    body.neo .deliverable-row:hover .ico-glyph > i,
    body.neo .feature-item:hover .ico-glyph > i {
        transform: none;
    }

    body.neo .tech-track {
        animation: none;
    }
}

/* ── The reCAPTCHA badge ────────────────────────────────────────────
   Google's v3 script injects `.grecaptcha-badge` with
   `position: fixed; width: 256px; right: -186px` — the collapsed
   "peek" state that slides out on hover. It is 186px wider than the
   viewport allows, and on every page of the site (the script is loaded
   in the layout) it added ~7px of horizontal scroll. On a phone that
   reads as the whole page rubber-banding sideways.

   The `overflow-x: clip` on `body` above cannot catch it: a fixed
   element's containing block is the viewport, so it escapes any
   clipping an ancestor sets. Clipping has to happen at the root.

   `clip` rather than `hidden` for the same reason as on body, and this
   was verified rather than assumed — with this rule the header still
   sticks (`.nav` holds top: 0 through a full-page scroll) and vertical
   scrolling is untouched. Restyling the badge itself was tried first
   and does not work: forcing `right: 0` keeps the 256px box on screen
   but the page still reports the same scroll width.

   Note this leaves Google's badge visible and functional, which is
   what their terms require unless the attribution text is added to
   each form instead. */
html {
    overflow-x: clip;
}

/* ── Remaining tap targets ──────────────────────────────────────────
   Two the audit turned up that the rules above didn't cover. */

/* The FAQ's table of contents becomes a horizontal pill row below
   900px, at which point each entry is a finger target rather than a
   sidebar link. It measured 32px. */
body.neo .toc-link {
    min-height: 40px;
}

@media (max-width: 900px) {
    body.neo .faq-toc .toc-link {
        display: inline-flex;
        align-items: center;
    }
}

/* "Learn more →" at the foot of each service card measured 21px tall.
   It's a standalone call to action, not a link inside a sentence, so it
   gets a real target. The padding is added and the same amount taken
   off the inline margin-top above it, so the card's spacing is
   unchanged. */
body.neo .service-card > a[href] {
    padding: .55rem 0;
    margin-top: .7rem !important;
}

/* Inline links inside a sentence — "get in touch", "send it directly",
   the mailto on the contact page — are deliberately left alone. WCAG
   2.5.8 exempts links whose target size is constrained by the line of
   text they sit in, and padding them out would break the paragraph's
   leading for no accessibility gain. */

/* The email address on the contact page is the page's primary action
   and sits on its own line rather than inside a sentence, so the
   inline-link exemption above doesn't apply to it. It measured 18px. */
body.neo .contact-info-item a[href] {
    display: inline-block;
    padding: .4rem 0;
}
