/* TechLeader Portfolio — main.css v10.0 */

/* ─── HERO — dark navy, subtle indigo shift, no purple bleed ─── */
.hero-v2{
  position:relative;min-height:100svh;display:flex;align-items:center;overflow:hidden;
  background:linear-gradient(135deg, #020C1B 0%, #071A38 30%, #0C2350 55%, #0E1E45 75%, #091830 100%)
}
/* ── HERO SPLIT LAYOUT ── */
.hero-split{display:flex;align-items:flex-start;gap:4rem;padding:7.5rem 0 4.5rem;min-height:100svh;box-sizing:border-box}
.hero-text-side{flex:1;min-width:0;padding-left:0.75rem}
.hero-photo-side{flex:0 0 460px}

/* ══ HERO ENTRANCE ══════════════════════════════════════════════════════
   The hero headline runs a per-line zoom-in on load, restored a third time
   with a new `will-change` variant — see the HERO HEADLINE block below for
   the full history and what's different this time. Nothing else in the
   hero animates.

   Measured CLS on this page is 0, meaning nothing ever physically moves, yet
   the hero still read as "shaky" on refresh. The cause is rasterisation, not
   layout. Chrome on Windows draws text with ClearType subpixel antialiasing,
   but any element carrying an opacity or transform animation is promoted to
   its own composited layer, where subpixel AA is unavailable. The glyphs
   render thinner for the duration of the animation and snap back to full
   weight when the layer is discarded, so the text changes weight twice per
   page load. (`-webkit-font-smoothing:antialiased` does not help. It is a
   no-op on Windows.)

   A first fix removed animation from the text and moved the entrance onto
   non-text elements only: the portrait, a gold rule, the stats divider and an
   ambient glow. That was still not enough, because of Chrome's overlap
   compositing. Once one element has its own layer, anything overlapping it is
   promoted too, so paint order is preserved. The ambient glow was a large
   radial sitting directly behind the headline, so animating it pulled all the
   hero copy onto composited layers regardless. Same symptom, one step removed.

   The focus-areas ticker that used to be the one exception living here (an
   `infinite` loop, safe because its layer is never torn down) has since
   moved out of the hero entirely — it's now a static summary in the About
   Me section (#about, .asl-focus). The headline's zoom-in is the only
   animation left in the hero. Do not add another entrance effect here
   without reading the HERO HEADLINE note below first. */
.hero-anim-1,.hero-anim-2,.hero-anim-3,.hero-anim-4,.hero-anim-5,.hero-anim-6,
.hero-anim-photo{opacity:1;transform:none;animation:none}

/* Gold rule under the headline. Static. */
.hero-accent-rule{height:3px;width:132px;margin:0 0 2rem;border-radius:3px;background:linear-gradient(90deg,#F5C97B,#C5A059 60%,rgba(197,160,89,0))}

/* The hero's ambient glow orbs are defined once, further down under
   "HERO GLOW ORBS". They are static. */

/* Tagline sub text */
/* Weight 300 at this size on a dark ground reads as grey mush — 400 with a
   brighter slate holds its colour. */
.hero-tagline-sub{font-size:1.05rem;font-weight:400;color:#CBD8E8;line-height:1.7;max-width:490px;margin-bottom:0.5rem}

/* Bounded photo frame */
.hero-photo-frame{position:relative;border-radius:22px;overflow:hidden;height:520px;background:#0C1A3A;box-shadow:0 24px 60px rgba(0,0,0,0.38),0 0 0 1px rgba(56,189,248,0.18)}
/* The "Ken Burns" ambient drift that briefly lived here is reverted. It was
   added on the reasoning that a continuous animation confined to a photo,
   never overlapping text, should be safe by this file's own rules — but it
   was an unrequested addition, it landed the round immediately before a
   fresh "shaky on refresh" report, and this codebase has a proven history
   of continuous animations near the hero causing exactly that symptom
   through mechanisms that were not obvious until measured (orb-drift,
   orb-breathe). Rather than re-litigate whether this specific one was
   actually the cause, it is simply removed: the hero has no reason to carry
   any animation that was not explicitly asked for. */
.hero-frame-img{width:100%;height:100%;object-fit:cover;object-position:50% 5%;mix-blend-mode:luminosity;filter:contrast(1.1) brightness(1.05) saturate(0);display:block}
.hero-frame-overlay{position:absolute;inset:0;background:linear-gradient(to bottom,transparent 60%,rgba(2,12,27,0.55) 100%)}

@media(max-width:1100px){.hero-photo-side{flex:0 0 380px}.hero-photo-frame{height:460px}}
@media(max-width:900px){.hero-split{flex-direction:column-reverse;gap:2rem;padding:5.5rem 0 3rem;min-height:auto}.hero-photo-side{flex:0 0 auto;width:100%;max-width:380px;margin:0 auto}.hero-photo-frame{height:380px}}

/* ── SCROLLING LOGO MARQUEE ── */
/* Warm champagne band — was a pale sky-blue left over from the old palette,
   which read as washed-out and clashed with the navy/gold scheme. */
.logo-bar-v2{background:linear-gradient(135deg,#FBF7EF 0%,#F7F1E4 50%,#FAF6ED 100%);border-top:1px solid #E4D5B7;border-bottom:1px solid #E4D5B7;padding:1.25rem 0 1.5rem;overflow:hidden}
.logo-marquee-wrap{overflow:hidden;-webkit-mask:linear-gradient(to right,transparent 0%,#000 8%,#000 92%,transparent 100%);mask:linear-gradient(to right,transparent 0%,#000 8%,#000 92%,transparent 100%)}
.logo-marquee-track{display:flex;align-items:center;gap:0;width:max-content;animation:marquee-scroll 30s linear infinite}
.logo-marquee-track:hover{animation-play-state:paused}
@keyframes marquee-scroll{0%{transform:translateX(0)}100%{transform:translateX(-50%)}}
.lm-item{display:flex;align-items:center;justify-content:center;padding:0 2.5rem;flex-shrink:0}
.lm-item img{height:32px;width:auto;object-fit:contain;filter:none;opacity:1;transition:opacity 0.2s}
.lm-item img:hover{opacity:0.8}
/* Bottom margin is carried by .hero-accent-rule, which follows this heading. */
/* ══ WHY NO `vw` IN FONT-SIZE, ANYWHERE ON THIS PAGE ══════════════════════
   Every heading on the page used `clamp(min, Nvw, max)` for fluid sizing.
   That looks harmless, but Windows at a non-100% display scale (checked:
   the reporting machine runs devicePixelRatio 1.25, i.e. 125% scaling — very
   common on laptops) computes `vw` from a CSS viewport width that itself
   depends on sub-pixel layout/scrollbar-gutter timing, and Chrome does not
   always resolve that to the exact same fractional pixel on every load. The
   `clamp()` then rounds that fractional input to a slightly different
   integer font-size between one page load and the next — the actual
   mechanism behind "the font size changes when I refresh". A metric-matched
   fallback font and self-hosting fixed the TYPEFACE swapping; this fixes
   the SIZE jitter, which is a separate bug that happened to look similar.
   The fix is to never let font-size depend on viewport width: every
   heading now steps between a small, fixed number of `rem` values at
   existing breakpoints, so the input to the size is always an integer CSS
   value, never a fractional viewport measurement. Do not reintroduce `vw`
   into a font-size on this page. */
.hero-v2-h1{font-family:var(--font-display);font-weight:700;letter-spacing:-0.02em;line-height:1.18;margin:0 0 1.05rem}

/* ══ HERO HEADLINE — zoom-in restored a THIRD time, new variant ══════════
   Prior five attempts (fade+rise, unified zoom, staggered zoom ×3 tuning
   rounds) all shared one property: `will-change` was deliberately left OFF
   the element, on the reasoning that keeping it minimal reduced risk. That
   was backwards. The actual documented mechanism is: the browser promotes
   the element to its own layer while the animation runs, then is free to
   DEMOTE it once the animation finishes — and that demotion is the exact
   moment glyphs can snap between subpixel and greyscale antialiasing.
   Without `will-change`, the browser has no reason to keep the layer alive
   after `forwards` freezes the final frame, so it demotes it almost
   immediately. This version declares `will-change:opacity,transform`
   PERMANENTLY (not toggled off after the animation ends) specifically so
   the browser keeps a standing reason to leave the layer promoted
   indefinitely — the demotion this bug depends on may simply never happen.
   This is a genuinely different attempt, not a repeat of what already
   failed twice (once removed after a shaky report, restored unchanged,
   shaky again) — but it has not been battle-tested yet either. Watch for
   any shakiness after several fresh reloads; if it recurs, this really is
   just an unavoidable property of one-shot animation on this exact
   Windows/Chrome/ClearType combination and the honest fix is to stop
   asking this element to animate on load at all. */
.hero-h1-line{display:block;font-size:2.4rem;color:#fff;text-wrap:balance;opacity:0;transform:scale(0.92);transform-origin:left top;will-change:opacity,transform;animation:h1-line-zoom 800ms cubic-bezier(.22,.61,.36,1) forwards}
.hero-h1-line--1{animation-delay:400ms}
.hero-h1-line--2{animation-delay:950ms}
.hero-h1-line--3{animation-delay:1500ms}
/* One key word per line, matched to the colour each concept is
   conventionally given across the industry rather than picked for
   in-house palette reasons: blue for cloud, green for security/trust,
   violet/purple for AI (OpenAI, Copilot and most AI-branded product UI
   use this same family). */
.h1w-cloud{color:#7FB8E8}   /* blue   — cloud        */
.h1w-secure{color:#5FD98A}  /* green  — security     */
.h1w-ai{color:#A78BFA}      /* violet — AI            */
@keyframes h1-line-zoom{
  from{opacity:0;transform:scale(0.92)}
  to{opacity:1;transform:scale(1)}
}
@media(prefers-reduced-motion:reduce){
  .hero-h1-line{animation:none;opacity:1;transform:none}
}
.hero-h1-accent{
  display:inline-block;
  color:#C5A059;
}
.hero-v2-sub{font-size:1.1rem;font-weight:600;color:rgba(255,255,255,0.9);line-height:1.5;max-width:480px;margin-bottom:1rem;letter-spacing:-0.01em}
.hero-v2-actions{display:flex;flex-wrap:wrap;gap:0.625rem;margin-top:3.25rem;margin-bottom:1.25rem}
/* Primary CTA — navy to gold, executive accent */
.btn-v2-primary{display:inline-flex;align-items:center;gap:0.4rem;padding:0.85rem 1.9rem;border-radius:9px;font-size:0.85rem;font-weight:600;background:linear-gradient(135deg,#0B2545,#C5A059);color:#fff;border:none;transition:transform 0.2s,box-shadow 0.2s}
.btn-v2-primary:hover{transform:translateY(-2px);box-shadow:0 10px 28px rgba(197,160,89,0.3)}
.btn-v2-outline{display:inline-flex;align-items:center;gap:0.4rem;padding:0.85rem 1.9rem;border-radius:9px;font-size:0.85rem;font-weight:600;background:transparent;color:#fff;border:1.5px solid rgba(255,255,255,0.35);transition:border-color 0.2s,background 0.2s,transform 0.2s}
/* The icon carries its own accent colour rather than following the white
   text, so a plain outline button still reads as "industry" and colourful
   rather than flat monochrome. */
.btn-v2-outline svg{color:#F5C97B;transition:color 0.2s}
.btn-v2-outline:hover{border-color:rgba(95,184,255,0.6);background:rgba(37,99,201,0.12);transform:translateY(-1px)}
.btn-v2-outline:hover svg{color:#5FB8FF}
.btn-v2-ghost{display:inline-flex;align-items:center;gap:0.4rem;padding:0.75rem 1rem;border-radius:8px;font-size:0.82rem;font-weight:500;background:rgba(255,255,255,0.06);color:rgba(203,213,225,0.8);border:1px solid rgba(255,255,255,0.1);transition:background 0.2s,color 0.2s}
.btn-v2-ghost:hover{background:rgba(255,255,255,0.1);color:#fff}

/* Separator dividing CTA buttons from stats block */
/* .hero-stats-sep removed from the markup. The hero already carries the gold
   accent rule under the headline, and a second horizontal divider above the
   stats read as clutter. */
/* Inline stats row — kept close to CTAs for a unified feel */
.hero-v2-stats{display:flex;align-items:center;gap:1.5rem;margin-top:0;margin-bottom:1.75rem}
.hvs{display:flex;flex-direction:column;gap:0.1rem}
/* Figure takes the stat's own accent (--sc); the label under it stays a
   neutral slate so the row doesn't turn into four competing colours. */
.hvs-n{font-size:1.45rem;font-weight:800;color:var(--sc,#fff);letter-spacing:-0.03em;line-height:1}
.hvs-l{font-size:0.68rem;color:#9FB2CC;font-weight:500;letter-spacing:0.03em}
/* Optional second micro-line under a stat's label — used only by the cloud
   count, to spell out which 4 platforms without cluttering the main label. */
.hvs-l2{font-size:0.58rem;color:#7A8CA6;font-weight:400;letter-spacing:0.02em;white-space:nowrap}
.hvs-div{width:1px;height:28px;background:rgba(255,255,255,0.12)}
/* .hero-scroll-cue (and its svg child rule) removed — confirmed via
   full-file audit to be dead CSS, declared TWICE (here and further down)
   with two conflicting animations (float-y vs bounce-arrow), and never
   referenced anywhere in front-page.php. Exactly the duplicate-selector
   landmine pattern this file has been bitten by before; removed both
   copies rather than leave a live trap for a future "why isn't this
   working" investigation. */

/* ═══════════════════════════════════════════════
   EXECUTIVE DESIGN SYSTEM
   Primary:   #0B2545  deep navy
   Secondary: #333333  charcoal
   Accent:    #C5A059  gold
   Dark bg:   #0B2545  navy
   Light bg:  #F8FAFC  off-white
   ═══════════════════════════════════════════════ */

/* ─── SECTION DIVIDER ─── */
.section-divider-gradient{height:3px;background:linear-gradient(90deg,#0B2545 0%,#173A66 50%,#C5A059 100%)}

/* ─── SECTION HEADINGS — per-domain colour via --sec-c1/--sec-c2, with matching accent underline ─── */
.h-section-light{font-family:var(--font-display);font-size:2.2rem;font-weight:800;letter-spacing:-0.02em;line-height:1.15;color:var(--sec-c1,#0B2545)}
.h-section-dark{font-family:var(--font-display);font-size:2.2rem;font-weight:800;letter-spacing:-0.02em;line-height:1.15;color:var(--sec-c2,#C5A059)}
.section-hdr h2::after{content:'';display:block;width:0;height:2px;background:var(--sec-c2,#C5A059);border-radius:2px;margin-top:0.7rem;transition:width 0.8s cubic-bezier(.22,1,.36,1) 0.3s}
.section-hdr.visible h2::after{width:48px}

.section-label,.label-teal,.label-purple{display:inline-block;font-size:0.7rem;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:#0B2545;font-family:var(--font-sans)}
.section-sub{font-size:0.88rem;color:#4A5A6E;margin-top:0.5rem;max-width:520px;line-height:1.6}
.section-sub-dark{font-size:0.88rem;color:#A8BACF;margin-top:0.5rem;max-width:520px;line-height:1.6}
.logo-bar-label{font-family:var(--font-sans);font-size:0.65rem;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;color:#0B2545;text-align:center;margin-bottom:1.25rem}

/* ─── EXPERTISE LIGHT SECTION (reference card style) ─── */
.exp-light-section{background:#f8fafc;padding:4rem 0}
.exp-light-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1.25rem;margin-top:2.5rem}
/* ─── COMPETENCIES — FLAT TINTED PANELS ───
   Deliberately NOT the white-card-with-coloured-top-bar-and-shadow pattern.
   That treatment is reserved for Testimonials only; it was being reused
   here, on Transformations and on Experience simultaneously, which is what
   made the page feel repetitive. These are flat panels washed in their own
   accent, with no border, no shadow and no top rule — colour carries the
   identity instead of chrome. */
.exp-light-card{
  background:color-mix(in srgb,var(--card-c,#C5A059) 9%,#fff);
  border:none;border-radius:14px;
  padding:1.75rem 1.5rem;display:flex;flex-direction:column;gap:0.875rem;
  box-shadow:none;
  transition:background 0.3s var(--reveal-ease),transform 0.3s var(--reveal-ease);
  cursor:default
}
.exp-light-card:hover{transform:translateY(-4px);background:color-mix(in srgb,var(--card-c,#C5A059) 16%,#fff);box-shadow:none}
.exp-light-icon{width:54px;height:54px;border-radius:13px;display:flex;align-items:center;justify-content:center;flex-shrink:0;border:1.5px solid rgba(0,0,0,0.06)}
.exp-light-title{font-family:var(--font-display);font-size:0.9rem;font-weight:800;color:#0F172A;line-height:1.35;margin:0}
.exp-light-pts{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:0.5rem}
.exp-light-pts li{font-family:var(--font-sans);font-size:0.775rem;color:#475569;line-height:1.6;padding-left:1rem;position:relative}
.exp-light-pts li::before{content:'›';position:absolute;left:0;color:#C5A059;font-weight:700}
@media(max-width:1100px){.exp-light-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:640px){.exp-light-grid{grid-template-columns:1fr}}

/* Nav Book a Call pill */
.nav-book-cta{display:inline-flex;align-items:center;gap:0.35rem;padding:0.4rem 0.9rem;border-radius:99px;font-size:0.78rem;font-weight:600;background:linear-gradient(135deg,#0B2545,#C5A059);color:#fff !important;border:none;transition:transform 0.2s,box-shadow 0.2s;white-space:nowrap;margin-left:0.5rem}
.nav-book-cta:hover{transform:translateY(-1px);box-shadow:0 6px 18px rgba(197,160,89,0.28)}

/* ─── LOGO BAR v2 ─── */
.logo-bar{background:#fff;border-top:1px solid var(--border-light);border-bottom:1px solid var(--border-light);padding:1.5rem 0}
.logo-bar .logo-bar-label{font-size:0.68rem;font-weight:600;letter-spacing:0.08em;text-transform:uppercase;color:rgba(100,116,139,0.6);text-align:center;margin-bottom:1.25rem;font-family:var(--font-mono)}
.logo-bar-row{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:1.5rem 3rem}
.lb-item{display:flex;align-items:center;opacity:0.5;filter:grayscale(1);transition:opacity 0.25s,filter 0.25s}
.lb-item:hover{opacity:1;filter:grayscale(0)}
.lb-item img{height:28px;width:auto;object-fit:contain}

/* ─── CONTACT v2 — fixed alignment ─── */
.contact-left-col{display:flex;flex-direction:column;gap:1.75rem}
.contact-subtext{font-size:0.88rem;color:var(--text-body);line-height:1.75;max-width:360px}
/* ═══════════════════════════════
   CONTACT SECTION — 2-column
   ═══════════════════════════════ */
.contact-layout{display:grid;grid-template-columns:1fr 1.4fr;gap:3rem;align-items:start;margin-top:2.5rem}

/* Left — contact info */
.contact-info-col{display:flex;flex-direction:column;gap:1.5rem}
.ci-heading{font-family:var(--font-display);font-size:1.5rem;font-weight:800;color:#0F172A;letter-spacing:-0.025em;line-height:1.2}
.ci-sub{font-size:0.84rem;color:#64748B;line-height:1.7;max-width:340px}
.ci-items{display:flex;flex-direction:column;gap:0.65rem}
.ci-item{display:flex;align-items:center;gap:0.875rem;padding:0.7rem 0.875rem;border-radius:10px;background:#fff;border:1.5px solid #E8EEF6;transition:border-color 0.2s,transform 0.2s,box-shadow 0.2s;font-size:0.82rem;color:#374151;font-weight:500;text-decoration:none}
.ci-item:hover{border-color:rgba(197,160,89,0.4);transform:translateX(3px);box-shadow:0 4px 14px rgba(0,0,0,0.06)}
.ci-icon{width:34px;height:34px;border-radius:9px;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.ci-cta{display:inline-flex;align-items:center;gap:0.5rem;padding:0.7rem 1.25rem;border-radius:10px;background:linear-gradient(135deg,#0B2545,#C5A059);color:#fff;font-size:0.84rem;font-weight:600;transition:transform 0.2s,box-shadow 0.2s;align-self:flex-start}
.ci-cta:hover{transform:translateY(-2px);box-shadow:0 8px 24px rgba(197,160,89,0.32)}
.ci-location{font-size:0.75rem;color:#94A3B8;display:flex;align-items:center;gap:0.35rem}

/* Right — gradient-border form card */
.cf-card-wrap{width:100%;position:relative;border-radius:18px;padding:1px;background:#E2E8F0;box-sizing:border-box}
.cf-card-wrap .cf{border:none;box-shadow:none;border-radius:15px;background:#fff;margin:0;padding:1.75rem 2rem}

/* ─── COLOR TOKENS EXTENSION ─── */
:root{--purple:#5B6472;--purple-light:#8A93A3;--maroon:#991B1B;--red-accent:#DC2626}

/* HEADER */
.tl-header{position:fixed;top:0;left:0;right:0;z-index:1000;transition:background 0.3s,box-shadow 0.3s}
.tl-header.is-scrolled{background:rgba(11,20,38,0.94);backdrop-filter:blur(14px);box-shadow:0 1px 0 rgba(255,255,255,0.07)}
.tl-header__inner{display:flex;align-items:center;justify-content:space-between;height:64px}
.tl-header__logo{display:flex;align-items:center;gap:0.55rem}
.tl-logo-mark{width:32px;height:32px;border-radius:7px;background:linear-gradient(135deg,var(--tl-teal),var(--tl-indigo));display:flex;align-items:center;justify-content:center;flex-shrink:0}
.tl-logo-mark__initial{font-size:0.78rem;font-weight:700;color:#fff;letter-spacing:-0.02em}
.tl-logo-name{display:block;font-size:0.82rem;font-weight:600;color:#fff;line-height:1.2}
.tl-logo-subtitle{display:block;font-size:0.62rem;color:var(--text-muted-d);font-weight:400}
.tl-nav__list{display:flex;align-items:center;gap:0;list-style:none}
.tl-nav__list a{position:relative;padding:0.375rem 0.7rem;font-size:0.8rem;font-weight:500;color:rgba(255,255,255,0.82);border-radius:6px;transition:color 0.2s,background 0.2s}
.tl-nav__list a:hover{color:#fff;background:rgba(255,255,255,0.1)}
/* Active-section indicator. Colour + an absolutely-positioned underline —
   deliberately NOT a font-weight change, which would resize the text and
   re-flow the nav row on every scroll. */
.tl-nav__list a.is-active{color:#F5C97B}
.tl-nav__list a.is-active::after{content:'';position:absolute;left:0.7rem;right:0.7rem;bottom:0.05rem;height:2px;border-radius:2px;background:linear-gradient(90deg,#F5C97B,#C5A059)}
.tl-hamburger{display:none;flex-direction:column;gap:4px;width:34px;height:34px;align-items:center;justify-content:center;border-radius:6px;transition:background 0.2s}
.tl-hamburger:hover{background:var(--surface)}
.tl-hamburger__bar{display:block;width:18px;height:1.5px;background:var(--text-muted-d);border-radius:2px;transition:transform 0.25s,opacity 0.25s}
.tl-header__progress{position:absolute;bottom:0;left:0;height:2px;background:linear-gradient(90deg,var(--tl-teal),var(--tl-indigo));width:0;transition:width 0.1s linear}
.tl-nav-overlay{display:none;position:fixed;inset:0;z-index:999;background:rgba(0,0,0,0.5);backdrop-filter:blur(3px)}

/* HERO */
.hero-section{position:relative;min-height:100svh;display:flex;align-items:center;background:var(--bg-hero);overflow:hidden;padding:7rem 0 4rem}
.hero-bg-grid{position:absolute;inset:0;display:grid;grid-template-columns:repeat(auto-fill,minmax(72px,1fr));align-content:space-evenly;pointer-events:none}
.hbg-icon{display:flex;align-items:center;justify-content:center;padding:1rem;opacity:0.05;filter:grayscale(1)}
.hero-overlay{position:absolute;inset:0;background:linear-gradient(135deg,rgba(11,20,38,0.95) 0%,rgba(11,20,38,0.7) 50%,rgba(11,20,38,0.9) 100%);pointer-events:none}
.hero-inner{position:relative;z-index:2;display:grid;grid-template-columns:1fr 340px;gap:3rem;align-items:center}
.hero-eyebrow{display:flex;align-items:center;gap:0.45rem;font-size:0.72rem;font-weight:500;color:var(--tl-teal);letter-spacing:0.05em;margin-bottom:1rem;font-family:var(--font-mono)}
.eyebrow-dot{width:6px;height:6px;border-radius:50%;background:var(--tl-teal);box-shadow:0 0 0 3px rgba(197,160,89,0.2);animation:pulse-ring 2.5s ease-in-out infinite;flex-shrink:0}
.hero-name{font-family:var(--font-display);font-size:clamp(2.2rem,5vw,3.5rem);font-weight:800;letter-spacing:-0.04em;line-height:1.05;color:#fff;margin-bottom:0.875rem}
.hero-name-teal{color:var(--tl-teal)}
.hero-typed{min-height:1.4em;font-family:var(--font-mono);font-size:clamp(0.82rem,1.4vw,0.95rem);color:var(--tl-indigo-light);margin-bottom:1rem}
.hero-typed .typed-cursor{color:var(--tl-teal)}
.hero-tagline{font-size:0.9rem;font-weight:300;color:var(--text-muted-d);line-height:1.75;max-width:500px;margin-bottom:1.5rem}
.hero-pills{display:flex;flex-wrap:wrap;gap:0.4rem;margin-bottom:1.5rem}
.hp{display:inline-flex;align-items:center;gap:0.3rem;padding:0.25rem 0.65rem;border-radius:5px;background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.1);font-size:0.72rem;font-weight:500;color:var(--text-muted-d);transition:background 0.2s,color 0.2s}
.hp:hover{background:rgba(197,160,89,0.1);color:var(--tl-teal-light)}
.hero-actions{display:flex;flex-wrap:wrap;gap:0.6rem}

/* Hero book card (right) */
.hero-book-card{background:rgba(255,255,255,0.04);border:1px solid rgba(255,255,255,0.1);border-radius:16px;padding:1.5rem;backdrop-filter:blur(8px)}
.hbc-avail{display:inline-flex;align-items:center;gap:0.4rem;padding:0.22rem 0.7rem;border-radius:99px;background:rgba(47,104,68,0.12);border:1px solid rgba(47,104,68,0.25);font-size:0.68rem;font-weight:600;color:var(--tl-green);letter-spacing:0.04em;margin-bottom:1rem}
.pulse-dot{width:6px;height:6px;border-radius:50%;background:var(--tl-green);animation:pulse-ring 2s ease-in-out infinite}
.hero-book-card h3{font-family:var(--font-display);font-size:1rem;font-weight:600;color:#fff;margin-bottom:0.4rem}
.hero-book-card>p{font-size:0.8rem;color:var(--text-muted-d);line-height:1.6;margin-bottom:1.25rem}
.hbc-stats{display:flex;align-items:center;justify-content:center;gap:0.75rem;padding-top:1rem;border-top:1px solid rgba(255,255,255,0.07);margin-top:1rem}
.hbc-stat{text-align:center}
.hbc-num{display:block;font-size:1.1rem;font-weight:700;color:var(--tl-teal);letter-spacing:-0.02em}
.hbc-lbl{font-size:0.64rem;color:var(--text-dim-d)}
.hbc-div{width:1px;height:26px;background:rgba(255,255,255,0.08)}


/* ABOUT */
.about-wrap{display:grid;grid-template-columns:300px 1fr;gap:4rem;align-items:start}
.about-photo-frame{border-radius:16px;overflow:hidden;box-shadow:0 8px 32px rgba(0,0,0,0.12);margin-bottom:1.25rem;aspect-ratio:4/5}
.about-img{width:100%;height:100%;object-fit:cover;display:block}
.about-chips{display:flex;flex-direction:column;gap:0.5rem;margin-bottom:0.75rem}
.achip{display:flex;align-items:center;gap:0.6rem;padding:0.5rem 0.75rem;background:var(--bg-light);border:1px solid var(--border-light);border-radius:8px;font-size:0.78rem;font-weight:500;color:var(--text-body)}
.achip svg,.achip img{flex-shrink:0}
.about-pillars{display:grid;grid-template-columns:1fr 1fr;gap:0.75rem;margin-top:1.5rem}
.apillar{display:flex;align-items:flex-start;gap:0.625rem;padding:0.875rem;border:1px solid var(--border-light);border-radius:10px;background:#fff;transition:border-color 0.2s,box-shadow 0.2s}
.apillar:hover{border-color:var(--tl-teal);box-shadow:0 2px 10px rgba(197,160,89,0.08)}
.apillar-dot{width:28px;height:28px;border-radius:7px;display:flex;align-items:center;justify-content:center;font-size:0.7rem;font-weight:700;color:#fff;flex-shrink:0}
.apillar h4{font-size:0.78rem;font-weight:600;color:var(--text-dark);margin-bottom:0.2rem}
.apillar p{font-size:0.72rem;color:var(--text-muted-l);line-height:1.5}

/* STATS (teal band) */
.stats-row{display:grid;grid-template-columns:repeat(5,1fr);gap:0}
.sstat{text-align:center;padding:1.5rem 0.5rem;border-right:1px solid rgba(255,255,255,0.15)}
.sstat:last-child{border-right:none}
.sstat-num{font-family:var(--font-display);font-size:clamp(1.75rem,3vw,2.5rem);font-weight:800;color:#fff;letter-spacing:-0.03em;line-height:1;margin-bottom:0.3rem}
.sstat-lbl{font-size:0.72rem;font-weight:400;color:rgba(255,255,255,0.7);letter-spacing:0.02em}

/* CAREER */
.career-list{display:flex;flex-direction:column;gap:0;position:relative}
.career-list::before{content:'';position:absolute;left:10px;top:14px;bottom:14px;width:2px;background:var(--border-light)}
.cjob{display:grid;grid-template-columns:22px 1fr;gap:1rem;padding-bottom:1.5rem;position:relative}
.cjob-marker{display:flex;flex-direction:column;align-items:center;padding-top:0.15rem}
.cjob-dot{width:10px;height:10px;border-radius:50%;background:var(--border-light2);border:2px solid var(--border-light);position:relative;z-index:1;flex-shrink:0}
/* Pulses continuously (box-shadow only, non-text, never torn down) — safe
   per the compositing note at the top of this file. */
.cjob-dot--active{background:var(--tl-teal);border-color:var(--tl-teal);animation:pulse-ring 2.2s ease-in-out infinite}
/* Timeline entries: flat, no shadow, no full border box. The left edge in
   the role's colour is the only chrome — it doubles as the timeline spine,
   which is a different visual idea from the Testimonials card. */
/* border-radius is now uniform on all four corners — it used to be squared
   off on the left (0 10px 10px 0) specifically to butt up against the
   coloured border-left that has since been removed. */
.cjob-body{background:transparent;border:none;border-radius:10px;padding:1.1rem 1.25rem;transition:background 0.25s,transform 0.25s}
.cjob-body:hover{background:color-mix(in srgb,var(--jc,#C5A059) 7%,transparent);box-shadow:none}
.cjob-hdr{display:flex;align-items:flex-start;gap:0.875rem;margin-bottom:0.875rem;flex-wrap:wrap}
.cjob-logo{width:36px;height:36px;border-radius:8px;background:var(--bg-light);border:1px solid var(--border-light);display:flex;align-items:center;justify-content:center;flex-shrink:0}
.cjob-badge-txt{font-family:var(--font-mono);font-size:0.55rem;font-weight:700;color:var(--tl-teal)}
.cjob-hdr h3{font-size:0.925rem;font-weight:600;color:var(--text-dark);margin-bottom:0.15rem}
.cjob-org{font-size:0.78rem;color:var(--text-muted-l)}
.cjob-right{display:flex;flex-direction:column;align-items:flex-end;gap:0.25rem;margin-left:auto;white-space:nowrap}
.curr-badge{font-size:0.62rem;font-weight:600;padding:0.12rem 0.5rem;border-radius:99px;background:rgba(197,160,89,0.1);color:var(--tl-teal-dark);border:1px solid rgba(197,160,89,0.25)}
.cjob-period{font-size:0.7rem;color:var(--text-muted-l);font-family:var(--font-mono)}
.cjob-pts{display:flex;flex-direction:column;gap:0.4rem;margin-bottom:0.875rem}
.cjob-pts li{font-size:0.83rem;font-weight:400;color:var(--text-body);line-height:1.6;padding-left:0.875rem;position:relative}
.cjob-pts li::before{content:'';position:absolute;left:0;top:0.55em;width:4px;height:4px;border-radius:50%;background:var(--tl-teal)}
.cjob-tags{display:flex;flex-wrap:wrap;gap:0.3rem}

/* CERTIFICATIONS */
.certs-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:var(--border-light);border:1px solid var(--border-light);border-radius:14px;overflow:hidden}
.cert-cat{background:#fff;padding:1.25rem;transition:background 0.2s}
.cert-cat:hover{background:var(--bg-light)}
.cert-cat-hdr{display:flex;align-items:center;gap:0.6rem;margin-bottom:1rem;padding-bottom:0.75rem;border-bottom:1px solid var(--border-light)}
.cert-cat-hdr h3{font-size:0.82rem;font-weight:600;color:var(--text-dark);flex:1;line-height:1.3}
.cert-cat-code{font-family:var(--font-mono);font-size:0.6rem;color:var(--text-muted-l)}
.cert-cnt{width:20px;height:20px;border-radius:50%;background:rgba(197,160,89,0.1);color:var(--tl-teal-dark);font-size:0.65rem;font-weight:700;display:flex;align-items:center;justify-content:center;flex-shrink:0}
.cert-list{display:flex;flex-direction:column;gap:0.4rem}
.cert-list li{display:flex;align-items:baseline;gap:0.4rem;flex-wrap:wrap}
.cert-dot{width:4px;height:4px;border-radius:50%;background:var(--tl-teal);flex-shrink:0;margin-top:0.45em}
.cert-name-txt{font-size:0.78rem;color:var(--text-body);flex:1}
.cert-level{font-size:0.64rem;color:var(--text-muted-l);white-space:nowrap;background:var(--bg-light);padding:0.1rem 0.4rem;border-radius:4px}

/* TECH STACK */
.ts-wrap{display:flex;flex-direction:column;gap:0;border:1px solid var(--border-light);border-radius:14px;overflow:hidden;background:var(--border-light)}
.ts-cat{background:#fff;padding:1.25rem 1.5rem;border-bottom:1px solid var(--border-light)}
.ts-cat:last-child{border-bottom:none}
.ts-cat-name{font-size:0.7rem;font-weight:600;text-transform:uppercase;letter-spacing:0.1em;color:var(--text-muted-l);margin-bottom:0.875rem}
.ts-icons{display:flex;flex-wrap:wrap;gap:0.5rem}
.ts-icon{width:46px;height:46px;border-radius:9px;display:flex;align-items:center;justify-content:center;background:var(--bg-light);border:1px solid var(--border-light);transition:border-color 0.2s,box-shadow 0.2s,transform 0.2s;cursor:default}
.ts-icon:hover{border-color:var(--tl-teal);box-shadow:0 2px 10px rgba(197,160,89,0.1);transform:translateY(-2px)}

/* EXPERTISE */
.exp-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1px;background:rgba(255,255,255,0.07);border:1px solid rgba(255,255,255,0.07);border-radius:14px;overflow:hidden}
.exp-card{background:var(--bg-dark);padding:1.5rem;transition:background 0.2s}
.exp-card:hover{background:var(--surface-2)}
.exp-icon{width:38px;height:38px;border-radius:9px;background:rgba(197,160,89,0.1);display:flex;align-items:center;justify-content:center;margin-bottom:0.875rem}
.exp-card h3{font-size:0.875rem;font-weight:600;color:var(--text-white);margin-bottom:0.4rem;line-height:1.3}
.exp-card p{font-size:0.78rem;color:var(--text-muted-d);line-height:1.65;margin-bottom:0.875rem}
.exp-tags{display:flex;flex-wrap:wrap;gap:0.3rem}

/* CONTACT icon-only row */
.ci-icons-row{display:flex;flex-direction:row;gap:0.75rem;flex-wrap:wrap}
.ci-icon-btn{display:flex;align-items:center;justify-content:center;text-decoration:none;transition:transform 0.2s,box-shadow 0.2s}
.ci-icon-btn:hover{transform:translateY(-3px)}
.ci-icon-wrap{width:52px;height:52px;border-radius:14px;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 12px rgba(0,0,0,0.12)}
.cch-teal   {background:rgba(197,160,89,0.12);color:var(--tl-teal)}
.cch-linkedin{background:#0A66C2}
.cch-wa     {background:#25D366}
.cch-phone  {background:rgba(91,100,114,0.12);color:var(--tl-indigo)}
.cch-cal    {background:rgba(197,160,89,0.12);color:var(--tl-teal)}
.cch-lbl{display:block;font-size:0.82rem;font-weight:500;color:var(--text-dark)}
.cch-sub{display:block;font-size:0.7rem;color:var(--text-muted-l)}
.contact-avail{display:flex;align-items:center;gap:0.45rem;font-size:0.74rem;color:var(--text-muted-l);padding:0.5rem 0.25rem;margin-top:0.25rem}
.avail-dot{width:7px;height:7px;border-radius:50%;background:var(--tl-green);box-shadow:0 0 0 3px rgba(47,104,68,0.18);animation:pulse-ring 2.5s ease-in-out infinite;flex-shrink:0}

/* Contact form */
.cf{display:flex;flex-direction:column;gap:0.875rem;background:#fff;border:2px solid rgba(13,148,136,0.2);border-radius:16px;padding:1.75rem;box-shadow:0 4px 24px rgba(13,148,136,0.07),0 2px 8px rgba(0,0,0,0.04)}
.cf-row2{display:grid;grid-template-columns:1fr 1fr;gap:0.75rem}
.cf-g{display:flex;flex-direction:column;gap:0.35rem}
.cf-g label{font-size:0.78rem;font-weight:500;color:var(--text-body)}
.req{color:var(--tl-teal)}
.cf-g input,.cf-g select,.cf-g textarea{padding:0.575rem 0.8rem;border:1.5px solid var(--border-light);border-radius:8px;font-size:0.85rem;color:var(--text-dark);background:var(--bg-light);transition:border-color 0.2s,box-shadow 0.2s;width:100%}
.cf-g input:focus,.cf-g select:focus,.cf-g textarea:focus{border-color:#0B2545;box-shadow:0 0 0 3px rgba(11,37,69,0.12);background:#fff}
.cf-g input.has-error,.cf-g textarea.has-error{border-color:var(--tl-red)}
.cf-e{font-size:0.7rem;color:var(--tl-red);min-height:1em}
.cf-g textarea{resize:vertical;min-height:95px}
.cf-feedback{font-size:0.8rem;font-weight:500;padding:0.7rem 1rem;border-radius:8px;text-align:center;display:none}
.cf-feedback:not(:empty){display:block}
.cf-success{background:rgba(47,104,68,0.08);color:#2F6844;border:1px solid rgba(47,104,68,0.2)}
.cf-error{background:rgba(239,68,68,0.07);color:#DC2626;border:1px solid rgba(239,68,68,0.18)}

/* FOOTER — single-row minimal */
.tl-footer{background:var(--bg-hero);border-top:1px solid var(--border-dark)}
.tl-footer__bottom{padding:1.25rem 0}
.tl-footer__bottom-inner{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap;gap:1rem}
.tl-footer__copyright{font-size:0.75rem;color:var(--text-dim-d)}
.tl-social-links{display:flex;gap:0.4rem}
.tl-social-link{width:30px;height:30px;border-radius:6px;display:flex;align-items:center;justify-content:center;background:var(--surface);border:1px solid var(--border-dark);transition:background 0.2s}
.tl-social-link:hover{background:rgba(197,160,89,0.12);border-color:rgba(197,160,89,0.3)}
@media(max-width:640px){.tl-footer__bottom-inner{flex-direction:column;text-align:center;gap:0.75rem}}

/* RESPONSIVE */
@media(max-width:1100px){
  .hero-inner{grid-template-columns:1fr;gap:2.5rem}
  .hero-book-card{max-width:440px}
  .certs-grid{grid-template-columns:repeat(2,1fr)}
  .exp-grid{grid-template-columns:repeat(2,1fr)}
  .tl-footer__grid{grid-template-columns:1fr 1fr;gap:1.75rem}
  .stats-row{grid-template-columns:repeat(3,1fr)}
  .sstat:nth-child(3){border-right:none}
  .sstat:nth-child(4),.sstat:nth-child(5){border-top:1px solid rgba(255,255,255,0.15);margin-top:-1px}
}
@media(max-width:768px){
  .tl-nav__list{display:none;flex-direction:column;position:fixed;top:64px;left:0;right:0;bottom:0;background:rgba(11,20,38,0.97);padding:2rem;z-index:999;overflow-y:auto;gap:0.25rem}
  .tl-nav.is-open .tl-nav__list{display:flex}
  .tl-nav__list a{font-size:1rem;padding:0.75rem 1rem;border-radius:9px}
  .tl-hamburger{display:flex}
  .tl-nav-overlay.is-open{display:block}
  .about-wrap{grid-template-columns:1fr}
  .about-photo-frame{max-width:280px;margin-inline:auto}
  .about-pillars{grid-template-columns:1fr}
  .contact-layout{grid-template-columns:1fr}
  .cf-row2{grid-template-columns:1fr}
  .cjob-hdr{flex-direction:column}
  .cjob-right{align-items:flex-start}
  .tl-footer__grid{grid-template-columns:1fr}
  .certs-grid{grid-template-columns:repeat(2,1fr)}
  .exp-grid{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:480px){
  .tl-container{padding-inline:1rem}
  .hero-actions{flex-direction:column}
  .hero-actions .btn{width:100%;justify-content:center}
  .certs-grid{grid-template-columns:1fr}
  .exp-grid{grid-template-columns:1fr}
  .stats-row{grid-template-columns:repeat(2,1fr)}
  .sstat:nth-child(5){grid-column:1/-1;border-right:none;border-top:1px solid rgba(255,255,255,0.15)}
}

/* ─── HERO SPLIT (photo on right) ─── */
.hero-split-inner{display:grid;grid-template-columns:1fr auto;align-items:center;gap:4rem;padding:4rem 0 3rem}
.hero-photo-wrap{display:flex;flex-direction:column;align-items:center;gap:0.75rem;flex-shrink:0}
.hero-photo-ring{width:240px;height:240px;border-radius:50%;padding:4px;background:linear-gradient(135deg,var(--tl-teal) 0%,var(--tl-indigo) 100%);box-shadow:0 0 0 10px rgba(197,160,89,0.12)}
.hero-photo-img{width:100%;height:100%;border-radius:50%;object-fit:cover;object-position:center top;display:block}
.hero-photo-badge{display:flex;align-items:center;gap:0.4rem;background:rgba(255,255,255,0.12);border:1px solid rgba(255,255,255,0.2);border-radius:30px;padding:0.3rem 0.75rem;backdrop-filter:blur(8px)}
.hero-photo-badge span{font-size:0.7rem;color:#fff;font-weight:600;font-family:var(--font-mono)}

/* ─── EMPLOYER LOGO BAR (legacy .logo-bar variant) ───
   Scoped to .logo-bar. Unscoped, this .logo-bar-label rule was overriding the
   navy one defined for .logo-bar-v2 above (same specificity, later wins),
   which is why the live "Trusted by Industry Leaders" label rendered grey. */
.logo-bar{background:#fff;border-top:1px solid var(--border-light);border-bottom:1px solid var(--border-light);padding:1.25rem 0}
.logo-bar .logo-bar-label{font-size:0.65rem;font-weight:600;text-transform:uppercase;letter-spacing:0.1em;color:var(--text-muted-l);margin-bottom:1rem;text-align:center}
.logo-bar-row{display:flex;align-items:center;justify-content:center;flex-wrap:wrap;gap:1.5rem 2.5rem}
.lb-item{display:flex;align-items:center;gap:0.5rem;opacity:0.55;transition:opacity 0.2s;filter:grayscale(1)}
.lb-item:hover{opacity:1;filter:grayscale(0)}
.lb-item span{font-size:0.75rem;font-weight:600;color:var(--text-dark);white-space:nowrap}

/* ─── ABOUT SPLIT ─── */
.about-split-section{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);min-height:480px}
.about-split-left{padding:4.5rem 4rem 4.5rem 2.5rem;display:flex;flex-direction:column;justify-content:center;background:linear-gradient(160deg,#F8F6F1 0%,#F3EFE7 40%,#EFEADF 100%)}
.asl-eyebrow{font-size:0.78rem;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;color:#0B2545}
.asl-rule{width:56px;height:3px;background:linear-gradient(90deg,#0B2545,#C5A059);border-radius:2px;margin:1.1rem 0 1.5rem}

/* ─── ABOUT LEFT — thick colour band under the heading ───
   Replaces the leadership-pillar list that used to sit here (its content
   duplicated Competencies/Experience/Transformations). Non-text element, so
   it can carry a wipe-in without touching glyph rasterisation. */
/* Went through two overcorrections: 300px ran well past "About Me" and read
   as a stray line past the end of the heading; the fix (90px) swung too far
   the other way and only covered roughly the width of "About" — well under
   half of the full "About Me" text (measured ~223px at this font-size).
   Set to match the heading's actual rendered width instead of picking a
   number by eye a third time. */
.asl-band{
  margin-top:1.5rem;height:10px;width:220px;border-radius:6px;
  background:linear-gradient(90deg,#C08A1E 0%,#C23B63 28%,#5B4FD6 52%,#2563C9 74%,#0C9488 100%);
  transform:scaleX(0);transform-origin:left center;
  transition:transform 0.9s cubic-bezier(.22,.68,.36,1) 0.15s
}
.about-split-left.visible .asl-band{transform:scaleX(1)}
@media(prefers-reduced-motion:reduce){
  .asl-band{transform:scaleX(1);transition:none}
}
.asl-heading{font-family:var(--font-display);font-size:2.3rem;font-weight:800;color:#0B2545;line-height:1.16;letter-spacing:-0.03em}

/* Leadership focus areas — moved here from the hero (was a rolling ticker
   there; a static summary reads better in "About Me" than in a hero meant
   to be scanned at a glance). No entrance animation of its own — see the
   note in front-page.php for why.
   First version coloured the tag's text and border directly with the vivid
   --tc hue (the same jewel tones the old hero ticker used). Those hues are
   tuned for a dark navy background — against this column's pale cream
   (#F8F6F1→#EFEADF) several of them (mint, sky, amber especially) don't
   clear a readable contrast ratio and the set as a whole read as too bright
   / vibrating against the light ground. Redesigned so the colour carries
   the identity via a small dot only, while the label itself is always the
   same high-contrast ink colour — legible regardless of which hue it is. */
/* Third pass on this block.
   v1: flex-wrap pills sized to their own text — left ~135-140px empty on
   the right of every row and ~335px next to the odd 7th item.
   v2: single-column stack of full-width rows — fixed the raggedness but
   made the whole column ~190px taller (7 rows instead of 4 wrapped ones),
   and .about-split-section grid-stretches both columns to match the taller
   one, so that extra height pushed the entire About section down.
   v3 (this one): back to pill-shaped chips, but arranged on a 2-column
   GRID instead of flex-wrap — a grid cell's width is fixed by the column
   track, not by its content, so each pill still stretches edge-to-edge
   with no leftover gap, without needing a full extra row per item. Back to
   ~4 short rows, so height goes back to roughly what it was, and the
   column no longer grows past what the right side's three paragraphs need.
   Dot marker gets a soft circular halo (a colour-mixed ring) instead of
   sitting bare, for a bit more presence at this smaller pill size. */
.asl-focus{margin-top:1.75rem}
.asl-focus-label{font-size:0.68rem;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;color:#0B2545;margin-bottom:0.75rem;display:block}
.asl-focus-tags{display:grid;grid-template-columns:1fr 1fr;gap:0.5rem 1.5rem}
/* Fourth pass on this block — the boxed chip (white bg/border/shadow,
   border-radius:8px) read fine on wide desktop columns but at tablet/mobile
   widths, where the grid narrows and labels like "Site Reliability &
   Operational Resilience" wrap, the box stretched into a tall, un-compact
   rectangle around wrapped text — reported as a problem at width beyond the
   old ≤640px-only fix, so the box is dropped entirely at every breakpoint
   now rather than splitting the look by screen size. Identity carried by a
   small colour dot (from the item's own --tc) instead of the box; the list
   itself is just plain compact text rows on both columns and single-column
   layouts. */
.asl-tag{display:flex;align-items:center;width:auto;font-size:0.76rem;font-weight:600;color:#1E293B;padding:0.1rem 0 0.1rem 1rem;border-radius:0;background:none;border:none;box-shadow:none;position:relative}
.asl-tag::before{content:'';position:absolute;left:0;top:50%;width:6px;height:6px;border-radius:50%;background:var(--tc);transform:translateY(-50%)}
@media(max-width:640px){
  .asl-focus-tags{grid-template-columns:1fr;gap:0.6rem}
}
.about-split-right{padding:4.5rem 3.5rem;display:flex;flex-direction:column;justify-content:center;background:linear-gradient(135deg,#081A33 0%,#0B2545 40%,#12305A 100%);color:#fff;position:relative;overflow:hidden}
.about-split-right::before{content:'';position:absolute;top:-60px;right:-60px;width:280px;height:280px;border-radius:50%;background:radial-gradient(circle,rgba(197,160,89,0.16) 0%,transparent 70%);pointer-events:none}
.about-split-right::after{content:'';position:absolute;bottom:-40px;left:-40px;width:200px;height:200px;border-radius:50%;background:radial-gradient(circle,rgba(197,160,89,0.1) 0%,transparent 70%);pointer-events:none}
/* About now runs three paragraphs instead of one; space them apart. */
.asr-summary{font-size:1rem;color:rgba(203,213,225,0.92);line-height:1.9;position:relative;z-index:1;margin-bottom:1rem}
.asr-summary:last-child{margin-bottom:0}

/* About certs (left panel) */
.asl-certs{margin-top:1.75rem;padding-top:1.5rem;border-top:1px solid #E9EEF4}
.asl-certs-label{font-size:0.68rem;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;color:#0B2545;margin-bottom:0.75rem}
.asl-cert-tags{display:flex;flex-wrap:wrap;gap:0.45rem}
.asl-cert-tag{font-size:0.7rem;font-weight:600;padding:0.25rem 0.65rem;border-radius:99px;border:1.5px solid var(--ct,#0B2545);color:var(--ct,#0B2545);background:color-mix(in srgb,var(--ct,#0B2545) 8%,transparent);white-space:nowrap}

/* About partnerships (right panel) */
.asr-partnerships{margin-top:1.5rem;position:relative;z-index:1}
.asr-partner-label{font-size:0.68rem;font-weight:700;letter-spacing:0.1em;text-transform:uppercase;color:rgba(45,212,191,0.8);margin-bottom:0.875rem}
.asr-partner-grid{display:grid;grid-template-columns:1fr 1fr;gap:0.65rem}
.asr-partner-item{display:flex;align-items:center;gap:0.625rem;background:rgba(255,255,255,0.06);border:1px solid rgba(255,255,255,0.1);border-radius:10px;padding:0.55rem 0.75rem}
.asr-partner-item span{font-size:0.75rem;color:rgba(203,213,225,0.9);font-weight:500;line-height:1.3}
.asr-partner-icon{width:30px;height:30px;border-radius:7px;display:flex;align-items:center;justify-content:center;flex-shrink:0}

/* ─── EXPERTISE COMPACT GRID ─── */
.exp-compact-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem}
.exp-compact-card{background:#fff;border:1px solid var(--border-light);border-radius:10px;padding:1.25rem;transition:box-shadow 0.2s,transform 0.2s}
.exp-compact-card:hover{box-shadow:0 4px 16px rgba(0,0,0,0.07);transform:translateY(-2px)}
.ecc-list{display:flex;flex-direction:column;gap:0.3rem}
.ecc-list li{font-size:0.75rem;color:var(--text-body);line-height:1.5;padding-left:0.875rem;position:relative}
.ecc-list li::before{content:'·';position:absolute;left:0;color:var(--tl-teal);font-weight:700;font-size:1rem;line-height:1.3}

/* ─── TOOLS MARQUEE ─── */
#tech-stack{overflow:hidden}
.ts-marquee-wrap{overflow:hidden;padding:0.5rem 0;max-width:100%;mask-image:linear-gradient(90deg,transparent 0%,#000 6%,#000 94%,transparent 100%);-webkit-mask-image:linear-gradient(90deg,transparent 0%,#000 6%,#000 94%,transparent 100%)}
.ts-marquee{display:flex;gap:0.75rem;width:max-content;animation:ts-scroll 40s linear infinite}
.ts-marquee--reverse{animation-direction:reverse;animation-duration:45s}
.ts-marquee:hover{animation-play-state:paused}
@keyframes ts-scroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.tsm-item{display:flex;align-items:center;gap:0.5rem;background:#fff;border:1px solid var(--border-light);border-radius:8px;padding:0.5rem 0.875rem;white-space:nowrap;transition:border-color 0.2s,box-shadow 0.2s}
.tsm-item:hover{border-color:var(--tl-teal);box-shadow:0 2px 8px rgba(197,160,89,0.12)}
.tsm-item span{font-size:0.72rem;font-weight:500;color:var(--text-body)}

/* ─── PROJECTS (simplified — no bottom bar) ─── */
.proj-card{background:#fff;border:1px solid var(--border-light);border-radius:14px;padding:1.5rem;display:flex;flex-direction:column;transition:box-shadow 0.25s,transform 0.25s}
.proj-card:hover{box-shadow:0 6px 24px rgba(0,0,0,0.08);transform:translateY(-3px)}
.proj-meta{display:flex;align-items:center;gap:0.5rem}
.proj-label{font-size:0.67rem;font-weight:600;letter-spacing:0.07em;text-transform:uppercase;font-family:var(--font-mono)}
.proj-card h3{font-size:0.9rem;font-weight:600;color:var(--text-dark);margin-bottom:0.5rem;line-height:1.35;margin-top:0.625rem}
.proj-card p{font-size:0.8rem;color:var(--text-body);line-height:1.7;flex:1}

/* ─── TESTIMONIALS (no stars, simplified) ─── */
.testi-card{width:360px;flex-shrink:0;background:#fff;border:1px solid var(--border-light);border-radius:14px;padding:1.5rem;box-shadow:0 2px 12px rgba(0,0,0,0.04)}
.testi-quote{font-size:0.83rem;color:var(--text-body);line-height:1.75;margin-bottom:1.1rem;font-style:italic}
.testi-author{display:flex;align-items:center;gap:0.625rem}
.testi-avatar{width:32px;height:32px;border-radius:50%;background:linear-gradient(135deg,var(--tl-teal),var(--tl-indigo));display:flex;align-items:center;justify-content:center;font-size:0.75rem;font-weight:700;color:#fff;flex-shrink:0}
.testi-author strong{font-size:0.8rem;font-weight:600;color:var(--text-dark)}

/* ─── CONTACT ICON-ONLY channels ─── */
.cch.cch-icon-only{flex-direction:column;align-items:center;text-align:center;padding:1.25rem 0.75rem;gap:0.5rem;min-width:80px;flex:1}
.cch.cch-icon-only .cch-icon{width:44px;height:44px;border-radius:12px}
.cch.cch-icon-only .cch-lbl{font-size:0.72rem;font-weight:600;color:var(--text-dark)}
.contact-channels{display:flex;flex-wrap:wrap;gap:0.75rem;align-items:stretch}

/* ─── ABOUT HIGHLIGHTS ─── */
.about-highlights{display:flex;gap:1.5rem}
.ah-item{display:flex;flex-direction:column;align-items:flex-start}
.ah-num{font-family:var(--font-display);font-size:1.75rem;font-weight:800;color:var(--tl-teal-dark);letter-spacing:-0.03em;line-height:1}
.ah-lbl{font-size:0.72rem;color:var(--text-muted-l);margin-top:0.2rem}

/* ─── CERTIFICATIONS — 4-col × 2-row dark grid ─── */
.cert-cats-grid{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;background:rgba(255,255,255,0.07);border:1px solid rgba(255,255,255,0.08);border-radius:18px;overflow:hidden}
.cert-cat-card{background:#0F1D2E;padding:1.5rem 1.25rem;transition:background 0.25s,box-shadow 0.25s}
.cert-cat-card:hover{background:#142233;box-shadow:inset 0 0 0 1px rgba(197,160,89,0.25)}
.cert-cat-head{display:flex;align-items:flex-start;gap:0.625rem;margin-bottom:1.1rem;padding-bottom:0.875rem;border-bottom:1px solid rgba(255,255,255,0.08)}
.cert-cat-icon{flex-shrink:0;margin-top:2px}
.cert-cat-head h3{font-size:0.8rem;font-weight:600;color:var(--tl-teal);line-height:1.3}
.cert-items-list{display:flex;flex-direction:column;gap:0.75rem}
.cert-items-list li{display:flex;align-items:flex-start;gap:0.625rem}
.cert-logo-sm{width:34px;height:34px;border-radius:8px;background:rgba(255,255,255,0.07);display:flex;align-items:center;justify-content:center;flex-shrink:0;padding:5px;border:1px solid rgba(255,255,255,0.07)}
.cert-item-info{display:flex;flex-direction:column;gap:0.15rem;min-width:0}
.cert-item-name{font-size:0.76rem;color:#e2e8f0;line-height:1.35;font-weight:500}
.cert-item-issuer{font-size:0.66rem;color:#9BAFC6;line-height:1.2}
.cert-txt-badge{font-size:0.55rem;font-weight:700;color:var(--tl-teal);letter-spacing:0.04em;font-family:var(--font-mono);text-align:center;line-height:1}
/* local brand logos — white bg so colours show correctly */
.cert-logo-sm--local{background:#fff !important;border-color:rgba(255,255,255,0.18) !important;padding:4px !important}
.cert-logo-sm--local img{object-fit:contain;width:28px;height:28px}

/* ─── TECH STACK (horizontal rows) ─── */
.ts-table{display:flex;flex-direction:column;border:1px solid var(--border-light);border-radius:14px;overflow:hidden}
.ts-row{display:flex;align-items:center;gap:1.5rem;padding:0.875rem 1.25rem;border-bottom:1px solid var(--border-light);background:#fff;transition:background 0.15s}
.ts-row:last-child{border-bottom:none}
.ts-row:hover{background:var(--bg-light)}
.ts-row-label{font-size:0.7rem;font-weight:600;color:var(--text-muted-l);text-transform:uppercase;letter-spacing:0.08em;min-width:175px;flex-shrink:0}
.ts-row-icons{display:flex;flex-wrap:wrap;gap:0.4rem;align-items:center}
.ts-icon{width:38px;height:38px;border-radius:8px;display:flex;align-items:center;justify-content:center;background:var(--bg-light);border:1px solid var(--border-light);transition:border-color 0.2s,transform 0.2s;cursor:default}
.ts-icon:hover{border-color:var(--tl-teal);transform:translateY(-2px)}

/* ─── EXPERTISE LIGHT (service cards) ─── */
.exp-grid-light{display:grid;grid-template-columns:repeat(3,1fr);gap:1.25rem}
.exp-card-light{background:#fff;border:1px solid var(--border-light);border-radius:12px;padding:1.5rem;position:relative;transition:box-shadow 0.2s,border-color 0.2s,transform 0.2s;overflow:hidden}
.exp-card-light:hover{box-shadow:0 6px 24px rgba(0,0,0,0.07);border-color:var(--tl-teal);transform:translateY(-2px)}
.ecl-dot{position:absolute;top:0;left:0;right:0;height:3px}
.exp-card-light h3{font-size:0.9rem;font-weight:600;color:var(--text-dark);margin-bottom:0.5rem;margin-top:0.25rem}
.exp-card-light p{font-size:0.8rem;color:var(--text-body);line-height:1.65;margin-bottom:0.875rem}

/* ─── KEY TRANSFORMATIONS — compact 2-up grid, each transformation in one box ─── */
.proj-section{background:#F1F5F9;padding:4rem 0}
.proj-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:1.5rem;margin-top:2.5rem}
/* ─── TRANSFORMATIONS — FLAT OUTLINED TILES ───
   No drop shadow and no coloured top bar: those belong to Testimonials.
   These read as case-study tiles — a full-bleed illustration above a plain
   outlined body, where the only colour on the frame is a hairline in the
   project's own accent that strengthens on hover. */
.proj-card{
  background:#fff;
  /* padding:0 overrides a stray padding:1.5rem left over from an older
     .proj-card rule earlier in this file (line ~637, pre-redesign, mostly
     superseded but never fully removed). This block was documented as
     "full-bleed illustration above a plain outlined body", but the old
     rule's padding was silently wrapping the image in 24px on every side —
     found live via getComputedStyle while investigating "images taking too
     much space". display/flex-direction are left to inherit from that old
     rule on purpose: .proj-card p{flex:1} further down depends on the card
     being a flex column to equalise card heights in the grid. */
  padding:0;
  border:1px solid color-mix(in srgb,var(--pc,#C5A059) 22%,#E8EEF6);
  border-radius:14px;overflow:hidden;box-shadow:none;
  transition:border-color 0.3s var(--reveal-ease),transform 0.3s var(--reveal-ease),background 0.3s
}
.proj-card:hover{
  border-color:color-mix(in srgb,var(--pc,#C5A059) 62%,transparent);
  background:color-mix(in srgb,var(--pc,#C5A059) 4%,#fff);
  box-shadow:none;transform:translateY(-4px)
}
/* Was 130px (a deliberate increase from an original 56px that squashed the
   custom per-project SVGs into an unreadable strip). Feedback was that
   130px is now too much space per card — reduced to 100px, still well
   above the 56px that was illegible, and the .proj-card padding fix above
   already recovers more visual space than this alone would. */
.proj-img{height:100px;position:relative;overflow:hidden}
.proj-img-shapes{position:absolute;inset:0;width:100%;height:100%;opacity:0.9}
.proj-body{padding:1rem 1.3rem 1.3rem}
.proj-label{display:block;font-family:var(--font-sans);font-size:0.64rem;font-weight:700;letter-spacing:0.09em;text-transform:uppercase}
.proj-body h3{font-family:var(--font-display);font-size:1rem;font-weight:800;color:#0B2545;line-height:1.3;margin:0.35rem 0 0}
.proj-body p{font-family:var(--font-sans);font-size:0.82rem;color:#475569;line-height:1.6;margin:0.4rem 0 0}
/* Strategic Outcomes */
.proj-sublabel{display:block;font-family:var(--font-sans);font-size:0.64rem;font-weight:700;letter-spacing:0.08em;text-transform:uppercase;color:#94A3B8;margin-bottom:0.4rem}
.proj-deliverables{margin-top:0.75rem}
.proj-deliverables ul{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:0.3rem}
.proj-deliverables li{font-family:var(--font-sans);font-size:0.78rem;color:#475569;line-height:1.45;padding-left:1.05rem;position:relative}
/* --pc is set on the card; --tc is only set on the tech tags, so this
   bullet was silently falling back to gold on every project. */
.proj-deliverables li::before{content:'';position:absolute;left:0;top:0.5em;width:5px;height:5px;border-radius:50%;background:var(--pc,#C5A059)}
/* Platforms Leveraged */
.proj-tech{margin-top:0.85rem;padding-top:0.85rem;border-top:1px solid #F1F5F9}
.proj-tech-tags{display:flex;flex-wrap:wrap;gap:0.35rem;margin-top:0.4rem}
/* Tinted with the project's own accent instead of near-white on white.
   #F8FAFC on #fff with grey text was effectively invisible — the services
   and platforms are the credibility signal on these cards, so they need to
   actually read as tags. */
.proj-tech-tag{
  font-family:var(--font-sans);font-size:0.66rem;font-weight:600;
  padding:0.28rem 0.65rem;border-radius:99px;white-space:nowrap;
  background:color-mix(in srgb,var(--tc,#C5A059) 12%,#fff);
  border:1px solid color-mix(in srgb,var(--tc,#C5A059) 34%,transparent);
  color:color-mix(in srgb,var(--tc,#C5A059) 78%,#0B2545);
  transition:background 0.2s,border-color 0.2s,transform 0.2s
}
.proj-tech-tag:hover{background:color-mix(in srgb,var(--tc,#C5A059) 20%,#fff);transform:translateY(-1px)}
@media(max-width:800px){
  .proj-grid{grid-template-columns:1fr}
}

/* ─── MISSING CLASSES FIX ─── */
.label-indigo{display:inline-block;font-size:0.7rem;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;color:#5B6472;font-family:var(--font-sans)}
.btn-outline-dark{display:inline-flex;align-items:center;gap:0.4rem;padding:0.75rem 1.5rem;border-radius:8px;font-size:0.85rem;font-weight:600;background:transparent;color:#0F172A;border:1.5px solid #CBD5E1;transition:border-color 0.2s,background 0.2s}
.btn-outline-dark:hover{border-color:#0F172A;background:#F8FAFC}
.section-light-2{background:#F8FAFC}
.tag{display:inline-flex;align-items:center;padding:0.2rem 0.6rem;border-radius:99px;font-size:0.68rem;font-weight:600;letter-spacing:0.04em;background:rgba(197,160,89,0.1);color:#0B2545;border:1px solid rgba(197,160,89,0.2);font-family:var(--font-sans)}
.tag-light{display:inline-flex;align-items:center;padding:0.2rem 0.6rem;border-radius:99px;font-size:0.68rem;font-weight:600;letter-spacing:0.04em;background:#F1F5F9;color:#475569;border:1px solid #E2E8F0;font-family:var(--font-sans)}

/* ─── FORM SUBMIT BUTTON ─── */
.btn-primary{display:inline-flex;align-items:center;justify-content:center;gap:0.5rem;padding:0.85rem 2rem;border-radius:8px;font-size:0.9rem;font-weight:600;background:linear-gradient(135deg,#0B2545,#C5A059);color:#fff;border:none;cursor:pointer;transition:transform 0.2s,box-shadow 0.2s}
.btn-primary:hover{transform:translateY(-2px);box-shadow:0 8px 28px rgba(197,160,89,0.3)}
.btn-full{width:100%}
/* ─── SECTION LABEL COLORS (per section) ─── */
.label-orange{color:#C5A059;font-size:0.7rem;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;font-family:var(--font-sans)}
#certifications .section-label,.label-sky{color:#0B2545;font-size:0.7rem;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;font-family:var(--font-sans)}
#expertise .section-label,.label-emerald{color:#0B2545;font-size:0.7rem;font-weight:700;letter-spacing:0.12em;text-transform:uppercase;font-family:var(--font-sans)}
/* ─── SECTION COLOR VARIETY ─── */
#projects{background:var(--bg-light)}
#testimonials{background:#fff}
#expertise{background:linear-gradient(180deg,#F8F6F1 0%,#F8FAFC 100%)}
.section-teal-band{background:linear-gradient(135deg,#0B2545 0%,#173A66 50%,#C5A059 100%)}

/* ─── CAREER TIMELINE COLOUR ACCENTS ───
   Each role sets --jc inline in front-page.php. It used to also draw a 3px
   coloured border-left on .cjob-body, running the full height of the card
   right next to the timeline's own spine (.career-list::before) — visually
   two parallel vertical lines per entry, which is exactly the clutter that
   was flagged. Removed. The timeline spine is the only vertical line now;
   colour identity lives in the dot, the tags and the hover tint instead. */
.cjob .cjob-dot{background:var(--jc,#C5A059);border-color:color-mix(in srgb,var(--jc,#C5A059) 40%,#fff)}
/* No box-shadow — flat is the point here; the shadowed card is reserved for
   Testimonials. Hover is the background tint set with the base rule. */
/* Tags inherit the role's colour instead of every role sharing one gold. */
.cjob .tag-light{background:color-mix(in srgb,var(--jc,#C5A059) 13%,#fff);color:color-mix(in srgb,var(--jc,#C5A059) 72%,#0B2545);border-color:color-mix(in srgb,var(--jc,#C5A059) 32%,transparent)}
/* Foot band, wipes in with the card. Non-text element. */
/* .cjob-band — the full-width horizontal rule under each role's tags — has
   been removed. Between the timeline's vertical line, the dot, the card's
   left colour spine, and this band, each entry was carrying four separate
   line elements; the band was the one adding nothing (the spine already
   identifies the role's colour). */

/* ─── EXPERTISE CARD BACKGROUNDS ─── */
.exp-compact-card:nth-child(1){background:linear-gradient(135deg,#F0FDFA,#fff)}
.exp-compact-card:nth-child(2){background:linear-gradient(135deg,#EEF2FF,#fff)}
.exp-compact-card:nth-child(3){background:linear-gradient(135deg,#FFF7ED,#fff)}
.exp-compact-card:nth-child(4){background:linear-gradient(135deg,#F0FDFA,#fff)}
.exp-compact-card:nth-child(5){background:linear-gradient(135deg,#EEF2FF,#fff)}
.exp-compact-card:nth-child(6){background:linear-gradient(135deg,#FFF7ED,#fff)}
.exp-compact-card:nth-child(7){background:linear-gradient(135deg,#F0FDF4,#fff)}
.exp-compact-card:nth-child(8){background:linear-gradient(135deg,#EEF2FF,#fff)}

/* ─── CERT CARD HOVER GLOW ─── */
.cert-cat-card{transition:background 0.25s,box-shadow 0.25s}
.cert-cat-card:hover{box-shadow:0 0 0 1px rgba(197,160,89,0.3),0 4px 20px rgba(197,160,89,0.12)}

/* ─── TOOL MARQUEE ITEM COLORS ─── */
.ts-marquee:nth-child(odd) .tsm-item:hover{border-color:var(--tl-teal);box-shadow:0 2px 10px rgba(197,160,89,0.15)}
.ts-marquee:nth-child(even) .tsm-item:hover{border-color:var(--tl-indigo);box-shadow:0 2px 10px rgba(91,100,114,0.15)}

/* ─── TESTI CARD ACCENT ─── */
.testi-card{border-top:3px solid transparent}

/* ─── ENHANCED ANIMATIONS ─── */
@keyframes float-y{0%,100%{transform:translateY(0)}50%{transform:translateY(-10px)}}
/* fade-up / scale-in / pulse-glow / slide-in-left / slide-in-right / count-up
   were defined here but referenced by nothing — removed. Several of them
   scaled or bounced text, so they were also a standing invitation to
   reintroduce the shimmer described in the hero note above. */

/* ══ SCROLL REVEAL ══════════════════════════════════════════════════════
   Text must never be scaled or bounced. A scale() on a text element makes
   the browser rasterise the glyphs at the wrong size and re-rasterise at
   the end, which reads as blur then a visible "snap"; an overshoot easing
   (cubic-bezier with a control point > 1) adds a literal bounce on top.
   Together those were the source of the shaky/bumpy headings.

   Rules now enforced site-wide:
     • no scale() on anything containing text — reveal or hover
     • no overshoot easings — one decelerating curve everywhere
     • short travel (10-14px) so the motion settles fast
     • headings and body copy fade with NO transform at all
   ───────────────────────────────────────────────────────────────────── */
:root{--reveal-ease:cubic-bezier(0.22,0.61,0.36,1);--reveal-dur:0.55s}

/* Containers never animate, for the compositing reason set out in the hero
   note at the top of this file. Every one of them holds text, and fading or
   sliding a container composites the text inside it.

   The [data-anim] attribute is kept, and main.js still adds .visible when an
   element scrolls into view, because that class is what drives the motion
   that DOES run: icons zooming, accent rules sweeping, credential logos
   popping. All of those are vector or solid-colour elements with no glyphs,
   so they can be composited freely. See the Core Competencies and Credentials
   block further down for the pattern to follow when adding more. */
[data-anim],
[data-anim="left"],[data-anim="right"],[data-anim="top"],
[data-anim="scale"],[data-anim="zoom-in"],[data-anim="zoom-out"],[data-anim="fade"],
[data-anim].visible{opacity:1;transform:none;transition:none}

/* About split — the large "Technology & Engineering Leadership." heading and
   the summary paragraph both stay static (see the section-header note above).
   The .asl-rule divider carries the entrance instead. */
.about-split-left[data-anim],
.about-split-right[data-anim],
.about-split-left[data-anim].visible,
.about-split-right[data-anim].visible{opacity:1;transform:none;transition:none}
.asl-rule{transform:scaleX(0);transform-origin:left center;transition:transform 0.7s var(--reveal-ease) 0.1s}
.about-split-left.visible .asl-rule{transform:scaleX(1)}

/* Section headers — heading text is static, exactly like the hero, and for the
   same reason: an opacity fade promotes the h2 to a composited layer, which
   drops subpixel antialiasing and makes the glyphs change weight when the
   layer is torn down. The reveal is carried instead by the gold rule under
   the heading (.section-hdr h2::after), which animates `width` — a paint
   property that never triggers compositing. JS still adds .visible here, so
   the rule still draws itself in on scroll. */
.section-hdr[data-anim],
.section-hdr[data-anim="top"],
.section-hdr[data-anim="left"],
.section-hdr[data-anim="zoom-in"],
.section-hdr[data-anim="zoom-out"],
.section-hdr[data-anim].visible{opacity:1;transform:none;transition:none}

/* ══ WHOLE-CARD SCROLL REVEALS ══════════════════════════════════════════
   Cards DO animate as whole cards. This is a deliberate, requested change
   from the previous approach (which animated only the thin accent rules and
   icons while the cards themselves stayed static).

   Why this is an acceptable place to move text, when the hero is not:
   these are ONE-SHOT transitions that run as an element scrolls into view,
   while the reader's eye is already moving, and they end cleanly on
   `transform:none; opacity:1`. The antialiasing flip when the composited
   layer is released lasts a single frame and lands on content the reader
   has not begun reading yet. The hero is the opposite case — static copy
   the reader is looking directly at — which is why it stays untouched, and
   why nothing behind text is ever given a looping animation.

   One distinct movement per section, so no two sections share a pattern:
     Experience      → slide in from the left  (timeline reads left to right)
     Credentials     → drop down from above
     Competencies    → zoom in from the centre
     Transformations → alternate right / left, column by column
     Contact         → rise from below
   ───────────────────────────────────────────────────────────────────── */
:root{--card-ease:cubic-bezier(.22,.68,.36,1);--card-dur:0.62s}

/* Experience — slide from the left */
.cjob[data-anim]{opacity:0;transform:translateX(-38px);transition:opacity var(--card-dur) var(--card-ease),transform var(--card-dur) var(--card-ease)}
.cjob[data-anim].visible{opacity:1;transform:none}

/* Credentials — drop in from above */
.cert-cat-card[data-anim]{opacity:0;transform:translateY(-26px);transition:opacity var(--card-dur) var(--card-ease),transform var(--card-dur) var(--card-ease)}
.cert-cat-card[data-anim].visible{opacity:1;transform:none}

/* Competencies — zoom in from the centre */
.exp-light-card[data-anim]{opacity:0;transform:scale(0.88);transition:opacity var(--card-dur) var(--card-ease),transform var(--card-dur) var(--card-ease)}
.exp-light-card[data-anim].visible{opacity:1;transform:none}
.exp-light-card{scroll-margin-top:80px}

/* Transformations — alternate sides, reverted back to this (the brief
   switch to "every card from the same side" wasn't liked once seen live).
   The grid is two columns, so odd cards come from the right and even from
   the left, meeting in the middle. */
.proj-card[data-anim]{opacity:0;transform:translateX(44px);transition:opacity 0.7s var(--card-ease),transform 0.7s var(--card-ease)}
.proj-card[data-anim]:nth-child(even){transform:translateX(-44px)}
.proj-card[data-anim].visible{opacity:1;transform:none}

/* Contact — rise from below */
.contact-info-col[data-anim],.cf-card-wrap[data-anim],.sstat[data-anim]{opacity:0;transform:translateY(30px);transition:opacity var(--card-dur) var(--card-ease),transform var(--card-dur) var(--card-ease)}
.cf-card-wrap[data-anim]{transition-delay:0.1s}
.contact-info-col[data-anim].visible,.cf-card-wrap[data-anim].visible,.sstat[data-anim].visible{opacity:1;transform:none}

@media(prefers-reduced-motion:reduce){
  .cjob[data-anim],.cert-cat-card[data-anim],.exp-light-card[data-anim],
  .proj-card[data-anim],.proj-card[data-anim]:nth-child(even),
  .contact-info-col[data-anim],.cf-card-wrap[data-anim],.sstat[data-anim]{opacity:1;transform:none;transition:none}
}

/* ─── CAREER TAGS — uniform clean style ─── */
/* Career tags — navy on champagne, with enough saturation to register.
   Previously an 8%-alpha sky blue that barely showed against the white card. */
.tag-light{background:rgba(197,160,89,0.16);color:#7A5B1E;border-color:rgba(197,160,89,0.42);font-size:0.68rem;font-weight:600}

/* ─── ABOUT CREDENTIAL ROW ─── */
.asl-credential-row{display:flex;align-items:center;gap:1rem;margin-top:1.5rem;padding-top:1.25rem;border-top:1px solid #E9EEF4}
.asl-cred{display:flex;flex-direction:column;align-items:center;gap:0.1rem}
.asl-cred-num{font-family:var(--font-display);font-size:1.5rem;font-weight:800;color:#0B2545;line-height:1}
.asl-cred-lbl{font-size:0.68rem;color:#64748B;font-weight:500;letter-spacing:0.03em}
.asl-cred-div{width:1px;height:28px;background:#E2E8F0}

/* ─── HOVER LIFT ─────────────────────────────────────────────────────
   Lift only. Scaling a card scales the text inside it, which re-rasterises
   the glyphs and reads as a shimmer/wobble on every hover. Icons (vector,
   not text) may still scale. */
.exp-light-card:hover{transform:translateY(-5px);box-shadow:0 16px 40px color-mix(in srgb,var(--card-c) 22%,transparent),0 4px 12px rgba(0,0,0,0.06)}
.exp-light-card:hover .exp-light-icon{transform:scale(1.08) rotate(-3deg)}
.exp-light-icon{transition:transform 0.3s var(--reveal-ease)}
/* Career cards */
/* Must name `background` too — this is a shorthand, so omitting it here
   would replace (not merge with) the base rule's transition list and kill
   the hover tint. */
.cjob-body{transition:transform 0.25s var(--reveal-ease),background 0.25s,border-color 0.25s}
/* Only the lift here. Colour comes from the --jc rule in the CAREER TIMELINE
   COLOUR ACCENTS block above — re-declaring border-color/box-shadow at this
   point in the file would win the cascade and force every role back to the
   same gold. */
.cjob-body:hover{transform:translateX(4px)}
/* Cert cards */
.cert-cat-card{transition:transform 0.3s var(--reveal-ease),box-shadow 0.3s}
.cert-cat-card:hover{transform:translateY(-5px);box-shadow:0 12px 32px rgba(11,37,69,0.16)}
/* Project cards */
/* Lift only. Colour/border come from the flat-tile rule above; re-declaring
   them here would win the cascade and undo it. */
.proj-card:hover{transform:translateY(-4px)}

/* ══ CORE COMPETENCIES & CREDENTIALS — richer reveal ════════════════════
   The "zoom in" is carried by the icon tiles and by accent bars, never by the
   card itself. Scaling the card would scale the heading and bullet text
   inside it, which is precisely the shimmer this stylesheet exists to avoid
   (see the hero note at the top). Icons are vector artwork with no glyph
   rasterisation, so they can scale freely.
   ───────────────────────────────────────────────────────────────────── */

/* --- Icon tiles zoom + settle, slightly behind the card --- */
.exp-light-card[data-anim] .exp-light-icon,
.cert-cat-card[data-anim] .cert-cat-icon{
  opacity:0;transform:scale(0.55) rotate(-8deg);
  transition:opacity 0.5s var(--reveal-ease) 0.12s,transform 0.55s cubic-bezier(.34,1.12,.64,1) 0.12s
}
.exp-light-card[data-anim].visible .exp-light-icon,
.cert-cat-card[data-anim].visible .cert-cat-icon{opacity:1;transform:scale(1) rotate(0)}

/* --- Competency cards: the top-rule sweep that used to live here is GONE.
   A coloured bar across the top of a white card is the Testimonials
   signature and must stay unique to that section. These panels reveal by
   zooming in as a whole card (see the card-reveal block above) and their
   colour comes from the tinted background, not a rule. --- */
.exp-light-card{position:relative;overflow:hidden}

/* --- Competency cards: hover --- */
.exp-light-card:hover .exp-light-icon{transform:scale(1.12) rotate(-4deg)}
.exp-light-card:hover .exp-light-pts li::before{color:var(--card-c,#C5A059);transform:translateX(2px)}
.exp-light-pts li::before{transition:color 0.25s var(--reveal-ease),transform 0.25s var(--reveal-ease)}

/* --- Credentials: gold sheen sweeps across the tile on hover --- */
.cert-cat-card{position:relative;overflow:hidden;isolation:isolate}
.cert-cat-card::after{
  content:'';position:absolute;inset:0;z-index:-1;pointer-events:none;
  background:linear-gradient(120deg,transparent 30%,rgba(197,160,89,0.10) 50%,transparent 70%);
  transform:translateX(-100%);transition:transform 0.75s var(--reveal-ease)
}
.cert-cat-card:hover::after{transform:translateX(100%)}
.cert-cat-card:hover .cert-cat-icon{transform:scale(1.12) rotate(-4deg)}
.cert-cat-icon{transition:transform 0.3s var(--reveal-ease)}

/* --- Credentials: issuer logos pop in, staggered down the list --- */
.cert-cat-card[data-anim] .cert-logo-sm{opacity:0;transform:scale(0.6);transition:opacity 0.4s var(--reveal-ease),transform 0.45s cubic-bezier(.34,1.12,.64,1)}
.cert-cat-card[data-anim].visible .cert-logo-sm{opacity:1;transform:scale(1)}
.cert-cat-card[data-anim].visible li:nth-child(1) .cert-logo-sm{transition-delay:0.20s}
.cert-cat-card[data-anim].visible li:nth-child(2) .cert-logo-sm{transition-delay:0.27s}
.cert-cat-card[data-anim].visible li:nth-child(3) .cert-logo-sm{transition-delay:0.34s}
.cert-cat-card[data-anim].visible li:nth-child(4) .cert-logo-sm{transition-delay:0.41s}
.cert-cat-card[data-anim].visible li:nth-child(5) .cert-logo-sm{transition-delay:0.48s}
/* Individual credential rows lift toward the reader on hover */
.cert-items-list li{transition:transform 0.25s var(--reveal-ease)}
.cert-items-list li:hover{transform:translateX(4px)}
.cert-logo-sm{transition:transform 0.25s var(--reveal-ease),border-color 0.25s,background 0.25s}
.cert-items-list li:hover .cert-logo-sm{transform:scale(1.1);border-color:rgba(197,160,89,0.45)}

/* --- Competency cards: the top rule alternates sweep direction card to
   card, left-to-right then right-to-left, for the rhythm requested. Purely
   decorative (a 4px bar), so direction and motion are free to vary — this
   is exactly the kind of element that can safely carry the "L-to-R / R-to-L"
   effect without going anywhere near the text inside the card. */
/* (The alternating sweep-direction rule for .exp-light-card::before was
   removed with the top rule itself — nothing to alternate any more.) */

/* --- Career: company logos zoom in as each row scrolls into view. Raster
   or vector logo marks, not text, so free to scale. --- */
.cjob-logo{overflow:visible}
.cjob-logo img{opacity:0;transform:scale(0.4) rotate(10deg);transition:opacity 0.45s var(--reveal-ease) 0.1s,transform 0.5s cubic-bezier(.34,1.15,.64,1) 0.1s}
.cjob[data-anim].visible .cjob-logo img{opacity:1;transform:scale(1) rotate(0)}
.cjob-body:hover .cjob-logo img{transform:scale(1.1)}

/* --- Key Transformations: choreographed reveal ─────────────────────────
   The whole card slides in first (see .proj-card[data-anim] above). On top
   of that, the icon and the text inside each card now reveal in their own
   staggered sequence, so it reads as a composed entrance rather than one
   rigid block moving as a unit: dot → category label → title → description
   → deliverables (one by one) → tech tags (one by one).

   Text pieces (label, title, description) use OPACITY ONLY — no transform.
   The card is already moving via transform at the same moment, and stacking
   a second transform onto the text itself would compound the compositing
   change right when it's most visible. Opacity alone still reads as a
   distinct "coming in after the card" beat without that risk. The smaller
   supporting pieces (deliverable bullets, tech tags) get a short transform
   too — established elsewhere on this page as safe at this scale (list-item
   and tag-sized elements, not headings), and it's what makes the list feel
   like it's assembling itself rather than just fading up as a block. --- */
.proj-label{position:relative;padding-left:1rem}
.proj-label::before{
  content:'';position:absolute;left:0;top:50%;
  width:6px;height:6px;border-radius:50%;background:currentColor;
  animation:pulse-ring 2.4s ease-in-out infinite;
  opacity:0;transform:translateY(-50%) scale(0);
  transition:opacity 0.4s var(--reveal-ease) 0.15s,transform 0.45s cubic-bezier(.34,1.15,.64,1) 0.15s
}
.proj-card[data-anim].visible .proj-label::before{opacity:1;transform:translateY(-50%) scale(1)}

.proj-card[data-anim] .proj-label{opacity:0;transition:opacity 0.45s var(--reveal-ease) 0.2s}
.proj-card[data-anim].visible .proj-label{opacity:1}
.proj-card[data-anim] .proj-body h3{opacity:0;transition:opacity 0.5s var(--reveal-ease) 0.3s}
.proj-card[data-anim].visible .proj-body h3{opacity:1}
.proj-card[data-anim] .proj-body>p{opacity:0;transition:opacity 0.5s var(--reveal-ease) 0.38s}
.proj-card[data-anim].visible .proj-body>p{opacity:1}

/* Deliverables assemble one at a time. */
.proj-card[data-anim] .proj-deliverables li{opacity:0;transform:translateX(-10px);transition:opacity 0.4s var(--reveal-ease),transform 0.4s var(--reveal-ease)}
.proj-card[data-anim].visible .proj-deliverables li{opacity:1;transform:none}
.proj-card[data-anim].visible .proj-deliverables li:nth-child(1){transition-delay:0.46s}
.proj-card[data-anim].visible .proj-deliverables li:nth-child(2){transition-delay:0.51s}
.proj-card[data-anim].visible .proj-deliverables li:nth-child(3){transition-delay:0.56s}
.proj-card[data-anim].visible .proj-deliverables li:nth-child(4){transition-delay:0.61s}
.proj-card[data-anim].visible .proj-deliverables li:nth-child(5){transition-delay:0.66s}
.proj-card[data-anim].visible .proj-deliverables li:nth-child(6){transition-delay:0.71s}

/* Tech tags pop in one at a time, after the deliverables have settled.
   `transition` here must also name background/border-color — the tag's own
   base rule already sets a 0.2s transition on those for its hover state,
   and redeclaring the shorthand without them would silently drop them, not
   merge with them. */
.proj-card[data-anim] .proj-tech-tag{opacity:0;transform:scale(0.8);transition:opacity 0.35s var(--reveal-ease),transform 0.4s cubic-bezier(.34,1.15,.64,1),background 0.2s,border-color 0.2s}
.proj-card[data-anim].visible .proj-tech-tag{opacity:1;transform:scale(1)}
.proj-card[data-anim].visible .proj-tech-tag:nth-child(1){transition-delay:0.78s}
.proj-card[data-anim].visible .proj-tech-tag:nth-child(2){transition-delay:0.82s}
.proj-card[data-anim].visible .proj-tech-tag:nth-child(3){transition-delay:0.86s}
.proj-card[data-anim].visible .proj-tech-tag:nth-child(4){transition-delay:0.9s}
.proj-card[data-anim].visible .proj-tech-tag:nth-child(5){transition-delay:0.94s}
.proj-card[data-anim].visible .proj-tech-tag:nth-child(6){transition-delay:0.98s}
.proj-card[data-anim].visible .proj-tech-tag:nth-child(n+7){transition-delay:1.02s}

/* A colour edge along the BASE of the illustration, not a bar across the
   top of the card — top bars are the Testimonials signature. It sits
   between the artwork and the copy, so it reads as part of the image block
   rather than as card chrome. */
.proj-card{position:relative}
/* Anchored to the top of .proj-body rather than a hardcoded pixel offset,
   so it stays glued to the underside of the illustration whatever height
   the image is at a given breakpoint. */
.proj-body{position:relative}
.proj-body::before{
  content:'';position:absolute;left:0;right:0;top:0;z-index:3;height:3px;
  background:var(--pc,#C5A059);
  transform:scaleX(0);transform-origin:center;
  transition:transform 0.65s var(--reveal-ease) 0.3s
}
.proj-card[data-anim].visible .proj-body::before{transform:scaleX(1)}

@media(prefers-reduced-motion:reduce){
  .exp-light-card[data-anim] .exp-light-icon,
  .cert-cat-card[data-anim] .cert-cat-icon,
  .cert-cat-card[data-anim] .cert-logo-sm,
  .cjob-logo img{opacity:1;transform:none;transition:none}
  .proj-label::before{animation:none;opacity:1;transform:translateY(-50%)}
  .proj-label,.proj-body h3,.proj-body>p,
  .proj-deliverables li,.proj-tech-tag{opacity:1;transform:none;transition:none}
  .proj-body::before{transform:scaleX(1);transition:none}
  .cert-cat-card::after{display:none}
}

/* will-change activated only on hover — avoids permanent stacking context leak */
.proj-card:hover,.exp-light-card:hover,.cert-cat-card:hover,.testi-card:hover,.cjob-body:hover{will-change:transform}
/* Testimonial track needs compositing for smooth marquee */
.testi-track,.logo-marquee-track,.ts-marquee{will-change:transform}

/* ─── SECTION TRANSITIONS — fade+slide sections into view ─── */
.section-white,.section-dark,.section-light,.section-light-2,.exp-light-section,.proj-section{
  transition:background-color 0.3s
}

/* ─── TESTIMONIALS MARQUEE — full quotes, no clamp, per-person colour ───
   Quotes used to be clipped at 6 lines (-webkit-line-clamp), cutting several
   off mid-sentence. Clamp removed entirely: every quote now shows in full.
   Card height still comes out uniform because the flex track's default
   align-items:stretch makes every card match the tallest one, and
   .testi-author's margin-top:auto keeps the author pinned to the bottom
   regardless of quote length — shorter quotes just leave more room above the
   author, which the big decorative quote mark below is designed to fill. */
.testi-track-wrap{overflow:hidden;padding:1rem 0 2rem;mask-image:linear-gradient(90deg,transparent 0%,#000 8%,#000 92%,transparent 100%);-webkit-mask-image:linear-gradient(90deg,transparent 0%,#000 8%,#000 92%,transparent 100%)}
.testi-track{display:flex;gap:1.25rem;width:max-content;animation:marquee-scroll 55s linear infinite}
.testi-track:hover{animation-play-state:paused}
@keyframes marquee-scroll{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.testi-card{
  width:360px;flex-shrink:0;display:flex;flex-direction:column;
  background:linear-gradient(165deg,color-mix(in srgb,var(--tc,#C5A059) 7%,#fff) 0%,#fff 160px),#fff;
  border:1px solid color-mix(in srgb,var(--tc,#C5A059) 18%,#E8EEF6);
  border-top:4px solid var(--tc,#C5A059);
  border-radius:18px;padding:1.75rem 1.5rem 1.25rem;
  box-shadow:0 4px 20px rgba(0,0,0,0.06);
  position:relative;overflow:hidden;
  transition:transform 0.3s var(--reveal-ease,ease),box-shadow 0.3s var(--reveal-ease,ease),border-color 0.3s
}
.testi-card:hover{transform:translateY(-6px);box-shadow:0 18px 40px color-mix(in srgb,var(--tc,#C5A059) 24%,transparent)}
/* Large decorative quotation mark — pure vector, sits behind the quote text,
   coloured per person. Safe to be part of the design because it never
   overlaps or touches actual text rendering; it just tints the backdrop. */
.testi-quote-mark{position:absolute;top:0.4rem;right:0.9rem;width:52px;height:52px;color:var(--tc,#C5A059);opacity:0.14;pointer-events:none;transition:opacity 0.3s,transform 0.3s}
.testi-card:hover .testi-quote-mark{opacity:0.24;transform:scale(1.08) rotate(-4deg)}
.testi-accent-bar{display:none} /* superseded by the quote-mark + gradient wash above */
.testi-quote{font-size:0.85rem;color:#374151;line-height:1.8;margin-bottom:1.25rem;font-style:italic;position:relative;z-index:1}
.testi-author{display:flex;align-items:center;gap:0.75rem;position:relative;z-index:1;margin-top:auto;padding-top:1rem;border-top:1px solid color-mix(in srgb,var(--tc,#C5A059) 14%,transparent)}
.testi-avatar{width:38px;height:38px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:0.9rem;font-weight:700;color:#fff;flex-shrink:0;box-shadow:0 2px 8px rgba(0,0,0,0.2),0 0 0 3px color-mix(in srgb,var(--tc,#C5A059) 20%,transparent);transition:transform 0.25s var(--reveal-ease,ease),box-shadow 0.25s}
/* A single-letter chip, not prose — a brief hover scale here doesn't carry
   the antialiasing risk a sentence would; it's the same allowance already
   made for card icons elsewhere on the page. */
.testi-card:hover .testi-avatar{transform:scale(1.08);box-shadow:0 4px 14px rgba(0,0,0,0.24),0 0 0 4px color-mix(in srgb,var(--tc,#C5A059) 32%,transparent)}
.testi-name{display:block;font-size:0.82rem;font-weight:700;color:#111827;line-height:1.3}
.testi-role{display:block;font-size:0.7rem;color:#6B7280;line-height:1.4;margin-top:0.15rem;max-width:260px}

/* ─── RESPONSIVE ADDITIONS ─── */
@media(max-width:1100px){
  .cert-cats-grid{grid-template-columns:repeat(2,1fr)}
  .cert-cats-grid{grid-template-columns:repeat(2,1fr)}
  .exp-compact-grid{grid-template-columns:repeat(2,1fr)}
  .proj-grid{grid-template-columns:repeat(2,1fr)} /* overridden by proj-section's own responsive */
  .hero-split-inner{grid-template-columns:1fr;gap:2rem;padding:3rem 0 2rem}
  .hero-photo-wrap{flex-direction:row;justify-content:center}
  .hero-photo-ring{width:160px;height:160px}
  .about-split-section{grid-template-columns:1fr}
  .about-split-left{padding:3rem 2rem}
  .about-split-right{padding:3rem 2rem}
}

/* ═══════════════════════════════════════════
   COMPREHENSIVE RESPONSIVE SYSTEM
   1200px → 1024px → 768px → 480px → 360px
   ═══════════════════════════════════════════ */

/* — Tablet landscape (≤1100px) — */
@media(max-width:1100px){
  .exp-dark-grid{grid-template-columns:repeat(2,1fr)}
  .exp-light-grid{grid-template-columns:repeat(2,1fr)}
  .cert-cats-grid{grid-template-columns:repeat(2,1fr)}
  .contact-layout{grid-template-columns:1fr;gap:2rem}
  .ci-sub{max-width:100%}
  .tl-footer__grid{grid-template-columns:1fr 1fr;gap:1.75rem}
  .about-split-section{grid-template-columns:minmax(0,1fr) minmax(0,1fr)}
  .hero-top-ctas{top:72px;right:1rem}
  .testi-card{width:310px}
  .proj-grid{grid-template-columns:repeat(2,1fr)}
}

/* — Tablet portrait (≤768px) — */
@media(max-width:768px){
  /* Nav */
  .tl-nav__list{display:none;flex-direction:column;position:fixed;top:64px;left:0;right:0;bottom:0;background:rgba(11,20,38,0.97);padding:2rem;z-index:999;overflow-y:auto;gap:0.25rem}
  .tl-nav.is-open .tl-nav__list{display:flex}
  .tl-nav__list a{font-size:1rem;padding:0.75rem 1rem;border-radius:9px}
  .tl-hamburger{display:flex}

  /* About */
  .about-split-section{grid-template-columns:1fr}
  .about-split-left,.about-split-right{padding:2.5rem 1.5rem}

  /* Contact */
  .contact-layout{grid-template-columns:1fr;gap:1.75rem}
  .cf-row2{grid-template-columns:1fr}
  .ci-item span{font-size:0.78rem;word-break:break-all}

  /* Career */
  .cjob-hdr{flex-direction:column}
  .cjob-right{align-items:flex-start}

  /* Expertise / certs */
  .exp-light-grid{grid-template-columns:repeat(2,1fr)}
  .cert-cats-grid{grid-template-columns:1fr}
  .exp-compact-grid{grid-template-columns:repeat(2,1fr)}
  .proj-grid{grid-template-columns:1fr}

  /* Hero */
  .hero-v2-content{padding:7rem 0 4rem}
  .hero-h1-line{font-size:1.9rem}
  .h-section-light,.h-section-dark{font-size:1.85rem}
  .asl-heading{font-size:1.85rem}
  .asl-band{width:160px}
  .hero-v2-stats{gap:1.1rem}
  .hvs-n{font-size:1.1rem}
  .hero-top-ctas{display:none}
  .hero-split-inner{grid-template-columns:1fr;gap:2rem;padding:5.5rem 0 3rem}
  .hero-photo-side{width:100%;max-width:320px;margin:0 auto}

  /* Tech stack / testimonials */
  .testi-card{width:280px}
  .logo-bar-row{gap:1rem 1.5rem}
  .lb-item img{height:22px}

  /* Footer */
  .tl-footer__grid{grid-template-columns:1fr}

  /* Sections */
  .section-dark,.section-dark-2,.section-white,.section-light,.section-light-2,.section-gradient{padding:3rem 0}
}

/* — Mobile (≤480px) — */
@media(max-width:480px){
  .tl-container{padding-inline:1rem}
  .exp-light-grid{grid-template-columns:1fr}
  .exp-compact-grid{grid-template-columns:1fr}
  .exp-dark-grid{grid-template-columns:1fr}
  .about-split-left,.about-split-right{padding:2rem 1rem}
  .asl-heading{font-size:1.5rem}
  .asl-band{width:130px}
  .hero-h1-line{font-size:1.6rem}
  .h-section-light,.h-section-dark{font-size:1.5rem}
  /* 2x2 grid rather than a single column. Stacking these vertically left the
     four stats 331px tall with the 1px vertical .hvs-div rules stranded
     between them, which is not what those dividers are for — they're hidden
     here and the grid provides the separation instead. */
  .hero-v2-stats{display:grid;grid-template-columns:repeat(2,auto);justify-content:start;gap:0.85rem 2.25rem;margin-bottom:1.5rem}
  .hvs-div{display:none}
  .hero-v2-actions{flex-direction:column;width:100%}
  .btn-v2-primary,.btn-v2-outline{width:100%;justify-content:center}
  .cf-card-wrap .cf{padding:1.25rem 1rem}
  .cf-row2{grid-template-columns:1fr}
  .testi-card{width:260px}
  .proj-grid{grid-template-columns:1fr}
  .section-dark,.section-dark-2,.section-white,.section-light,.section-light-2{padding:2.5rem 0}
  .asr-partner-grid{grid-template-columns:1fr}
  .ci-heading{font-size:1.25rem}
}

/* — Small mobile (≤360px) — */
@media(max-width:360px){
  .tl-container{padding-inline:0.75rem}
  .testi-card{width:240px}
  .h-section-light,.h-section-dark{font-size:1.4rem}
}

/* Prevent horizontal overflow globally (width:100% avoids the 100vw scrollbar-overflow bug) */
html,body{width:100%;max-width:100%;overflow-x:hidden}
.testi-track-wrap{max-width:100%;overflow:hidden}
.lm-track-wrap{max-width:100%;overflow:hidden}
img,svg{max-width:100%;height:auto}

/* ═══════════════════════════════════════════════════════════
   PERFORMANCE — content-visibility for below-fold sections
   ═══════════════════════════════════════════════════════════ */
#career,#certifications,#tech-stack,#expertise,#testimonials{
  content-visibility:auto;
  contain-intrinsic-size:auto 600px
}
/* Projects cards are much taller now (deliverables + tech stack) — larger intrinsic estimate avoids layout jump */
#projects{
  content-visibility:auto;
  contain-intrinsic-size:auto 1600px
}

/* ═══════════════════════════════════════════════════════════
   HERO GLOW ORBS - STATIC, AND THEY MUST STAY STATIC
   These two orbs are 700px and 500px wide, sit at z-index 1 directly behind
   the hero copy, and used to run `orb-drift ... infinite`, a continuous
   translate+scale. That was the last and largest source of the "shaky" hero.

   The orbs never touch the text directly, but Chrome composites by overlap:
   as an animating layer moves, the browser keeps re-deciding which content
   overlaps it and needs its own layer to preserve paint order. With a huge
   orb drifting across the whole hero, the headline, tagline and stats were
   being promoted and demoted continuously, and each transition flips them
   between subpixel and greyscale antialiasing. The result is text that
   shimmers the entire time the page is open, which is why removing the
   entrance animations alone never fixed it.

   Static orbs give the same depth for free. Do not re-add the animation.
   ═══════════════════════════════════════════════════════════ */
.hero-v2::before{
  content:'';position:absolute;width:700px;height:700px;border-radius:50%;
  background:radial-gradient(circle,rgba(197,160,89,0.18) 0%,transparent 70%);
  top:-180px;right:-120px;
  pointer-events:none;z-index:1
}
.hero-v2::after{
  content:'';position:absolute;width:500px;height:500px;border-radius:50%;
  background:radial-gradient(circle,rgba(13,148,136,0.14) 0%,transparent 70%);
  bottom:-80px;left:-80px;
  pointer-events:none;z-index:1
}

/* ─── Hero stat numbers ───
   Previously carried `animation: stat-pop ... cubic-bezier(.34,1.56,.64,1)`,
   an overshoot bounce on hero text. The @keyframes it named was never defined
   anywhere in the theme, so it did nothing — but it is exactly the kind of
   rule that must not come back here: hero text is not animated. */
.hvs-n{
  display:inline-block
}

/* ─── Section divider — clean static separator ─── */
.section-divider-gradient{
  height:1px;
  background:#E2E8F0
}

/* ═══════════════════════════════════════════════════════════
   CAREER TIMELINE — pulsing active dot + line glow
   ═══════════════════════════════════════════════════════════ */
.cjob-dot--active{
  box-shadow:0 0 0 4px rgba(197,160,89,0.2)
}
.career-list::before{
  background:linear-gradient(to bottom,#0B2545 0%,#C5A059 50%,rgba(203,213,225,0.3) 100%);
  animation:timeline-grow 1.2s cubic-bezier(.22,1,.36,1) both;
  animation-delay:0.4s
}
@keyframes timeline-grow{
  from{transform:scaleY(0);transform-origin:top}
  to{transform:scaleY(1);transform-origin:top}
}

/* ═══════════════════════════════════════════════════════════
   CONTACT FORM — micro-animations
   ═══════════════════════════════════════════════════════════ */
.cf-g input,.cf-g select,.cf-g textarea{
  transition:border-color 0.2s,box-shadow 0.2s,transform 0.15s
}
.cf-g input:focus,.cf-g select:focus,.cf-g textarea:focus{
  transform:translateY(-1px)
}
/* ═══════════════════════════════════════════════════════════
   CTA BUTTONS — clean hover lift
   ═══════════════════════════════════════════════════════════ */
.btn-v2-primary:hover{
  transform:translateY(-3px);
  box-shadow:0 12px 36px rgba(197,160,89,0.3)
}

/* ─── Back to top — pulse ring ─── */
.tl-back-to-top{
  position:fixed;bottom:2rem;right:2rem;width:44px;height:44px;
  border-radius:50%;background:linear-gradient(135deg,#0B2545,#C5A059);
  border:none;cursor:pointer;display:flex;align-items:center;justify-content:center;
  color:#fff;opacity:0;transform:translateY(20px);
  transition:opacity 0.3s,transform 0.3s,box-shadow 0.3s;z-index:900
}
.tl-back-to-top.show{opacity:1;transform:none}
.tl-back-to-top:hover{
  transform:translateY(-2px);
  box-shadow:0 10px 28px rgba(13,148,136,0.28)
}

/* ─── Availability dot — pulsing ring ─── */
.avail-dot,.eyebrow-dot,.pulse-dot{
  animation:avail-pulse 2.2s ease-in-out infinite
}
@keyframes avail-pulse{
  0%,100%{box-shadow:0 0 0 0 rgba(47,104,68,0.4)}
  50%{box-shadow:0 0 0 5px rgba(47,104,68,0)}
}

/* ═══════════════════════════════════════════════════════════
   LOGO MARQUEE — smooth fade masks, variable speed
   ═══════════════════════════════════════════════════════════ */
.logo-marquee-track{animation-duration:25s}

/* ─── Tool stack marquee — hover pause propagation fix ─── */
.ts-marquee-wrap:hover .ts-marquee{animation-play-state:paused}

/* ═══════════════════════════════════════════════════════════
   ABOUT SPLIT — this glow orb is now STATIC. It used to "breathe"
   (animation:orb-breathe, an opacity pulse, infinite) directly behind the
   About right-column paragraph text. That is the exact same mechanism that
   caused the hero's shimmer bug (see the compositing note at the top of this
   file): a continuously-animating element sitting behind static text forces
   Chrome to keep re-deciding whether the text needs its own composited
   layer to preserve paint order, and every promotion/demotion flips the
   text between subpixel and greyscale antialiasing. This one was missed in
   the original sweep because that sweep only searched the hero, not every
   section. It is the most likely cause of "still bumpy and shaky" reports
   after the hero was fixed. Do not re-animate anything that sits behind
   text anywhere on this page — search the whole file for
   `animation:...infinite` before adding one, not just the section you're
   working in.
   ═══════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════════════════
   PROJECT CARDS — image hover zoom
   `transition` is a shorthand: redeclaring it here without `opacity` would
   silently wipe out the opacity transition set earlier for the scroll-in
   reveal (last declaration replaces the whole list, it doesn't merge with
   the prior one). Both properties are named on every line below so neither
   rule can clobber the other regardless of edit order.
   ═══════════════════════════════════════════════════════════ */
.proj-img-shapes{
  transition:opacity 0.6s var(--reveal-ease) 0.05s,transform 0.5s cubic-bezier(.22,1,.36,1) 0.05s
}
.proj-card:hover .proj-img-shapes{
  transform:scale(1.08)
}

/* ═══════════════════════════════════════════════════════════
   ACCESSIBILITY — respect reduced-motion preference
   ═══════════════════════════════════════════════════════════ */
@media(prefers-reduced-motion:reduce){
  *,::before,::after{
    animation-duration:0.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:0.01ms !important
  }
  [data-anim],[data-anim="left"],[data-anim="right"],[data-anim="top"],
  [data-anim="zoom-in"],[data-anim="zoom-out"],[data-anim="fade"],
  [data-anim].visible{opacity:1;transform:none}
  .hero-anim-1,.hero-anim-2,.hero-anim-3,.hero-anim-4,.hero-anim-5,.hero-anim-6,.hero-anim-photo,
  .cjob[data-anim],.exp-light-card[data-anim],
  .proj-card[data-anim],.cert-cat-card[data-anim]{opacity:1;transform:none}
  .testi-track,.logo-marquee-track,.ts-marquee{animation:none;transform:none}
}

/* ═══════════════════════════════════════════════════════════
   MISSING UTILITY CLASSES (audit fixes)
   ═══════════════════════════════════════════════════════════ */

/* Header logo text — was missing from CSS */
.tl-logo-text{display:flex;flex-direction:column;gap:0;line-height:1}

/* Spinning loader for submit button */
@keyframes spin-anim{to{transform:rotate(360deg)}}
.spin{animation:spin-anim 0.8s linear infinite;display:inline-block}
.btn-spin{display:none;align-items:center;gap:0.35rem}
#cf-submit.loading .btn-text{display:none}
#cf-submit.loading .btn-spin{display:inline-flex}
/* Contact submit — navy/gold executive theme */
/* Navy-to-gold, matching the hero's primary CTA — flat navy-on-navy read as
   plain against the rest of the page's colour. */
#cf-submit{background:linear-gradient(135deg,#0B2545,#C5A059)}
#cf-submit:hover{box-shadow:0 10px 28px rgba(197,160,89,0.35);transform:translateY(-2px)}

/* Testi card hover lift is defined once, near the TESTIMONIALS MARQUEE
   block above, coloured per person via --tc. This duplicate (flat grey,
   no colour) used to load later in the cascade and silently win, killing
   the colourful hover everywhere. Removed. */

/* ═══════════════════════════════════════════════════════════
   MOBILE SIMPLIFICATIONS
   ═══════════════════════════════════════════════════════════ */
@media(max-width:768px){
  /* This block used to re-hide containers here (opacity:0 plus a slide on
     [data-anim], .cjob, .contact-info-col, .cf-card-wrap) and to re-apply
     scale() to the cards. All of it is gone on purpose: containers hold text,
     and animating them composites that text. See the hero note at the top of
     this file. Motion on mobile comes from the same child icons and accent
     rules as on desktop. */
  /* Hero adjustments */
  .hero-v2::before,.hero-v2::after{display:none} /* hide orbs on mobile */
  /* .hero-photo-frame carries no animation on any breakpoint any more — this
     override is a no-op, kept only because removing it has no benefit and
     this is a defensive belt-and-braces line, not a live bug. */
  .hero-photo-frame{animation:none}
  /* Reduce marquee speed for better readability */
  .logo-marquee-track{animation-duration:35s}
  .ts-marquee{animation-duration:50s}
  .ts-marquee--reverse{animation-duration:55s}
}

/* ─── 640px intermediate breakpoint ─── */
@media(max-width:640px){
  .hero-photo-side{max-width:280px}
  .hero-photo-frame{height:320px}
  .exp-light-grid{grid-template-columns:1fr}
  .proj-grid{grid-template-columns:1fr}
  .cert-cats-grid{grid-template-columns:1fr}
  .hero-v2-stats{gap:1rem}
  .hvs-n{font-size:1.1rem}
  /* The h1 font-size override that used to live here (clamp(1.5rem,6vw,2rem))
     is removed. This block sits AFTER the ≤480px block in the file, so on
     any screen ≤480px wide it was silently overriding that block's h1 size
     with a different vw-based formula — two rules fighting over the same
     viewport range, resolved only by source order. The ≤768px step (2rem)
     now simply carries through to 481px, and the ≤480px step (1.7rem) takes
     over below that, with nothing else competing for the range in between. */
}

/* ─── Form 2-col fix for mobile ─── */
@media(max-width:600px){
  .cf-row2{grid-template-columns:1fr}
}

/* ─── Section padding for small mobile ─── */
@media(max-width:480px){
  .about-split-left{padding:2.5rem 1.25rem}
  .about-split-right{padding:2.5rem 1.25rem}
  .cf-card-wrap .cf{padding:1.25rem 1rem}
  .section-hdr{margin-bottom:1.5rem}
  .testi-card{width:260px;padding:1.25rem}
}

/* ─── Hover interactions — pointer-coarse devices only (touch) ─── */
@media(hover:none),(pointer:coarse){
  /* Disable hover transforms that rely on precise cursor positioning */
  .exp-light-card:hover{transform:none}
  .proj-card:hover{transform:none;box-shadow:0 4px 16px rgba(0,0,0,0.08)}
  .cert-cat-card:hover{transform:none}
  .cjob-body:hover{transform:none}
  .ci-icon-btn:hover{transform:none}
  /* Tap feedback. The cards used to use scale(0.98), which shrinks all the
     text inside them on every tap — the same glyph re-rasterisation that this
     stylesheet avoids everywhere else. A brief opacity dip reads as "pressed"
     without touching layout or text rendering. Buttons keep their scale:
     their label is short, centred, and the press is momentary. */
  .exp-light-card:active,.proj-card:active,.cert-cat-card:active{opacity:0.82;transition:opacity 0.1s linear}
  .btn-v2-primary:active,.btn-primary:active{transform:scale(0.97)}
  /* Disable will-change on touch */
  .proj-card:hover,.exp-light-card:hover,.cert-cat-card:hover,
  .testi-card:hover,.cjob-body:hover{will-change:auto}
}

/* ─── Landscape mobile ─── */
@media(max-width:900px) and (orientation:landscape){
  .hero-split{flex-direction:row;min-height:auto;padding:5rem 0 3rem}
  .hero-photo-side{flex:0 0 220px}
  .hero-photo-frame{height:280px}
}

/* ─── Focus visible — enhanced keyboard navigation ─── */
:focus-visible{
  outline:2.5px solid #C5A059;
  outline-offset:3px;
  border-radius:4px
}
.cf-g input:focus-visible,.cf-g select:focus-visible,.cf-g textarea:focus-visible{
  outline:none; /* border-color + box-shadow already shown */
}
.tl-nav__list a:focus-visible,.ci-icon-btn:focus-visible{
  outline:2px solid #C5A059;
  outline-offset:2px
}

/* ═══════════════════════════════════════════════════════════
   TECH STACK — categorised grid (replaces marquee)
   ═══════════════════════════════════════════════════════════ */
.ts-cat-grid{
  display:grid;
  grid-template-columns:repeat(3,minmax(0,1fr));
  gap:1.25rem;
  margin-top:2.5rem;
  margin-bottom:1rem
}
.ts-cat-panel{
  background:#fff;
  border:1px solid #E8EEF6;
  border-radius:16px;
  padding:1.5rem 1.25rem;
  box-shadow:0 1px 3px rgba(15,23,42,0.04);
  transition:border-color 0.3s cubic-bezier(.22,1,.36,1),box-shadow 0.3s cubic-bezier(.22,1,.36,1),transform 0.3s cubic-bezier(.22,1,.36,1)
}
.ts-cat-panel:hover{
  border-color:var(--cat-color,#C5A059);
  box-shadow:0 12px 30px rgba(15,23,42,0.08);
  transform:translateY(-3px)
}
.ts-cat-label{
  font-family:var(--font-sans);
  font-size:0.72rem;
  font-weight:700;
  letter-spacing:0.1em;
  text-transform:uppercase;
  color:var(--cat-color,#C5A059);
  margin-bottom:0.75rem;
  display:flex;
  align-items:center;
  gap:0.5rem
}
.ts-cat-label::before{
  content:'';
  display:inline-block;
  width:8px;height:8px;
  border-radius:50%;
  background:var(--cat-color,#C5A059);
  flex-shrink:0;
  opacity:0.7
}
.ts-domain-desc{
  font-size:0.88rem;
  line-height:1.7;
  color:var(--text-muted-l);
  margin:0
}
.ts-chip-row{
  display:flex;
  flex-wrap:wrap;
  gap:0.45rem
}
.ts-chip{
  display:inline-flex;
  align-items:center;
  gap:0.35rem;
  padding:0.3rem 0.65rem;
  background:#F8FAFC;
  border:1px solid #E2E8F0;
  border-radius:99px;
  font-size:0.72rem;
  font-weight:500;
  color:#374151;
  transition:background 0.18s,border-color 0.18s,color 0.18s,transform 0.18s;
  cursor:default;
  white-space:nowrap
}
.ts-chip:hover{
  background:#fff;
  border-color:var(--cat-color,#C5A059);
  color:#111827;
  transform:translateY(-1px)
}
.ts-chip img{
  flex-shrink:0;
  border-radius:2px
}
/* Responsive */
@media(max-width:1100px){.ts-cat-grid{grid-template-columns:repeat(2,1fr)}}
@media(max-width:640px){.ts-cat-grid{grid-template-columns:1fr;gap:0.875rem}}
@media(hover:none),(pointer:coarse){.ts-chip:hover,.ts-cat-panel:hover{transform:none}}

/* ═══════════════════════════════════════════════════════════
   CONTACT FORM — clean minimal version
   ═══════════════════════════════════════════════════════════ */
/* Remove extra row height from the stripped-back form */
.cf .cf-g textarea{min-height:120px;resize:vertical}
/* Ensure the 2-col row collapses cleanly at 600px */
@media(max-width:600px){
  .cf .cf-row2{grid-template-columns:1fr}
}
