/*
 * V2 comment round — hand-written CSS, loaded AFTER dist/app.css.
 *
 * Why a second stylesheet instead of editing assets/css/app.css: that file is the
 * Tailwind SOURCE and the site serves assets/css/dist/app.css, which is a compiled
 * bundle. There is no node/npm on the deploy machine, so anything added to the
 * source silently never reaches production. Everything here is plain CSS that
 * needs no build step.
 *
 * @package KennethKwan
 */

/* ------------------------------------------------------------------ *
 * Keynote coverflow — red glow on EVERY card
 *
 * Only the centre card and whichever card happened to stick out past the
 * carousel's own box lit up on hover; every card in between stayed dead.
 *
 * The cause is the 3D stack, not z-index. Swiper's coverflow puts
 * .swiper-wrapper into transform-style: preserve-3d and pushes every
 * non-active slide backwards (translateZ -124px, -248px, -372px...). The
 * wrapper's own plane stays at z = 0, so it sits IN FRONT of those slides and
 * swallows the pointer — document.elementFromPoint over a side card returns
 * .swiper-wrapper, so the card never matches :hover and ::after never
 * animates. The wrapper is only as wide as the carousel while the slides
 * overflow past it, which is why the outermost card did work: its centre falls
 * outside the wrapper's box.
 *
 * z-index cannot fix this — inside a preserve-3d context the painting order
 * comes from the 3D geometry, not from z-index. Take the wrapper out of
 * hit-testing instead and hand it back to the slides. Dragging is unaffected:
 * Swiper binds its pointer handlers to the .swiper container, and events on
 * the slides still bubble up through the wrapper.
 * ------------------------------------------------------------------ */
.kk-roadmap .swiper-wrapper { pointer-events: none; }
.kk-roadmap .swiper-slide   { pointer-events: auto; }

/* Outside the carousel the cards sit in ordinary flat grids, where a later
   sibling would paint over the hovered card's outer glow. Lift the hovered one.
   (Inert inside .kk-roadmap — see above — but harmless there.) */
.kk-hovercard:hover { z-index: 3; }

/* ------------------------------------------------------------------ *
 * Fluent Forms — confirmation message
 *
 * The plugin appends the success message to #fluentform_N_errors, which sits
 * AFTER the whole form. On the tall contact form that put the confirmation
 * roughly a screen below where the person was looking. Pull the message block
 * to the top of the form wrapper and make it read as a confirmation panel.
 * app.js scrolls it into view.
 * ------------------------------------------------------------------ */
/* The flex container has to be .fluentform (the shortcode's own wrapper): the
   <form> and the #fluentform_N_errors block are ITS children, not .kk-ff's. */
.kk-ff .fluentform { display: flex; flex-direction: column; }
.kk-ff .fluentform > .ff-errors-in-stack { order: -1; }
.kk-ff .ff-errors-in-stack:empty { display: none; }

.kk-ff .ff-message-success {
  margin: 0 0 1.5rem;
  padding: 1.125rem 1.25rem;
  border: 1px solid rgba(255, 42, 57, 0.35);
  border-left: 3px solid #e11d2a;
  border-radius: 14px;
  background: rgba(225, 29, 42, 0.08);
  color: #fff;
  font-size: 0.95rem;
  line-height: 1.6;
}
.kk-ff .ff-message-success p:last-child { margin-bottom: 0; }

/* ------------------------------------------------------------------ *
 * Newsletter (Fluent Form 2) — one consent line, not two
 *
 * The form carries its own Terms & Conditions block with an italic blue
 * "Privacy Policy." that links to "#" (dead). The page already prints a red,
 * working consent line underneath, so the form's copy was a duplicate.
 * Hidden here; it should also be deleted in the form builder.
 * ------------------------------------------------------------------ */
.kk-ff form.fluent_form_2 .ff-el-tc { display: none; }

/* ------------------------------------------------------------------ *
 * Meeting Professionals — Process section balance
 *
 * The two photos ran to the full column width while the step cards next to
 * them are text-height, so the right-hand photo towered over the blocks it sat
 * beside. Cap the photo height and even out the gaps between blocks.
 * ------------------------------------------------------------------ */
.kk-proc-media {
  max-height: 300px;
  margin-inline: auto;
  width: 100%;
}
/* V3: still unbalanced — "the image on the right is currently much larger than
   the content blocks on the left". A step card runs roughly 160-180px tall on
   desktop, so the cap now lands just above that and the two columns read as one
   rhythm. The boxes keep their full column width, so their edges stay aligned
   with the cards; only the crop gets shallower. Mobile is a single column and
   is left alone. Was 260px / 300px. */
@media (min-width: 1024px) { .kk-proc-media { max-height: 210px; } }
@media (min-width: 1280px) { .kk-proc-media { max-height: 230px; } }

/* ------------------------------------------------------------------ *
 * About — pull quote (V2 design)
 * ------------------------------------------------------------------ */
.kk-pullquote { text-align: center; }
.kk-pullquote .kk-pullquote-mark {
  display: block;
  font-size: 3.5rem;
  line-height: 1;
  color: #e11d2a;
  font-weight: 700;
}
.kk-pullquote blockquote {
  margin: 0.75rem auto 0;
  max-width: 46rem;
  font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.35rem);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: -0.01em;
  color: #fff;
}
.kk-pullquote .kk-pullquote-rule {
  display: block;
  width: 56px;
  height: 2px;
  margin: 1.75rem auto 1.5rem;
  background: #e11d2a;
}
.kk-pullquote .kk-pullquote-sub {
  margin: 0 auto;
  max-width: 34rem;
  font-style: italic;
  font-size: 0.975rem;
  line-height: 1.7;
  color: rgba(255, 255, 255, 0.6);
}

/* Short red rule under a section heading (design reference).
   .h-label paints its text with a clipped gradient and a transparent
   text-fill-colour; both are reset here so the rule cannot inherit them and
   disappear. */
.kk-rule::after {
  content: "";
  display: block;
  width: 56px;
  height: 2px;
  margin-top: 1rem;
  background: #e11d2a;
  background-clip: border-box;
  -webkit-background-clip: border-box;
  -webkit-text-fill-color: currentColor;
}
.kk-rule.kk-rule-center::after { margin-inline: auto; }

/* "The Person Behind the Stage" used to draw a short red rule between every
   paragraph block (.kk-storyblock). V4 comment: "Do not add the red line after
   each paragraph, as shown on the current live page." The rule is gone and the
   markup no longer carries the class; spacing alone separates the beats now.
   .kk-rule above is a different thing (one rule under a section heading) and
   stays. */
/* ------------------------------------------------------------------ *
 * Utilities the compiled Tailwind bundle does not contain
 * ------------------------------------------------------------------ */
.kk-italic { font-style: italic; }
.kk-gap-14 { gap: 3.5rem; }
@media (min-width: 1024px) { .kk-lg-gap-20 { gap: 5rem; } }

/* Video card: the V2 thumbnails are designed artwork, so only a light wash sits
   over them — the compiled bundle has no bg-black/10 or group-hover:bg-black/0. */
.kk-video-wash {
  background: rgba(0, 0, 0, 0.12);
  transition: background-color 0.2s ease;
  pointer-events: none;
}
.group:hover > .kk-video-wash { background: rgba(0, 0, 0, 0); }

/* ------------------------------------------------------------------ *
 * Speaking dropdown — width
 *
 * The markup asks for min-w-[310px], but that arbitrary value was never
 * compiled into dist/app.css (no npm on the build machine), so the panel
 * collapsed to its content width and every label wrapped: "Motivational
 * Speaker" alone took two lines and the menu ran off the screen.
 *
 * Set the width here instead, keep the topic name on one line, and let the
 * description wrap to at most two — so no row exceeds three lines.
 * ------------------------------------------------------------------ */
.kk-navdd { min-width: 320px; }

.kk-navitem > span:first-child {
  white-space: nowrap;      /* topic name never wraps */
}

.kk-navitem > span + span {
  display: -webkit-box;
  -webkit-line-clamp: 2;    /* description: 2 lines max, then ellipsis */
  -webkit-box-orient: vertical;
  overflow: hidden;
}

/* ------------------------------------------------------------------ *
 * Credentials — card design from the client's V2 mockup
 *
 * Two changes from the shared image:
 *   1. The heading is sentence case there, but .h-label forces uppercase for
 *      every section title on the site. Opt out here only, so no other
 *      heading is affected.
 *   2. Cards in the mockup share one height per row; ours were content-height,
 *      so a two-line title left its neighbour visibly short.
 * ------------------------------------------------------------------ */
.kk-h-sentence { text-transform: none; }

/* Equal-height cards. The mockup keeps the description directly under the
   title (not pushed to the card's bottom edge), so only the card stretches —
   the text block stays at the top. */
.kk-cred-col { display: flex; flex-direction: column; gap: 1.25rem; height: 100%; }
.kk-cred-col > .kk-cred-card { flex: 1 1 0; }

/* Card interior: icon on the left, text column on the right. */
.kk-cred {
  display: flex;
  align-items: flex-start;
  gap: 1.15rem;
}

.kk-cred-icon {
  flex: 0 0 auto;
  display: block;
  line-height: 0;          /* no baseline gap above the glyph */
}
.kk-cred-icon svg {
  width: 2.75rem;
  height: 2.75rem;
}

.kk-cred-body { min-width: 0; }   /* let long titles wrap instead of overflowing */

/* Short red rule between the title and the context line. */
.kk-cred-body > p {
  margin-top: 0.85rem;
  padding-top: 0.85rem;
  position: relative;
}
.kk-cred-body > p::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: 1.75rem;
  height: 2px;
  background: #e11d2a;
}

/* ------------------------------------------------------------------ *
 * About — Global Leadership Forum photo, squared
 *
 * The source is 1145x1374 (5:6). At 9/10 it rendered ~800px tall against
 * ~290px of copy beside it and towered over the section. A square box is the
 * gentlest crop that fixes that: the frame is only 17% narrower in height
 * than the source, so almost all of the photo survives.
 *
 * object-position 50% 20% decides which 17% goes. It leaves the visible band
 * at 3%-87% of the frame; Kenneth's head sits at 19%-35% and his gesture at
 * ~47%-55%, so both clear comfortably and the loss is the stage floor under
 * the monitors. Centred (the default) would have taken an equal bite off the
 * top, which is where the Global Leadership Forum banner is.
 * ------------------------------------------------------------------ */
.kk-about-photo { aspect-ratio: 1 / 1; }
.kk-about-photo img { object-position: 50% 20%; }

/* ------------------------------------------------------------------ *
 * Meeting Professionals — hero headline on small screens
 *
 * The H1 is `max-w-xl text-right` (36rem). On a 390px phone that is wider
 * than the viewport, so the words ran off the edge and back over Kenneth —
 * the very overlap the wider banner was meant to remove. Pre-dates this
 * round; fixed here because the brief was "text must not sit on him".
 *
 * Below 640px: let it use the full column and align left, over the dark
 * side of the frame. The right-aligned desktop treatment is untouched.
 * ------------------------------------------------------------------ */
@media (max-width: 639px) {
  .kk-mp-hero-title {
    /* Measured: at the 40px mobile h-display size "PROFESSIONALS" is 290px
       wide and the container gives ~326px, so the type already fits. The only
       real problem was max-w-xl (36rem) being wider than the viewport, which
       pushed the right-aligned text off-screen and back over Kenneth.
       Drop the cap and align left over the dark side. No font change needed. */
    max-width: 100%;
    text-align: left;
  }
  .kk-mp-hero-row { justify-content: flex-start; }
}

/* ==========================================================================
   V3 COMMENT ROUND (KW revision V3.odt)
   ========================================================================== */

/* ------------------------------------------------------------------ *
 * Client logos — grey-tone strip on the dark page
 *
 * V3: "something similar to the sample ... please use a grey-tone version of
 * the logo rather than the original brand colours". The V1 white panel is gone
 * from the markup, so the marquee now runs straight on the section background.
 *
 * The grey tone is baked into clients-di/mono/*.png, not done here with a CSS
 * filter — see the note in template-parts/sections/client-logos.php for why a
 * filter cannot do it without losing DHL and SGX.
 * ------------------------------------------------------------------ */
/* Section padding: the panel is back (V4 follow-up, below), so this reverts to
   plain .section-pad (py-20 / md:py-[120px] / xl:py-[50px]) and the panel's own
   py-12 / md:py-14 supplies the rest, same as V1. While the panel was gone the
   totals lived here instead — see git history if that split is needed again. */
.kk-clients-strip { padding-top: 5rem; padding-bottom: 5rem; }
@media (min-width: 768px)  { .kk-clients-strip { padding-top: 120px; padding-bottom: 120px; } }
@media (min-width: 1280px) { .kk-clients-strip { padding-top: 50px; padding-bottom: 50px; } }
/* Full strength: these are the brand's own colours now, so there is nothing
   to hold back. The old 0.85 was softening grey marks that were waiting to be
   revealed on hover. */
.kk-clients-strip .kk-logo-plain img {
  opacity: 1;
  transition: transform 0.25s ease;
}
.kk-clients-strip .kk-logo-plain:hover img { transform: scale(1.04); }

/* V4 follow-up (2026-09-17): "Can we exactly have this one including
 * background" — the sample is a light panel, not logos loose on the dark
 * page. Scoped to .kk-clients-strip .kk-logo-panel rather than the bare class:
 * dist/app.css already has two older .kk-logo-panel rules (an unused frosted
 * variant plus the V1 white-panel one) and this needs to win over both without
 * touching the compiled bundle. A flat light grey reads closer to the sample
 * than V1's pure white. */
.kk-clients-strip .kk-logo-panel {
  background: #f0f0f0;
  border-color: rgba(0, 0, 0, 0.08);
}
/* NO filter here, deliberately. This used to carry filter: invert(1), which
 * existed only to rescue the grey mono/ artwork on a light panel. The strip
 * now renders the full-colour files (client-logos.php, 2026-09-23), and an
 * invert would turn every brand mark into its photographic negative. If a
 * logo ever looks washed out on #f0f0f0, fix the PNG, not this. */

/* ------------------------------------------------------------------ *
 * Service hero strapline (V3)
 *
 * Facilitation's H1 is now the descriptive line the client asked for, so the
 * headline it replaced — "Decisions, Not Decks", which they explicitly asked to
 * keep — sits under it as a strapline. Sized between the H1 and the body copy
 * so it reads as a claim, not as a subtitle for the paragraph below.
 * ------------------------------------------------------------------ */
.kk-hero-tagline {
  font-size: 1.25rem;
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #ff5a64;
}
@media (min-width: 768px) { .kk-hero-tagline { font-size: 1.5rem; } }

/* ------------------------------------------------------------------ *
 * Publicity photo lightbox (V3)
 *
 * "foto fullnya jadi modal bukan buka tab web baru". The dialog is built by
 * app.js and appended to <body>, so it escapes every section's stacking
 * context. z-index clears the fixed header (z-80) and its dropdown (z-90).
 *
 * The [hidden] rule is required, not defensive: `display: flex` below is an
 * author style and would otherwise beat the browser's own [hidden] rule,
 * leaving the modal permanently on screen.
 * ------------------------------------------------------------------ */
.kk-lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1.5rem;
}
.kk-lightbox[hidden] { display: none; }
.kk-lightbox-backdrop {
  position: absolute;
  inset: 0;
  background: rgba(5, 6, 10, 0.92);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.kk-lightbox-img {
  position: relative;
  display: block;
  max-width: 100%;
  max-height: 86vh;
  width: auto;
  height: auto;
  border-radius: 16px;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.6);
}
.kk-lightbox-close {
  position: absolute;
  top: 1rem;
  right: 1rem;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 9999px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  font-size: 1.6rem;
  line-height: 1;
  cursor: pointer;
  transition: background-color 0.2s ease, border-color 0.2s ease;
}
.kk-lightbox-close:hover {
  background: rgba(255, 255, 255, 0.2);
  border-color: rgba(255, 255, 255, 0.45);
}
/* Stop the page scrolling behind the modal. */
html.kk-lightbox-open, html.kk-lightbox-open body { overflow: hidden; }

/* ------------------------------------------------------------------ *
 * Speaking headlines — stop the orphaned article ("A", "An")
 *
 * `.kk-title-red` carries `white-space: nowrap` (app.css) so the keynote-type
 * phrase never splits. On the topic pages that backfired: at xl the headline is
 * 72px inside a 768px column, and "LEADERSHIP KEYNOTE" alone is already about
 * the full width. The unbreakable span could not share a line with the "A"
 * before it, so it dropped to the next line and left the "A" stranded on its
 * own — four of the six topic titles have this shape ("... · A <red> ...",
 * "... · An <red> ...").
 *
 * Letting the red phrase wrap costs nothing — wrapping happens at spaces, never
 * mid-word, which is what the original note was actually guarding against — and
 * `text-wrap: balance` then evens the lines out. Browsers without balance still
 * get the fix, because normal wrapping alone removes the orphan.
 *
 * Scoped to the speaking hero H1s so other headlines keep their current
 * behaviour.
 * ------------------------------------------------------------------ */
.kk-h1-topic { text-wrap: balance; }
.kk-h1-topic .kk-title-red { white-space: normal; }

/* --------------------------------------------------------------------
 * Anchor offset for in-page jump links (added 2026-09-15 for /book/#enquire).
 *
 * Tailwind's scroll-mt-* is NOT in dist/app.css and cannot be added: there is
 * no node/npm on the deploy box, so the bundle is never rebuilt. Same reason
 * this file exists at all. Written as plain CSS here instead.
 *
 * 7rem clears the fixed header; without it the target heading lands underneath
 * the nav and the section looks like it starts mid-sentence.
 * ------------------------------------------------------------------ */
.kk-anchor-offset { scroll-margin-top: 7rem; }

/* --------------------------------------------------------------------
 * FAQ accordions, two columns (V4 comment: "FAQs for each page - can we
 * have them in 2 rows instead of one whole block").
 *
 * The lists were one tall stack of <details>; on a desktop page that is a
 * single column of questions running past the fold. Two columns halve the
 * run and put the whole set in view.
 *
 * Grid, not `columns: 2`: a multi-column layout would break an open
 * <details> across the column boundary, splitting a question from its
 * answer. Grid keeps each Q+A whole.
 *
 * Cells stretch (the default) rather than sit at the top of their row. Each
 * <details> draws the hairline under itself, so leaving them at their natural
 * height puts the two rules in a row at different heights whenever one
 * question wraps to two lines and its neighbour does not. Stretching lands
 * both on the row's baseline.
 *
 * Plain CSS, not Tailwind utilities — dist/app.css cannot be rebuilt
 * (no node on the deploy box), same reason as the rest of this file.
 * ------------------------------------------------------------------ */
.kk-faq-grid { display: grid; gap: 0 3rem; }

@media (min-width: 768px) {
    .kk-faq-grid { grid-template-columns: 1fr 1fr; }
}

/* --------------------------------------------------------------------
 * The $21 block — part 2 of the split "Person Behind the Stage" section
 * (V4 comment: "can we divide this section into 2 parts? Sample given
 * below").
 *
 * The sample sets the number as a display figure with the sentence it
 * belongs to sitting beside its baseline, an accent rule under the figure,
 * and the "one step -> another -> another" line drawn as three moves.
 *
 * clamp() rather than Tailwind's text-* scale: the compiled bundle stops at
 * text-6xl and cannot be rebuilt (no node on the deploy box), and a figure
 * this size wants to track the viewport anyway.
 * ------------------------------------------------------------------ */
.kk-figure {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 0.5rem 1.5rem;
}

.kk-figure-num {
  font-size: clamp(3.5rem, 9vw, 6.5rem);
  font-weight: 800;
  line-height: 0.9;
  letter-spacing: -0.045em;
  color: #fff;
  padding-bottom: 0.75rem;
  border-bottom: 3px solid #ba0013;
}

.kk-figure-say {
  font-size: clamp(1.15rem, 2.4vw, 1.6rem);
  font-weight: 700;
  line-height: 1.25;
  color: #fff;
  padding-bottom: 0.75rem;
}

/* "One step -> another -> another". The arrows are decoration (aria-hidden in
   the markup); the three words are the sentence and stay readable. */
.kk-steps {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.5rem 1rem;
  font-size: 0.95rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #ba0013;
}

.kk-steps-arrow { font-size: 1.15rem; opacity: 0.75; }

/* --------------------------------------------------------------------
 * "The Person Behind the Stage" story bands.
 *
 * V4, second pass: "dibikin sama kaya contoh (mepet dan blend)". The sample
 * runs each photo hard to the edge of the page — no container gutter, no card
 * radius — with the two bands flush against each other, so this is a full-bleed
 * two-column grid rather than a container with a photo inside it.
 *
 * The edge of the photo that faces the copy is faded into the page background
 * instead of being cut square. On a dark page a hard vertical seam against a
 * brightly lit photo reads as a rendering fault; the fade is what "blend"
 * means here.
 *
 * Plain CSS, not Tailwind utilities — dist/app.css cannot be rebuilt (no node
 * on the deploy box), same reason as the rest of this file.
 * ------------------------------------------------------------------ */
.kk-story {
  display: grid;
  position: relative;
  background: #0a0b11;
}

/* Photo first on small screens, so the section opens on the picture. */
.kk-story-photo {
  position: relative;
  min-height: 22rem;
  aspect-ratio: 4 / 3;
}

/* Direct child only. A descendant selector also catches the book cover inside
   .kk-story-badge and blows it up to fill the whole band. */
.kk-story-photo > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* The fade. Vertical while the columns are stacked, horizontal once they sit
   side by side (below). ::after so it layers over the <img> without a wrapper. */
.kk-story-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg, rgba(10, 11, 17, 0) 55%, rgba(10, 11, 17, 0.75) 82%, #0a0b11 100%);
}

.kk-story-badge a:first-child { width: 3.5rem; height: 3.5rem; }
.kk-story-badge a:first-child img { width: 100%; height: 100%; object-fit: contain; }

.kk-story-badge {
  position: absolute;
  bottom: 1.5rem;
  left: 1.5rem;
  z-index: 2;
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.75rem 1.25rem 0.75rem 0.75rem;
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 12px;
  background: rgba(14, 16, 24, 0.95);
  box-shadow: 0 0 25px 2px rgba(0, 0, 0, 0.2);
  backdrop-filter: blur(8px);
}

.kk-story-text {
  padding: 3.5rem 1.25rem 4rem;
}

.kk-story-inner { max-width: 34rem; }

@media (min-width: 640px) {
  .kk-story-text { padding-left: 2rem; padding-right: 2rem; }
}

@media (min-width: 1024px) {
  .kk-story {
    grid-template-columns: 1fr 1fr;
    align-items: stretch;
  }

  /* Height comes from the copy; the photo stretches to match it. */
  .kk-story-photo {
    aspect-ratio: auto;
    min-height: 34rem;
  }

  .kk-story-text {
    display: flex;
    align-items: center;
    padding: 5rem 3.5rem;
  }

  /* Part 1: photo left, so the fade runs left-to-right into the copy. */
  .kk-story-photo--left::after {
    background: linear-gradient(90deg, rgba(10, 11, 17, 0) 58%, rgba(10, 11, 17, 0.7) 84%, #0a0b11 100%);
  }

  /* Part 2 mirrors it: source order still puts the photo first (so it leads on
     mobile), and the flip moves it to column 2 without touching the markup. */
  .kk-story--flip .kk-story-photo { grid-column: 2; grid-row: 1; }
  .kk-story--flip .kk-story-text  { grid-column: 1; grid-row: 1; justify-content: flex-end; }

  .kk-story-photo--right::after {
    background: linear-gradient(270deg, rgba(10, 11, 17, 0) 58%, rgba(10, 11, 17, 0.7) 84%, #0a0b11 100%);
  }
}

@media (min-width: 1280px) {
  .kk-story-text { padding: 6rem 5rem; }
}

/* --------------------------------------------------------------------
 * Client logo grid (V4 comment: "Kenneth requested a different presentation
 * of logo, sample added, we want all the logos"; restated 2026-09-22 as
 * "ditampilkan semua ya tanpa ada live slider" — show them all, no slider).
 *
 * Replaces the four scrolling marquee rows. The client's sample is a still
 * grid, and a marquee cannot show "all the logos" at once by definition — half
 * the set is always off-screen. Six across on desktop matches the sample's
 * density and makes the first two rows a real, stable position rather than
 * whatever happens to be sliding past.
 *
 * .kk-logo-row's own rules in app.css (flex, width:max-content, the scroll
 * animation) are scoped to that class, which the markup no longer carries, so
 * nothing here inherits them. The shared sizing on .kk-logo-plain img
 * (max-height 48px, max-width 150px, contain) is unscoped and still applies —
 * raised below.
 * ------------------------------------------------------------------ */
/* Flex-wrap rather than grid, for one reason: the last row.
 *
 * 57 logos does not divide by the column count. On a grid the remainder sits
 * hard left with the rest of the row empty — 3 marks and three blank cells at
 * six across, and a single stranded mark at four across. Adelia, 2026-09-29:
 * "posisinya center align jadi seperti triangle terbalik".
 *
 * flex-wrap + justify-content: center changes nothing about the full rows,
 * because a row whose items exactly fill the line has no free space to
 * distribute. It only centres the short last row, so the block tapers to the
 * middle instead of hanging off to the left. Adding or removing a logo keeps
 * working — there is no remainder to hardcode.
 *
 * The basis is the grid track it replaces, minus a hundredth of a pixel: an
 * exact calc can round a hair wide on fractional viewport widths and drop the
 * last item of every row onto its own line. */
.kk-logo-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 2.25rem 1.5rem;
}

.kk-logo-grid .kk-logo-plain {
  flex: 0 0 calc((100% - 2 * 1.5rem) / 3 - 0.01px);
}

@media (min-width: 640px) {
  .kk-logo-grid .kk-logo-plain {
    flex-basis: calc((100% - 3 * 1.5rem) / 4 - 0.01px);
  }
}

/* Seven across, not six. Adelia, 2026-09-29: "dan ini cuma ada 7 row" — the
   client's reference sheet is seven rows deep, and the row count is what she is
   matching, not the column count.

   Seven is the number that delivers it at both logo counts: 44 marks today go
   6 full rows plus 2, and 46 once Dell EMC and Symantec arrive go 6 plus 4.
   Seven rows either way, so the layout does not change shape on the day those
   two files land. Six across would give eight rows now and eight then.

   The column gap comes down with the extra column, otherwise the cells lose
   more width to gutters than they gain from the split. */
@media (min-width: 1024px) {
  .kk-logo-grid { gap: 2.75rem 1.5rem; }

  .kk-logo-grid .kk-logo-plain {
    flex-basis: calc((100% - 6 * 1.5rem) / 7 - 0.01px);
  }
}

/* app.css caps the mark at 150px wide, which was tuned when the cell was always
   wider than that. At seven across it is not, so the cap has to yield to the
   cell or a wide wordmark pushes its row to six and the seventh mark wraps. */
.kk-logo-grid .kk-logo-plain img {
  max-width: min(150px, 100%);
}

/* The cell is a fixed-height flex box so every mark sits on the same optical
   baseline whatever its aspect ratio, and so the hover overlay below has a
   stable box to inset against. */
.kk-logo-grid .kk-logo-plain {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 70px;
}

/* The full set is not the strip of wordmarks the 48px ceiling in app.css was
   tuned for: a square crest (MAS, MINDEF, MUIS) hits the height limit at 48px
   wide and its lettering stops being readable, while a long wordmark like
   PHILIPS gets the whole 150px. Raising only the height evens out the optical
   weight; the wide marks are still held by max-width and do not move. The cell
   height above grows to match so the taller marks are not clipped. */
.kk-clients-strip .kk-logo-plain img { max-height: 58px; }

/* The hover colour-swap that stood here is gone (2026-09-23). It faded a grey
   mono logo out and a ::after background-image of the colour file in, so that
   the brand colours appeared on hover only — which meant touch users never saw
   them, and the @media (hover: none) block below it existed to say so.
   The <img> is now the colour file itself, so there is nothing to swap. */


/* ---------------------------------------------------------------------------
   Footer "Pages" disclosure
   ---------------------------------------------------------------------------
   The three non-keynote services (Masterclasses, Executive Coaching,
   Facilitation) sit behind one collapsible label in the Pages column instead
   of running on as the tail of the Speaking column.

   Plain CSS rather than Tailwind: hiding the native summary marker and
   rotating the chevron on [open] both need selectors the compiled build does
   not carry, and there is no Node toolchain on the build machine, so footer
   chrome is styled here the same way the client-logo grid is.

   The nested links are deliberately flush with the rest of the column: no
   indent and no rule down their left. An earlier pass had both, in brand red
   — removed on request, so the disclosure reads as part of one continuous
   list rather than a nested block. */
.kk-footer-dd > summary {
  list-style: none;
}

/* Safari/Chrome draw their own triangle from a pseudo-element that
   list-style: none does not reach. */
.kk-footer-dd > summary::-webkit-details-marker {
  display: none;
}

.kk-footer-dd-chev {
  display: inline-flex;
  transition: transform 0.2s ease;
}

.kk-footer-dd[open] .kk-footer-dd-chev {
  transform: rotate(180deg);
}

/* ------------------------------------------------------------------ *
 * Experience across industries — /our-clients/ (client round 5.2-5.6)
 *
 * Replaces the flat sector rows the page shipped with. Plain CSS, not
 * Tailwind: dist/app.css is never rebuilt (no Node on this machine), the
 * same reason the client-logo grid and the footer disclosure live here.
 *
 * 5.6 is what drives the light card. 36 of the 57 client marks are dark
 * artwork on transparency, so on the dark page more than half the wall was
 * washing out. #f0f0f0 matches .kk-clients-strip .kk-logo-panel on the
 * homepage, so the two logo treatments read as one system. No invert()
 * here: these are the full-colour brand files, which is exactly what a
 * white background is for. The homepage panel is the same colour and also
 * carries no invert() since 5db2f44 — it dropped the grey mono variants and
 * now serves the same colour files these cards do.
 *
 * 5.4 is the rest of it: one ceiling height for every mark regardless of
 * its aspect, a hairline border rather than a heavy card, and no motion of
 * any kind. Nothing here scrolls or auto-advances.
 * ------------------------------------------------------------------ */
.kk-ind-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.25rem;
}

/* 5.5: one column on mobile. Two only once there is room for two logos
   plus their gutters inside each card without the marks shrinking. */
@media (min-width: 768px) {
  .kk-ind-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }

  /* The wireframe runs its last card across the full width rather than
     leaving it stranded at half width on a row of its own. There are seven
     cards, so that is the seventh.

     :last-child:nth-child(odd) rather than :nth-child(7): in a two-column
     grid an item is alone on its row only when it is both last and at an odd
     position. Merge or add a category and this corrects itself instead of
     spanning the wrong card or spanning one that already has a neighbour. */
  .kk-ind-card:last-child:nth-child(odd) {
    grid-column: 1 / -1;
  }

  /* That card is twice as wide, so it gets twice the logos per row and the
     row reads as one band, which is how the wireframe draws it. */
  .kk-ind-card:last-child:nth-child(odd) .kk-ind-logos {
    grid-template-columns: repeat(4, minmax(0, 1fr));
  }
}

@media (min-width: 1024px) {
  .kk-ind-card:last-child:nth-child(odd) .kk-ind-logos {
    grid-template-columns: repeat(6, minmax(0, 1fr));
  }
}

.kk-ind-card {
  background: #f0f0f0;
  border: 1px solid rgba(0, 0, 0, 0.08);
  border-radius: 24px; /* .rounded-card */
  padding: 1.75rem 1.5rem;
}

@media (min-width: 768px) {
  .kk-ind-card {
    padding: 2rem 1.75rem;
  }
}

.kk-ind-title {
  margin: 0;
  color: #1a1a1a;
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  line-height: 1.4;
  text-transform: uppercase;
}

/* 5.5: "two logos per row" on mobile, and it stays two for the whole of the
   single-column stack the same sentence asks for — i.e. everywhere below the
   768px point where .kk-ind-grid becomes two columns.

   There used to be a step to 3 across at 480px. It was wrong: from 480px to
   767px the cards are still stacked one per row, so that range is exactly the
   mobile layout 5.5 describes, and it was showing three. Removing the step
   also removes the rule that used to put it back to 2 at 768px, because two
   is now simply what the base declares. A half-width card at 768px wants two
   anyway — three would squeeze the wordmarks. */
.kk-ind-logos {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem 1rem;
  margin-top: 1.5rem;
}

@media (min-width: 1024px) {
  .kk-ind-logos {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* The fixed box is what gives 5.4 "consistent visual weight": a wide
   wordmark and a square crest both get the same cell, and neither is
   allowed to dominate by being taller. */
.kk-ind-logo {
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
  height: 68px;
}

/* 5.4, the half that a height ceiling alone does not deliver: "keep all logos
   at consistent visual weight and avoid oversized logos".
 *
 * Capping only the height makes the disparity worse, not better. At one
 * ceiling a 5:1 wordmark (PHILIPS, ENERGIZER, MARRIOTT, ORACLE) spreads across
 * the whole cell while a square crest (MAS, MINDEF, ICA, A*STAR, AXA, HP) fills
 * a box the height of one line of text — on the rendered page the wordmarks
 * carried roughly four times the ink of the crests, which is exactly the
 * "oversized" the client is objecting to.
 *
 * So cap BOTH axes, in px rather than 100%: the wordmarks are held by width and
 * come down, the crests are held by height and go up, and the two meet near the
 * same ink area. This is the fix the homepage strip already documents for the
 * same artwork ("raising only the height evens out the optical weight; the wide
 * marks are still held by max-width"); the cards had inherited a height-only
 * ceiling instead. The cell above grows to 68px so the taller crests are not
 * clipped. */
.kk-ind-logo img {
  max-height: 52px;
  max-width: 132px;
  width: auto;
  height: auto;
  object-fit: contain;
}

/* ------------------------------------------------------------------ *
 * FAQ: the deeper-resource pointer (client round 3.1)
 *
 * The FAQ answers the short decision-stage version of a question and hands
 * off to the article or commercial page that covers it properly. Before
 * this the page linked to none of them, which is what made it compete with
 * the blog rather than feed it. See the analysis in page-faq.php.
 *
 * .kk-faq-body > * + * already supplies the top margin, so this rule only
 * has to colour the link and line the arrow up with the text.
 * ------------------------------------------------------------------ */
.kk-faq-more a {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: #e11d2a;
  font-weight: 600;
  transition: color 0.2s ease;
}

.kk-faq-more a:hover {
  color: #fff;
}

.kk-faq-more svg {
  flex-shrink: 0;
  transition: transform 0.2s ease;
}

.kk-faq-more a:hover svg {
  transform: translateX(2px);
}
