body {
    font-family: 'Fira Sans', sans-serif;
    background-color: #f8f9fa;
    color: #343a40;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}
h1, h2, h3, h4, h5, h6, .font-bold, .font-extrabold, .font-semibold {
    font-family: 'Lora', serif;
}
.container {
    max-width: 1200px;
    margin: 0 auto;
    padding: 0 1rem;
}
.btn-primary {
    background-color: #174a7c;
    color: white;
    padding: 0.75rem 1.5rem;
    border-radius: 0.5rem;
    transition: background-color 0.3s ease;
}
.btn-primary:hover {
    background-color: #123c66;
}

/* Site-wide sticky nav bar. Solid white background with dark navy text,
   matching the hero/about sections' navy so the brand color still reads
   through the header even though the background itself is now light. */
.site-header {
    position: sticky;
    top: 0;
    z-index: 50;
    background-color: #ffffff;
    flex-shrink: 0;
}
.site-header a,
.site-header span,
.site-header button {
    color: #0b1f3a;
}
.site-header a:hover {
    color: #174a7c;
}
.site-mobile-menu {
    background-color: #ffffff;
}
.site-mobile-menu a {
    color: #0b1f3a;
}
.site-mobile-menu a:hover {
    background-color: rgba(11, 31, 58, 0.08);
}

/* Full-height homepage hero. 72px subtracted is the sticky nav's
   rendered height, so hero + nav together fill exactly one viewport. */
.hero-section {
    background-color: #0b1f3a;
    min-height: calc(100vh - 72px);
    display: flex;
    align-items: center;
    position: relative;
    overflow: hidden;
}

/* Low-poly triangle mesh (hero-mesh.js draws into this). Every instance
   fills its immediate parent, which must be position:relative with a
   defined size — .hero-section on the home page, .about-mesh-box on the
   About page. Pointer-events stay off so the mouse-parallax listener on
   the parent itself keeps receiving events. */
.js-mesh-canvas {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}

.hero-content {
    position: relative;
    z-index: 1;
}

/* Grows to fill any leftover space between header and footer, the same
   way .hero-section's explicit min-height does on the homepage, so the
   dark background always covers the full viewport regardless of content
   length or window size. */
.about-page,
#contact {
    flex: 1 0 auto;
}

.about-page {
    background-color: #ffffff;
    color: #0b1f3a;
}

/* Contact page also carries .about-page (for the shared flex-grow layout
   behavior above), which would otherwise leave it with a white background
   its light-text contact panels weren't designed for. Restore navy. */
#contact {
    background-color: #0b1f3a;
    color: #ffffff;
}

/* Services page reuses .about-page's layout/flex-grow behavior but wants
   the full animated triangle mesh as its background instead (same as the
   home hero) — the #services ID override beats .about-page's white
   regardless of stylesheet order. Its cards already use light text
   (text-white/text-gray-300) expecting a dark ground. */
#services {
    position: relative;
    overflow: hidden;
    background-color: #0b1f3a;
    color: #ffffff;
    min-height: calc(100vh - 72px);
    display: flex;
    flex-direction: column;
    justify-content: center;
}
.services-content {
    position: relative;
    z-index: 1;
}

/* Matches .about-hero-layout's max-width and horizontal padding exactly
   (rather than the site-wide .container + inner px-* wrapper this used
   to sit in), so "Our Mission" etc. line up on the same left edge as
   "About Us" in the hero above. */
.about-sections {
    max-width: 1800px;
    margin: 0 auto;
    padding: 0 clamp(1rem, 5vw, 4rem);
    width: 100%;
}

/* Mission/Approach/Principles as one card: the triangle mesh fills the
   whole background, and a white collapsible table sits on top of it. */
.about-modules-section {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 620px;
    padding: clamp(2rem, 6vw, 4.5rem);
    background-color: #0b1f3a;
    border-radius: 4px;
    overflow: hidden;
}
.about-modules-section .js-mesh-canvas {
    z-index: 0;
}

.modules-table {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 760px;
    background: #ffffff;
    border-radius: 3px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
    /* Without this, the white cursor set on the parent .about-modules-section
       (navy mesh) would just inherit straight through onto this white table. */
    cursor: var(--cursor-blue);
}
.modules-row + .modules-row {
    border-top: 1px solid #cbd5e1;
}

/* Row header is the click target; only the title shows until opened.
   cursor is set after "all: unset" resets it back to inherit. */
.modules-row-toggle {
    all: unset;
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1.5rem;
    width: 100%;
    padding: 1.75rem 2.5rem;
    cursor: var(--cursor-blue);
}
.modules-row-toggle h3 {
    margin: 0;
    font-size: 1.15rem;
    font-weight: 700;
    color: #0b1f3a;
    font-family: 'Lora', serif;
}
.modules-row-arrow {
    flex-shrink: 0;
    width: 22px;
    height: 22px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #174a7c;
    transition: transform 650ms cubic-bezier(0.65, 0, 0.35, 1);
}
.collapsible-row.is-open .modules-row-arrow {
    transform: rotate(90deg);
}

/* Collapsed panel animates open via the 0fr -> 1fr grid-row trick, which
   (unlike max-height) animates to the content's real height exactly. A
   slower, symmetric ease-in-out reads as a glide rather than a quick drop. */
.modules-row-panel {
    display: grid;
    grid-template-rows: 0fr;
    transition: grid-template-rows 650ms cubic-bezier(0.65, 0, 0.35, 1);
}
.collapsible-row.is-open .modules-row-panel {
    grid-template-rows: 1fr;
}
.modules-row-panel-inner {
    overflow: hidden;
}
.modules-row-panel p {
    margin: 0;
    padding: 0 2.5rem 1.75rem;
    font-size: 0.95rem;
    line-height: 1.6;
    color: #4b5563;
}

/* Services page: all five services in one white rectangle, stacked as
   horizontal rows (matches the About page's vertical .modules-table).
   Clicking a segment (main.js, [data-seg]) grows it — .services-seg-body
   reveals a row with the description on the left (reaching about the
   middle of the box) and its animated visual on the right — while any
   previously open row collapses back. */
.services-accordion {
    width: 100%;
    display: flex;
    flex-direction: column;
    background: #ffffff;
    border-radius: 3px;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
    overflow: hidden;
    cursor: var(--cursor-blue);
}
.services-seg {
    flex: none;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    padding: 1.75rem 1.5rem;
    cursor: var(--cursor-blue);
    position: relative;
    overflow: hidden;
}
.services-seg + .services-seg {
    border-top: 1px solid #cbd5e1;
}

/* Matches the About page table's .modules-row-toggle h3 exactly
   (1.15rem/700/navy) — font-family: Lora comes for free since h3 is
   already covered by the site-wide heading rule. */
.services-seg-title {
    margin: 0;
    width: 100%;
    padding-right: 2rem;
    font-size: 1.15rem;
    font-weight: 700;
    color: #0b1f3a;
    text-align: left;
}

/* Collapses/reveals the description+visual row as one unit via the
   0fr -> 1fr grid-row trick (same technique as .modules-row-panel), so
   they grow and shrink together instead of each needing its own height
   accounting. */
.services-seg-body {
    display: grid;
    grid-template-rows: 0fr;
    width: 100%;
    transition: grid-template-rows 1100ms cubic-bezier(0.65, 0, 0.35, 1);
}
.services-seg.is-open .services-seg-body {
    grid-template-rows: 1fr;
}
.services-seg-body-inner {
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 2rem;
}

/* Matches the About page table's .modules-row-panel p exactly
   (0.95rem/1.6/#4b5563), but capped at half the box's width so it reaches
   the middle rather than crowding toward the visual on the right. */
.services-seg-desc {
    margin: 0;
    padding-top: 0.85rem;
    flex: 1 1 50%;
    max-width: 50%;
    font-size: 0.95rem;
    line-height: 1.6;
    color: #4b5563;
    opacity: 0;
    transition: opacity 300ms ease;
}
.services-seg.is-open .services-seg-desc {
    opacity: 1;
    transition: opacity 500ms ease 500ms;
}

/* Arrow sits top-right, level with the title — same position (relative
   to the header text) and same rotate-to-point-down-on-click behavior
   as the About page's table rows. Always visible as the click affordance. */
.services-seg-arrow {
    position: absolute;
    top: 1.75rem;
    right: 1.5rem;
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    display: flex;
    align-items: center;
    justify-content: center;
    color: #174a7c;
    transition: transform 650ms cubic-bezier(0.65, 0, 0.35, 1);
}
.services-seg.is-open .services-seg-arrow {
    transform: rotate(90deg);
}

/* Each service gets its own animated data-widget (labeled bars, a repo
   flow loop, a scan-line comparison, a donut with legend, a liquidity
   area chart) instead of a generic icon — sits on the right side of the
   revealed row, fading in once its box has grown. */
.services-seg-visual {
    flex-shrink: 0;
    width: 280px;
    height: 180px;
    opacity: 0;
    pointer-events: none;
    transition: opacity 300ms ease;
}
.services-seg.is-open .services-seg-visual {
    opacity: 1;
    transition: opacity 500ms ease 500ms;
}
.services-visual-svg {
    width: 100%;
    height: 100%;
    overflow: visible;
}
@media (max-width: 640px) {
    .services-seg-body-inner {
        flex-direction: column;
        align-items: flex-start;
        gap: 1.25rem;
    }
    .services-seg-desc {
        max-width: 100%;
    }
    .services-seg-visual {
        width: 240px;
        height: 154px;
    }
}

/* Shared chrome for every widget: a light card background (no outline),
   a title caption, and consistent axis/data-label typography (matches
   the site body font). */
.visual-card-bg {
    fill: #eef1f5;
}
.visual-title {
    font-family: 'Fira Sans', sans-serif;
    font-size: 12px;
    font-weight: 600;
    fill: #0b1f3a;
}
.visual-axis-label {
    font-family: 'Fira Sans', sans-serif;
    font-size: 9px;
    fill: #94a3b8;
}
.visual-data-label {
    font-family: 'Fira Sans', sans-serif;
    font-size: 9px;
    fill: #4b5563;
}
.visual-baseline {
    stroke: #cbd5e1;
    stroke-width: 1;
}

/* Prime Brokerage & Financing Optimisation: the five donut segments
   (each broker's share of total margin, unlabeled) resize against one
   another on a loop, matching the Collateral Mix donut's style. Centered
   in the card now that the legend is gone. */
.services-seg.is-open .visual-financing .fin-seg-1 {
    animation: fin-seg-1 4.5s ease-in-out 1300ms infinite;
}
.services-seg.is-open .visual-financing .fin-seg-2 {
    animation: fin-seg-2 4.5s ease-in-out 1300ms infinite;
}
.services-seg.is-open .visual-financing .fin-seg-3 {
    animation: fin-seg-3 4.5s ease-in-out 1300ms infinite;
}
.services-seg.is-open .visual-financing .fin-seg-4 {
    animation: fin-seg-4 4.5s ease-in-out 1300ms infinite;
}
.services-seg.is-open .visual-financing .fin-seg-5 {
    animation: fin-seg-5 4.5s ease-in-out 1300ms infinite;
}
@keyframes fin-seg-1 {
    0%, 100% { stroke-dashoffset: 0; }
    50% { stroke-dashoffset: -9; }
}
@keyframes fin-seg-2 {
    0%, 100% { stroke-dashoffset: -98; }
    50% { stroke-dashoffset: -89; }
}
@keyframes fin-seg-3 {
    0%, 100% { stroke-dashoffset: -170; }
    50% { stroke-dashoffset: -161; }
}
@keyframes fin-seg-4 {
    0%, 100% { stroke-dashoffset: -229; }
    50% { stroke-dashoffset: -220; }
}
@keyframes fin-seg-5 {
    0%, 100% { stroke-dashoffset: -281; }
    50% { stroke-dashoffset: -272; }
}

/* Repo & Securities Finance: a client-dashboard-style stacked bar chart —
   each broker's repo balance (dark) and reverse repo balance (light),
   matching Hazeltree's two-tone "Cash Trend" widget. Both segments in a
   column resize together (each pair animates the same y/height values
   used to keep the seam between them touching, rather than a transform
   anchored on one box) so the whole bar visibly grows or shrinks with no
   gap at the join. Each column runs its own duration/delay so the three
   read as independent live data rather than one uniform pulse. */
.services-seg.is-open .visual-repo .repo-dark-seg.repo-col-1 {
    animation: repo-dark-1 3.2s ease-in-out 1400ms infinite;
}
.services-seg.is-open .visual-repo .repo-reverse-seg.repo-col-1 {
    animation: repo-light-1 3.2s ease-in-out 1400ms infinite;
}
.services-seg.is-open .visual-repo .repo-dark-seg.repo-col-2 {
    animation: repo-dark-2 3.8s ease-in-out 1550ms infinite;
}
.services-seg.is-open .visual-repo .repo-reverse-seg.repo-col-2 {
    animation: repo-light-2 3.8s ease-in-out 1550ms infinite;
}
.services-seg.is-open .visual-repo .repo-dark-seg.repo-col-3 {
    animation: repo-dark-3 3.4s ease-in-out 1700ms infinite;
}
.services-seg.is-open .visual-repo .repo-reverse-seg.repo-col-3 {
    animation: repo-light-3 3.4s ease-in-out 1700ms infinite;
}
.services-seg.is-open .visual-repo .repo-dark-seg.repo-col-4 {
    animation: repo-dark-4 3.6s ease-in-out 1500ms infinite;
}
.services-seg.is-open .visual-repo .repo-reverse-seg.repo-col-4 {
    animation: repo-light-4 3.6s ease-in-out 1500ms infinite;
}
.services-seg.is-open .visual-repo .repo-dark-seg.repo-col-5 {
    animation: repo-dark-5 3.0s ease-in-out 1650ms infinite;
}
.services-seg.is-open .visual-repo .repo-reverse-seg.repo-col-5 {
    animation: repo-light-5 3.0s ease-in-out 1650ms infinite;
}
@keyframes repo-dark-1 {
    0%, 100% { y: 105px; height: 45px; }
    50% { y: 115px; height: 35px; }
}
@keyframes repo-light-1 {
    0%, 100% { y: 85px; height: 20px; }
    50% { y: 101px; height: 14px; }
}
@keyframes repo-dark-2 {
    0%, 100% { y: 100px; height: 50px; }
    50% { y: 90px; height: 60px; }
}
@keyframes repo-light-2 {
    0%, 100% { y: 72px; height: 28px; }
    50% { y: 57px; height: 33px; }
}
@keyframes repo-dark-3 {
    0%, 100% { y: 120px; height: 30px; }
    50% { y: 114px; height: 36px; }
}
@keyframes repo-light-3 {
    0%, 100% { y: 92px; height: 28px; }
    50% { y: 82px; height: 32px; }
}
@keyframes repo-dark-4 {
    0%, 100% { y: 112px; height: 38px; }
    50% { y: 120px; height: 30px; }
}
@keyframes repo-light-4 {
    0%, 100% { y: 94px; height: 18px; }
    50% { y: 107px; height: 13px; }
}
@keyframes repo-dark-5 {
    0%, 100% { y: 125px; height: 25px; }
    50% { y: 120px; height: 30px; }
}
@keyframes repo-light-5 {
    0%, 100% { y: 103px; height: 22px; }
    50% { y: 93px; height: 27px; }
}

/* Margin Replication & Analytics: an unlabeled histogram — four securities
   (deliberately un-named on the x-axis) ranked by total margin consumed,
   each bar split into three broker segments matching the Broker A/B/C
   legend above. Each whole bar (all three segments as one rigid group)
   grows/shrinks from the baseline on its own duration/delay — simpler
   than tracking each segment's seam individually, and just as effective
   since the segments' proportions stay intact either way. */
.visual-margin .hist-bar {
    transform-box: fill-box;
    transform-origin: bottom;
}
.services-seg.is-open .visual-margin .hist-col-1 {
    animation: hist-bar-pulse 3.2s ease-in-out 1400ms infinite;
}
.services-seg.is-open .visual-margin .hist-col-2 {
    animation: hist-bar-pulse 3.6s ease-in-out 1500ms infinite;
}
.services-seg.is-open .visual-margin .hist-col-3 {
    animation: hist-bar-pulse 3.0s ease-in-out 1600ms infinite;
}
.services-seg.is-open .visual-margin .hist-col-4 {
    animation: hist-bar-pulse 3.4s ease-in-out 1700ms infinite;
}
@keyframes hist-bar-pulse {
    0%, 100% { transform: scaleY(1); }
    50% { transform: scaleY(0.8); }
}

/* Capital & Cross-Asset Optimisation: a horizontal bar chart of
   risk-adjusted performance ratios (ties to the description's "improve
   overall performance ratios"). Each bar grows/shrinks from its fixed
   left edge on its own duration/delay, matching the other widgets'
   bar-pulse style. */
.visual-capital .cap-bar {
    transform-box: fill-box;
    transform-origin: left;
}
.services-seg.is-open .visual-capital .cap-bar-1 {
    animation: cap-bar-pulse 2.8s ease-in-out 1400ms infinite;
}
.services-seg.is-open .visual-capital .cap-bar-2 {
    animation: cap-bar-pulse 3.2s ease-in-out 1500ms infinite;
}
.services-seg.is-open .visual-capital .cap-bar-3 {
    animation: cap-bar-pulse 2.6s ease-in-out 1600ms infinite;
}
.services-seg.is-open .visual-capital .cap-bar-4 {
    animation: cap-bar-pulse 3.0s ease-in-out 1700ms infinite;
}
@keyframes cap-bar-pulse {
    0%, 100% { transform: scaleX(1); }
    50% { transform: scaleX(0.82); }
}

/* Treasury & Liquidity Management: a Hazeltree-style "Cash Trend" stacked
   histogram — four cash categories (Operating, Reserve, Buffer, Excess),
   each split into an Available (dark) and Reserved (light) segment. Both
   segments in a column resize together (matching y/height keyframes so
   the seam between them stays touching, no gap) on their own
   duration/delay, reading as continuously live data. */
.services-seg.is-open .visual-treasury .cash-dark-seg.cash-col-1 {
    animation: cash-dark-1 3.2s ease-in-out 1400ms infinite;
}
.services-seg.is-open .visual-treasury .cash-light-seg.cash-col-1 {
    animation: cash-light-1 3.2s ease-in-out 1400ms infinite;
}
.services-seg.is-open .visual-treasury .cash-dark-seg.cash-col-2 {
    animation: cash-dark-2 3.6s ease-in-out 1500ms infinite;
}
.services-seg.is-open .visual-treasury .cash-light-seg.cash-col-2 {
    animation: cash-light-2 3.6s ease-in-out 1500ms infinite;
}
.services-seg.is-open .visual-treasury .cash-dark-seg.cash-col-3 {
    animation: cash-dark-3 3.0s ease-in-out 1600ms infinite;
}
.services-seg.is-open .visual-treasury .cash-light-seg.cash-col-3 {
    animation: cash-light-3 3.0s ease-in-out 1600ms infinite;
}
.services-seg.is-open .visual-treasury .cash-dark-seg.cash-col-4 {
    animation: cash-dark-4 3.4s ease-in-out 1700ms infinite;
}
.services-seg.is-open .visual-treasury .cash-light-seg.cash-col-4 {
    animation: cash-light-4 3.4s ease-in-out 1700ms infinite;
}
@keyframes cash-dark-1 {
    0%, 100% { y: 95px; height: 55px; }
    50% { y: 105px; height: 45px; }
}
@keyframes cash-light-1 {
    0%, 100% { y: 60px; height: 35px; }
    50% { y: 75px; height: 30px; }
}
@keyframes cash-dark-2 {
    0%, 100% { y: 105px; height: 45px; }
    50% { y: 98px; height: 52px; }
}
@keyframes cash-light-2 {
    0%, 100% { y: 80px; height: 25px; }
    50% { y: 68px; height: 30px; }
}
@keyframes cash-dark-3 {
    0%, 100% { y: 115px; height: 35px; }
    50% { y: 122px; height: 28px; }
}
@keyframes cash-light-3 {
    0%, 100% { y: 95px; height: 20px; }
    50% { y: 105px; height: 17px; }
}
@keyframes cash-dark-4 {
    0%, 100% { y: 125px; height: 25px; }
    50% { y: 118px; height: 32px; }
}
@keyframes cash-light-4 {
    0%, 100% { y: 110px; height: 15px; }
    50% { y: 98px; height: 20px; }
}

@media (prefers-reduced-motion: reduce) {
    .services-seg,
    .services-seg-body,
    .services-seg-arrow,
    .services-seg-visual,
    .services-seg-desc,
    .visual-financing .fin-seg-1,
    .visual-financing .fin-seg-2,
    .visual-financing .fin-seg-3,
    .visual-financing .fin-seg-4,
    .visual-financing .fin-seg-5,
    .visual-repo .repo-dark-seg,
    .visual-repo .repo-reverse-seg,
    .visual-margin .hist-bar,
    .visual-capital .cap-bar,
    .visual-treasury .cash-dark-seg,
    .visual-treasury .cash-light-seg {
        animation: none;
        transition: none;
    }
}

.about-hero-pin-wrap {
    position: relative;
}

/* Below md, this still reads as its own full-bleed "page" (min-height,
   not a fixed height) but is free to grow taller than one screen so the
   intro, mesh and all three paragraphs get room to breathe instead of
   being capped to exactly one viewport and clipped. */
.about-hero-section {
    background-color: #0b1f3a;
    color: #ffffff;
    display: flex;
    min-height: calc(100vh - 72px);
}

/* Overrides .container's site-wide 1200px cap: the hero text and mesh box
   should keep growing as the window widens, not stall past 1200px. */
.about-hero-layout {
    display: flex;
    flex-direction: column;
    gap: 2.5rem;
    width: 100%;
    max-width: 1800px;
    padding: 3rem clamp(1rem, 5vw, 4rem);
}
@media (min-width: 768px) {
    /* True two-column grid: left (intro + mesh) and right (partner
       paragraphs) each get an equal, real half of the screen — not a
       fixed-width block that ends up pinned to the far edge. */
    .about-hero-layout {
        display: grid;
        grid-template-columns: 1fr 1fr;
        align-items: stretch;
        gap: 3rem;
    }

    /* Pin/reveal-on-scroll only makes sense once the two-column grid above
       guarantees the intro, mesh and all three paragraphs fit within one
       screen. Below this breakpoint everything stacks in a single column
       (see .about-hero-layout's mobile default) and is tall enough that
       pinning it to a single-screen height would push the later paragraphs
       permanently off-screen — so mobile just scrolls normally instead. */

    /* Tall spacer giving the sticky hero below room to stay pinned on screen
       while the user scrolls through the two staged reveals in the right
       column; it releases once this wrapper's extra height is used up,
       continuing into "Our Mission" in the sibling .about-page below. */
    .about-hero-pin-wrap {
        height: 210vh;
    }

    /* Pinned About intro — position:sticky keeps it visually fixed through
       both staged reveals before releasing into the rest of the page. */
    .about-hero-section {
        position: sticky;
        top: 72px;
        height: calc(100vh - 72px);
    }
}

.about-hero-left {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.about-hero-intro {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    text-align: left;
    margin-bottom: 2rem;
}

/* Fills whatever vertical space is left under the intro text — no dead
   gap, just the intro's own margin-bottom as breathing room. */
.about-mesh-box {
    position: relative;
    flex: 1;
    min-height: 220px;
    width: 100%;
    overflow: hidden;
    border-radius: 3px;
    background-color: rgba(255, 255, 255, 0.03);
}

/* Right half of the grid — centers the paragraph block within the entire
   right-hand half of the screen (not pinned to the far edge), so it stays
   centered as the window widens. */
.about-hero-right-half {
    display: flex;
}
@media (min-width: 768px) {
    .about-hero-right-half {
        align-items: center;
        justify-content: center;
    }
}
.about-hero-side {
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 1.75rem;
    width: 100%;
}
@media (min-width: 768px) {
    .about-hero-side {
        max-width: 340px;
    }
}

/* +60% over the paragraph's old text-2xl/md:text-3xl sizing (100% bumped,
   then dialed back down 20%). */
.about-hero-lede {
    font-family: 'Lora', serif;
    font-size: 1.9rem;
    font-weight: 600;
    line-height: 1.2;
    text-align: left;
}
@media (min-width: 768px) {
    .about-hero-lede {
        font-size: 2.4rem;
    }
}

/* "unparalleled" lifts up-and-right with a soft dark drop shadow (a 3D
   pop off the page) plus a dim blue glow, triggered on hover and held for
   5s by main.js (see the .is-active toggle there) regardless of whether
   the cursor stays put. Quick to appear, slow to fade back out — the
   revert transition lives on the base (non-.is-active) rule since that's
   the state being transitioned *to* when .is-active is removed. */
.glow-word {
    display: inline-block;
    transition: color 1200ms ease, text-shadow 1200ms ease, transform 1200ms ease;
}
.glow-word.is-active {
    color: #1d4ed8;
    transform: translate(3px, -3px);
    text-shadow: 2px 3px 3px rgba(11, 31, 58, 0.3), 0 0 8px rgba(37, 99, 235, 0.35), 0 0 18px rgba(37, 99, 235, 0.18);
    transition: color 250ms ease, text-shadow 250ms ease, transform 250ms ease;
}
@media (prefers-reduced-motion: reduce) {
    .glow-word,
    .glow-word.is-active {
        transition: none;
    }
}

/* Each divider line is its own permanent element, separate from the melt
   animation below — so all three lines are visible from first paint and
   only the paragraph text fades/melts in. */
.about-hero-side-item {
    display: flex;
    flex-direction: column;
}
.about-hero-side-line {
    height: 1px;
    background: rgba(156, 163, 175, 0.45);
    margin-bottom: 1.5rem;
    flex-shrink: 0;
}
.about-hero-side p {
    margin: 0;
    font-size: 0.95rem;
    line-height: 1.6;
    color: #d1d5db;
}
@media (min-width: 768px) {
    .about-hero-side p {
        font-size: 1rem;
    }
}

/* Slow "melt" reveal for the 2nd/3rd paragraphs — main.js adds
   .is-visible as the user scrolls through the pinned hero. Bottom-to-top:
   they start lower and rise into place as they sharpen/fade in. */
.about-hero-melt {
    opacity: 0;
    transform: translateY(36px);
    filter: blur(8px);
    transition: opacity 2200ms cubic-bezier(0.16, 1, 0.3, 1),
        transform 2200ms cubic-bezier(0.16, 1, 0.3, 1),
        filter 2200ms cubic-bezier(0.16, 1, 0.3, 1);
}
.about-hero-melt.is-visible {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
}
@media (prefers-reduced-motion: reduce) {
    .about-hero-melt {
        transition: none;
        opacity: 1;
        transform: none;
        filter: none;
    }
}

/* Same glass-card treatment previously shared with the About page's tab
   panels, for the Contact page's form and office-info blocks. */
/* Third contact-grid panel: same footprint/height as .contact-panel next
   to it (the grid's default stretch makes all three match the tallest),
   but houses the animated triangle mesh instead of text. */
.contact-mesh-box {
    position: relative;
    min-height: 320px;
    border-radius: 3px;
    overflow: hidden;
    background-color: rgba(255, 255, 255, 0.03);
    cursor: var(--cursor-white);
}

.contact-panel {
    background: #ffffff;
    border-radius: 3px;
    padding: 2rem;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
}

/* About page sections melt in as they're scrolled into view (main.js toggles
   .is-visible via IntersectionObserver), matching the home hero's fade-in. */
.about-reveal-section {
    opacity: 0;
    transform: translateY(40px);
    filter: blur(6px);
    transition: opacity 900ms cubic-bezier(0.16, 1, 0.3, 1),
        transform 900ms cubic-bezier(0.16, 1, 0.3, 1),
        filter 900ms cubic-bezier(0.16, 1, 0.3, 1);
}
.about-reveal-section.is-visible {
    opacity: 1;
    transform: translateY(0);
    filter: blur(0);
}
@media (prefers-reduced-motion: reduce) {
    .about-reveal-section {
        opacity: 1;
        transform: none;
        filter: none;
        transition: none;
    }
}

footer {
    flex-shrink: 0;
}

/* ---- Cookie consent banner + preferences panel ---- */

.ds-cookie-btn {
    font-family: 'Fira Sans', sans-serif;
    font-size: 0.875rem;
    font-weight: 600;
    padding: 0.65rem 1.25rem;
    border-radius: 0.5rem;
    border: 1px solid transparent;
    cursor: pointer;
    transition: background-color 0.2s ease, border-color 0.2s ease;
    white-space: nowrap;
}
.ds-cookie-btn-solid {
    background-color: #174a7c;
    color: #ffffff;
}
.ds-cookie-btn-solid:hover {
    background-color: #123c66;
}
.ds-cookie-btn-outline {
    background-color: transparent;
    border-color: rgba(255, 255, 255, 0.5);
    color: #ffffff;
}
.ds-cookie-btn-outline:hover {
    background-color: rgba(255, 255, 255, 0.1);
}

#ds-cookie-banner {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 9999;
    background-color: #0b1f3a;
    border-top: 1px solid rgba(255, 255, 255, 0.15);
    box-shadow: 0 -8px 24px rgba(0, 0, 0, 0.25);
}
.ds-cookie-banner-inner {
    max-width: 1200px;
    margin: 0 auto;
    padding: 1.25rem 1.5rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
}
.ds-cookie-text {
    color: #e5e7eb;
    font-size: 0.875rem;
    line-height: 1.5;
    margin: 0;
    flex: 1 1 320px;
    max-width: 640px;
}
.ds-cookie-text-short { display: none; }
.ds-cookie-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    flex-shrink: 0;
}

#ds-cookie-overlay {
    position: fixed;
    inset: 0;
    z-index: 10000;
    background-color: rgba(11, 31, 58, 0.7);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    overflow-y: auto;
}
.ds-cookie-panel {
    background-color: #0b1f3a;
    color: #ffffff;
    border: 1px solid rgba(255, 255, 255, 0.2);
    border-radius: 1rem;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
    max-width: 560px;
    width: 100%;
    padding: 2rem;
    margin: auto;
}
.ds-cookie-panel-title {
    font-family: 'Lora', serif;
    font-size: 1.5rem;
    font-weight: 700;
    margin-bottom: 0.75rem;
}
.ds-cookie-panel-intro {
    font-size: 0.875rem;
    color: #d1d5db;
    line-height: 1.5;
    margin-bottom: 1.5rem;
}
.ds-cookie-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    padding: 1rem 0;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
}
.ds-cookie-row-text {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}
.ds-cookie-row-label {
    font-family: 'Lora', serif;
    font-weight: 600;
    font-size: 1rem;
}
.ds-cookie-row-label em {
    color: #93c5fd;
    font-style: normal;
    font-size: 0.75rem;
    font-weight: 400;
}
.ds-cookie-row-desc {
    font-size: 0.8125rem;
    color: #d1d5db;
    line-height: 1.5;
    max-width: 360px;
}
.ds-cookie-panel-actions {
    display: flex;
    justify-content: flex-end;
    gap: 0.75rem;
    margin-top: 1.5rem;
    padding-top: 1.5rem;
    border-top: 1px solid rgba(255, 255, 255, 0.12);
}

/* Toggle switch, styled to match the site's blue accent */
.ds-cookie-toggle {
    position: relative;
    display: inline-block;
    width: 2.75rem;
    height: 1.5rem;
    flex-shrink: 0;
}
.ds-cookie-toggle input {
    opacity: 0;
    width: 0;
    height: 0;
}
.ds-cookie-toggle-slider {
    position: absolute;
    inset: 0;
    background-color: rgba(255, 255, 255, 0.25);
    border-radius: 999px;
    transition: background-color 0.2s ease;
    cursor: pointer;
}
.ds-cookie-toggle-slider::before {
    content: "";
    position: absolute;
    height: 1.15rem;
    width: 1.15rem;
    left: 0.175rem;
    top: 0.175rem;
    background-color: #ffffff;
    border-radius: 50%;
    transition: transform 0.2s ease;
}
.ds-cookie-toggle input:checked + .ds-cookie-toggle-slider {
    background-color: #174a7c;
}
.ds-cookie-toggle input:checked + .ds-cookie-toggle-slider::before {
    transform: translateX(1.25rem);
}
.ds-cookie-toggle input:disabled + .ds-cookie-toggle-slider {
    background-color: #174a7c;
    opacity: 0.6;
    cursor: not-allowed;
}

/* ---- Consent-gated embeds (e.g. the Contact page's Google Map) ---- */

.ds-embed {
    margin-top: 1.5rem;
}
.ds-embed-iframe {
    width: 100%;
    height: 220px;
    border: 0;
    border-radius: 0.75rem;
    display: block;
}
.ds-embed:not(.ds-embed-activated) .ds-embed-iframe {
    display: none;
}
.ds-embed.ds-embed-activated .ds-embed-placeholder {
    display: none;
}
.ds-embed-placeholder {
    background: rgba(11, 31, 58, 0.05);
    border: 1px dashed rgba(11, 31, 58, 0.25);
    border-radius: 0.75rem;
    padding: 1.25rem;
    text-align: center;
}
.ds-embed-placeholder p {
    font-size: 0.8125rem;
    color: rgba(11, 31, 58, 0.8);
    line-height: 1.5;
    margin-bottom: 0.75rem;
}
.ds-embed-enable-btn {
    font-family: 'Fira Sans', sans-serif;
    font-size: 0.8125rem;
    font-weight: 600;
    padding: 0.55rem 1.1rem;
    border-radius: 0.5rem;
    border: none;
    background-color: #174a7c;
    color: #ffffff;
    cursor: pointer;
    transition: background-color 0.2s ease;
}
.ds-embed-enable-btn:hover {
    background-color: #123c66;
}

@media (max-width: 640px) {
    #ds-cookie-banner {
        border-radius: 1rem 1rem 0 0;
    }
    .ds-cookie-banner-inner {
        flex-direction: column;
        align-items: stretch;
        padding: 0.6rem 1rem;
        gap: 0.4rem;
    }
    .ds-cookie-text-long { display: none; }
    .ds-cookie-text-short { display: inline; }
    .ds-cookie-text {
        flex: none;
        font-size: 0.8rem;
        line-height: 1.4;
    }
    .ds-cookie-actions {
        justify-content: stretch;
        gap: 0.375rem;
    }
    .ds-cookie-actions .ds-cookie-btn {
        flex: 1 1 0;
        padding: 0.35rem 0.5rem;
        font-size: 0.8rem;
    }
    .ds-cookie-panel {
        padding: 1.5rem;
    }
    .ds-cookie-row {
        flex-direction: column;
        gap: 0.75rem;
    }
}

/* Sub-hero copy fades in on load, and replays via main.js whenever the tab
   regains focus (visibilitychange / pageshow) or is restored from bfcache. */
.hero-fade-text {
    opacity: 0;
}
.hero-fade-text.hero-fade-in {
    animation: hero-fade-in 1500ms cubic-bezier(0.16, 1, 0.3, 1) both;
}
@keyframes hero-fade-in {
    0% { opacity: 0; transform: translateY(22px); filter: blur(10px); }
    60% { opacity: 0.85; filter: blur(3px); }
    100% { opacity: 1; transform: translateY(0); filter: blur(0); }
}
@media (prefers-reduced-motion: reduce) {
    .hero-fade-text {
        opacity: 1;
        animation: none;
    }
}

/* Home page only: just the sub-hero paragraph sized up 25% over the
   site-wide default. Nav, heading, button, and footer stay at normal size. */
.home-page .hero-content p {
    font-size: 1.40625rem; /* text-lg (1.125rem) * 1.25 */
}
@media (min-width: 768px) {
    .home-page .hero-content p {
        font-size: 1.5625rem; /* md:text-xl (1.25rem) * 1.25 */
    }
}

/* Custom cursor: one ring + one center dot that recolors to contrast
   whatever background it's under — white over the navy hero, the nav bar's
   own dark navy text color over the white nav bar. Hotspot sits at the
   ring's center (matches the 14 14 offset). */
:root {
    --cursor-white: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 28 28'><circle cx='14' cy='14' r='11' fill='none' stroke='%23ffffff' stroke-width='1.6'/><circle cx='14' cy='14' r='1.8' fill='%23ffffff'/></svg>") 14 14, auto;
    --cursor-blue: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 28 28'><circle cx='14' cy='14' r='11' fill='none' stroke='%230b1f3a' stroke-width='1.6'/><circle cx='14' cy='14' r='1.8' fill='%230b1f3a'/></svg>") 14 14, auto;
    --cursor-scroll: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='28' height='28' viewBox='0 0 28 28'><circle cx='14' cy='14' r='11' fill='none' stroke='%23ffffff' stroke-width='1.6'/><path d='M14 9 L14 17 M10.5 13.5 L14 17 L17.5 13.5' fill='none' stroke='%23ffffff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/></svg>") 14 14, auto;
}
body {
    cursor: var(--cursor-white);
}
.hero-section,
.hero-section a,
.hero-section button {
    cursor: var(--cursor-white);
}
.site-header,
.site-header a,
.site-header button,
.site-mobile-menu,
.site-mobile-menu a {
    cursor: var(--cursor-blue);
}

/* About page: a down-arrow-in-a-ring cursor over the right half of the
   pinned hero, signaling to the user that scrolling advances the staged
   paragraph reveals (and eventually the rest of the page). */
.about-hero-right-half,
.about-hero-right-half a {
    cursor: var(--cursor-scroll);
}

/* About page: the Mission/Approach/Principles section is on a white
   background, so it gets the same dark-on-light cursor as the nav bar. */
.about-page,
.about-page a {
    cursor: var(--cursor-blue);
}

/* ...except the mesh card itself (navy, like the hero), which keeps the
   white cursor; its white table falls back to the inherited --cursor-blue
   from .about-page above (plain ring + dot, no arrow). */
.about-modules-section {
    cursor: var(--cursor-white);
}

/* Services page also carries the .about-page class (for shared layout
   behavior), which would otherwise blanket its navy mesh background in
   the blue cursor meant for the About page's white section. .services-
   accordion already overrides back to blue for its own white table. */
#services {
    cursor: var(--cursor-white);
}

/* Same fix for the Contact page: its navy background gets the white
   cursor; its glass .contact-panel boxes get an explicit --cursor-blue
   override below (they don't carry .about-page themselves, so they
   wouldn't inherit it — they'd otherwise inherit the white set here). */
#contact {
    cursor: var(--cursor-white);
}
.contact-panel,
.contact-panel a {
    cursor: var(--cursor-blue);
}
