/* ============================================================
   Carousel — production layer
   Static replacements for design-time <image-slot> placeholders.
   .islot mirrors the layout rules the design CSS applies to the
   custom element (renamed to .islot by tools/build-home.py).
   ============================================================ */

/* ------------------------------------------------------------------
   "Living painting" treatment for the decorative loops.

   A canvas weave sits over the footage and stays FIXED TO THE SCREEN
   while the scene moves underneath it — that mismatch is what makes the
   eye read paint instead of video. Multiply blend so it darkens into the
   image rather than hazing over it; `isolation` keeps the blend from
   reaching the cream page behind.

   Values tuned by Charles against the 15s hero: weave 180px at 0.06,
   vignette off, playback 0.80x (that last part lives in media.js).
   Deliberately barely-there — at 0.06 you should feel it, not see it.
   ------------------------------------------------------------------ */
.yc-hero-vid,
.foot-art{isolation:isolate}
.yc-hero-vid::before,
.foot-art::after{
  content:"";
  position:absolute;
  inset:0;
  z-index:0;
  background-image:url("/assets/img/canvas-weave.webp");
  background-size:180px;
  background-repeat:repeat;
  mix-blend-mode:multiply;
  opacity:.06;
  pointer-events:none;
}
/* the cream fade must stay on top of the weave in both places */
.yc-hero-vid::after{z-index:1}

.art-ph{background:linear-gradient(160deg,#F3EFE6,#EAE4D6)}
span.islot{display:block}
img.islot{display:block;object-fit:cover}
.hw-shot>img.islot{border-radius:14px}

/* customer-story tiles: typographic wordmarks until real logos land */
.cst-txt{display:flex;align-items:center;justify-content:center;width:100%;height:100%;color:var(--ink-soft);white-space:nowrap}
.cst-txt.v-serif{font-family:var(--serif);font-weight:460;font-size:clamp(20px,2.2vw,30px);letter-spacing:-.01em}
.cst-txt.v-serif2{font-family:var(--serif);font-style:italic;font-weight:430;font-size:clamp(20px,2.2vw,30px)}
.cst-txt.v-sans{font-family:var(--sans);font-weight:700;font-size:clamp(17px,1.9vw,25px);letter-spacing:-.01em}
.cst-txt.v-caps{font-family:var(--sans);font-weight:700;font-size:clamp(15px,1.7vw,22px);letter-spacing:.14em}
.cst-txt.v-mono{font-family:var(--mono);font-weight:600;font-size:clamp(14px,1.6vw,20px);letter-spacing:.08em}

/* Language menu checkmark. The design rule uses float:right, but the anchor's
   subtitle <span> is display:block — so the float lands in the last line box,
   sitting beside "Canada / US" instead of centred on the row. */
.lang-menu a { position: relative; padding-right: 34px }
.lang-menu a.active::after {
  float: none; position: absolute; top: 50%; right: 13px;
  transform: translateY(-50%); line-height: 1;
}

/* Footer brand block on small screens. The design's row treatment wraps the
   social circles and the "Montréal, Québec" label onto one composite row,
   vertically misaligned. Stack the four pieces instead. */
@media (max-width:760px){
  .foot-brand { display: block }
  .foot-brand p { margin-top: 10px }
  .foot-brand .foot-social { margin-top: 18px }
  .foot-brand .foot-place { margin-top: 18px }
}

/* Collapsed code blocks (docs). code-collapse.js wraps any long .dc-body pre
   in .clp; the cap here must match CAP in that script. */
.clp { position: relative; margin: 0 0 1.2em }
.clp pre { max-height: 340px; overflow: hidden; margin: 0 }
.clp.open pre { max-height: none; overflow-x: auto }
.clp::before {
  /* fade the preview into the block's own dark background */
  content: ""; position: absolute; left: 0; right: 0; bottom: 44px; height: 90px;
  background: linear-gradient(to bottom, rgba(26,23,20,0), var(--ink, #1a1714));
  border-radius: 0 0 14px 14px; pointer-events: none;
}
.clp.open::before { display: none }
.clp .clp-btn {
  display: block; width: 100%; font-family: var(--mono, monospace);
  font-size: 12.5px; font-weight: 500; letter-spacing: .1em; text-transform: uppercase;
  color: #EDE7DA; background: var(--ink, #1a1714); border: 0; border-top: 1px solid rgba(237,231,218,.14);
  border-radius: 0 0 14px 14px; padding: 13px 0 15px; cursor: pointer;
}
.clp .clp-btn:hover { color: #fff }
.clp pre:first-child { border-radius: 14px 14px 0 0 }

/* Docs tile cards. The shell's inline-link rule (.dc-body a — specificity
   0,1,1) styles text links with a terra underline and padding-bottom:1px;
   the tiles are also <a> inside .dc-body, so it crushed their bottom padding
   to 1px and repainted their bottom border. Outrank it, both states. */
.dc-body a.dc-tile { padding-bottom: clamp(18px, 2vw, 24px); border-bottom: 1px solid var(--line-2) }
.dc-body a.dc-tile:hover { border-bottom-color: var(--muted-2) }

/* Mobile drawer: two-column link lists (Charles, 2026-08-08). The open/close
   animation runs on .m-acc-body's grid-template-rows, so the inner list can be
   its own grid. Group headings (Resources) span both columns. */
@media (max-width: 1000px){
  .m-acc-inner { display: grid; grid-template-columns: 1fr 1fr; column-gap: 10px }
  .m-acc-inner .m-grp-h { grid-column: 1 / -1 }
}

/* Drawer link tap-highlight: the design's 10px radius reads square on the
   wide two-column rows; the drawer's own CTAs right below are full pills. */
.mobile-nav .m-acc-body a { border-radius: 999px }

/* Drawer refinements (Charles, 2026-08-08):
   1) The design bleeds link pills past the column edge (margin:0 -10px), which
      reads as broken padding next to the group headings — inset them instead.
   2) Section buttons carry a leading icon (injected at build time); the button
      keeps its space-between layout by pushing the +/- toggle right. */
.mobile-nav .m-acc-body a { margin: 0 !important; padding: 13px 14px !important }
.mobile-nav .m-grp-h { padding-left: 14px }
.m-acc-btn { justify-content: flex-start; gap: 13px }
.m-acc-btn .m-tog { margin-left: auto }
.m-acc-btn .m-ico { display: grid; place-items: center; flex: 0 0 auto; color: #A9A296 }
.m-acc-btn .m-ico svg { width: 21px; height: 21px }

/* Desktop nav icons tried and removed (Charles, 2026-08-08) — the drawer
   keeps its icons; the desktop buttons are text-only. The .d-ico markup is
   still injected by the build, just never shown. */
.menu-item > button .d-ico { display: none }

/* ---- Blog (production-generated from the editorial pipeline) ---- */
.bl-art img, .bp-cover-in img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block }
.bp-av-mono { display: grid; place-items: center; font-family: var(--mono); font-size: 12px; font-weight: 600; color: var(--terra, #3F5B4C) }
.bp-body table { width: 100%; border-collapse: collapse; margin: clamp(26px, 3vw, 38px) 0; font-size: 16.5px; line-height: 1.45 }
.bp-body th { font-family: var(--mono); font-size: 12px; font-weight: 500; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); text-align: left; padding: 10px 14px 10px 0; border-bottom: 1px solid var(--line) }
.bp-body td { padding: 12px 14px 12px 0; border-bottom: 1px solid var(--line-2, #DED9CF); color: var(--ink-soft); vertical-align: top }
.bp-body .bp-faq strong { color: var(--ink) }
.bp-body hr { border: 0; border-top: 1px solid var(--line-2, #DED9CF); margin: clamp(36px, 4vw, 58px) 0 }
@media (max-width: 640px){ .bp-body table { display: block; overflow-x: auto } }

/* blog byline avatar */
.bp-av img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block }

/* Tag rail to first section: the hero's bottom padding stacked on the
   section's top padding left ~110px of dead air (Charles). Halve it on the
   section that directly follows the hero — blog and News Room both. */
.bl-hero + .bl-sec { padding-top: clamp(22px, 2.6vw, 36px) }

/* Wider breathing room between nav sections at full width (Charles). */
@media (min-width: 1281px){ .menu { gap: 14px } }

/* The tag filter sets [hidden] on rows, but .bl-row{display:grid} outranks
   the UA's [hidden]{display:none} — author styles always beat UA styles, so
   filtered rows never disappeared (blog and News Room both). */
.bl-row[hidden] { display: none !important }

/* filtered state: the cross-pillar Latest showcase collapses so results
   are immediately visible under the chips */
.bl-sec[hidden] { display: none !important }

/* Header brand left alignment (Charles). The logo art carries ~32.6%
   transparent padding per side; the design corrects for it below 760px
   (-12.4px at 38px tall) but never at desktop sizes, so the mark's ink sat
   ~10px right of the gutter. Same ratio at the base 32px height. */
@media (min-width: 761px){ body > header .brand .mark img { margin-left: -10.4px } }

/* Featured-card art in the mega panels: fill the frame, crop to fit */
.mega-promo-art { position: relative; overflow: hidden }
.mega-promo-art img.islot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block }

/* Capital Lynk case study art */
.csy-shot-in img.islot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top }
.csy-logo img.islot { width: 100%; height: 100%; object-fit: contain; object-position: left }

/* A mega panel without a Featured card collapses to one column (Capital).
   !important because the design pins .mega-cust's two-column grid and width
   with !important of its own. */
.dropdown.mega.mega-one.mega-cust:not(:has(.mega-promo)) {
  grid-template-columns: minmax(0, 1fr) !important;
  width: min(560px, calc(100vw - 48px)) !important;
}

/* Customer carousel showcase tiles: an image tile fills the whole frame,
   not the small centered wordmark strip the design reserves for logos */
.cst-tile { position: relative; overflow: hidden }
.cst-tile:has(img.islot) .cst-logo { position: absolute; inset: 0; display: block; width: 100%; max-width: none; height: 100%; aspect-ratio: auto }
.cst-logo { position: relative; overflow: hidden }
.cst-logo img.islot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: top }

/* testimonial cards: real portal/gradient art in the photo panel */
.tm-photo { position: relative; overflow: hidden }
.tm-photo img.islot { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: left top; display: block }

/* Flat brand panels replace the blurred-abstract tiles (Charles: they sucked).
   Logos render at or below native size so nothing is upscaled soft. */
.cst-brand { position: absolute; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 15px; background: var(--paper-deep, #F1EDE4) }
.cst-brand img { display: block; width: auto }
.cst-brand.b-unity img { height: 44px }
.cst-brand.b-forward img { height: 42px }
.cst-brand.b-canacap img { height: 46px }
.cst-brand b { font-family: var(--serif, Georgia); font-weight: 500; font-size: 23px; letter-spacing: -.01em; color: var(--ink, #1a1714) }
.cst-tile:has(.cst-brand) .cst-logo, .tm-photo:has(.cst-brand) { }
.cst-tile:has(.cst-brand) .cst-logo { position: absolute; inset: 0; display: block; width: 100%; max-width: none; height: 100%; aspect-ratio: auto }

/* logo marks on testimonial cards */
.tm-mark-logo { display: inline-flex; align-items: center; gap: 10px }
.tm-mark-logo img { display: block }
.tm-mark-logo i { font-style: normal; font-family: var(--serif, Georgia); font-weight: 500; font-size: 20px; line-height: 1; color: var(--ink, #1a1714) }
.tm-mark-logo i:empty { display: none }

/* How-it-works product shots: the container is portrait (10/11) but the
   screenshots are landscape — anchor the crop left so the form panel (the
   UI's leftmost content) is what stays visible (Charles). */
.hw-shot { overflow: hidden }
.hw-shot img.islot { width: 100%; height: 100%; object-fit: cover; object-position: left center; display: block }

/* Testimonial cards are ALWAYS portrait (Charles): photo on top, text below,
   at every viewport. The design's side-by-side grid is overridden. */
.tm-card {
  grid-template-columns: 1fr !important;
  grid-template-rows: auto 1fr;
  width: clamp(330px, 27vw, 430px) !important;
  min-height: 0 !important;
}
.tm-photo { min-height: 0 !important; aspect-ratio: 16/10 }
.tm-body { gap: 16px }
/* Equal-height cards (Charles, 2026-08-09), with the slack placed where it
   reads as alignment rather than as dead space: the cards stretch to the
   tallest quote, and the KPI rule + attribution are pushed to the floor so
   those three lines sit on the same baseline across the whole row. The quote
   keeps the top. grid-template-rows is 1fr, not `auto 1fr` — the photo panel
   that used to hold the first row is gone, so the body has to fill the card
   for margin-top:auto to have anything to push against. */
/* A related-story card with no portal shot (Charles, 2026-08-09: "bug here
   this shouldnt happen"). .cst-tile paints a bordered 16/9.4 box whatever is
   inside it, so an empty anchor read as a broken image. These now carry the
   customer's wordmark, which keeps every card in the carousel the same height. */
.cst-tile .cst-txt { padding: 0 18px; text-align: center }

/* Statement headline, cycling first word (Charles, 2026-08-09) — see
   src/word-cycle.js. Width is animated because the two words differ in length
   and a bare swap would re-break the line under the reader. No overflow:hidden:
   the box is briefly narrower than its text mid-swap, but that text is at
   opacity 0 by then, and clipping would cut the descender off "Lending". */
.st-h .stw-swap { display: inline-block; transition: width .5s cubic-bezier(.4, 0, .2, 1) }
.st-h .stw-in { display: inline-block; transition: opacity .26s ease }
@media (prefers-reduced-motion: reduce) {
  .st-h .stw-swap, .st-h .stw-in { transition: none }
}

/* Large pill CTAs (Charles, 2026-08-09): 28px of side padding on a 54px-tall
   pill left the text sitting almost exactly where the 27px corner radius ends,
   so the label read as crowded against the curve. 38px clears the radius by a
   comfortable margin. Left the nav CTA alone — .nav-actions .btn has its own
   responsive ladder (20 → 17 → 15px) that tightens as the bar runs out of room,
   and widening it would eat that headroom. Both CTA rows are flex-wrap:wrap, so
   the extra width wraps rather than overflowing. */
.btn-lg { padding-left: 38px; padding-right: 38px }

/* Blog post titles (Charles, 2026-08-09). carousel-home.css carries a bare
   `h1{max-width:15ch}` — a home-page hero constraint that leaks to every h1 on
   the site. On a post that clamped the title to ~486px inside its own 760px
   measure, so a long headline broke into five stunted lines with the column
   half empty beside it. The measure is the measure; the title should use it.
   Left `text-wrap: balance` alone — it's what keeps the last line from
   orphaning once the width is right. */
.bp-h1 { max-width: none }

/* Docs + contact tables (Charles, 2026-08-09: "tables are broken on resources
   section"). Two rules in docs.css disagreed: the mobile block sets
   .dc-table{white-space:nowrap} while the later card treatment sets
   thead/tbody{table-layout:fixed}. Fixed column widths plus text that refuses
   to wrap means every cell overflows into the one beside it — which is exactly
   what shows on a phone, "Identity VerificationOnfido / Ondato" printed on top
   of itself. Let the cells wrap; the fixed layout then does its job. */
.dc-body table.dc-table,
.dc-body table.dc-table td,
.dc-body table.dc-table th { white-space: normal }
.dc-body table.dc-table td { overflow-wrap: anywhere }
@media (max-width: 760px) {
  /* three columns cannot hold their shape on a phone — let the table scroll
     as one block instead of crushing each column to a few characters */
  .dc-body table.dc-table { display: block; overflow-x: auto }
  .dc-body table.dc-table thead,
  .dc-body table.dc-table tbody { display: table; min-width: 520px }
}

/* Onboarding mock, mobile (Charles, 2026-08-09): the window ran the full width
   of its column and stood in a 440px body, so the shorter steps — step 01 needs
   332px — carried a slab of dead white under the Continue button. Narrowed to
   288px and floored at the tallest step's real height (353px measured at this
   width), which keeps the frame from resizing as the steps advance. The
   min-height selector has to carry .sv-snaps to outrank
   tenant-screening-v5.css:219. */
@media (max-width: 720px) {
  .og-win { width: min(100%, 288px); margin-left: auto; margin-right: auto }
  .sv-snaps .og-win-body { min-height: 356px }
}

.tm-card { min-height: 0 !important; grid-template-rows: 1fr !important }
.tm-kpi { margin-top: auto }
.tm-body figcaption { margin-top: 0 }

/* Final-CTA collage: four panels (Charles's highlighted set) — each half of
   the design's two-column grid carries a side-by-side pair */
.fin-pair { display: grid; grid-template-columns: 1fr 1fr; width: 100%; height: 100% }
.fin-pair img { width: 100%; height: 100%; object-fit: cover; display: block }
@media (max-width: 760px){ .fin-pair { grid-template-columns: 1fr } .fin-pair img + img { display: none } }

/* Hard number on a testimonial card, between the quote and the attribution.
   Only cards whose figure has a row in Case Studies/02-EVIDENCE-LEDGER.md carry
   one; the rest render without the block, which is why it isn't in the grid. */
.tm-kpi { display: flex; align-items: baseline; gap: 11px; padding-top: 15px; border-top: 1px solid var(--line-2, #E8E3D8) }
.tm-kpi-n { flex: none; font-family: var(--serif, Georgia); font-weight: 500; font-size: clamp(26px, 2.1vw, 34px); line-height: 1; letter-spacing: -.02em; color: var(--ink, #1a1714) }
.tm-kpi-l { font-family: var(--mono); font-size: 11px; font-weight: 500; letter-spacing: .1em; text-transform: uppercase; line-height: 1.35; color: var(--muted-2, #8b8578) }

/* Trusted-by marquee: real customer logos, not the design's invented names.
   The row sits on the dark hero gradient and the logos are a mix of dark
   wordmarks and coloured containers with reversed-out type, so a knockout
   filter isn't available — each mark gets a white chip and reads in its own
   colours. Files that already carry a wordmark (.ym-lg-wide) print no label. */
.ym-lg-co { display: inline-flex; align-items: center; gap: 12px; font-family: var(--sans); font-weight: 600; font-size: clamp(19px, 1.6vw, 24px); letter-spacing: -.01em; color: #fff; opacity: 1 }
.ym-lg-co img { display: block; height: 26px; width: auto; filter: brightness(0) invert(1) }
@media (max-width: 700px) { .ym-lg-co img { height: 22px } }

/* Mega panels reserve a fixed promo track (252px, 200px, 188px by viewport) on
   every .mega-one — but the Capital panel carries no .mega-promo, so the track
   stayed empty and read as a huge right pad. Reserve it only when a promo is
   actually there, and shrink the panel to its links. Loaded after
   carousel-home.css. The `:has(.mega-feat a)` is load-bearing, not decoration:
   it matches the specificity of the rule being overridden (0,5,1) so source
   order decides — without it this loses and the empty track comes back. */
.dropdown.mega.mega-one:has(.mega-feat a):not(:has(.mega-promo)) {
  grid-template-columns: minmax(0, 1fr) !important;
  width: min(620px, calc(100vw - 40px)) !important;
}
