/* ─────────────────────────────────────────────────────────────────────────────
   Mobile corrections.

   Loaded after the theme's inline <style>, so equal-specificity rules win on
   order and !important is only used where the rule being corrected used it.
   ───────────────────────────────────────────────────────────────────────────── */

/* ══ MODALS ═══════════════════════════════════════════════════════════════════
   Every panel was sized in vh. On iOS Safari and Chrome for Android vh resolves
   to the viewport with the browser chrome RETRACTED, so a 95vh panel is taller
   than what you can actually see: the top of the card hides behind the URL bar
   and the bottom behind the toolbar, which is what the screenshots showed.

   dvh tracks the visible area as the chrome comes and goes. The vh line stays
   first as the fallback for anything that does not know dvh.                  */

.bo-lb__box      { height: 95vh; height: 95dvh; }
.bo-pipe-lb__box { max-height: 88vh; max-height: 88dvh; }
.bo-pipe-lb__card{ max-height: 86vh; max-height: 86dvh; }
.bo-pipe-lb__box video, .bo-pipe-lb__media video, .bo-pipe-lb__media img {
  max-height: 76vh !important; max-height: 76dvh !important;
}
.cpc-lb__box video { max-height: 76vh !important; max-height: 76dvh !important; }

/* The overlay itself keeps clear of the notch and the home indicator. */
.bo-lb, .cpc-lb, .bo-pipe-lb, .bp-modal {
  /* 28px, not 12: this is the gap that keeps the panel clear of the URL bar,
     and modal-ui.css sizes the panel against this box so the close pill below it
     is always on screen too. */
  padding-top:    max(28px, calc(env(safe-area-inset-top) + 20px));
  padding-bottom: max(12px, env(safe-area-inset-bottom));
  padding-left:   max(12px, env(safe-area-inset-left));
  padding-right:  max(12px, env(safe-area-inset-right));
}

/* Scrolling inside a modal was reaching the page behind it and then stopping
   at the ends. Contain it, and let the panel itself scroll when it is taller
   than the viewport. */
.bo-lb__box, .cpc-lb__box, .bo-pipe-lb__box, .bo-pipe-lb__card, .bp-modal__card {
  overscroll-behavior: contain;
  -webkit-overflow-scrolling: touch;
}

@media (max-width: 900px) {
  /* The close buttons used to be corrected here — three pushed outside the panel
     corner, the fourth pulled inside it. They are now relocated out of the panel
     entirely by modal-ui.js and styled as one pill by modal-ui.css, because
     hanging a child outside a scroll container is what clipped them and what put
     6px of horizontal scroll inside every modal. */

  /* A media lightbox on a phone was a 94vh black panel with a 16:9 video
     floated in the middle of it — two thick black bars and a small video. Let
     the panel take the height of what is in it, and put the close button on
     the media rather than on the bar above it. */
  .bo-lb__box {
    height: auto !important;
    width: min(96vw, 100%);
    justify-content: center;
  }
  .bo-lb__stage { flex: 0 1 auto !important; background: transparent !important; }
  .bo-lb__box video {
    height: auto !important;
    max-height: calc(100dvh - 150px) !important;
    object-fit: contain;
  }
  .bo-lb__box img { max-height: calc(100dvh - 150px) !important; }
  .cpc-lb__box, .bo-pipe-lb__box { overflow-y: auto; }
}

/* ══ #3 THE HERO'S 300px OF NOTHING ═══════════════════════════════════════════
   Measured on an iPhone 13: the CTA row ends at 868 and the logo strip starts
   at 1108 — 240px of empty black, from a 300px padding-bottom on the hero
   container that a desktop layout needs and a stacked one does not. */
@media (max-width: 900px) {
  .elementor-element-b4499db { padding-bottom: 140px !important; }
}

/* ══ #6 THE PLATFORM MARKS IN THE ONE-BUILDING CARD ═══════════════════════════
   "Files arrive", "The twin" and "Handover" each carried a Scope3D or Clickpad
   lockup beside the heading. On a phone the row wraps and the mark reads as
   part of the title. The step names carry it on their own. */
@media (max-width: 768px) {
  .exp-timelines .exp-logo { display: none !important; }
}

/* ══ #7 THE ONE-BUILDING PRODUCT TOGGLE ═══════════════════════════════════════
   The unselected half was unreadable. Three separate causes:

     - a blanket opacity:.55 on .exp-tab, which dims the fill, the border AND the
       wordmark together — the Clickpad indigo at 55% on a near-black pill is what
       made it vanish;
     - the theme fills .exp-tab with var(--jkd-border), 12.5% white on #1c1c1c;
     - the intended active tint here was dead code. .exp-tab.active is (0,2,0) and
       lost to the theme's .jkd-experience .exp-tabs .exp-tab.active at (0,4,0),
       so the selected half is green only because the ::after knob shows through
       the transparent button. That is fine, and is left alone.

   The ink follows the ground rather than the scheme. The knob is #00ff85 in BOTH
   schemes, so the selected half always wants the dark-ink artwork; the unselected
   half sits on the panel and follows the page theme like every other logo. */
.exp-tab.active .exp-tab-logo--dark        { display: none  !important; }
.exp-tab.active .exp-tab-logo--light       { display: block !important; }
.exp-tab:not(.active) .exp-tab-logo--dark  { display: block !important; }
.exp-tab:not(.active) .exp-tab-logo--light { display: none  !important; }
:root[data-color-scheme="light"] .exp-tab:not(.active) .exp-tab-logo--dark  { display: none  !important; }
:root[data-color-scheme="light"] .exp-tab:not(.active) .exp-tab-logo--light { display: block !important; }

.exp-tab {
  /* the stronger of the two border tokens, so the unselected half reads as a
     half rather than as empty track */
  border: 1px solid var(--jkd-border-active, rgba(255,255,255,.3));
  transition: border-color .2s ease, background-color .2s ease;
}
/* the theme's only hover rule changes `color`, and these buttons contain no text,
   so there was no hover feedback at all that this is a switch */
.exp-tab:not(.active):hover,
.exp-tab:not(.active):focus-visible {
  background-color: color-mix(in srgb, var(--jkd-heading) 15%, transparent) !important;
  border-color: rgb(var(--jkd-accent-rgb, 0,255,133)) !important;
}
.exp-tab.active,
.exp-tab[aria-selected="true"] {
  /* the knob supplies the fill; a border on top of it just draws a green line
     on green */
  border-color: transparent !important;
}

/* and the panel takes the height of its content rather than clipping it */
@media (max-width: 900px) {
  .exp-timelines, .exp-timelines .exp-timeline { height: auto !important; min-height: 0 !important; }
  .exp-timelines .exp-item { overflow: visible !important; }
}

/* ══ #2 FOOTER EXTERNAL LINKS ═════════════════════════════════════════════════
   The ↗ was a bare character, which several mobile fonts render as a coloured
   emoji arrow. It is a mask-image glyph now, inheriting the link's own colour,
   and the rows are set slightly tighter so they hold one line. */
.ft-nav a .bo-ext,
.bo-plat__link .bo-ext,
.bo-cta__ext.bo-ext {
  display: inline-block;
  width: .72em; height: .72em;
  margin-left: .32em;
  vertical-align: -.02em;
  background: currentColor;
  opacity: .62;
  -webkit-mask: var(--bo-ext-mask) center / contain no-repeat;
          mask: var(--bo-ext-mask) center / contain no-repeat;
}
.ft-nav a:hover .bo-ext { opacity: 1; }
:root {
  --bo-ext-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M7 17 17 7M9 7h8v8'/%3E%3C/svg%3E");
}
/* The three footer columns share 390px on a phone, which leaves each about
   110px for labels that measure up to 149px — "Scope3D pricing" was running
   50px past the viewport and being clipped. nowrap was making that worse, not
   better: the row cannot hold one line at this width, so let the columns take
   the full width and stack instead, and keep the type a touch smaller. */
@media (max-width: 900px) {
  .ft-nav a { font-size: .92em; letter-spacing: -.005em; white-space: normal; }
  .ft-bottom { flex-wrap: wrap; }
  .ft-bottom .ft-menu { flex: 1 1 46%; min-width: 46%; }
}
@media (max-width: 560px) {
  .ft-bottom .ft-menu { flex: 1 1 100%; min-width: 100%; }
}

/* The tail under the legal row, which on a phone is just dead space. The 50px
   it inherits is not declared against `.site-footer` anywhere greppable — the
   footer is assembled at runtime — so this is one of the few places !important
   is the honest tool rather than a shortcut. */
@media (max-width: 900px) {
  footer.site-footer, .site-footer { padding-bottom: 24px !important; }
}

/* ══ #5 THE MOBILE DRAWER'S BOTTOM ════════════════════════════════════════════
   The overlay was 100vh, so its last row — the social icons — sat under
   Chrome's toolbar and the LinkedIn mark was never reachable. dvh plus the
   safe-area inset gives it back, and the cloned theme toggle sits above it. */
#nav-bar .nav-overlay {
  height: 100vh; height: 100dvh;
  max-height: 100vh; max-height: 100dvh;
  padding-bottom: calc(18px + env(safe-area-inset-bottom));
  overflow-y: auto;
  overscroll-behavior: contain;
}

/* ══ CASE STUDY: THE FRAME MOVES TO THE STORY IT ILLUSTRATES ══════════════════
   The single screenshot or clip used to sit in the Summary beside a two-
   sentence precis; it now sits above the Overview body, which is where the
   thing it shows is actually described. The Summary keeps a way in. */
.project-content .bo-ovm--article { margin: 22px 0 26px; }
.project-content .content-top { scroll-margin-top: 96px; }
.bo-readmore { margin-top: 22px; }
@media (max-width: 900px) {
  .bo-readmore { margin-top: 18px; width: 100%; justify-content: center; }
  /* the nav is 80px from the top un-scrolled at this width, 65 scrolled */
  .project-content .content-top { scroll-margin-top: 84px; }
  .project-content .bo-ovm--article { margin-bottom: 20px; }
}

/* The drawer's close, taken off the animation's critical path. !important is
   deliberate: gsap animates `opacity` as an inline style, and an inline
   declaration is exactly what an author !important is defined to beat.

   pointer-events:none on the overlay alone does NOT do it. The theme carries
   `#nav-bar .nav-overlay .menu-item.is-active{pointer-events:auto!important}`,
   so the children opt themselves back in and keep catching taps through a
   parent that has opted out — measured: with the parent at none and opacity 0,
   elementFromPoint at the centre of the screen still returned a menu <a>.
   Hence the descendant rules, the last of which is (1,4,0) against the theme's
   (1,3,0) so it actually wins, and `visibility` as the backstop: it is
   inherited and cannot be opted out of the same way. It flips only after the
   fade, via a 0s transition with a delay, so the close still animates. */
#nav-bar .nav-overlay.bo-drawer-closing {
  opacity: 0 !important;
  visibility: hidden !important;
  transition: opacity .16s ease, visibility 0s linear .16s !important;
}
#nav-bar .nav-overlay.bo-drawer-closing,
#nav-bar .nav-overlay.bo-drawer-closing *,
#nav-bar .nav-overlay.bo-drawer-closing .menu-item.is-active {
  pointer-events: none !important;
}

/* ══ THE DRAWER'S THEME TOGGLE ════════════════════════════════════════════════
   Ported verbatim from the main branch, markup and rules both, so the two sites
   share one control rather than two that drift. The theme binds every
   [data-color-scheme-toggle] at init and syncs their aria-pressed and .is-light
   together, so a second one in the drawer needs no JavaScript of its own. */
#nav-overlay .builtos-drawer-theme{display:flex;align-items:center;justify-content:center;gap:14px;margin:0 0 20px}
#nav-overlay .builtos-drawer-theme__label{font-size:15px;font-weight:500;opacity:.85;letter-spacing:.01em;color:var(--jkd-heading)}
#nav-overlay .builtos-drawer-theme .jkd-scheme-toggle{display:flex!important;align-items:center;justify-content:center;cursor:pointer;border:none!important;box-shadow:none!important;outline:none!important;padding:0;opacity:1!important;visibility:visible!important}
#nav-overlay .builtos-drawer-theme .scheme-toggle-track{align-items:center;background:var(--jkd-border);border-radius:100px;display:flex;flex-shrink:0;height:26px;padding:0 3px;position:relative;transition:background .35s ease;width:48px}
#nav-overlay .builtos-drawer-theme .scheme-toggle-knob{align-items:center;background:var(--jkd-inverted);border-radius:50%;display:flex;flex-shrink:0;height:20px;justify-content:center;position:relative;transform:translateX(0);transition:transform .4s cubic-bezier(.34,1.4,.64,1),background .35s ease;width:20px}
#nav-overlay .builtos-drawer-theme .scheme-icon{color:var(--jkd-bg);position:absolute;transition:opacity .22s ease,transform .3s cubic-bezier(.34,1.4,.64,1)}
#nav-overlay .builtos-drawer-theme .scheme-icon--moon{height:12px;width:12px;opacity:1;transform:scale(1) rotate(0deg)}
#nav-overlay .builtos-drawer-theme .scheme-icon--sun{font-size:12px;line-height:1;opacity:0;transform:scale(0) rotate(-45deg)}
#nav-overlay .builtos-drawer-theme .jkd-scheme-toggle.is-light .scheme-toggle-knob{transform:translateX(22px)}
#nav-overlay .builtos-drawer-theme .jkd-scheme-toggle.is-light .scheme-icon--moon{opacity:0;transform:scale(0) rotate(45deg)}
#nav-overlay .builtos-drawer-theme .jkd-scheme-toggle.is-light .scheme-icon--sun{opacity:1;transform:scale(1) rotate(0deg)}
/* ══ A BLOG POST THAT HAS A CLIP PLAYS IT ═════════════════════════════════════
   Eight of the thirteen posts describe something the demo library actually
   shows, and those swap their stock photograph for that clip. It inherits the
   figure's own shape so nothing else about the header moves, and carries
   data-bo-autoplay rather than autoplay, so video-perf.js holds it at its
   poster until it is on screen. The other five keep the photograph — no clip
   in the library shows a QR tag being scanned or a text message arriving. */
.post-thumbnail__vid {
  display: block;
  width: 100%;
  height: auto;
  border-radius: inherit;
  background: #0b0d0c;
}

/* ══ THE PHASE DOTS KEEP THEIR COLOUR ═════════════════════════════════════════
   Forced :hover on the selected dot, measured: background goes from the accent
   to rgba(127,127,127,.12) while the text stays --jkd-on-accent, which is
   #0f0f0f. Near-black on a grey wash over a dark page is the "impossible to
   read" — and on a phone a tap leaves :hover stuck there afterwards, so it is
   the state you are left looking at rather than one you pass through.

   The selected dot now holds the accent through hover, focus and active. */
.jkd-process-steps .steps-nav .step-dot.is-active,
.jkd-process-steps .steps-nav .step-dot.is-active:hover,
.jkd-process-steps .steps-nav .step-dot.is-active:focus,
.jkd-process-steps .steps-nav .step-dot.is-active:focus-visible,
.jkd-process-steps .steps-nav .step-dot.is-active:active {
  background-color: var(--jkd-accent) !important;
  border-color: var(--jkd-accent) !important;
  color: var(--jkd-on-accent) !important;
}
/* and where there is no real pointer, an unselected dot should not keep a
   hover skin it can never leave */
@media (hover: none) {
  .jkd-process-steps .steps-nav .step-dot:not(.is-active):hover {
    background-color: transparent;
    border-color: var(--jkd-border);
    color: var(--jkd-heading);
  }
}

/* ══ THE EXPAND ICON BECOMES A REAL TARGET ════════════════════════════════════
   .bmd__play is pointer-events:none, so a tap anywhere on a card — the icon
   included — lands on the <video> and the whole card behaves as one button.
   That is why "tap to pause" and "tap the expand icon" could not both be had:
   there was only ever one target.

   On touch the icon takes its own hits. A tap on it bubbles to the
   [data-bo-open] button and opens the lightbox, exactly as before; a tap
   anywhere else on the picture reaches the video, where mobile-fix.js pauses it
   rather than opening anything. Pointer devices are untouched — there the
   whole card opens, which is what a cursor and a hover state already promise. */
@media (hover: none) {
  .bmd__play { pointer-events: auto !important; }
}

/* sound: the mute button is always there (founder, 2026-11-02: "make sure it always exists like the
   stock theme has"). The theme hides the sound cell at 1024px and below; main.min.js?v=2 also starts
   the sound module on phones, so the button works there. */
@media(max-width:1024px){#nav-bar .jkd-sound-toggle{display:flex!important;width:50px;margin-right:0}}

/* ══ CONTRAST: EVERY WORD READS IN BOTH THEMES (CT-1, 2026-11-03) ═════════════
   The founder, on /contact/ in the light theme: "fix ugly ass things like this
   all around where we cant see the text unless i highlight it". Two kinds of bug
   did it, both site-wide; scripts/check-contrast.mjs measures every text node on
   every page in light and dark at 1440 and 390 and fails on either:
     (a) a colour written for one theme that survives into the other, and muted
         text faded with opacity until it sat under WCAG AA (4.5:1, 3:1 large);
     (b) text laid straight over a photo, video or canvas with no backing.
   The fixes are here, in the one stylesheet every page loads, so each one covers
   every page that uses the pattern.                                          */

/* (a) The theme mutes text with opacity (.62 / .82) on top of --jkd-text, which
   was already at the AA line (#6e6e73 on #f5f5f7 is 4.69:1), so every footer
   label, date, breadcrumb and count fell under it. The scale stays, one step
   firmer, and the light grey a step darker, so muted still reads as muted.    */
:root { --jkd-op-md: .8; --jkd-op-sm: .9; --jkd-text: #a3a3a3; }
:root[data-color-scheme="light"] { --jkd-op-md: .9; --jkd-op-sm: .95; --jkd-text: #55555b; }
[data-color-scheme="light"] [data-color-scheme="dark"] { --jkd-op-md: .8; --jkd-op-sm: .9; --jkd-text: #a3a3a3; }

/* (b) Page headers: white words on a photo or film under a 15% black wash. A
   scrim from the foot, where the words sit, keeps the picture and makes the
   words read on any frame of it.                                              */
.page-header:not(.no-bg) .page-header__inner:after {
  opacity: 1 !important;
  background: linear-gradient(to top, rgba(0,0,0,.78) 0%, rgba(0,0,0,.66) 55%, rgba(0,0,0,.5) 100%) !important;
}

/* (b) The "One operating system for every building you own" band before every
   footer: white words on a photo under a 30% green wash. The wash goes to 82%,
   so the photo shows through as texture and the band reads as deep green; the
   line under the heading drops its fade.                                      */
html body .elementor-1966 .elementor-element.elementor-element-0a59bc3 { --overlay-opacity: .82; } /* post-1966.css loads after this file */
html body .elementor-1966 .elementor-element.elementor-element-d4e2b80 { color: rgba(255,255,255,.9); }

/* /contact/: the "Tell us about your property" card floats over the Scope3D
   tour with no backing (dark words on the film in light, white in dark). It
   becomes a panel in the theme's own surface colour, frosted over the film.   */
/* The founder: "sexify the tell us about your property section": a floating glass card over the film, with a
   scrim under it so the film never fights the words, an eyebrow, a bigger headline and a reply-time chip. */
.elementor-118 .elementor-element.elementor-element-1071aac {
  max-width: 440px;
  padding: 26px 28px 24px !important; gap: 10px !important;
  background: rgba(18,20,19,.82);
  -webkit-backdrop-filter: blur(18px) saturate(1.3); backdrop-filter: blur(18px) saturate(1.3);
  border: 1px solid rgba(255,255,255,.12); border-radius: 18px;
  box-shadow: 0 24px 60px rgba(0,0,0,.35); background-image: none !important;
}
.elementor-118 .elementor-element-1071aac::before, .elementor-118 .elementor-element-1071aac::after { display: none !important; }

.elementor-118 .elementor-element-81a7769 .elementor-heading-title {
  font-size: clamp(26px, 2.4vw, 34px) !important; line-height: 1.08 !important; letter-spacing: -.02em; color: #fff !important;
}
.elementor-118 .elementor-element-9d5e793, .elementor-118 .elementor-element-9d5e793 p {
  font-size: 15px !important; line-height: 1.55 !important; color: rgba(255,255,255,.82) !important;
}
.elementor-118 .elementor-element-9d5e793 p::after {
  content: "Replies within 24 hours · Mon–Fri ET"; display: block; width: fit-content; margin-top: 14px;
  font-size: 12.5px; font-weight: 600; color: #fff; padding: 7px 12px; border-radius: 999px;
  background: rgba(255,255,255,.1); border: 1px solid rgba(255,255,255,.14);
}
:root[data-color-scheme="light"] .elementor-118 .elementor-element.elementor-element-1071aac {
  background: rgba(255,255,255,.9); border-color: rgba(0,0,0,.08); box-shadow: 0 24px 60px rgba(20,22,26,.18);
}
:root[data-color-scheme="light"] .elementor-118 .elementor-element-81a7769 .elementor-heading-title { color: #14161a !important; }
:root[data-color-scheme="light"] .elementor-118 :is(.elementor-element-9d5e793, .elementor-element-9d5e793 p) { color: #44464d !important; }
:root[data-color-scheme="light"] .elementor-118 .elementor-element-9d5e793 p::after { color: #14161a; background: #f2f3f1; border-color: rgba(0,0,0,.08); }
@media (max-width: 767px) { .elementor-118 .elementor-element.elementor-element-1071aac { padding: 20px 20px 18px !important; max-width: none; } }
/* /contact/: the four info cards' values were #FFFFFF99, which in light is
   white on the light grey page.                                               */
:root[data-color-scheme="light"] .elementor-118 :is(.elementor-element-7942147, .elementor-element-86c0beb, .elementor-element-a39f97d, .elementor-element-f99a46e),
:root[data-color-scheme="light"] .elementor-118 :is(.elementor-element-7942147, .elementor-element-86c0beb, .elementor-element-a39f97d, .elementor-element-f99a46e) a { color: var(--jkd-text); }

/* (a) The brand green #00ff85 is a dark-theme ink: on the light page it is
   about 1.3:1, a colour you can see but words you cannot read. In light, green
   WORDS take a deep ink of the same green (5.7:1 on #f5f5f7); green fills,
   dots and rules keep #00ff85.                                                */
:root { --ct-green-ink: #00703f; }
:root[data-color-scheme="light"] .post-details .post-navigation .nav-subtitle,
:root[data-color-scheme="light"] .entry-content a:not(.wp-block-button__link):not(.wp-block-file__button):not(.post-page-numbers):not(.tag-cloud-link):not(.button,.tag-item),
:root[data-color-scheme="light"] .jkd-counter .counter-suffix,
:root[data-color-scheme="light"] body #page-agent :is(.bb-eye, .bb-n, .bb-micro, .bb-lbl--live),
:root[data-color-scheme="light"] body .bo-plat__link { color: var(--ct-green-ink); }
:root[data-color-scheme="light"] body #page-agent .bb-lbl--next { color: #8a4f00; }
/* one .bb-micro carries its green in a style attribute */
:root[data-color-scheme="light"] body #page-agent .bb-micro[style*="--jkd-accent"] { color: var(--ct-green-ink) !important; }
/* the pricing calculator's green words, the same way */
:root[data-color-scheme="light"] .bo-pr :is(td.b, .bo-pr__bandbtn, .bo-pr__line--keep .bo-pr__k, .bo-pr__list mark,
  .bo-pr__list i, .bo-pr__none a, .bo-pr__picked em, .bo-pr__prod input:checked + span small,
  .bo-pr__seg--stack input:checked + span em, .bo-pr__stats dt, .bo-pr__terms a,
  .bo-pr__tiers3 input:checked + span small, .bo-pr__eyebrow) { color: var(--ct-green-ink); }
:root[data-color-scheme="light"] .bo-pr td[style*="--pr-accent"] { color: var(--ct-green-ink) !important; }
/* light-theme green buttons with white words: #00994f is 3.3:1, this is 5.4:1 */
:root[data-color-scheme="light"] body .bo-cta--primary { background: #007a40; border-color: #007a40; }

/* (a) The pricing calculator's third ink was 40% white / 44% black. (pricing.css
   loads after this file, hence the extra weight.)                            */
html body .bo-pr { --pr-ink-2: rgba(255,255,255,.74); --pr-ink-3: rgba(255,255,255,.6); }
:root[data-color-scheme="light"] body .bo-pr { --pr-ink-2: rgba(13,15,14,.78); --pr-ink-3: rgba(13,15,14,.68); }

/* (a) testimonial bylines under the theme's 42% fade */
html body .jkd-testimonials .author-sub { opacity: .8; }

/* (b) Case-study film tiles: the caption sat on a scrim that only reached 65%
   at the very foot. It now starts higher and ends darker.                     */
html body .bmd__scrim { opacity: 1; background: linear-gradient(180deg, transparent 35%, rgba(0,0,0,.86) 100%); }
html body .bmd__dur { color: rgba(255,255,255,.86); }
/* (b) the "Video" badge on a playing portfolio tile: a pill of its own */
.project-media .media-type {
  background: rgba(10,12,11,.72); color: #fff; padding: 6px 10px; border-radius: 999px;
  -webkit-backdrop-filter: blur(6px); backdrop-filter: blur(6px);
}
/* (b) the scroll-progress ring floats over every film and photo on the page:
   give its number a disc in the page colour.                                 */
.scroll-top .scroll-top__circle { background: var(--jkd-bg); border-radius: 50%; }
.scroll-top .scroll-top__number { opacity: 1; }

/* (a) /clickpad/click/: the iMessage mock. iOS's own blue (#08f) under white
   words is 3.3:1 and its greys are 3:1 or less; a deeper blue and firmer
   greys keep the look and read.                                              */
html body #page-agent .bb-bub--you,
html body #page-agent .bb-bub--you.bb-bub--tail::before { background-image: linear-gradient(#0a6cf0, #0055c4); }
html body #page-agent .bb-bub--you.bb-bub--tail { background-image: none; }
html body #page-agent .bb-lnk { color: #0058c4; }
html body #page-agent .bb-bub--you .bb-lnk { color: #fff; }
html body #page-agent .bb-stamp { color: rgba(60,60,67,.78); }
html body #page-agent .bb-receipt { color: rgba(60,60,67,.78); }
html body #page-agent .bb-field { color: rgba(60,60,67,.72); }
html body #page-agent .bb-field--typed { color: var(--bb-ink); }

/* (a) Home page: small print faded to 40-58% under the theme's own grey. */
html body .bo-cap__d { opacity: .72; }
html body .bo-step__d, html body .bo-band__sub { opacity: .8; }
html body .bo-step__n { opacity: .8; }
:root[data-color-scheme="light"] body .bo-step__n { opacity: 1; }
html body .bo-more { opacity: .8; }
html body .bhd__count, html body .bhd__hint { opacity: .78; }
html body .jkd-process-steps .steps-nav .step-dot .bo-step-n { opacity: .78; }
html body .jkd-process-steps .steps-nav .step-dot.is-active .bo-step-n { opacity: .9; }
/* the four Homes steps: the ones not playing dimmed to 62%, words and all */
html body .bo-hcard { opacity: .86; }
html body .bo-hcard__tool { color: rgba(20,22,26,.7); }
html body .bo-hcard__d { color: rgba(20,22,26,.78); }
:root:not([data-color-scheme="light"]) body .bo-hcard__tool { color: rgba(255,255,255,.7); }
:root:not([data-color-scheme="light"]) body .bo-hcard__d { color: rgba(255,255,255,.78); }
:root[data-color-scheme="light"] body .bo-hcard__n,
:root[data-color-scheme="light"] body .bo-band--homes .bo-step__n { color: #c8102e; }
/* the Clickpad carousel was written white-on-dark; in light its heading sat
   white on the light page while the card labels went dark on dark photos   */
:root[data-color-scheme="light"] body .cpc__head { color: var(--jkd-heading); }
html body .cpc__eyebrow { opacity: .78; }
html body .cpc__card, html body .cpc__card .cpc__label, html body .cpc__card .cpc__watch { color: #fff; }
html body .cpc__card .cpc__watch { opacity: 1; }
/* Scope3D's blue words in light */
:root[data-color-scheme="light"] body .bo-layers__base { color: #0047c7 !important; }
:root[data-color-scheme="light"] body .bo-slab__tag { color: #0047c7; }

/* The founder (2026-11-04, a phone): the stats strip's top and bottom rules sat right on the numbers and the
   location line. The strip (3b8a71e) has the borders and no padding; give it room on phones and tablets. */
@media (max-width: 1024px) {
  .elementor-64 .elementor-element.elementor-element-3b8a71e { padding-top: 22px !important; padding-bottom: 18px !important; row-gap: 14px !important; }
  /* The strip was pinned (absolute) to the hero's foot with a fixed padding reserved for it, so on a phone with
     larger text it grew up over Book a Call. On phones and tablets it now sits in the flow after the buttons. */
  .elementor-64 .elementor-element.elementor-element-3b8a71e { position: relative !important; inset: auto !important; bottom: auto !important; top: auto !important; margin-top: 44px !important; width: 100% !important; order: 99 !important; }
  .elementor-64 .elementor-element.elementor-element-b4499db { padding-bottom: 0 !important; }
}

/* ══ #8 FOOTER AND HEADER TAPS ON A PHONE (BC-LOOK, v6) ═══════════════════════
   Measured at 390 on every Commercial page: each footer link was 20px tall at a
   27px pitch, the email and phone 22px, LinkedIn 24px, the asterisk 30px, and the
   drawer's theme switch 48x26 and LinkedIn 20px. Rows are 44px now; to keep the footer from growing
   by a third, the four link columns sit two by two (the longest label, "BuiltOS
   Commercial", is 147px and each column has 165px). Small icons keep their look
   and get a 44px hit area. */
@media (max-width: 767px) {
  .ft-bottom .ft-menu { flex: 1 1 calc(50% - 12px) !important; min-width: 0 !important; }
  #site-footer .ft-nav li { margin: 0 !important; padding: 0 !important; }
  #site-footer .ft-nav a { display: flex; align-items: center; min-height: 44px; padding: 0; line-height: 1.25; }
  #site-footer .ft-contact-block .ft-value { display: inline-flex; align-items: center; min-height: 44px; }
  #site-footer .ft-cta, #site-footer .social-item, #nav-bar .social-item, .jkd-scheme-toggle { position: relative; }
  #site-footer .ft-cta::after, #site-footer .social-item::after, #nav-bar .social-item::after { content: ""; position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); }
  .jkd-scheme-toggle::after { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 44px; transform: translateY(-50%); }
}
