/* ── Mega menu (click-based, no hover open) ── */
.mega-drop{display:none;position:fixed;top:68px;left:0;right:0;background:#fff;border-top:2px solid #131B94;border-bottom:1px solid #e5e7eb;box-shadow:0 20px 60px rgba(0,0,0,.12);z-index:400;}
.mega-drop.open{display:block;}

/* ── Mega menu item styles ── */
.mega-label-row{display:flex;align-items:center;gap:6px;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.1em;color:#131B94;padding-bottom:8px;margin-bottom:4px;border-bottom:1px solid #f3f4f6;}
.mega-label-row.mt{margin-top:16px;}
.mega-item-link{display:flex;align-items:center;gap:8px;padding:6px 8px;border-radius:6px;font-size:13px;font-weight:500;color:#4b5563;text-decoration:none;transition:background .15s,color .15s;margin-bottom:1px;}
.mega-item-link:hover{background:rgba(19,27,148,.06);color:#131B94;}
.mega-icon-wrap{width:24px;height:24px;border-radius:5px;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.ic-b{background:rgba(19,27,148,.1);color:#131B94;}
.ic-g{background:rgba(16,185,129,.1);color:#10B981;}
.ic-a{background:rgba(245,158,11,.1);color:#F59E0B;}
.ic-r{background:rgba(251,113,133,.1);color:#FB7185;}
.ic-v{background:rgba(139,92,246,.1);color:#8B5CF6;}
.ic-c{background:rgba(6,182,212,.1);color:#06B6D4;}
.mega-badge-tag{font-size:9px;font-weight:700;text-transform:uppercase;letter-spacing:.04em;background:rgba(19,27,148,.1);color:#131B94;border-radius:3px;padding:1px 5px;margin-left:auto;flex-shrink:0;}
.mega-badge-tag.new{background:rgba(16,185,129,.12);color:#10B981;}
.mega-cta-box{background:linear-gradient(135deg,rgba(19,27,148,.06),rgba(19,27,148,.03));border:1px solid rgba(19,27,148,.15);border-radius:12px;padding:20px;height:100%;}

/* ── Nav button active indicator ── */
.nav-btn-active{color:#131B94!important;background:rgba(19,27,148,.08)!important;}

/* ── Mobile accordion ── */
.mob-panel{display:none;}
.mob-panel.open{display:block;}
.mob-chev{transition:transform .2s;}
.mob-chev.open{transform:rotate(180deg);}

/* ── Search panel ──────────────────────────────────────────────────────
 *
 * Whether the panel is open is a class on <body>, not a class on the
 * panel. It has to be, because the panel is rendered by a Livewire
 * component that re-renders on every keystroke: any state written into
 * its own markup is overwritten by the next server response, which is
 * precisely how the old panel came to close itself the moment anyone
 * typed into it. <body> is outside the component, so nothing Livewire
 * does can reach it.
 */
.gs-overlay{position:fixed;inset:0;z-index:600;pointer-events:none;}
body.search-open .gs-overlay{pointer-events:auto;}

.gs-backdrop{position:absolute;inset:0;background:rgba(0,0,0,.45);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);opacity:0;transition:opacity .3s ease;}
body.search-open .gs-backdrop{opacity:1;}

.gs-panel{position:absolute;left:0;right:0;top:0;background:#fff;border-bottom:1px solid #e5e7eb;box-shadow:0 24px 60px rgba(0,0,0,.18);transform:translateY(-100%);transition:transform .38s cubic-bezier(.16,1,.3,1);max-height:88vh;display:flex;flex-direction:column;}
body.search-open .gs-panel{transform:translateY(0);}

/* The bar is centred on the same 720px column as the results, so the
   magnifier lines up with the rows underneath it rather than sitting
   out at the window edge with the list floating in the middle. */
.gs-bar{display:flex;align-items:center;gap:4px;height:64px;padding:0 14px;border-bottom:1px solid #f3f4f6;flex-shrink:0;max-width:720px;width:100%;margin:0 auto;}
@media(min-width:640px){.gs-bar{height:68px;padding:0 24px;}}
.gs-input{flex:1;min-width:0;border:none;outline:none;background:transparent;padding:0 10px;font-family:'Inter',sans-serif;font-size:15px;color:#0a0b0f;}
@media(min-width:640px){.gs-input{font-size:16px;padding:0 16px;}}
.gs-input::placeholder{color:#9ca3af;}
.gs-input::-webkit-search-cancel-button{-webkit-appearance:none;appearance:none;}

.gs-go{display:inline-flex;align-items:center;gap:6px;flex-shrink:0;background:#131B94;color:#fff;border:none;cursor:pointer;border-radius:10px;padding:9px 14px;font-family:'Inter',sans-serif;font-size:13px;font-weight:700;transition:background .15s;}
.gs-go:hover{background:#1f2ab5;}
.gs-close{width:40px;height:40px;flex-shrink:0;border:none;background:transparent;cursor:pointer;border-radius:10px;display:flex;align-items:center;justify-content:center;color:#6b7280;transition:background .15s,color .15s;}
.gs-close:hover{background:rgba(19,27,148,.06);color:#131B94;}

.gs-results{overflow-y:auto;padding:18px 14px 22px;max-width:720px;width:100%;margin:0 auto;}
@media(min-width:640px){.gs-results{padding:20px 24px 26px;}}
.gs-head{font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.08em;color:#6b7280;margin:14px 0 8px;}
.gs-head:first-child{margin-top:0;}
.gs-list{display:grid;gap:2px;}
.gs-row{display:flex;align-items:center;gap:11px;padding:9px 10px;border-radius:10px;text-decoration:none;transition:background .15s;}
.gs-row:hover{background:rgba(19,27,148,.05);}
.gs-row-icon{width:26px;height:26px;border-radius:7px;display:flex;align-items:center;justify-content:center;flex-shrink:0;background:rgba(19,27,148,.1);color:#131B94;}
.gs-row-icon-alt{background:rgba(16,185,129,.1);color:#059669;}
.gs-row-text{display:flex;flex-direction:column;min-width:0;flex:1;}
.gs-row-label{font-size:13.5px;font-weight:600;color:#374151;line-height:1.35;}
.gs-row:hover .gs-row-label{color:#131B94;}
.gs-row-desc{font-size:12px;color:#6b7280;line-height:1.4;margin-top:2px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.gs-row-kind{flex-shrink:0;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.05em;color:#6b7280;background:#f9fafb;border:1px solid #f3f4f6;border-radius:999px;padding:3px 8px;}
@media(max-width:479px){.gs-row-kind{display:none;}}

.gs-empty{font-size:13.5px;color:#6b7280;padding:6px 0 12px;}
.gs-all{display:flex;align-items:center;justify-content:center;gap:7px;width:100%;margin-top:16px;border:1px solid rgba(19,27,148,.2);background:#fff;color:#131B94;cursor:pointer;border-radius:12px;padding:11px 16px;font-family:'Inter',sans-serif;font-size:13px;font-weight:700;transition:background .15s,border-color .15s;}
.gs-all:hover{background:rgba(19,27,148,.05);border-color:#131B94;}

/* ── Search results page ── */
.sr-row{display:flex;flex-direction:column;gap:6px;padding:18px 0;border-bottom:1px solid #f3f4f6;}
.sr-row:last-child{border-bottom:none;}
.sr-kind{display:inline-flex;align-items:center;gap:6px;align-self:flex-start;font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:#131B94;background:rgba(19,27,148,.07);border:1px solid rgba(19,27,148,.14);border-radius:999px;padding:3px 9px;}
.sr-title{font-family:'Inter Tight',sans-serif;font-weight:800;font-size:18px;color:#0a0b0f;line-height:1.3;text-decoration:none;}
.sr-title:hover{color:#131B94;}
.sr-desc{font-size:13.5px;color:#6b7280;line-height:1.7;}
.sr-url{font-size:12px;color:#6b7280;}
/* ── Footer ───────────────────────────────────────────────────────
   Contrast is the point here. The previous version used Tailwind's
   `text-muted` (#6b7280) and `text-gray-600` on a #0a0b0f background,
   which sits at roughly 3:1 and below - under the 4.5:1 WCAG AA
   threshold for body text. Everything below clears it.                */

.site-footer .footer-bio{font-size:13.5px;line-height:1.75;color:rgba(255,255,255,.66);margin-bottom:22px;max-width:34ch;}

.site-footer .footer-head{font-size:12px;font-weight:800;letter-spacing:.09em;text-transform:uppercase;color:#fff;margin-bottom:16px;}
.site-footer .footer-link{display:block;font-size:13.5px;line-height:1.5;color:rgba(255,255,255,.66);margin-bottom:11px;transition:color .18s;}
.site-footer .footer-link:last-child{margin-bottom:0;}
.site-footer .footer-link:hover{color:#fff;}

.site-footer .footer-chip{display:inline-flex;align-items:center;gap:6px;background:rgba(255,255,255,.07);border:1px solid rgba(255,255,255,.14);border-radius:7px;padding:5px 10px;}
.site-footer .footer-chip span{font-size:11.5px;font-weight:600;color:rgba(255,255,255,.75);}

/* Social buttons: white-on-dark with a real border, so they are visible
   against the near-black footer instead of disappearing into it. */
.site-footer .social-btn{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:10px;border:1px solid rgba(255,255,255,.18);background:rgba(255,255,255,.07);color:rgba(255,255,255,.88);transition:background .18s,border-color .18s,color .18s,transform .18s;}
.site-footer .social-btn:hover{background:#131B94;border-color:#131B94;color:#fff;transform:translateY(-2px);}
.site-footer .social-btn svg{width:18px;height:18px;display:block;}

.site-footer .footer-contact{display:flex;align-items:center;gap:10px;}
.site-footer .footer-contact-icon{width:32px;height:32px;border-radius:9px;background:rgba(19,27,148,.32);color:#8b9bff;display:flex;align-items:center;justify-content:center;flex-shrink:0;}
.site-footer .footer-contact-label{font-size:11px;font-weight:700;text-transform:uppercase;letter-spacing:.06em;color:rgba(255,255,255,.55);margin-bottom:2px;}
.site-footer .footer-contact-value{display:block;font-size:13.5px;font-weight:500;color:rgba(255,255,255,.88);}

.site-footer .footer-loc-head{font-size:11.5px;font-weight:800;text-transform:uppercase;letter-spacing:.1em;color:rgba(255,255,255,.62);margin-bottom:10px;}
.site-footer .footer-loc-link{font-size:12.5px;font-weight:500;color:rgba(255,255,255,.55);transition:color .18s;}
.site-footer .footer-loc-link:hover{color:#fff;}
.site-footer .footer-loc-sep{font-size:12px;color:rgba(255,255,255,.22);}

.site-footer .footer-legal{font-size:12.5px;color:rgba(255,255,255,.55);}
.site-footer .footer-legal-link{font-size:12.5px;color:rgba(255,255,255,.55);transition:color .18s;}
.site-footer .footer-legal-link:hover{color:rgba(255,255,255,.9);}
.site-footer .ib-locale-btn{display:inline-flex;align-items:center;gap:6px;height:32px;padding:0 12px;border-radius:999px;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.04);color:rgba(255,255,255,.75);font-size:12.5px;line-height:1;cursor:pointer;transition:border-color .18s,color .18s;}
.site-footer .ib-locale-btn:hover,.site-footer .ib-locale-btn:focus-visible{border-color:rgba(255,255,255,.35);color:#fff;outline:none;}
.site-footer .ib-locale-select{appearance:none;-webkit-appearance:none;padding-right:12px;}
.site-footer .ib-locale-select option{color:#111;}
.site-footer .ib-locale-menu{position:absolute;bottom:calc(100% + 8px);left:50%;transform:translateX(-50%);min-width:200px;max-height:60vh;overflow:auto;padding:6px;border-radius:14px;background:#1d2023;border:1px solid rgba(255,255,255,.1);box-shadow:0 18px 40px rgba(0,0,0,.45);z-index:40;}
.site-footer .ib-locale-item{display:block;padding:9px 12px;border-radius:9px;font-size:13px;color:rgba(255,255,255,.8);white-space:nowrap;}
.site-footer .ib-locale-item:hover{background:rgba(255,255,255,.06);color:#fff;}
.site-footer .ib-locale-item.is-active{color:#fff;font-weight:600;background:rgba(255,255,255,.08);}
.site-footer .footer-legal-btn{border:none;background:transparent;cursor:pointer;padding:0;font-family:inherit;}
/* ── Platform mark ─────────────────────────────────────────────── */
.platform-mark{display:inline-flex;align-items:center;gap:7px;font-size:12px;font-weight:700;letter-spacing:.01em;padding:5px 12px 5px 5px;border-radius:999px;border:1px solid var(--pm-border,#e5e7eb);background:var(--pm-bg,#f9fafb);color:var(--pm-fg,#374151);}
.platform-mark-sm{font-size:11px;padding:3px 9px 3px 3px;gap:5px;}
.platform-mark-dot{display:inline-flex;align-items:center;justify-content:center;width:22px;height:22px;border-radius:999px;background:var(--pm-fg,#374151);color:#fff;flex-shrink:0;}
.platform-mark-sm .platform-mark-dot{width:18px;height:18px;}
.platform-mark-sm .platform-mark-dot svg{width:11px;height:11px;}

.platform-mark[data-platform="shopify"]    {--pm-fg:#5E8E3E;--pm-bg:rgba(94,142,62,.08);--pm-border:rgba(94,142,62,.22);}
.platform-mark[data-platform="wordpress"]  {--pm-fg:#21759B;--pm-bg:rgba(33,117,155,.08);--pm-border:rgba(33,117,155,.22);}
.platform-mark[data-platform="laravel"]    {--pm-fg:#F05340;--pm-bg:rgba(240,83,64,.08);--pm-border:rgba(240,83,64,.22);}
.platform-mark[data-platform="codeigniter"]{--pm-fg:#DD4814;--pm-bg:rgba(221,72,20,.08);--pm-border:rgba(221,72,20,.22);}
.platform-mark[data-platform="react"]      {--pm-fg:#087EA4;--pm-bg:rgba(8,126,164,.08);--pm-border:rgba(8,126,164,.22);}
.platform-mark[data-platform="meta-ads"]   {--pm-fg:#0866FF;--pm-bg:rgba(8,102,255,.08);--pm-border:rgba(8,102,255,.22);}
.platform-mark[data-platform="google-ads"] {--pm-fg:#4285F4;--pm-bg:rgba(66,133,244,.08);--pm-border:rgba(66,133,244,.22);}
.platform-mark[data-platform="seo"]        {--pm-fg:#0F9D58;--pm-bg:rgba(15,157,88,.08);--pm-border:rgba(15,157,88,.22);}
.platform-mark[data-platform="design"]     {--pm-fg:#8B5CF6;--pm-bg:rgba(139,92,246,.08);--pm-border:rgba(139,92,246,.22);}

/* ── Review cards ──────────────────────────────────────────────── */
.rv-section{position:relative;}
.rv-grid{display:grid;grid-template-columns:1fr;gap:20px;}
@media(min-width:768px){.rv-grid{grid-template-columns:repeat(2,1fr);}}
@media(min-width:1024px){.rv-grid{grid-template-columns:repeat(3,1fr);}}
.rv-card{background:#fff;border:1px solid #e5e7eb;border-radius:18px;padding:26px;display:flex;flex-direction:column;transition:border-color .2s,box-shadow .2s,transform .2s;}
.rv-card:hover{border-color:rgba(19,27,148,.18);box-shadow:0 16px 40px rgba(19,27,148,.07);transform:translateY(-3px);}
.rv-stars{display:inline-flex;gap:2px;color:#F5B301;margin-bottom:14px;}
.rv-quote{font-size:14.5px;line-height:1.75;color:#374151;margin-bottom:20px;flex:1;}
.rv-foot{display:flex;align-items:center;gap:12px;padding-top:16px;border-top:1px solid #f3f4f6;}
.rv-avatar{width:42px;height:42px;border-radius:999px;flex-shrink:0;object-fit:cover;}
.rv-initial{width:42px;height:42px;border-radius:999px;flex-shrink:0;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:15px;color:#fff;background:#131B94;}
.rv-name{font-size:13.5px;font-weight:700;color:#0f1115;line-height:1.3;}
.rv-role{font-size:12px;color:#6b7280;line-height:1.4;}
.rv-source{margin-left:auto;font-size:11px;font-weight:600;color:#6b7280;white-space:nowrap;display:inline-flex;align-items:center;gap:4px;}
/* The same chip, but as a link when the review has a source_url - a Google or
   Shopify Partner review can then be read at its origin. Underlined only on
   hover so the card footer stays quiet. */
a.rv-source{text-decoration:none;transition:color .16s;}
a.rv-source:hover{color:#131B94;text-decoration:underline;}

/* Platform-framed variant: a tinted rail and mark around the whole block */
.rv-framed{border:1px solid var(--pm-border,#e5e7eb);background:var(--pm-bg,#fafafa);border-radius:26px;padding:28px 22px;}
@media(min-width:1024px){.rv-framed{padding:36px 32px;}}
.rv-framed[data-platform="shopify"]    {--pm-fg:#5E8E3E;--pm-bg:rgba(94,142,62,.045);--pm-border:rgba(94,142,62,.20);}
.rv-framed[data-platform="wordpress"]  {--pm-fg:#21759B;--pm-bg:rgba(33,117,155,.045);--pm-border:rgba(33,117,155,.20);}
.rv-framed[data-platform="laravel"]    {--pm-fg:#F05340;--pm-bg:rgba(240,83,64,.045);--pm-border:rgba(240,83,64,.20);}
.rv-framed[data-platform="codeigniter"]{--pm-fg:#DD4814;--pm-bg:rgba(221,72,20,.045);--pm-border:rgba(221,72,20,.20);}
.rv-framed[data-platform="react"]      {--pm-fg:#087EA4;--pm-bg:rgba(8,126,164,.045);--pm-border:rgba(8,126,164,.20);}
.rv-framed[data-platform="meta-ads"]   {--pm-fg:#0866FF;--pm-bg:rgba(8,102,255,.045);--pm-border:rgba(8,102,255,.20);}
.rv-framed[data-platform="google-ads"] {--pm-fg:#4285F4;--pm-bg:rgba(66,133,244,.045);--pm-border:rgba(66,133,244,.20);}
.rv-framed[data-platform="seo"]        {--pm-fg:#0F9D58;--pm-bg:rgba(15,157,88,.045);--pm-border:rgba(15,157,88,.20);}
.rv-framed[data-platform="design"]     {--pm-fg:#8B5CF6;--pm-bg:rgba(139,92,246,.045);--pm-border:rgba(139,92,246,.20);}

/* ── Assigned blog posts ───────────────────────────────────────── */
.rp-grid{display:grid;grid-template-columns:1fr;gap:18px;}
@media(min-width:640px){.rp-grid{grid-template-columns:repeat(2,1fr);}}
@media(min-width:1024px){.rp-grid{grid-template-columns:repeat(3,1fr);}}
.rp-card{background:#fff;border:1px solid #e5e7eb;border-radius:16px;overflow:hidden;display:flex;flex-direction:column;transition:transform .22s,box-shadow .22s,border-color .22s;}
.rp-card:hover{transform:translateY(-4px);box-shadow:0 16px 38px rgba(19,27,148,.08);border-color:rgba(19,27,148,.18);}
.rp-thumb{aspect-ratio:16/9;background:#f3f4f6;display:flex;align-items:center;justify-content:center;overflow:hidden;}
.rp-thumb img{width:100%;height:100%;object-fit:cover;}
.rp-body{padding:18px;display:flex;flex-direction:column;flex:1;}
.sm-video{display:block;width:100%;height:auto;background:#0f1115;}

/* Inside a card, a video takes the whole slot, so a video card can never
   stand taller than the photo cards beside it.
   
   It is CONTAINED rather than cropped: a video is a composition someone
   framed, and cutting the sides off it is worse than a band of dark at the
   top and bottom. An image is cropped to fill instead, because a still can
   lose its edges without losing its point. Both end up the same height,
   which is what makes a row line up.
   
   The band is the video element's own #0f1115, so it reads as a plate
   rather than as a gap. */
.cs-thumb .sm-video,
.prod-thumb .sm-video,
.story-media .sm-video,
.case-thumb .sm-video,
.blog-thumb .sm-video,
.feat-thumb .sm-video{
  width:100%;height:100%;
  object-fit:contain;
  object-position:center center;
}

/* The poster shown in place of a video that could not play, or that a
   visitor has asked not to autoplay. Same slot, same size. */
.sm-fallback{width:100%;height:100%;object-fit:cover;object-position:center top;display:block;}

/* The slider and the two wide banners are not cards and keep their own
   behaviour. */
.slide .sm-video,.prod-hero-plate .sm-video,.super-media .sm-video{width:100%;height:auto;}
.super-media .sm-video{max-height:420px;border-radius:12px;}
.prod-hero-cropped .sm-video{height:100%;object-fit:cover;object-position:center top;}
.sm-video-wrap{position:relative;line-height:0;}
.sm-badge{position:absolute;left:10px;bottom:10px;display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:700;letter-spacing:.03em;color:#fff;background:rgba(0,0,0,.55);border:1px solid rgba(255,255,255,.18);border-radius:999px;padding:3px 9px;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);pointer-events:none;}

/* Media library / picker video tile */
.media-vid-badge{position:absolute;left:6px;bottom:6px;display:inline-flex;align-items:center;gap:4px;font-size:10.5px;font-weight:700;color:#fff;background:rgba(0,0,0,.62);border-radius:5px;padding:2px 6px;pointer-events:none;}
[data-media-capture][data-busy]{opacity:.55;pointer-events:none;}
.field-label{font-size:13px;font-weight:600;color:#374151;}
.field-label span{color:#ef4444;margin-left:2px;}
.field-input{background:#fff;border:1.5px solid #e5e7eb;border-radius:12px;padding:12px 16px;font-size:14px;font-family:'Inter',sans-serif;color:#0a0b0f;outline:none;transition:border-color .18s,box-shadow .18s;width:100%;}
.field-input::placeholder{color:#9ca3af;}
.field-input:focus{border-color:#131B94;box-shadow:0 0 0 3px rgba(19,27,148,.08);}
.field-select{background:#fff;border:1.5px solid #e5e7eb;border-radius:12px;padding:12px 16px;font-size:14px;font-family:'Inter',sans-serif;color:#0a0b0f;outline:none;transition:border-color .18s;width:100%;appearance:none;cursor:pointer;}
.field-select:focus{border-color:#131B94;box-shadow:0 0 0 3px rgba(19,27,148,.08);}
/* The chevron for .field-select, which sets appearance:none and so has no
   arrow of its own. These two rules were left behind in the Contact page
   template when the rest of the form's CSS moved here, so the component's
   two <select> fields rendered as plain boxes with no dropdown indicator
   anywhere the form is embedded other than /company/contact - the homepage
   being the one that does. */
.select-wrap{position:relative;}
.select-wrap::after{content:'';position:absolute;right:16px;top:50%;transform:translateY(-50%);width:0;height:0;border-left:4px solid transparent;border-right:4px solid transparent;border-top:5px solid #6b7280;pointer-events:none;}
.field-textarea{background:#fff;border:1.5px solid #e5e7eb;border-radius:12px;padding:12px 16px;font-size:14px;font-family:'Inter',sans-serif;color:#0a0b0f;outline:none;transition:border-color .18s,box-shadow .18s;width:100%;resize:vertical;min-height:120px;}
.field-textarea::placeholder{color:#9ca3af;}
.field-textarea:focus{border-color:#131B94;box-shadow:0 0 0 3px rgba(19,27,148,.08);}
.field-error{font-size:12px;color:#ef4444;display:none;}
.field-group.has-error .field-error,.field-error-shown{display:block;}
.field-group.has-error .field-input,.field-group.has-error .field-textarea{border-color:#ef4444;}
.budget-chip{position:relative;cursor:pointer;display:flex;align-items:center;gap:8px;background:#fff;border:1.5px solid #e5e7eb;border-radius:10px;padding:9px 14px;font-size:13px;font-weight:600;color:#374151;transition:all .15s;user-select:none;}
.budget-chip:hover{border-color:rgba(19,27,148,.3);color:#131B94;}
.budget-chip.selected{background:#131B94;border-color:#131B94;color:#fff;}
.svc-chip{position:relative;cursor:pointer;display:inline-flex;align-items:center;gap:6px;background:#fff;border:1.5px solid #e5e7eb;border-radius:8px;padding:7px 13px;font-size:12.5px;font-weight:600;color:#374151;transition:all .15s;user-select:none;}
.svc-chip:hover{border-color:rgba(19,27,148,.3);color:#131B94;}
.svc-chip.selected{background:#131B94;border-color:#131B94;color:#fff;}
.svc-chip-check{display:none;font-size:10px;}
.svc-chip.selected .svc-chip-check{display:inline;}
.chip-input{position:absolute;opacity:0;width:1px;height:1px;pointer-events:none;}
.svc-chip:has(.chip-input:checked),.budget-chip:has(.chip-input:checked){background:#131B94;border-color:#131B94;color:#fff;}
.svc-chip:has(.chip-input:checked) .svc-chip-check{display:inline;}
.svc-chip:has(.chip-input:focus-visible),.budget-chip:has(.chip-input:focus-visible){outline:2px solid #131B94;outline-offset:2px;}
/* The server-side class follows the box once Livewire re-renders; until
   then the checkbox decides, so an untick shows at once as well. */
.svc-chip.selected:has(.chip-input:not(:checked)),.budget-chip.selected:has(.chip-input:not(:checked)){background:#fff;border-color:#e5e7eb;color:#374151;}
.svc-chip.selected:has(.chip-input:not(:checked)) .svc-chip-check{display:none;}
.submit-btn{width:100%;background:#131B94;color:#fff;font-family:"Inter Tight",sans-serif;font-weight:700;font-size:15px;padding:15px 24px;border:none;border-radius:14px;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:9px;transition:background .2s,transform .18s,box-shadow .2s;}
.submit-btn:hover{background:#1e2ab5;transform:translateY(-1px);box-shadow:0 8px 24px rgba(19,27,148,.25);}
.submit-btn:active{transform:none;}
.submit-btn:disabled{background:#9ca3af;cursor:not-allowed;transform:none;box-shadow:none;}
.prog-dot{width:8px;height:8px;border-radius:50%;background:#e5e7eb;transition:background .3s;}
.prog-dot.active{background:#131B94;}
.prog-dot.done{background:#10B981;}
/* "Add more details (optional)" fold */
.cf-more{border:1px solid #e5e7eb;border-radius:12px;background:#fafafb;}
.cf-more-summary{list-style:none;display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 14px;cursor:pointer;font-size:13px;font-weight:600;color:#0a0b0f;}
.cf-more-summary::-webkit-details-marker{display:none;}
.cf-more-opt{font-weight:500;color:#6b7280;}
.cf-more-chev{width:16px;height:16px;color:#6b7280;transition:transform .2s ease;flex-shrink:0;}
.cf-more[open] .cf-more-chev{transform:rotate(180deg);}
.cf-more-body{padding:4px 14px 14px;display:flex;flex-direction:column;gap:16px;}
*,*::before,*::after{box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{font-family:'Inter',sans-serif;-webkit-font-smoothing:antialiased;overflow-x:hidden;}
h1,h2,h3,h4,h5,h6{font-family:'Inter Tight',sans-serif;}
img{max-width:100%;display:block;}
a{text-decoration:none;}
::-webkit-scrollbar{width:5px;}
::-webkit-scrollbar-track{background:#f0f0f5;}
::-webkit-scrollbar-thumb{background:#c7c7d4;border-radius:3px;}

/* ── Scrollbar-free horizontal strips ──
   scrollbar-hide comes from a Tailwind plugin this build does not load, so
   the class was inert everywhere it appeared: the sticky section nav on the
   long service pages and the category rail on /blog both showed a scrollbar
   under a 48px-high strip. It is used by three templates, so it lives here
   rather than being pasted into each of them. The element keeps its own
   overflow-x-auto; only the bar is hidden.                                */
.scrollbar-hide{-ms-overflow-style:none;scrollbar-width:none;}
.scrollbar-hide::-webkit-scrollbar{display:none;}

/* ── Stroke text for hero ── */
.stroke-text{-webkit-text-stroke:2.5px #131B94;color:transparent;}

/* ── Hero grid bg ── */
.hero-grid-bg{position:absolute;inset:0;pointer-events:none;background-image:linear-gradient(rgba(19,27,148,.04) 1px,transparent 1px),linear-gradient(90deg,rgba(19,27,148,.04) 1px,transparent 1px);background-size:48px 48px;-webkit-mask-image:radial-gradient(ellipse 80% 70% at 50% 30%,black 0%,transparent 80%);mask-image:radial-gradient(ellipse 80% 70% at 50% 30%,black 0%,transparent 80%);}

/* ── Animations ── */
@keyframes float{0%,100%{transform:translateY(0)}50%{transform:translateY(-10px)}}
@keyframes blink{0%,100%{opacity:1}50%{opacity:.3}}
/* Entrance animation. It no longer starts from opacity 0: a page's
   headline is usually its largest element, and a headline that starts
   invisible holds back the "largest paint" until the page's script has run
   and the fade has finished. It now slides in, fully visible throughout. */
@keyframes fadeUp{from{transform:translateY(14px)}to{transform:translateY(0)}}
@keyframes marquee{0%{transform:translateX(0)}100%{transform:translateX(-50%)}}
.float-a{animation:float 4s ease-in-out infinite;}
.float-b{animation:float 6s ease-in-out infinite 1s;}
.partner-blink{animation:blink 2s ease infinite;}
.marquee-track{animation:marquee 30s linear infinite;}
.fade-up{animation:fadeUp .6s ease forwards;}
.fade-up-1{animation:fadeUp .6s ease .1s forwards;}
.fade-up-2{animation:fadeUp .6s ease .2s forwards;}
.fade-up-3{animation:fadeUp .6s ease .3s forwards;}
.fade-up-4{animation:fadeUp .6s ease .4s forwards;}
@keyframes orbit1{from{transform:rotate(0deg) translateX(140px) rotate(0deg)}to{transform:rotate(360deg) translateX(140px) rotate(-360deg)}}
@keyframes orbit2{from{transform:rotate(120deg) translateX(110px) rotate(-120deg)}to{transform:rotate(480deg) translateX(110px) rotate(-480deg)}}
@keyframes orbit3{from{transform:rotate(240deg) translateX(160px) rotate(-240deg)}to{transform:rotate(600deg) translateX(160px) rotate(-600deg)}}
.orbit-1{transform-origin:210px 210px;animation:orbit1 12s linear infinite;}
.orbit-2{transform-origin:210px 210px;animation:orbit2 18s linear infinite;}
.orbit-3{transform-origin:210px 210px;animation:orbit3 22s linear infinite reverse;}
@media(prefers-reduced-motion:reduce){*,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important;}}

/* ── Marquee mask ── */
.marquee-mask{-webkit-mask-image:linear-gradient(90deg,transparent,black 12%,black 88%,transparent);mask-image:linear-gradient(90deg,transparent,black 12%,black 88%,transparent);}

/* ── Dot pattern ── */
.dot-pattern{position:absolute;inset:0;pointer-events:none;background-image:radial-gradient(rgba(255,255,255,.12) 1.5px,transparent 1.5px);background-size:22px 22px;-webkit-mask-image:radial-gradient(ellipse 60% 60% at 80% 50%,black,transparent);mask-image:radial-gradient(ellipse 60% 60% at 80% 50%,black,transparent);}

/* ── Industry grid ── */
.ind-2col{display:grid;grid-template-columns:repeat(2,1fr);gap:3px;}
.ind-item{display:flex;align-items:center;gap:7px;padding:7px 8px;border-radius:6px;border:1px solid transparent;color:#4b5563;font-size:12.5px;font-weight:500;text-decoration:none;transition:all .15s;}
.ind-item:hover{background:rgba(19,27,148,.06);border-color:rgba(19,27,148,.12);color:#131B94;}

/* ── Service card ──
 *
 * The base rule went missing when these pages were brought over from the
 * HTML designs. Only the accent bar below it made it across, and an accent
 * bar is the one part of the card that cannot work on its own: it is
 * position:absolute, so without position:relative on the card it anchored
 * itself to whatever was positioned further up the page, and with no
 * background, border, radius or padding the cards read as loose text on the
 * page background. Every industry page, the home page and three service
 * pages render this class, so all of them showed it.
 *
 * Copied from the HTML designs rather than rewritten: 71 of the 72 files
 * carry exactly these three rules, so this is the design, not an
 * approximation of it. display:flex with a column direction is what the
 * flex-1 on each card's paragraph needs to push the cards to equal height.
 */
.svc-card{position:relative;background:#fff;border:1px solid #e5e7eb;border-radius:18px;padding:24px;overflow:hidden;transition:transform .22s,box-shadow .22s,border-color .22s;display:flex;flex-direction:column;}
.svc-card:hover{transform:translateY(-4px);box-shadow:0 14px 36px rgba(19,27,148,.09);border-color:rgba(19,27,148,.2);}
.svc-card::after{content:'';position:absolute;top:0;left:0;right:0;height:3px;border-radius:18px 18px 0 0;background:linear-gradient(90deg,#131B94,#4a5fe8);transform:scaleX(0);transform-origin:left;transition:transform .3s;}
.svc-card:hover::after{transform:scaleX(1);}

/*
 * divide-x puts a left border on every child but the first. In a grid that
 * wraps, that means the first cell of every row after the first carries a
 * stray vertical line hanging off the left edge with nothing to its left.
 * It shows on the four-tile stat strips: two columns on a phone, so tile
 * three starts row two and drew a line at the container edge.
 *
 * Each block below removes it for the widths at which that grid is actually
 * two columns wide, using the class attribute to tell a grid that switches
 * at sm from one that switches at md from one that never switches.
 *
 * The [class] on each selector is not decoration. Tailwind's own rule is
 * `.divide-x > :not([hidden]) ~ :not([hidden])`, which scores exactly as
 * high as `.divide-x.grid-cols-2 > :nth-child(odd)`, and the Play CDN
 * injects its stylesheet at runtime, after this block. On a tie the later
 * rule wins, so without one more attribute selector to tip the score these
 * rules parse, match, and lose. */
@media (max-width:639.98px){
  .divide-x.grid-cols-2[class] > :nth-child(odd){border-left-width:0;}
}
@media (min-width:640px) and (max-width:767.98px){
  .divide-x.grid-cols-2[class]:not([class*="sm:grid-cols"]) > :nth-child(odd){border-left-width:0;}
}
@media (min-width:768px){
  .divide-x.grid-cols-2[class]:not([class*="sm:grid-cols"]):not([class*="md:grid-cols"]):not([class*="lg:grid-cols"]) > :nth-child(odd){border-left-width:0;}
}

/* Star row. Used by the testimonials hero, where the average rating is
 * printed as star characters; without this it inherits body colour and
 * reads as grey text rather than a rating. */
.stars{color:#f59e0b;letter-spacing:2px;font-size:13px;}

/* ── Project scroll stack ── */
.projects-sticky-container{position:relative;}
.project-sticky-card{position:sticky;top:80px;border-radius:20px;overflow:hidden;}

/* The picture panel of a stacked project card.
 *
 * Contained, not cropped, on a neutral plate: the whole screenshot is
 * meant to be readable, and a 570px panel next to a 340px column is not
 * the same shape as any upload, so cover would always be cutting
 * something off. The plate is the same light grey the listing cards use,
 * so a letterboxed picture reads as framed rather than as a gap.
 *
 * Nothing is layered on top of it. The tint that used to live here is
 * gone for good; if a project has no picture, the plate is replaced by a
 * placeholder gradient on the element itself rather than by a wash over
 * the image. */
.ps-media{display:flex;align-items:center;justify-content:center;overflow:hidden;background:#eef0f6;min-height:570px;}
.ps-media-sm{display:flex;align-items:center;justify-content:center;overflow:hidden;background:#eef0f6;aspect-ratio:16/10;}
.ps-media-img{width:100%;height:100%;object-fit:contain;display:block;}

/* ── Portfolio image zoom ── */
.port-img{transition:transform .5s ease;}
.port-card:hover .port-img{transform:scale(1.04);}
.blog-img{transition:transform .5s ease;}
.blog-card:hover .blog-img{transform:scale(1.04);}

/* ── Industries pill ── */
.ind-pill{display:inline-flex;align-items:center;gap:8px;background:#fff;border:1px solid #e5e7eb;border-radius:999px;padding:8px 18px 8px 10px;font-size:13.5px;font-weight:500;color:#374151;text-decoration:none;transition:all .2s;}
.ind-pill:hover{border-color:#131B94;color:#131B94;box-shadow:0 2px 12px rgba(19,27,148,.1);}
.ind-pill-icon{width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;}

/* ── Devicons sizing ── */
.devicon-sized::before,.devicon-sized{font-size:32px!important;}
.devicon-inline::before,.devicon-inline{font-size:16px!important;line-height:1;}

/* ── Compact tech pill (the component's "compact" variant) ──
   Same box the plain text tags in a card already had, with room for a
   16px mark. Lives here rather than in one page's head push because the
   component is site-wide. */
.tech-pill-sm{display:inline-flex;align-items:center;gap:6px;background:#f9fafb;border:1px solid #f3f4f6;border-radius:8px;padding:5px 10px;font-size:12px;font-weight:600;color:#374151;transition:border-color .18s;}
.tech-pill-sm:hover{border-color:rgba(19,27,148,.2);}

/* Sticky portfolio offsets */
.ps-1{top:88px;}.ps-2{top:96px;}.ps-3{top:104px;}.ps-4{top:112px;}.ps-5{top:120px;}
/* Devicon sizing */
.dev-icon{font-size:36px!important;}
/* Project card gradients */
.proj-grad-1{background:linear-gradient(135deg,#0f0a2e,#131B94);}
.proj-grad-2{background:linear-gradient(135deg,#49202b,#8a3d50);}
.proj-grad-3{background:linear-gradient(135deg,#0a2463,#1a5294);}
.proj-grad-4{background:linear-gradient(135deg,#1f3a1e,#2d5c2b);}
.proj-grad-5{background:linear-gradient(135deg,#1c1c3e,#3b3b7a);}
.proj-grad-6{background:linear-gradient(135deg,#14013a,#3a006f);}
.proj-grad-7{background:linear-gradient(135deg,#1a0a00,#7c3a00);}
.proj-grad-8{background:linear-gradient(135deg,#001a2e,#004d6e);}
.proj-grad-9{background:linear-gradient(135deg,#0d1a00,#2a4a00);}
.proj-grad-10{background:linear-gradient(135deg,#1a001a,#5a005a);}

/* ══════════════════════════════════════════════════════════════════
   EVERY MEDIA SLOT HOLDS ITS SHAPE
   ══════════════════════════════════════════════════════════════════
   These wrappers used to be un-boxed: each one took its height from
   whatever was inside it, so a picture rendered at its own proportions.
   That reads fine on one card and badly on a row of three, because a
   video and a photograph are almost never the same shape. A row ended up
   with its titles at three different heights and its "View case study"
   links scattered down the card.

   So every media slot now keeps a fixed shape and whatever sits in it
   fills that shape, image or video, on every listing on the site.

   TWO SHAPES, NOT ONE

     --card-media   the listing cards: Work, Products, Services, Solutions
                    and the More Work strip. 9:16, the shape of a phone
                    screen, because what goes in these slots is phone
                    mockups and screen recordings. A 9:16 video fills it
                    edge to edge with nothing cropped and no dark bands,
                    which is the whole reason for this number.

     --wide-media   the wider tiles that were always landscape: blog cards,
                    review cards, the industry case tiles and the product
                    page's screenshot plates.

   Change either line and every grid that uses it follows. That is the
   whole point of them being variables.

   The !important flags are load bearing: several templates put Tailwind's
   h-full / h-auto / object-cover straight on the tag, and a plain rule
   would lose to them. object-fit is deliberately NOT forced, so a record
   set to "Show the whole image" can still say object-contain and be
   obeyed. */
:root{
  --card-media:9/16;
  --wide-media:16/10;
}

.cs-thumb,
.prod-thumb,
.story-media{
  aspect-ratio:var(--card-media);
}

.rp-thumb{aspect-ratio:16/9;}
.feat-thumb{aspect-ratio:21/9;}
.blog-thumb,
.case-thumb,
.shot-frame,
.prod-shot{
  aspect-ratio:var(--wide-media);
}

.cs-thumb,
.prod-thumb,
.story-media,
.rp-thumb,
.blog-thumb,
.feat-thumb,
.case-thumb,
.shot-frame,
.prod-shot{
  display:block;
  overflow:hidden;
  line-height:0;
  min-height:0;
}

/* .work-thumb and .rw-thumb used to be here. They belonged to the
   hand-written work cards the service pages each carried a copy of: a fixed
   pixel height set per template, and an override to drag that tile back
   into line with every other card grid on the site. Those grids are the
   shared work card now, so there is nothing left to reconcile. */

/* Intermediate wrappers: several templates put a gradient div between the
   plate and the picture, and it has to pass the height through. */
.cs-thumb>*,
.prod-thumb>*,
.story-media>*,
.rp-thumb>*,
.blog-thumb>*,
.feat-thumb>*,
.case-thumb>*,
.shot-frame>*,
.prod-shot>*{
  height:100%;
}

/* Badges and gradient overlays are positioned, so they are exempt: giving
   them a height would stretch a pill into a bar.

   ── THIS LIST STOPPED BEING THE EXEMPTION ────────────────────────────────

   It is a hand-written list of badge class names, and the markup outgrew
   it. The blog archive's category badge is `.cat-badge`, and the case study
   cards' client badge is `.result-badge`. Neither name is below, so both
   were caught by the height:100% rule above, stretched to the full height
   of their thumbnail, and then rounded off by their own border-radius:999px
   into a tall white capsule down the left of the card with the label
   floating in the middle of it.

   That is a fault nothing reports. The page renders, the badge is present
   and readable, it is simply the wrong shape, on every article card and
   every case study card on the site.

   A list of names was always going to drift, because the fix is applied
   once and the badges keep being added. So the rule below it is keyed on
   what actually matters instead: a child positioned out of flow has no
   business being given the plate's height, and every one of these overlays
   carries Tailwind's `absolute`. The names stay for the handful of badges
   positioned by their own class rather than a utility. */
.cs-thumb>.absolute,
.prod-thumb>.absolute,
.story-media>.absolute,
.rp-thumb>.absolute,
.blog-thumb>.absolute,
.feat-thumb>.absolute,
.case-thumb>.absolute,
.shot-frame>.absolute,
.prod-shot>.absolute,
.cs-thumb>.cs-cat-badge,
.cs-thumb>.cs-result-badge,
.cs-thumb>.cs-thumb-overlay,
.cs-thumb>.sm-badge,
.story-media>.story-badge,
.story-media>.story-result,
.story-media>.sm-badge,
.prod-thumb>.cs-cat-badge,
.prod-thumb>.cs-thumb-overlay,
.prod-thumb>.sm-badge,
.shot-frame>.shot-caption,
.case-thumb>.case-badge{
  height:auto;

  /* And the line-height back.
   *
   * The plates above set line-height:0 to kill the descender gap under an
   * inline image, and every child inherits it, badges included. While the
   * badges were being stretched to the plate's full height that went
   * unnoticed: there was plenty of room for the text either way. Exempting
   * them from the height uncovered it, and the badge collapsed to six
   * pixels - its padding, with a zero-height line of text in the middle.
   *
   * So the two faults were hiding each other, which is why the badge only
   * ever looked wrong rather than broken. The picture does not need
   * line-height:0 any more in any case: the rule further down sets
   * display:block on every img and video in these plates, and a block image
   * has no descender gap to close. */
  line-height:1.45;
}

/* The picture itself, image or video, fills the slot it was given. */
.cs-thumb img, .cs-thumb video,
.prod-thumb img, .prod-thumb video,
.story-media img, .story-media video,
.rp-thumb img, .rp-thumb video,
.blog-thumb img, .blog-thumb video,
.feat-thumb img, .feat-thumb video,
.case-thumb img, .case-thumb video,
.shot-frame img, .shot-frame video,
.prod-shot img, .prod-shot video{
  display:block !important;
  width:100% !important;
  height:100% !important;
  max-height:none !important;
  position:static !important;
  transform:none !important;
  object-fit:cover;
  object-position:center top;
}

/* A VIDEO IS NEVER CROPPED.
   
   An image can lose its edges without losing its point, so it fills the
   slot. A video is a composition somebody framed, and cutting the sides off
   it is worse than a band of dark above and below. Both still occupy the
   same slot, so a row of cards lines up either way.
   
   This lives here rather than in the smart-media stylesheet because that
   one is printed earlier in the head, and the blanket rule above would
   otherwise win on source order alone. */
.cs-thumb video,
.prod-thumb video,
.story-media video,
.case-thumb video,
.blog-thumb video,
.feat-thumb video{
  object-fit:contain;
  object-position:center center;
}

/* The two wrappers whose own template asks for the whole picture keep it. */
.shot-frame img[class*="object-contain"],
.prod-shot img[class*="object-contain"],
.cs-thumb-fit img.cs-thumb-img{
  object-fit:contain;
}
.feat-thumb:not(:has(img)){aspect-ratio:21/9 !important;}

/* Overlays inside these plates are absolutely positioned against the
   wrapper, which needs a positioning context now that it is display:block. */
.rp-thumb,.blog-thumb,.feat-thumb,.case-thumb,.shot-frame,.prod-shot{position:relative;}

/* Project Cards (Work Page) */
.cs-card-wrap{transition:all .3s ease;}
.cs-card{display:flex;flex-direction:column;height:100%;background:#fff;border:1px solid #e5e7eb;border-radius:20px;overflow:hidden;box-shadow:0 4px 20px rgba(0,0,0,.03);transition:transform .2s ease,box-shadow .2s ease;}
.cs-card:hover{transform:translateY(-4px);box-shadow:0 12px 30px rgba(19,27,148,.08);border-color:rgba(19,27,148,.15);}
/* No fixed height: the tile grows to the screenshot so it is shown whole.
   .cs-thumb-cropped opts a single project back into a uniform tile. */
.cs-thumb{position:relative;width:100%;overflow:hidden;line-height:0;}
.cs-thumb-img{display:block;width:100%;height:auto;}
.cs-thumb-cropped{aspect-ratio:16/10;}
.cs-thumb-cropped .cs-thumb-img{height:100%;object-fit:cover;object-position:center top;}
.cs-thumb-empty{aspect-ratio:16/10;display:flex;align-items:center;justify-content:center;}
.cs-thumb-overlay{position:absolute;inset:0;background:linear-gradient(to top,rgba(0,0,0,.3) 0%,transparent 40%);}
.cs-cat-badge{position:absolute;top:12px;left:12px;display:inline-flex;align-items:center;gap:5px;font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;background:rgba(255,255,255,.18);color:#fff;border:1px solid rgba(255,255,255,.25);border-radius:999px;padding:4px 10px;backdrop-filter:blur(6px);-webkit-backdrop-filter:blur(6px);}
.cs-body{padding:22px 24px 24px;display:flex;flex-direction:column;flex:1;}
.cs-tags{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:14px;}
.cs-tag{display:inline-flex;align-items:center;gap:4px;font-size:11.5px;font-weight:600;border-radius:6px;padding:3px 9px;}
.cs-card-featured .cs-thumb-cropped{aspect-ratio:16/8;}

/* Filter pills */
.filter-pill{display:inline-flex;align-items:center;gap:5px;font-size:13px;font-weight:600;padding:7px 16px;border-radius:999px;border:1px solid #e5e7eb;background:#fff;color:#6b7280;cursor:pointer;transition:all .18s;white-space:nowrap;}
.filter-pill:hover{border-color:#131B94;color:#131B94;}
.filter-pill.active{background:#131B94;border-color:#131B94;color:#fff;}
.filter-pill.active .fp-count{background:rgba(255,255,255,.22);color:#fff;}
.fp-count{font-size:11px;font-weight:700;background:#f0f0f5;color:#6b7280;border-radius:999px;padding:1px 7px;transition:all .18s;}

/* Reveal on scroll */
.reveal{opacity:0;transform:translateY(22px);transition:opacity .55s ease,transform .55s ease;}
.reveal.visible{opacity:1;transform:translateY(0);}

/* Stats ticker */
.stat-item{text-align:center;padding:0 24px;border-right:1px solid rgba(19,27,148,.1);}
.stat-item:last-child{border-right:none;}

/* Featured label strip */
.featured-strip{display:inline-flex;align-items:center;gap:6px;font-size:10.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;color:#131B94;background:rgba(19,27,148,.08);border:1px solid rgba(19,27,148,.15);border-radius:4px;padding:3px 9px;margin-bottom:10px;}

/* Card hidden when filtered out */
.cs-card-wrap.hidden-by-filter{display:none;}

/* Single Case Study Elements */
.cs-section{padding-top:24px;border-top:1px solid rgba(0,0,0,.05);}
.cs-section:first-child{padding-top:0;border-top:none;}
.cs-bar{width:100%;height:6px;background:#f0f0f5;border-radius:999px;overflow:hidden;}
.cs-bar-fill{height:100%;border-radius:999px;width:0;transition:width 1s cubic-bezier(.16,1,.3,1);}
.cs-bar-fill.emerald{background:#10b981;}
.cs-bar-fill.rose{background:#f43f5e;}
.cs-bar-fill.violet{background:#8b5cf6;}
.cs-bar-fill.cyan{background:#06b6d4;}

/* ── Headings on a phone ──────────────────────────────────────────────
 *
 * Every heading that is genuinely large on a phone comes down to three
 * quarters of its size below 640px. The page reads the same; it just
 * stops shouting on a 390px screen, where a 36px headline was taking
 * three lines before the first word of the copy.
 *
 * WHY THIS IS A LIST AND NOT ONE RULE
 *
 * CSS cannot multiply a font size it has not been told. font-size:75%
 * and font-size:.75em both resolve against the PARENT, not against the
 * heading's own size, so either one would set most headings to about
 * 12px regardless of how big they were. The sizes have to be named, so
 * every size actually used on a heading in this codebase is named here.
 *
 * WHERE IT STOPS
 *
 * Only sizes of 20px and up are scaled. Three quarters of a 17px card
 * title is under 13px, which is smaller than the paragraph beneath it
 * and stops looking like a heading at all. Card titles are already sized
 * for a phone and are left alone.
 *
 * The element plus the class is what makes these win over the utility
 * without !important, whichever order the stylesheets land in, and it
 * also keeps the rule off the many non-heading elements that carry the
 * same size classes.
 */
@media (max-width:639.98px){
  h1.text-5xl,h2.text-5xl,h3.text-5xl,h4.text-5xl,h5.text-5xl,h6.text-5xl{font-size:36px;}
  h1.text-\[2\.5rem\],h2.text-\[2\.5rem\],h3.text-\[2\.5rem\],h4.text-\[2\.5rem\],h5.text-\[2\.5rem\],h6.text-\[2\.5rem\]{font-size:30px;}
  h1.text-\[2\.4rem\],h2.text-\[2\.4rem\],h3.text-\[2\.4rem\],h4.text-\[2\.4rem\],h5.text-\[2\.4rem\],h6.text-\[2\.4rem\]{font-size:28.8px;}
  h1.text-\[2\.3rem\],h2.text-\[2\.3rem\],h3.text-\[2\.3rem\],h4.text-\[2\.3rem\],h5.text-\[2\.3rem\],h6.text-\[2\.3rem\]{font-size:27.6px;}
  h1.text-4xl,h2.text-4xl,h3.text-4xl,h4.text-4xl,h5.text-4xl,h6.text-4xl{font-size:27px;}
  h1.text-\[2\.2rem\],h2.text-\[2\.2rem\],h3.text-\[2\.2rem\],h4.text-\[2\.2rem\],h5.text-\[2\.2rem\],h6.text-\[2\.2rem\]{font-size:26.4px;}
  h1.text-\[2\.1rem\],h2.text-\[2\.1rem\],h3.text-\[2\.1rem\],h4.text-\[2\.1rem\],h5.text-\[2\.1rem\],h6.text-\[2\.1rem\]{font-size:25.2px;}
  h1.text-\[2rem\],h2.text-\[2rem\],h3.text-\[2rem\],h4.text-\[2rem\],h5.text-\[2rem\],h6.text-\[2rem\]{font-size:24px;}
  h1.text-\[32px\],h2.text-\[32px\],h3.text-\[32px\],h4.text-\[32px\],h5.text-\[32px\],h6.text-\[32px\]{font-size:24px;}
  h1.text-\[1\.9rem\],h2.text-\[1\.9rem\],h3.text-\[1\.9rem\],h4.text-\[1\.9rem\],h5.text-\[1\.9rem\],h6.text-\[1\.9rem\]{font-size:22.8px;}
  h1.text-3xl,h2.text-3xl,h3.text-3xl,h4.text-3xl,h5.text-3xl,h6.text-3xl{font-size:22.5px;}
  h1.text-\[26px\],h2.text-\[26px\],h3.text-\[26px\],h4.text-\[26px\],h5.text-\[26px\],h6.text-\[26px\]{font-size:19.5px;}
  h1.text-\[1\.6rem\],h2.text-\[1\.6rem\],h3.text-\[1\.6rem\],h4.text-\[1\.6rem\],h5.text-\[1\.6rem\],h6.text-\[1\.6rem\]{font-size:19.2px;}
  h1.text-2xl,h2.text-2xl,h3.text-2xl,h4.text-2xl,h5.text-2xl,h6.text-2xl{font-size:18px;}
  h1.text-\[1\.5rem\],h2.text-\[1\.5rem\],h3.text-\[1\.5rem\],h4.text-\[1\.5rem\],h5.text-\[1\.5rem\],h6.text-\[1\.5rem\]{font-size:18px;}
  h1.text-\[22px\],h2.text-\[22px\],h3.text-\[22px\],h4.text-\[22px\],h5.text-\[22px\],h6.text-\[22px\]{font-size:16.5px;}
  h1.text-xl,h2.text-xl,h3.text-xl,h4.text-xl,h5.text-xl,h6.text-xl{font-size:15px;}
  h1.text-\[20px\],h2.text-\[20px\],h3.text-\[20px\],h4.text-\[20px\],h5.text-\[20px\],h6.text-\[20px\]{font-size:15px;}
}

/* Technology marks drawn as inline SVG (devicon_svg()), replacing the
   Devicon font. Sized by width/height attributes. */
.devicon-svg{display:inline-block;flex-shrink:0;vertical-align:middle;}

/* Hero image shapes on the service templates (were inline style attributes). */
.aspect-\[260\/460\]{aspect-ratio:260/460;}
.aspect-\[400\/440\]{aspect-ratio:400/440;}
.aspect-\[480\/420\]{aspect-ratio:480/420;}
.aspect-\[480\/380\]{aspect-ratio:480/380;}
